Home > functions > dsPlot2.m

dsPlot2

PURPOSE ^

% handles=dsPlot(data,'option',value)

SYNOPSIS ^

function [handles,xp] = dsPlot2(data,varargin)

DESCRIPTION ^

% handles=dsPlot(data,'option',value)
 Purpose: plot data in various ways depending on what data was provided
 and what options are defined. this function is wrapped by dsPlotWaveforms,
 PlotPower, ... to provide a single function for organizing and displaying
 data.
 Inputs:
   data: DynaSim data structure (see dsCheckData)
   Accepts the following name/value pairs:
     'plot_type' {'waveform' (default),'rastergram','rates','power'} - what to plot
     'population' - name of population to plot (default: 'all'); accepts
                    regexp strings
     'variable' - name of variable to plot for each population (default: state variable, X or V);
                      accepts regexp strings
     'varied1' - Indices of 1st varied model parameter to plot. If the parameter
                 is numeric, specify indices (e.g. 1:3 corresponds to 1st-3rd
                 varied values. If the parameter is a char array, uses
                 regular expressions. Instead of 'varied1', can also use
                 the actual parameter name (e.g. 'E_Iapp')
     'varied2' - As varied 1, for 2nd varied parameter
     ....
     'variedN' - As varied 1, for 2nd varied parameter
     'num_embedded_subplots' - maximum # of waveforms to overlay per plot
     'max_num_overlaid' - maximum # of waveforms to overlay per plot
     'do_mean' - {false, true} - Turn on/off averaging across all units
                 in a population
     'force_last' - {'none', 'populations' (default), 'variables', 'varied1' ... 'variedN'}
                       If there is only one cell in a population, this forces
                       dsPlot2 to add other information to the overlay.
     'xlims' - [XMIN XMAX], x-axis limits (default: all data)
     'ylims' - [YMIN YMAX], y-axis limits (default: all data)
     'lock_axes' - {false, true}, locks abscissa and ordinate to be
                                  the same across all subplots
     'do_zoom' - {false, true} - Turn on zoom function in subplot_grid
     'yscale' {'linear','log','log10'}, whether to plot linear or log scale
     'visible' {'on','off'}
     NOTE: analysis options available depending on plot_type
       see see dsCalcFR options for plot_type 'rastergram' or 'rates'
       see dsCalcPower options for plot_type 'power'
 Outputs:
   handles: graphic handles to figures

 See also: dsCalcFR, dsCalcPower, dsPlotWaveforms, dsCheckData, dsPlot, MDD,
           MDD

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SUBFUNCTIONS ^

SOURCE CODE ^

0001 function [handles,xp] = dsPlot2(data,varargin)
0002 %% handles=dsPlot(data,'option',value)
0003 % Purpose: plot data in various ways depending on what data was provided
0004 % and what options are defined. this function is wrapped by dsPlotWaveforms,
0005 % PlotPower, ... to provide a single function for organizing and displaying
0006 % data.
0007 % Inputs:
0008 %   data: DynaSim data structure (see dsCheckData)
0009 %   Accepts the following name/value pairs:
0010 %     'plot_type' {'waveform' (default),'rastergram','rates','power'} - what to plot
0011 %     'population' - name of population to plot (default: 'all'); accepts
0012 %                    regexp strings
0013 %     'variable' - name of variable to plot for each population (default: state variable, X or V);
0014 %                      accepts regexp strings
0015 %     'varied1' - Indices of 1st varied model parameter to plot. If the parameter
0016 %                 is numeric, specify indices (e.g. 1:3 corresponds to 1st-3rd
0017 %                 varied values. If the parameter is a char array, uses
0018 %                 regular expressions. Instead of 'varied1', can also use
0019 %                 the actual parameter name (e.g. 'E_Iapp')
0020 %     'varied2' - As varied 1, for 2nd varied parameter
0021 %     ....
0022 %     'variedN' - As varied 1, for 2nd varied parameter
0023 %     'num_embedded_subplots' - maximum # of waveforms to overlay per plot
0024 %     'max_num_overlaid' - maximum # of waveforms to overlay per plot
0025 %     'do_mean' - {false, true} - Turn on/off averaging across all units
0026 %                 in a population
0027 %     'force_last' - {'none', 'populations' (default), 'variables', 'varied1' ... 'variedN'}
0028 %                       If there is only one cell in a population, this forces
0029 %                       dsPlot2 to add other information to the overlay.
0030 %     'xlims' - [XMIN XMAX], x-axis limits (default: all data)
0031 %     'ylims' - [YMIN YMAX], y-axis limits (default: all data)
0032 %     'lock_axes' - {false, true}, locks abscissa and ordinate to be
0033 %                                  the same across all subplots
0034 %     'do_zoom' - {false, true} - Turn on zoom function in subplot_grid
0035 %     'yscale' {'linear','log','log10'}, whether to plot linear or log scale
0036 %     'visible' {'on','off'}
0037 %     NOTE: analysis options available depending on plot_type
0038 %       see see dsCalcFR options for plot_type 'rastergram' or 'rates'
0039 %       see dsCalcPower options for plot_type 'power'
0040 % Outputs:
0041 %   handles: graphic handles to figures
0042 %
0043 % See also: dsCalcFR, dsCalcPower, dsPlotWaveforms, dsCheckData, dsPlot, MDD,
0044 %           MDD
0045 
0046 %% Set Master parameters
0047 
0048 % Flag for returning error if the user specifies name/value pairs that are not in the
0049 % dsCheckOptions list
0050 strict_mode = 0;        % Should be set to zero for this to work within simulate model
0051 
0052 %% Convert data input to appropriate form
0053 
0054 % If data is path to studyinfo...
0055 if ischar(data)
0056     study_dir = data;
0057 
0058     % Import plot files
0059     data_img = dsImportPlots(study_dir);
0060 
0061     [handles, xp] = dsPlot2(data_img,varargin{:});
0062     return;
0063 end
0064 
0065 % Convert the incoming DynaSim data structure to an MDD object
0066 if ~isa(data,'MDD')
0067     [xp,is_image] = dsAll2mdd(data);
0068 else
0069     xp = data;
0070     if iscell(xp.data{1})
0071         is_image = 1;
0072     else
0073         is_image = 0;
0074     end
0075 end
0076 
0077 %% Convert varargin to appropriate forms
0078 % Find out names of varied variables
0079 varied_names = only_varieds(xp);  % Returns only the names of the varied variables
0080 
0081 % Convert 'varied1'...'variedN' values in varargin to the names of the
0082 % actual varied parameters
0083 myargin = varargin;
0084 for i = 1:length(myargin)
0085     % Char entries
0086     if ischar(myargin{i})
0087         myargin{i} = variedN_to_axisnames(myargin{i},varied_names);
0088     end
0089 
0090     % Nested char entries within cell array entries
0091     if iscell(myargin{i})
0092         for j = 1:length(myargin{i})
0093             if ischar(myargin{i}{j})
0094                 myargin{i}{j} = variedN_to_axisnames(myargin{i}{j},varied_names);
0095             end
0096         end
0097     end
0098 end
0099 
0100 % %% Add dummy axes as needed. Having these greatly simplifies the code below.
0101 % if isempty(xp.findaxis('populations'))
0102 %     Na=length(xp.axis);
0103 %     xp.axis(Na+1).name = 'populations';
0104 %     xp.axis(Na+1).values = 'Pop1';
0105 % end
0106 %
0107 % if isempty(xp.findaxis('variables'))
0108 %     Na=length(xp.axis);
0109 %     xp.axis(Na+1).name = 'variables';
0110 %     xp.axis(Na+1).values = 'X';
0111 % end
0112 %
0113 % if isempty(findaxis_varied(xp))  % If no varied axes
0114 %     Na=length(xp.axis);
0115 %     xp.axis(Na+1).name = 'Varied1';
0116 %     xp.axis(Na+1).values = 1;
0117 % end
0118 
0119 %% Parse varargin and set up defaults
0120 [options, options_extras0] = dsCheckOptions(myargin,{...
0121   'population',[],[],...
0122   'variable',[],[],...
0123   'num_embedded_subplots',2,{1,2,3,4},...
0124   'max_num_overlaid',50,[],...
0125   'do_mean',false,[false true],...
0126   'force_last',[],[],...
0127   'do_overlay_shift',false,[false true],...
0128   'overlay_shift_val',[],[],...
0129   'do_zscore',[false],[false true],...
0130   'plot_type','waveform',{'waveform','waveformErr','imagesc','rastergram','raster','power','heatmapFR','heatmap_sortedFR','meanFR','meanFRdens','FRpanel'},...
0131   'xlims',[],[],...
0132   'ylims',[],[],...
0133   'zlims',[],[],...
0134   'LineWidth',[],[],...
0135   'plotargs',[],[],...
0136   'figwidth',[1],[],...
0137   'figheight',[1],[],...
0138   'crop_range',[],[],...
0139   'lock_axes',true,[false true],...
0140   'saved_fignum',[1],[],...
0141   'max_num_newfigs',[10],[],...
0142   'plot_options',struct,[],...
0143   'subplot_options',struct,[],...
0144   'figure_options',struct,[],...
0145   'do_zoom',false,[false true],...
0146   'yscale','linear',{'linear','log','log10','log2'},...
0147   'visible','on',{'on','off'},...
0148   'show_colorbar',false,[false true],...
0149   'ColorMap',[],[],...
0150   'save_figures',false,[false true],...
0151   'save_figname_prefix',[],[],...
0152   'save_figname_path',[],[],...
0153   'prepend_date_time',true,[false true],...
0154   'supersize_me',false,[false true],...
0155   'save_res',[],[],...
0156   'Ndims_per_subplot',[],[],...
0157   'dim_stacking',[],[],...
0158   'subplot_handle',@xp_subplot_grid,[],...
0159   'plot_handle',[],[],...
0160   'plotFR_override',[],[false true],...
0161   },false);
0162 handles=[];
0163 
0164 % If plotFR_override is true, then go directly to dsPlotFR
0165 if options.plotFR_override
0166     handles = dsPlotFR(data,varargin{:});
0167     return;
0168 end
0169 
0170 % Pull out fields from options struct
0171 plot_type = options.plot_type;
0172 plot_options = options.plot_options;
0173 subplot_options = options.subplot_options;
0174 figure_options = options.figure_options;
0175 num_embedded_subplots = options.num_embedded_subplots;
0176 do_mean = options.do_mean;
0177 force_last = options.force_last;
0178 crop_range = options.crop_range;
0179 lock_axes = options.lock_axes;
0180 Ndims_per_subplot = options.Ndims_per_subplot;
0181 subplot_handle = options.subplot_handle;
0182 plot_handle = options.plot_handle;
0183 
0184 % Add default options to structures
0185 % Plot_options
0186 % Used when running xp_matrix_advancedplot3D
0187     plot_options = struct_addDef(plot_options,'ylims',options.ylims);
0188     plot_options = struct_addDef(plot_options,'xlims',options.xlims);
0189     plot_options = struct_addDef(plot_options,'zlims',options.zlims);
0190     plot_options = struct_addDef(plot_options,'LineWidth',options.LineWidth);
0191     plot_options = struct_addDef(plot_options,'plotargs',options.plotargs);
0192 % Used when running xp_plotimage
0193     plot_options = struct_addDef(plot_options,'saved_fignum',options.saved_fignum);
0194 % Used when running xp_PlotData or xp_PlotFR2
0195     plot_options = struct_addDef(plot_options,'args',{});
0196 % Used when running waveformErr
0197     plot_options = struct_addDef(plot_options,'meanfunc',@(x) mean(x,2));
0198     plot_options = struct_addDef(plot_options,'errfunc',@(x) std(x,[],2) ./ (sqrt(size(x,2)) * ones(size(x,1),1)));
0199 % Used when running xp_matrix_imagesc
0200     plot_options = struct_addDef(plot_options,'ColorMap',options.ColorMap);
0201 
0202 % Subplot_options
0203 subplot_options = struct_addDef(subplot_options,'subplotzoom_enabled',options.do_zoom);
0204 subplot_options = struct_addDef(subplot_options,'force_rowvect',true);
0205 subplot_options = struct_addDef(subplot_options,'autosuppress_interior_tics',true);
0206 
0207 
0208 % Figure options
0209 figure_options = struct_addDef(figure_options,'visible',options.visible);
0210 figure_options = struct_addDef(figure_options,'save_figures',options.save_figures);
0211 figure_options = struct_addDef(figure_options,'save_figname_path',options.save_figname_path);
0212 figure_options = struct_addDef(figure_options,'save_figname_prefix',options.save_figname_prefix);
0213 figure_options = struct_addDef(figure_options,'prepend_date_time',options.prepend_date_time);
0214 figure_options = struct_addDef(figure_options,'supersize_me',options.supersize_me);
0215 figure_options = struct_addDef(figure_options,'save_res',options.save_res);
0216 figure_options = struct_addDef(figure_options,'max_num_newfigs',options.max_num_newfigs);
0217 figure_options = struct_addDef(figure_options,'figwidth',options.figwidth);
0218 figure_options = struct_addDef(figure_options,'figheight',options.figheight);
0219 
0220 %% Pre-process raw data contained in xp.data (mean + downsample)
0221 % % Note: these options don't work if data are images
0222 % Apply max overlaid
0223 MTPP = options.max_num_overlaid; % max traces per plot
0224 if any(strcmp(options.plot_type,{'waveform','waveformErr','power'})) && all(cellfun(@isnumeric,xp.data(:))) && ~do_mean && ~is_image
0225     mydata = xp.data;
0226     mydata2 = cell(size(mydata));
0227     for i = 1:numel(mydata)
0228         if ~isempty(mydata{i})
0229             mydata2{i} = mydata{i}(:,1:min(size(mydata{i},2),MTPP));
0230         end
0231     end
0232 
0233     xp.data = mydata2;
0234     clear mydata mydata2
0235 
0236     % Update cell numbers metadata
0237     cell_names = [1:max(cellfun(@(x) size(x,2),xp.data(:)))];
0238     cell_names_str = cellfunu(@(s) ['Cell ' num2str(s)], num2cell(cell_names));
0239     xp.meta.datainfo(2).values = cell_names_str;
0240 end
0241 
0242 % Average across cells if necessary
0243 if do_mean && ~is_image
0244     mydata = xp.data;
0245     mydata = cellfun(@(x) mean(x,2), mydata, 'UniformOutput', 0);
0246     xp.data = mydata;
0247     xp.meta.datainfo(2).values = {'<Cells>'};
0248 end
0249 
0250 %% Arrange dimensions of xp in appropriate order
0251 % % Should be variables x populations x varied1 x ... x variedN
0252 
0253 % Axis indices of populations
0254 ax_ind_var = xp.findaxis('variables');
0255 ax_ind_pop = xp.findaxis('population');
0256 ax_ind_varied = findaxis_varied(xp);
0257 
0258 % Permute to put varied variables last
0259 myorder = [ax_ind_var, ax_ind_pop, ax_ind_varied(:)'];
0260 if length(myorder) > 1
0261     xp = permute(xp,myorder);
0262 end
0263 
0264 %% Identify user selections for populations, variables, etc., and convert xp to xp2
0265 % %  (xp2 contains only user selections)
0266 % User selection for populations
0267 chosen_pop = options.population;
0268 if isempty(chosen_pop)
0269     chosen_pop = ':';
0270 end
0271 
0272 % User selection for state variables
0273 chosen_vars = options.variable;
0274 if isempty(chosen_vars)
0275     chosen_vars = getdefaultstatevar(xp);
0276 end
0277 
0278 % User selection for varied parameters
0279 options_extras = options_extras0;
0280 [chosen_varied , options_extras ]= get_chosen_varied(varied_names,options_extras);
0281 
0282 % If any options are still leftover, these are extraneous. Report an error
0283 leftover_fields = fieldnames(options_extras);
0284 if ~isempty(leftover_fields) && strict_mode
0285     error('The following unrecogized name/value pairs were passed in: %s', sprintf('%s ',leftover_fields{:}));
0286 end
0287 
0288 % Convert any "all" strings in chosen_varied to colon operators
0289 inds = cellfun(@ischar,chosen_varied);
0290 chosen_varied(inds) = cellfun(@(s) strrep(s,'all',':'),chosen_varied(inds),'UniformOutput',0);
0291 if strcmp(chosen_vars,'all'); chosen_vars = ':'; end
0292 if strcmp(chosen_pop,'all'); chosen_pop = ':'; end
0293 
0294 % Select out chosen data
0295 chosen_all = {};
0296 if ~isempty(ax_ind_varied); chosen_all = [chosen_varied,chosen_all]; end
0297 if ~isempty(xp.findaxis('populations')); chosen_all = [chosen_pop,chosen_all]; end
0298 if ~isempty(xp.findaxis('variables')); chosen_all = [chosen_vars,chosen_all]; end
0299 %xp2 = xp(chosen_vars,chosen_pop,chosen_varied{:});
0300 if ndims(xp) == 2 && ~isempty(strfind(xp.axis(2).name,'Dim')) && length(chosen_all) == 1
0301     chosen_all = [chosen_all {':'}];        % If xp is a column vector and only 1 varied entry present, fill out chosen_all to be size 2.
0302 end
0303 xp2 = xp(chosen_all{:});
0304 
0305 
0306 %% Squeeze out unused dimensions
0307 % Squeeze to eliminate superfluous dimensions
0308 xp2 = xp2.squeeze;
0309 Nd = ndims(xp2);
0310 
0311 % Rearrange dimensions of xp2 for stacking
0312 if ~isempty(options.dim_stacking)
0313     ax_names = xp2.exportAxisNames;
0314     if length(options.dim_stacking) ~= length(ax_names) -1
0315         error('Incorrect number of dimensions specified. dim_stacking must be some permutation of the following: %s', sprintf('%s ',ax_names{1:end}));
0316     end
0317     xp2.permute(options.dim_stacking);
0318 end
0319 
0320 
0321 
0322 %% If doing force overlay, move overlay population to the end
0323 if ~isempty(force_last)
0324 
0325     % If it's a stand-alone string, convert to cell array
0326     if ischar(force_last)
0327         force_last = {force_last};
0328     end
0329 
0330     % Functionalize this at some point... building list of requested axes
0331     ax_names = xp2.exportAxisNames;
0332     ax_ind = zeros(1,length(force_last));
0333     for i = 1:length(force_last)
0334         temp = xp2.findaxis(force_last{i});
0335         if isempty(temp)
0336             error('Requested axis not found. force_last must be one of the following: : %s', sprintf('%s ',ax_names{1:end}));
0337         end
0338         ax_ind(i) = temp;
0339     end
0340 
0341 %     % % Note: I am disabling this for now, because it is messing up
0342 %     certain plotting options. % %
0343 %     % Dims per subplot should be at least 2 if we're forcing last...
0344 %     % perhaps change this later
0345 %     if isempty(Ndims_per_subplot)
0346 %         Ndims_per_subplot = 2;
0347 %     end
0348 %     if Ndims_per_subplot == 1
0349 %         Ndims_per_subplot = 2;
0350 %     end
0351 
0352     others_ind = true(1,ndims(xp2));
0353     others_ind(ax_ind) = false;
0354     xp2 = xp2.permute([find(others_ind), ax_ind]);        % Move chosen axis to the back!
0355     xp2 = xp2.fixAxes;                                   % This permute can create naming issues if using default axis names (Dim 1, Dim 2, etc. For example, Dim2 can end up associated with xp2.axis(1)).
0356 
0357 end
0358 
0359 
0360 %% If only one cell
0361 
0362 % If only 1 cell, move in 2nd cell
0363 if length(xp2.meta.datainfo(2).values) <= 1 && ~is_image
0364     % Move populations axis to the end if it exists
0365 
0366     ax2overlay = [];
0367     if isempty(force_last) && isempty(options.dim_stacking)
0368         ax2overlay = xp2.findaxis('populations');           % If force_last or dim_stacking isn't specified, then choose populations
0369     end
0370 
0371     if isempty(ax2overlay)
0372         ax2overlay = xp2.ndims;     % If can't find populations, use last axis on the stack
0373     end
0374 
0375     % Save variables associated with this axis
0376     packed_vars = xp2.axis(ax2overlay).values;
0377     packed_name = xp2.axis(ax2overlay).name;
0378 
0379     % Add <average> symbols if necessary to packed_vars
0380     cellnames = xp2.meta.datainfo(2).values;
0381     temp = cellfun(@isempty,strfind(cellnames,'<'));    % Check if originals were averages!
0382     if any(~temp)
0383         if isnumeric(packed_vars); packed_vars = cellfunu(@(s) [strrep(packed_name,'_',' ') ' ' num2str(s)],num2cell(packed_vars)); end
0384         packed_vars = cellfunu(@(s) ['<' s '>'], packed_vars);
0385     end
0386 
0387     xp2.meta.datainfo(2).name = packed_name;
0388     xp2.meta.datainfo(2).values = packed_vars(:)';
0389 
0390     xp2 = xp2.packDim(ax2overlay,2);
0391     xp2 = xp2.squeezeRegexp('Dim');
0392 end
0393 
0394 %% Set up do z-score & overlay shift
0395 if options.do_zscore && all(cellfun(@isnumeric,xp2.data(:))) && ~is_image
0396 
0397     % xp2 = recursivePlot({@xp_parfor, @xpzscore}
0398     mydata = xp2.data;
0399     for i = 1:numel(mydata)
0400         mydata{i} = zscore(mydata{i});
0401     end
0402     xp2.data = mydata;
0403 end
0404 
0405 % Shift the overlay by a certain amount
0406     if options.do_overlay_shift && all(cellfun(@isnumeric,xp2.data(:))) && ~is_image
0407         if isempty(Ndims_per_subplot) || Ndims_per_subplot <= 1
0408             % If xp2.data is going to be NxM, shift each column
0409             mydata = xp2.data;
0410             for i = 1:numel(mydata)
0411                 mydata{i} = do_shift_lastdim (mydata{i},options.overlay_shift_val);
0412             end
0413             xp2.data = mydata;
0414         else
0415             % If Ndims_per_subplot > 1, then this means we're going to be
0416             % packing an additional dim into xp2.data. Therefore, shift the
0417             % last dimension in xp2. We'll do this by temporarily packing
0418             % it into xp2.data (e.g. along dim 4, which is unused) and then
0419             % unpacking it later.
0420             sz = size(xp2);
0421             ind = find(sz > 1, 1, 'last');
0422             if ~isempty(ind)
0423                 xp2 = xp2.packDim(ind,4);
0424             end
0425             mydata = xp2.data;
0426             for i = 1:numel(mydata)
0427                 mydata{i} = do_shift_lastdim (mydata{i},options.overlay_shift_val);
0428             end
0429             xp2.data = mydata;
0430             if ~isempty(ind)
0431                 xp2 = xp2.unpackDim(4,ind);
0432                 xp2 = xp2.squeezeRegexp('Dim');
0433             end
0434         end
0435     end
0436 
0437 %% Crop data
0438 % This is inserted here because apparently the operation is slow and it's
0439 % faster to do this after we've already squeezed / selected.
0440 if ~isempty(crop_range) &&  all(cellfun(@isnumeric,xp2.data(:))) && ~is_image
0441     t_temp = xp2.meta.datainfo(1).values;
0442     ind = (t_temp > crop_range(1) & t_temp <= crop_range(2));
0443     for i = 1:numel(xp2.data)
0444         if ~isempty(xp2.data{i}); xp2.data{i} = xp2.data{i}(ind,:); end
0445     end
0446     xp2.meta.datainfo(1).values = t_temp(ind);
0447 
0448     % Also crop DynaSim metadata info about time.
0449     t_temp2 = xp2.meta.dynasim.time;
0450     ind = (t_temp2 > crop_range(1) & t_temp2 <= crop_range(2));
0451     t_temp2 = t_temp2(ind);
0452     xp2.meta.dynasim.time = t_temp2;
0453 
0454 end
0455 
0456 %% Set up legend entries and axis limits
0457 % Set up legend entries
0458 subplot_options.legend1 = setup_legends(xp2);
0459 
0460 % Get axis lims
0461 if isempty(plot_options.xlims) && lock_axes && ~is_image
0462         xdat = xp2.meta.datainfo(1).values;
0463         plot_options.xlims = [min(xdat) max(xdat)];
0464 end
0465 if isempty(plot_options.ylims) && lock_axes && ~is_image
0466     switch plot_type
0467         case {'waveform','waveformErr'}
0468             % Merge all data into one single huge column
0469             data_all = xp2.data(:);
0470             data_all = cellfunu(@(x) x(:), data_all);
0471             data_all = vertcat(data_all{:});
0472             % Find the max and minima - these are the largest and smallest
0473             % values we could ever see.
0474             data_lims = [min(data_all) max(data_all)];
0475             plot_options.ylims = data_lims;
0476     end
0477 end
0478 
0479 if isempty(plot_options.zlims) && lock_axes && ~is_image
0480     switch plot_type
0481         case 'imagesc'
0482             data_all = xp2.data(:);
0483             data_all = cellfunu(@(x) x(:), data_all);
0484             data_all = vertcat(data_all{:});
0485             data_lims = [min(data_all) max(data_all)];
0486             plot_options.zlims = data_lims;
0487     end
0488 end
0489 
0490 %% Prepare plotting handles for specific plot types
0491 if is_image
0492     % Is an image
0493     data_plothandle = @xp_plotimage;
0494     plot_options.scale = .5;           % Scale of .5 enforces some anti-aliasing
0495 else
0496     switch plot_type
0497         case 'waveform'
0498             % Is data
0499             data_plothandle = @xp1D_matrix_plot;
0500             if ~isempty(plot_handle); data_plothandle = plot_handle; end
0501         case 'waveformErr'
0502             data_plothandle = @xp1D_matrix_boundedline;
0503             if ~isempty(plot_handle); data_plothandle = plot_handle; end
0504         case 'imagesc'
0505             data_plothandle = @xp_matrix_imagesc;
0506             if ~isempty(plot_handle); data_plothandle = plot_handle; end
0507             % Disable legend when using imagesc
0508             subplot_options.legend1 = [];
0509             % Add time information
0510             plot_options.xdat = xp2.meta.datainfo(1).values;
0511             % Control colorbar
0512             if lock_axes
0513                 % If axes are locked, only need to show 1 colorbar across
0514                 % all subplots
0515                 subplot_options.do_colorbar = options.show_colorbar;
0516                 plot_options.do_colorbar = false;
0517 %                 subplot_options.do_colorbar = false;
0518 %                 plot_options.do_colorbar = true;
0519             else
0520                 subplot_options.do_colorbar = false;
0521                 plot_options.do_colorbar = options.show_colorbar;
0522             end
0523 
0524         case {'power','rastergram','raster'}
0525             % Disable legend when using dsPlot
0526             subplot_options.legend1 = [];
0527 
0528             % Setup call to xp_PlotData
0529             plot_options.args = {plot_options.args{:}, 'plot_type',plot_type};
0530             data_plothandle = @xp_PlotData;
0531             if ~isempty(plot_handle); data_plothandle = plot_handle; end
0532 
0533             if any(strcmp(plot_type,{'rastergram','raster'})) && isempty(force_last) && isempty(options.dim_stacking)
0534                 % Move populations axis to the end of xp2. (Only do this if
0535                 % we're not already overwriting dims stacking order).
0536                 ax_names = xp2.exportAxisNames;
0537                 ind_pop = false(1,length(ax_names));
0538                 ind_pop(xp2.findaxis('populations')) = true;
0539                 ind_rest = ~ind_pop;
0540                 order = [find(ind_rest) find(ind_pop)];
0541                 xp2 = xp2.permute(order);
0542             end
0543             if any(strcmp(plot_type,{'rastergram','raster'}))
0544                 % Force Ndims_per_subplot to 2 fro rastergram.
0545                 if isempty(Ndims_per_subplot)
0546                     if ~isempty(xp2.findaxis('populations'))
0547                         Ndims_per_subplot = 2;                 % Overwrite Ndims_per_subplot to 2. This ensures
0548                                                                % that multiple populations can be stacked in a
0549                                                                % single subplot.
0550                     else
0551                         Ndims_per_subplot = 1;                 % Only do this if population axis is still present!
0552                     end
0553                 end
0554 
0555             end
0556 
0557         case {'heatmapFR','heatmap_sortedFR','meanFR','meanFRdens'}
0558             % Disable legend when using dsPlotFR2
0559             subplot_options.legend1 = [];
0560             % Remove FR suffix from heatmap and heatmap_sorted plot types
0561             if any(strcmp(plot_type,{'heatmapFR','heatmap_sortedFR'}))
0562                 plot_type = strrep(plot_type,'FR','');
0563             end
0564 
0565             % Setup call to xp_PlotFR2
0566             plot_options.args = {plot_options.args{:}, 'plot_type',plot_type};
0567             data_plothandle = @xp_PlotFR2;
0568             if ~isempty(plot_handle); data_plothandle = plot_handle; end
0569             
0570         case {'FRpanel'}
0571             data_plothandle = @xp_PlotFRpanel;
0572             
0573             % Axis indices of populations
0574             ax_ind_var = xp2.findaxis('variables');
0575             ax_ind_pop = xp2.findaxis('population');
0576             %ax_ind_varied = findaxis_varied(xp2);
0577             ax_ind_other = setdiff(1:ndims(xp2),[ax_ind_var, ax_ind_pop]);
0578 
0579             % Permute to put varied variables last
0580             myorder = [ax_ind_other(:)', ax_ind_var, ax_ind_pop];
0581             if length(myorder) > 1
0582                 xp2 = permute(xp2,myorder);
0583             end
0584             
0585             Ndims_per_subplot = 1 + ~isempty(ax_ind_pop) + ~isempty(ax_ind_var);    % Allows for multiple populations to get passed to dsPlotFR to produce the panel
0586             num_embedded_subplots = 0;                                              % No subplotting
0587     end
0588 end
0589 
0590 % If Ndims_per_subplot has not been set yet, set it now!
0591 if isempty(Ndims_per_subplot)
0592     Ndims_per_subplot = 1;
0593 end
0594 
0595 %% Prepare plotting structure depending on number of embedded subplots
0596 % Split available axes into the number of dimensions supported by each
0597 % axis handle
0598 switch num_embedded_subplots
0599     case 0
0600         % Ordering of axis handles
0601         function_handles = {@xp_handles_newfig, data_plothandle};   % Specifies the handles of the plotting functions
0602         dims_per_function_handle = [1,Ndims_per_subplot];
0603         function_args = {{figure_options},{plot_options}};
0604     case 1
0605         % Ordering of axis handles
0606         function_handles = {@xp_handles_newfig, subplot_handle,data_plothandle};   % Specifies the handles of the plotting functions
0607         dims_per_function_handle = [1,1,Ndims_per_subplot];
0608         function_args = {{figure_options},{subplot_options},{plot_options}};
0609 
0610     case 2
0611         % Ordering of axis handles
0612         function_handles = {@xp_handles_newfig, subplot_handle,data_plothandle};   % Specifies the handles of the plotting functions
0613         dims_per_function_handle = [1,2,Ndims_per_subplot];
0614         function_args = {{figure_options},{subplot_options},{plot_options}};
0615 
0616     case 3
0617         % Ordering of axis handles
0618         function_handles = {@xp_handles_newfig, subplot_handle, subplot_handle,data_plothandle};   % Specifies the handles of the plotting functions
0619         dims_per_function_handle = [1,2,1,Ndims_per_subplot];
0620         subplot_options2 = subplot_options;
0621         subplot_options2.legend1 = [];
0622         subplot_options.display_mode = 1;
0623         function_args = {{figure_options},{subplot_options2},{subplot_options},{plot_options}};
0624     case 4
0625         % Ordering of axis handles
0626         function_handles = {@xp_handles_newfig, subplot_handle, subplot_handle,data_plothandle};   % Specifies the handles of the plotting functions
0627         dims_per_function_handle = [1,2,2,Ndims_per_subplot];
0628         subplot_options2 = subplot_options;
0629         subplot_options2.legend1 = [];
0630         subplot_options.display_mode = 1;
0631         function_args = {{figure_options},{subplot_options2},{subplot_options},{plot_options}};
0632 end
0633 
0634 %% Auto trim dimensions as needed
0635 % Linearize dimensions of xp2 that are in excess of the total number we can
0636 % plot
0637 maxNplotdims = sum(dims_per_function_handle)-1;
0638 xp2 = reduce_dims(xp2,maxNplotdims);
0639 
0640 % Stack up available dimensions based on how much each axis handle can hold
0641 ax_names = [xp2.exportAxisNames, 'data'];
0642 
0643 dimensions = get_dimensions(ax_names,dims_per_function_handle);
0644 
0645 
0646 % Remove any excess function handles that aren't needed
0647 available_dims = ~cellfun(@isempty,dimensions);
0648 function_handles = function_handles(available_dims);
0649 dimensions = dimensions(available_dims);
0650 function_args = function_args(available_dims);
0651 
0652 %% Run the plots!
0653 % Open new figure if necessary & plot the data
0654 if ~isequal(@xp_handles_newfig, function_handles{1})
0655     % Cheap hack to force it to create a new figure using our desired
0656     % parameters for instances when it wouldn't normally call
0657     % xp_handles_newfig.
0658     xp3 = MDD;
0659     fhandle = @() recursivePlot(xp2,function_handles,dimensions,function_args);
0660     xp3 = xp3.importData({fhandle});
0661     handles = xp_handles_newfig(xp3,figure_options);
0662 else
0663     handles = xp2.recursivePlot(function_handles,dimensions,function_args);
0664 end
0665 
0666 
0667 end
0668 
0669 
0670 function var_out = getdefaultstatevar(xp)
0671     % search through and try to find the variable represnting voltage. If can't find
0672     % it, just return the first variable listed.
0673 
0674     % See if variables axis even exists
0675     if isempty(xp.findaxis('variables'))
0676         % If reach here, it means variables is not used in the code. Just
0677         % return some dummy values and move on.
0678         var_out = ':';
0679         return;
0680     end
0681 
0682     vars_from_labels = dsGet_variables_from_meta(xp);
0683     if ~isempty(vars_from_labels)
0684         vars_from_labels = vars_from_labels(1);   % Best guess at default state variable. Usually its the 1st entry in labels
0685     end
0686 
0687     % Pull out variables
0688     vars_orig = xp.axis('variables').values;
0689 
0690     % Make everything uppercase to ensure
0691     % case-insensitive.
0692     vars = upper(vars_orig);
0693     possibilities = upper({vars_from_labels{:},'V','X','Vm','Xm','Y','Ym'});
0694 
0695     ind = [];
0696     i=0;
0697     while isempty(ind) && i < length(possibilities)
0698         i=i+1;
0699         ind = find(strcmpi(vars,possibilities{i}));
0700     end
0701 
0702     if ~isempty(ind)
0703         var_out = vars_orig{ind};
0704     else
0705         var_out = vars_orig{1};
0706     end
0707 end
0708 
0709 function [chosen_varied, options_varied ]= get_chosen_varied(varied_names,options_varied)
0710 
0711     % Initialize output
0712     chosen_varied = repmat({':'},1,length(varied_names));
0713 
0714     % Varied name-value pairs entered by user
0715     varied_NVPs = fieldnames(options_varied);
0716 
0717     % See if any of these match actual varied parameters
0718     for i =  1:length(varied_NVPs)
0719         ind = find(strcmp(varied_names,varied_NVPs{i}));
0720         if length(ind) == 1
0721             chosen_varied{ind} = options_varied.(varied_NVPs{i});
0722 
0723             % Optional (remove from options_varied)
0724             options_varied = rmfield(options_varied,varied_NVPs{i});
0725         elseif length(ind) > 1
0726             error('Multiple varied arguments found');
0727         else
0728             % Not a varied variable name
0729         end
0730 
0731 
0732     end
0733 
0734 end
0735 
0736 function str_out = variedN_to_axisnames(str_in,ax_names_varied)
0737 
0738         if strcmp(str_in(1:min(6,end)),'varied')        % User has entered variedX
0739             % fn is original fieldname (e.g. variedX)
0740             % fn2 is new field name of varied parameter (e.g. E_Iapp)
0741             str_out = ax_names_varied{str2num(str_in(7:end))};
0742         else
0743             str_out = str_in;
0744         end
0745 
0746 end
0747 
0748 function ax_ind_varied = findaxis_varied(xp)
0749     % Uses metadata to identify a list of varied variables. Then validates
0750     % that they match the available axis names and returns their index.
0751     varied = xp.meta.dynasim.varied;
0752     ax_names = xp.exportAxisNames;
0753     ax_ind_varied = false(1,length(ax_names));
0754     for i = 1:length(varied)
0755         ind = strcmp(varied{i},ax_names);
0756         if sum(ind) ~= 1; error('Varied axis not found OR something wrong with varied label'); end
0757         ax_ind_varied = ax_ind_varied | ind;
0758     end
0759 
0760     ax_ind_varied = find(ax_ind_varied);
0761 end
0762 
0763 function dimensions = get_dimensions(ax_names,dims_per_function_handle)
0764     % Split available axes into the number of dimensions supported by each
0765     % axis handle
0766 
0767     i = length(dims_per_function_handle);
0768     while i > 0 && ~isempty(ax_names)
0769 
0770         Ndims_curr = dims_per_function_handle(i);
0771         dimensions{i} = ax_names(max(1,end-Ndims_curr+1):end);
0772         ax_names = ax_names(1:end-Ndims_curr);
0773         i=i-1;
0774     end
0775 
0776 end
0777 
0778 function xp2 = reduce_dims(xp2,maxNplotdims)
0779     Nd = ndims(xp2);
0780     if Nd > maxNplotdims
0781         xp2 = xp2.mergeDims( [maxNplotdims:Nd] );
0782         xp2 = xp2.squeeze;
0783         Nd = ndims(xp2);
0784 
0785         if Nd ~= maxNplotdims; error('something wrong'); end
0786     end
0787 end
0788 
0789 function varied_names = only_varieds(xp)
0790     % Get list of varied axis names
0791     varied_names = xp.meta.dynasim.varied;
0792 
0793     % Make sure that they are acutally in xp.axis.names.
0794     findaxis_varied(xp); % This function will return an error if they are missing!
0795 
0796 end
0797 
0798 function varied_names = only_varieds_old_deleteme(all_names)
0799     warning('update this command or possibly merge with findaxis_varied');
0800     inds = true(1,length(all_names));
0801     inds(strcmp(all_names,'populations')) = false;
0802     inds(strcmp(all_names,'variables')) = false;
0803     varied_names = all_names(inds);
0804 end
0805 
0806 function mydata_out = do_shift_lastdim (mydata,shift)
0807     sz = size(mydata);
0808     nd = ndims(mydata);
0809 
0810     if isempty(shift)
0811         % Do adaptive shift
0812         upscale_factor = 2;
0813         temp = reshape(mydata,prod(sz(1:nd-1)),sz(nd));
0814         if ~strcmp(reportUI,'matlab') && exist('nanstd') ~= 2 % 'nanstd is not in Octave's path
0815           try
0816             pkg load statistics; % trying to load octave forge 'statistics' package before using nanstd function
0817           catch
0818             error('nanstd function is needed, please install the statistics package from Octave Forge');
0819           end
0820         end
0821         stdevs = nanstd(temp)*upscale_factor;               % STD ignoring NaNs
0822         sh = [0, stdevs(1:end-1) + stdevs(2:end)]';
0823         sh = sh * -1;        % Forces shifts to be downward (same as subplots)
0824         sh = cumsum(sh);     % Dave note - this seemed to be missing so added it for case of size(Nd)=2; not sure if it will mess up other cases.
0825     else
0826         sh = shift*[0:sz(end)-1]';      % Fixed shift amount
0827         sh = sh * -1;        % Forces shifts to be downward (same as subplots)
0828     end
0829 
0830 
0831     sh = permute(sh, [2:nd,1]);
0832     if length(sz(1:nd-1)) == 1
0833         sh2 = repmat(sh, sz(1:nd-1),1);     % Special case for scalar input to repmat. When repmat receives a scalar, it repeats BOTH rows and columns instead of just rows
0834     else
0835         sh2 = repmat(sh, sz(1:nd-1));
0836     end
0837 
0838     mydata_out = mydata + sh2;
0839 
0840 end
0841 
0842 function leg1 = setup_legends(xp2)
0843 
0844     % Pull out all metadata names and values
0845     for i = 1:length(xp2.meta.datainfo)
0846         mn{i} = xp2.meta.datainfo(i).name;
0847         mv{i} = xp2.meta.datainfo(i).values;
0848     end
0849 
0850     % Convert any numeric entries to cell strings as needed
0851     for i = 2:length(xp2.meta.datainfo)
0852         if isnumeric(mv{i})
0853             % If axis is numeric, as in the case with varied parameters, convert to
0854             % a cell array of strings
0855             mv{i} = cellfun(@num2str,num2cell(mv{i}),'UniformOutput',0);
0856 
0857             % Also pre-pend the name of the variable being varied
0858             for j = 1:length(mv{i})
0859                 mv{i}{j} = [strrep(mn{i},'_',' ') ' ' mv{i}{j}];
0860             end
0861         end
0862     end
0863 
0864     if length(mv) == 2
0865         leg1 = mv{2};
0866     elseif length(mv) == 3
0867         %Cartesean product of mv{2} and mv{3}
0868         k = 0;
0869         for j = 1:length(mv{3})
0870             for i = 1:length(mv{2})         % We plot the 2nd dimension 1st; they are grouped together
0871                 k=k+1;
0872                 leg1{k} = [mv{2}{i} ' ' mv{3}{j}];
0873             end
0874         end
0875     else
0876         error('should not reach');
0877     end
0878 end

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