Home > src > population.m

population

PURPOSE ^

- population object

SYNOPSIS ^

This is a script file.

DESCRIPTION ^

 - population object

 copyright 2009-2012 Blair Armstrong, Christine Watson, David Plaut

    This file is part of SOS

    SOS is free software: you can redistribute it and/or modify
    it for academic and non-commercial purposes
    under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.  For commercial or for-profit
    uses, please contact the authors (sos@cnbc.cmu.edu).

    SOS is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SUBFUNCTIONS ^

SOURCE CODE ^

0001 % - population object
0002 %
0003 % copyright 2009-2012 Blair Armstrong, Christine Watson, David Plaut
0004 %
0005 %    This file is part of SOS
0006 %
0007 %    SOS is free software: you can redistribute it and/or modify
0008 %    it for academic and non-commercial purposes
0009 %    under the terms of the GNU General Public License as published by
0010 %    the Free Software Foundation, either version 3 of the License, or
0011 %    (at your option) any later version.  For commercial or for-profit
0012 %    uses, please contact the authors (sos@cnbc.cmu.edu).
0013 %
0014 %    SOS is distributed in the hope that it will be useful,
0015 %    but WITHOUT ANY WARRANTY; without even the implied warranty of
0016 %    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0017 %    GNU General Public License for more details.
0018 
0019 %    You should have received a copy of the GNU General Public License
0020 %    along with SOS (see COPYING.txt).
0021 %    If not, see <http://www.gnu.org/licenses/>.
0022 
0023 
0024 classdef population < dataFrame 
0025     %% creates and manipulates population objects
0026     %
0027     %   This class provides support for functions and data storage that are
0028     %   specific to population objects, from which samples are created.
0029     %
0030     %   Additional functionality is inherited from parent class <dataFrame>
0031     %
0032     %
0033     %PROPERTIES
0034     %   samples - Array of samples associated with the population
0035     %   name - string name associated with the variable
0036     %
0037     % ** ALSO manages the global property 'popCount', which tracks the
0038     % number of populations that have been created.
0039     %
0040     %METHODS
0041     %   population(filename, ['isHeader',<logical>, 'isFormatting',<logical>, 'outFile',<string>]) -  constructor
0042     %   addSample(sample) - associate a sample with the population
0043     %   popItem(itemIndex) - pops and returns the item at {itemIndex}
0044     %   insertItem(itemIndex,item) - inserts {item} at {itemIndex}
0045     %
0046     %METHODS (STATIC)
0047     %   populationInputParser() - generates an input parser for the constructor
0048     %
0049     %METHODS (Static, Access=private)
0050     % function p = parseConstructorArgs(fileName,varargin) - parses constructor args
0051 
0052     %% PROPERTIES
0053     properties
0054         samples % Array of samples associated with the population
0055         name % string name associated with the variable
0056     end %# properties
0057 
0058     %% METHODS
0059     methods
0060         
0061         %% population CONSTRUCTOR
0062         function obj = population(fileName,varargin)
0063         % Constructor - Creates a population object
0064             %
0065             % CALL:
0066             % population(filename, ['isHeader',<logical>, 'isFormatting',<logical>, 'outFile',<string>])
0067             %
0068             % SYNOPSIS:
0069             % Constructor - Creates a population object and returns it
0070             %
0071             % PARAMETERS:
0072             %  REQUIRED:
0073             %   fileName - src file for the population is required, which must
0074             %       follow the SOS dataFrame format specifications.
0075             %
0076             %  OPTIONAL:
0077             %   isHeader/logical - param/logical-value pair indicating if
0078             %       the source file has a header.  Defaults to false.
0079             %   isFormatting/logical -  param/logical-value indicating if
0080             %       the source file has formating.  Defaults to false.
0081             %   outFile - param/string-value pair indicating the name
0082             %       (inc. path, if other than pwd is desired) of
0083             %       of file to save the residual population in after
0084             %       optimization has been completed.  Outfile is not
0085             %       validated until write.  Defaults to 'null'
0086             %   name/string - string name for the variable.
0087             %
0088             % EXAMPLE:
0089             %   p1 = population('p1.txt',1,5);
0090             %
0091             
0092             verbosePrint([char(10) 'Creating and Configuring Population Object'], ...
0093                 'population_constructor_startObjCreation');
0094             
0095             p = population.parseConstructorArgs(fileName,varargin);
0096 
0097             
0098              global popCount;
0099             if(isempty(popCount))
0100                 curCount = 1;
0101             else
0102                 curCount = popCount + 1;
0103             end
0104             
0105             %override the default outFile with the sample number if a user
0106             %specified value was not specified.
0107             if any(strcmp(p.UsingDefaults,'outFile'))
0108                 outFile = ['pop',num2str(curCount),'.res.out.txt'];
0109             else
0110                 outFile = p.Results.outFile;
0111             end
0112             
0113             %check that the new outfile is a valid filename, warn if file
0114             %exists
0115             if ischar(outFile) == false || strcmp(outFile,'null')
0116                 error('Outfile has not been set to a string != null.');
0117             end
0118             
0119             if (exist(outFile,'file'))
0120                verbosePrint([char(10) 'WARNING: File {', outFile, '} already exists.  ', ...
0121                    'If you attempt to write to this file, ',...
0122                    'the existing one will be overridden' char(10)], ...
0123                     'population_constructor_fileExists');  
0124             end
0125             
0126             %similarly, add a default name based on the sample count if no
0127             %name was supplied
0128             if (any(strcmp(p.UsingDefaults,'name')))
0129                 name = ['pop',num2str(curCount)]; %#ok<PROP>
0130             else
0131                 name = p.Results.name; %#ok<PROP>
0132             end
0133                
0134             
0135             obj = obj@dataFrame('fileName',p.Results.fileName,'isHeader',p.Results.isHeader, ...
0136                 'isFormatting',p.Results.isFormatting,'outFile', ...
0137                  outFile);       
0138             
0139             obj.name = name; %#ok<PROP>
0140              
0141             verbosePrint(['Creation of Population Object Complete' char(10)], ...
0142                 'population_constructor_endObjCreation');
0143             
0144             popCount = curCount;
0145             
0146         end % population constructor
0147         
0148         %% addSample METHOD
0149         function obj = addSample(obj,sample)
0150             % Associates a sample with a population
0151             %
0152             %CALL:
0153             % <populationObj>.addSample(sample)
0154             %
0155             %SYNOPSIS:
0156             %associates a sample with the population.  Also updates the number
0157             %and order of columns in the population and its samples so that
0158             %all of these dataframes are in sync.
0159             %
0160             %PARAMETERS:
0161             %   sample - a sample object
0162             %
0163             %EXAMPLE:
0164             %   p1.addSample(obj,s1); % where s1 is a sample object
0165             
0166             obj.samples = [obj.samples sample];
0167 
0168             %ensure that that all the samples associated with the
0169             %population have the same columns and order of columns as in
0170             %the population.  If addSample is called in the intended way,
0171             %i.e., from within the sample.setPop() method, the population
0172             %will already be synchronized with the new sample, so this just
0173             %pushes those changes to the other samples associated with the
0174             %population
0175             
0176             %First, make sure all the samples contain the same columns as
0177             %the population
0178             for i=1:length(obj.samples)
0179                 updatedSample = dataFrame.aContainsb(obj.samples(i),obj);
0180                 obj.samples(i) = updatedSample;
0181             end 
0182             
0183             %Second, make sure all the columns are ordered in the same way
0184             %across all the samples and the population.
0185             for i=1:length(obj.samples)
0186                 tmpData = obj.samples(i).data;  
0187                 
0188                 %if the sample does have data, need to make sure it's
0189                 %odered.
0190                 
0191                 %This section of the code could be make more efficient, as
0192                 %it currently applies the same blind 'matching' algorithm
0193                 %to all non-empty dataframes, even those that are already
0194                 %sorted.  However, for present purposes, this method is a
0195                 %simple, guaranteed way to make sure the columns line up.
0196                 %Best to spend the time adding more features ;)
0197                 if (isempty(tmpData) == 0)
0198                     for j=1:length(obj.header)
0199                        for k=1:length(obj.samples(i).header)
0200                             if(strcmp(char(obj.header{j}), ...
0201                                     char(obj.samples(i).header{k})))
0202                                 sampleIndex = k;
0203                             end;
0204                        end
0205                    
0206                        tmpData(j) = obj.samples(i).data(sampleIndex);
0207                        
0208                     end
0209                 end
0210                 
0211                 %update the sample dataframe and header information so it's
0212                 %all synched with the population
0213                 obj.samples(i).data = tmpData;
0214                 obj.samples(i).header = obj.header;
0215                 obj.samples(i).format = obj.format;
0216                            
0217             end     
0218         end %addSample
0219         
0220         %% popItem(itemIndex) METHOD
0221         function item = popItem(obj,itemIndex)  
0222             % pops and returns the item at {item index}
0223             %
0224             %CALL:
0225             % item =  <populationObj>.popItem(itemIndex)
0226             %
0227             %SYNOPSIS:
0228             % pops and returns the item at {itemIndex}
0229             %
0230             %PARAMETERS:
0231             %   itemIndex - the row index of the to-be-popped item
0232             
0233             p = inputParser;
0234             
0235             p.addRequired('obj');
0236             p.addRequired('itemIndex',@(itemIndex)validateattributes(itemIndex, {'numeric'}, ...
0237                 {'scalar', 'integer', 'positive','>' 0}));
0238             p.parse(obj,itemIndex);
0239             
0240             if(isempty(obj.data{1}) == true)
0241                 error(['ERROR: No data in dataframe object - cannot pop item.',...
0242                        char(10),'       If you are filling samples, make sure the pop size >= to',...
0243                        char(10),'       The number of items in all the samples drawing from it.']);
0244             elseif itemIndex > length(obj.data{1})
0245                 error('{itemIndex} exceeds row range of data array');
0246             end
0247             
0248             item = popItem@dataFrame(obj,itemIndex);
0249         end
0250         
0251         %% insertItem(item, itemIndex) METHOD
0252         function obj = appendItem(obj,item)
0253             % inserts {item} at {itemIndex}
0254             %
0255             % Warning!!!  Method does not confirm that the column structure
0256             % of {item} (i.e., what columns of data are in what order)
0257             % match that of the population's data.  This should be the case if
0258             % SOS is manipulating the items since it will only insert items
0259             % into the population that belong to the corresponding samples,
0260             % which should be in sync.  However, manual invocation of this
0261             % method does not have this guarantee.  Use carefully!
0262             %
0263             %CALL:
0264             % <populationObj>.insertItem(itemIndex,item)
0265             %
0266             %SYOPSIS:
0267             %inserts {item} at {itemIndex}
0268             %
0269             %PARAMETERS:
0270             %item - an item (row) consistent with the population
0271             %itemIndex - the index at which this item should be inserted
0272             
0273             appendItem@dataFrame(obj,item);
0274         end
0275             
0276     end %methods
0277 
0278     methods (Static)
0279         
0280         %% p = populationInputParser() STATIC METHOD
0281         function p = populationInputParser()
0282         % generates an input parser with parameter/value pairs and validators for the constructor args.
0283 
0284             p = inputParser;
0285             
0286             %Define required and optional arguments, and specify how they
0287             %are to be validated
0288             
0289             p.addRequired('fileName',@(fileName)validFileName(fileName));
0290             p.addParamValue('isHeader',false, ...
0291                 @(isHeader)validLogical(isHeader));
0292             p.addParamValue('isFormatting',false, ...
0293                 @(isFormatting)validLogical(isFormatting));
0294             p.addParamValue('name','noname', ...
0295                 @(name)ischar(name));
0296             %Note that outfile is not validated at this point; this will be
0297             %done when it comes time to write to the file.  Motivation is
0298             %that I don't want to write to create a file (and directory
0299             %structure) unless the user ultimately wants to write
0300             %something.
0301             p.addParamValue('outFile','null',@(outFile)validStringOrNull(outFile));             
0302             
0303         end
0304         
0305     end
0306     
0307     methods (Static, Access=private)
0308         
0309         %% p = parseConstructorArgs(fileName,varargin) STATIC PRIVATE METHOD
0310         function p = parseConstructorArgs(fileName,varargin)
0311             % parses arguments from population constructor
0312             %
0313             %CALL:
0314             % p = population.parseConstructorArgs(fileName,varargin)
0315             %
0316             %SYOPSIS:
0317             %parses the arguments from the population constructor.  Default
0318             %values are substituted where appropriate.  Returns a struct
0319             %with the parsed args
0320             %
0321             %PARAMETERS:
0322             % SAME as population CONSTRUCTOR
0323             %
0324             %RETURNS:
0325             % the parsed constructor arguments in struct format
0326     
0327             %this cell gets recursively wrapped when it is passed, so
0328             %unwrap one layer.
0329             varargin = varargin{1};
0330            
0331             p = population.populationInputParser();
0332 
0333             p.parse(fileName,varargin{:});
0334   
0335         end %parse Constructor Args
0336             
0337     end % methods (Static)
0338 end
0339 
0340 
0341

Generated on Fri 27-Jan-2012 16:18:41 by m2html © 2005