Home > functions > internal > dsUpdateStudy.m

dsUpdateStudy

PURPOSE ^

UPDATESTUDY - helper function to keep track of study metadata when anything is saved

SYNOPSIS ^

function studyinfo = dsUpdateStudy(study_dir,varargin)

DESCRIPTION ^

UPDATESTUDY - helper function to keep track of study metadata when anything is saved

 This only updates simulation-specific info in the DynaSim studyinfo
 structure, tracks status of simulations and analyses, and manages the queue
 for simultaneous processes updating studyinfo structure.

 Usage:
   studyinfo=dsUpdateStudy(study_dir,varargin)

 Inputs:
   - study_dir
   - options: TODO

 Outputs:
   - studyinfo

 Notes:
 - Note: this function is not intended for users. it is an internal function
   called by functions like dsSimulate, dsAnalyzeStudy, and dsCreateBatch.
 - Note: this function should only update metadata stored in the
   studyinfo.simulations substructure.

 TODO: this multiple things in this function should be split up into individual functions

 See also: dsCheckStudyinfo, dsSetupStudy, dsSimulate, dsCreateBatch, dsAnalyzeStudy

 Author: Jason Sherfey, PhD <jssherfey@gmail.com>
 Copyright (C) 2016 Jason Sherfey, Boston University, USA

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SOURCE CODE ^

0001 function studyinfo = dsUpdateStudy(study_dir,varargin)
0002 %UPDATESTUDY - helper function to keep track of study metadata when anything is saved
0003 %
0004 % This only updates simulation-specific info in the DynaSim studyinfo
0005 % structure, tracks status of simulations and analyses, and manages the queue
0006 % for simultaneous processes updating studyinfo structure.
0007 %
0008 % Usage:
0009 %   studyinfo=dsUpdateStudy(study_dir,varargin)
0010 %
0011 % Inputs:
0012 %   - study_dir
0013 %   - options: TODO
0014 %
0015 % Outputs:
0016 %   - studyinfo
0017 %
0018 % Notes:
0019 % - Note: this function is not intended for users. it is an internal function
0020 %   called by functions like dsSimulate, dsAnalyzeStudy, and dsCreateBatch.
0021 % - Note: this function should only update metadata stored in the
0022 %   studyinfo.simulations substructure.
0023 %
0024 % TODO: this multiple things in this function should be split up into individual functions
0025 %
0026 % See also: dsCheckStudyinfo, dsSetupStudy, dsSimulate, dsCreateBatch, dsAnalyzeStudy
0027 %
0028 % Author: Jason Sherfey, PhD <jssherfey@gmail.com>
0029 % Copyright (C) 2016 Jason Sherfey, Boston University, USA
0030 
0031 
0032 % check inputs
0033 options=dsCheckOptions(varargin,{...
0034   'process_id',[],[],... % identifier for simulation to update
0035   'status',[],[],... % status of simulation
0036   'modifications_set',[],[],... % search space
0037   'model',[],[],... % base_model or modified_model
0038   'simulator_options',[],[],... % base_simulator_options
0039   'solve_file',[],[],... % m- or mex-file solving the system
0040   'prefix','study',[],... % prefix prepended to all output files
0041   'email',[],[],... % email to send notification upon study completion
0042   'verbose_flag',0,{0,1},...
0043   'duration',[],[],... % process duration
0044   },false);
0045 %   'base_data_files',[],[],... % base data files to analyze
0046 %   'project_id',[],[],... % unique identifier of parent project
0047 
0048 % load most recent version of studyinfo structure from file
0049 studyinfo=dsCheckStudyinfo(study_dir,'process_id',options.process_id, varargin{:});
0050 already_finished = all(strcmp('finished',{studyinfo.simulations.status}));
0051 
0052 % track status of simulations and analyses
0053 % index to this simulation in studyinfo
0054 sim_ind=find([studyinfo.simulations.sim_id]==options.process_id);
0055 % update studyinfo.simulations
0056 % update basic fields
0057 if ~isempty(options.simulator_options)
0058   studyinfo.simulations(sim_ind).simulator_options=options.simulator_options;
0059 end
0060 if ~isempty(options.solve_file)
0061   studyinfo.simulations(sim_ind).solve_file=options.solve_file;
0062 end
0063 % status-specific updates
0064 if ~isempty(options.status) && ~isempty(studyinfo.simulations)
0065   if options.verbose_flag
0066     fprintf('setting status=''%s'' where sim_id=%g\n',options.status,options.process_id);
0067   end
0068   studyinfo.simulations(sim_ind).status=options.status;
0069   switch options.status
0070     case 'finished'
0071       % set stop_time
0072       studyinfo.simulations(sim_ind).stop_time=datestr(now);
0073       studyinfo.simulations(sim_ind).simulator_options=options.simulator_options;
0074       % save DynaSim model structure
0075       if isstruct(options.model)
0076         model=options.model;
0077         model_file=studyinfo.simulations(sim_ind).modified_model_file;
0078         try
0079           save(model_file,'model','-v7');
0080           if ~strcmp(reportUI,'matlab')
0081             [wrn_msg,wrn_id] = lastwarn;
0082             if strcmp(wrn_msg,'save: wrong type argument ''function handle''')
0083               error('save: wrong type argument ''function handle''');
0084             end
0085           end
0086         catch
0087           fprintf('Data is not ''-v7'' compatible. Saving in hdf5 format.\n')
0088           save(model_file,'model','-hdf5');
0089         end
0090         if options.verbose_flag
0091           fprintf('model saved to %s\n',model_file);
0092         end
0093       end
0094       % obtain and record machine info
0095       try
0096         [~,kernel] = system('uname -v');
0097         [~,OS]     = system('uname -o');
0098        [~,home]    = system('echo $HOME');  % home directory
0099        [zzz, computername] = system('hostname');           % Uses linux system command to get the machine name of host.
0100        [zzz, meminfo]      = system('cat /proc/meminfo');  % Uses linux system command to get a report on system memory
0101        total_memory        = textscan(meminfo, '%*s %s %s', 1);  % Parses the memory report for 2nd and 3rd space-delimited items of first line: memory amount.
0102        total_memory        = [total_memory{1}{1} ' ' total_memory{2}{1}];  % Extracts the info from cell array to create char array.
0103        [zzz, cpuinfo]      = system('cat /proc/cpuinfo');  % Uses linux system command to get a report on CPU types and speeds, etc.
0104        cpuinfo             = textscan(cpuinfo, '%*s %*s %*s %*s %s %*s %*s %s', 1, 'delimiter', '\n'); % Extracts lines 5 and 8 of report: Proc Type, and Cache
0105        CPU_type            = textscan(cpuinfo{1}{1}, '%*s %s', 1, 'delimiter' , ':'); % Parses line that includes CPU type.
0106        CPU_type            = [strrep(CPU_type{1}{1},'  ','') ];    % ## Look for better way for this: collapse all repeated white space stretches to single spaces.
0107        CPU_cache           = textscan(cpuinfo{2}{1}, '%*s %s', 1, 'delimiter' , ':'); % Parses line that includes the cache info
0108        CPU_cache           = [CPU_cache{1}{1} ];                                      % Takes the cache info out of the cell array.
0109        machine_info.host_name=strtrim(computername);
0110        machine_info.total_memory=total_memory;
0111        machine_info.CPU_type=CPU_type;
0112        machine_info.CPU_cache=CPU_cache;
0113        machine_info.num_cores=feature('numcores');          % Matlab command to get the number of processor cores on current host machine.
0114        machine_info.operating_system=strtrim(OS);
0115        machine_info.kernel=strtrim(kernel);
0116        machine_info.home_dir=strtrim(home);
0117        studyinfo.simulations(sim_ind).machine_info=machine_info;
0118       end
0119       % set duration
0120       if isempty(options.duration)
0121         %t1=datevec(studyinfo.simulations(sim_ind).start_time);
0122         %t2=datevec(now);
0123         duration=nan;%etime(t2,t1);
0124       else
0125         duration=options.duration;
0126       end
0127       studyinfo.simulations(sim_ind).duration=duration;
0128       % copy cluster logs to study directory
0129       if isdir(studyinfo.simulations(sim_ind).batch_dir)
0130         log_dir=fullfile(studyinfo.study_dir,'logs');
0131         log_file=fullfile(studyinfo.simulations(sim_ind).batch_dir,'pbsout',['sim_job' num2str(options.process_id) '.out']);
0132         if exist(log_file,'file')
0133           if ~exist(log_dir,'dir')
0134             if options.verbose_flag
0135               fprintf('creating study logs directory: %s\n',log_dir);
0136             end
0137             mkdir(log_dir);
0138           end
0139           if options.verbose_flag
0140             fprintf('copying cluster log to study logs directory: %s\n',log_file);
0141           end
0142           [success,msg]=copyfile(log_file,log_dir);
0143           if ~success, error(msg); end
0144         end
0145       end
0146     case 'failed'
0147       % set error_log
0148       %studyinfo.simulations(sim_ind).error_log=MException.last;
0149         % usage: displayError(studyinfo.simulations(k).error_log);
0150       studyinfo.simulations(sim_ind).error_log=lasterr;
0151       % copy cluster logs to study directory
0152       if isdir(studyinfo.simulations(sim_ind).batch_dir)
0153         log_dir=fullfile(studyinfo.study_dir,'logs');
0154         log_file=fullfile(studyinfo.simulations(sim_ind).batch_dir,'pbsout',['sim_job' num2str(options.process_id) '.out']);
0155         errfile=fullfile(studyinfo.simulations(sim_ind).batch_dir,'pbsout',['sim_job' num2str(options.process_id) '.err']);
0156         if exist(log_file,'file')
0157           if options.verbose_flag
0158             fprintf('copying cluster logs to study logs directory...\n');
0159             fprintf('\t%s\n',log_file);
0160           end
0161           copyfile(log_file,log_dir);
0162         end
0163         if exist(errfile,'file')
0164           if options.verbose_flag
0165             fprintf('\t%s\n',errfile);
0166           end
0167           copyfile(errfile,log_dir);
0168         end
0169       end
0170     otherwise
0171       % do nothing
0172   end
0173 end
0174 % update studyinfo.analysis
0175 if ~isempty(options.status) && ~isempty(studyinfo.analysis)
0176   % ...
0177 end
0178 % check if study is complete; clean up if so (e.g, remove batchdirs)
0179 if all(strcmp('finished',{studyinfo.simulations.status}))
0180   fprintf('ALL SIMULATIONS HAVE FINISHED!\n');
0181   % cleanup study
0182   if ~already_finished % this is the first time the study has completed
0183     if 0
0184       % cleanup batch directory
0185       batch_dirs=unique({studyinfo.simulations.batch_dir});
0186       log_dir=fullfile(studyinfo.study_dir,'logs');
0187       if ~exist(log_dir,'dir')
0188         if options.verbose_flag
0189           fprintf('creating log directory: %s\n',log_dir);
0190         end
0191         mkdir(log_dir);
0192       end
0193       for i=1:length(batch_dirs)
0194         if ~exist(batch_dirs{i},'dir')
0195           continue;
0196         end
0197         % copy log files from batch_dir to study_dir/logs
0198         if exist(fullfile(batch_dirs{i},'pbsout'),'dir')
0199           if options.verbose_flag
0200             fprintf('copying log files from batch directory to study logs directory...\n');
0201           end
0202           copyfile(fullfile(batch_dirs{i},'pbsout'),log_dir);
0203         end
0204         % remove batch directory
0205         if options.verbose_flag
0206           fprintf('removing batch directory: %s\n',batch_dirs{i});
0207         end
0208         rmdir(batch_dirs{i},'s');
0209       end
0210     end
0211     % email notification:
0212     if ~isempty(options.email)
0213       %% Send Email
0214       if options.verbose_flag
0215         fprintf('emailing notification of study completion to %s\n',options.email);
0216       end
0217       email_attachments = {};
0218       reply_address = 'batch@infinitebrain.org';
0219       try
0220         setpref('Internet','SMTP_Server','127.0.0.1'); % Sets the outgoing mail server - often the default 127.0.0.1
0221         setpref('Internet','E_mail',reply_address);    % Sets the email FROM/reply address for all outgoing email reports.
0222         if ~isempty(email_attachments)
0223           fprintf('Files attached to report email:\n');
0224           email_attachments{:}
0225         end
0226         sendmail(options.email,sprintf('Analysis report for study: "%s"',studyinfo.study_dir),...
0227            [10 options.prefix '. Max simulation time: ' sprintf('%0.2f min',max([studyinfo.simulations.duration])/60) '. Browse models (results?) online at infinitebrain.org. Current time: ' datestr(now,31) '  (Automated message from DynaSim (github.com/dynasim/dynasim).)' 10],...
0228            {email_attachments{:}});
0229         fprintf('\nreport emailed successfully to: %s\n',options.email);
0230       catch exception
0231         fprintf('\nFailed to email report to: %s\n',options.email);
0232         displayError(exception);
0233       end
0234     end
0235   end
0236 end
0237 
0238 % todo: auto-relaunch batch? ...
0239 % ...
0240 
0241 % update studyinfo on disk
0242 dsStudyinfoIO(studyinfo.simulations(sim_ind),study_dir,options.process_id,options.verbose_flag);
0243 
0244 
0245 %     case 'started'
0246 %       % set start_time
0247 %       studyinfo.simulations(sim_ind).start_time=datestr(now);
0248 %       studyinfo.simulations(sim_ind).simulator_options=options.simulator_options;
0249 %       % save DynaSim model structure
0250 %       if isstruct(options.model)
0251 %         model=options.model;
0252 %         model_file=studyinfo.simulations(sim_ind).modified_model_file;
0253 %         save(model_file,'model','-v7.3');
0254 %         if options.verbose_flag
0255 %           fprintf('model saved to %s\n',model_file);
0256 %         end
0257 %       end
0258 %        % obtain and record machine info
0259 %        try
0260 %          [~,kernel] = system('uname -v');
0261 %          [~,OS]     = system('uname -o');
0262 %         [~,home]    = system('echo $HOME');  % home directory
0263 %         [zzz, computername] = system('hostname');           % Uses linux system command to get the machine name of host.
0264 %         [zzz, meminfo]      = system('cat /proc/meminfo');  % Uses linux system command to get a report on system memory
0265 %         total_memory        = textscan(meminfo, '%*s %s %s', 1);  % Parses the memory report for 2nd and 3rd space-delimited items of first line: memory amount.
0266 %         total_memory        = [total_memory{1}{1} ' ' total_memory{2}{1}];  % Extracts the info from cell array to create char array.
0267 %         [zzz, cpuinfo]      = system('cat /proc/cpuinfo');  % Uses linux system command to get a report on CPU types and speeds, etc.
0268 %         cpuinfo             = textscan(cpuinfo, '%*s %*s %*s %*s %s %*s %*s %s', 1, 'delimiter', '\n'); % Extracts lines 5 and 8 of report: Proc Type, and Cache
0269 %         CPU_type            = textscan(cpuinfo{1}{1}, '%*s %s', 1, 'delimiter' , ':'); % Parses line that includes CPU type.
0270 %         CPU_type            = [strrep(CPU_type{1}{1},'  ','') ];    % ## Look for better way for this: collapse all repeated white space stretches to single spaces.
0271 %         CPU_cache           = textscan(cpuinfo{2}{1}, '%*s %s', 1, 'delimiter' , ':'); % Parses line that includes the cache info
0272 %         CPU_cache           = [CPU_cache{1}{1} ];                                      % Takes the cache info out of the cell array.
0273 %         machine_info.host_name=strtrim(computername);
0274 %         machine_info.total_memory=total_memory;
0275 %         machine_info.CPU_type=CPU_type;
0276 %         machine_info.CPU_cache=CPU_cache;
0277 %         machine_info.num_cores=feature('numcores');          % Matlab command to get the number of processor cores on current host machine.
0278 %         machine_info.operating_system=strtrim(OS);
0279 %         machine_info.kernel=strtrim(kernel);
0280 %         machine_info.home_dir=strtrim(home);
0281 %         studyinfo.simulations(sim_ind).machine_info=machine_info;
0282 %        end

Generated on Tue 12-Dec-2017 11:32:10 by m2html © 2005