annotate utilities/UTIL_plotMatrix.m @ 38:c2204b18f4a2 tip

End nov big change
author Ray Meddis <rmeddis@essex.ac.uk>
date Mon, 28 Nov 2011 13:34:28 +0000
parents f233164f4c86
children
rev   line source
rmeddis@0 1 function UTIL_plotMatrix(toPlot, method)
rmeddis@0 2 % UTIL_plotMatrix general purpose plotting utility for plotting the results
rmeddis@0 3 % of the MAP auditory model.
rmeddis@0 4 % All plots are placed in subplots of a figure (default figure 1).
rmeddis@38 5 %
rmeddis@0 6 % Input arguments:
rmeddis@0 7 % 'toPlot' is matrix (either numeric or logical)
rmeddis@0 8 % 'method' is a structure containing plot instructions
rmeddis@0 9 %
rmeddis@0 10 % mandatory parameters:
rmeddis@38 11 % method.displaydt xValues spacing between data points
rmeddis@38 12 % method.yValues yaxis labels mandatory only for 3D plots
rmeddis@0 13 %
rmeddis@0 14 % optional
rmeddis@38 15 % method.figureNo default figure(1)
rmeddis@38 16 % method.numPlots number of subPlots in the figure (default=1)
rmeddis@38 17 % method.subPlotNo number of this plot (default=1)
rmeddis@38 18 % method.zValuesRange [min max] value pair to define yaxis limits
rmeddis@38 19 % method.zValuesRange [min max] CLIMS for 3-D plot
rmeddis@38 20 % method.yLabel (string) y-axis label
rmeddis@38 21 % method.minyMaxy y-axis limits
rmeddis@38 22 % method.xLabel (string) x-axis label
rmeddis@38 23 % method.title (string) subplot title
rmeddis@0 24 % method.bar =1, to force bar histogram (single channel only)
rmeddis@38 25 % method.view 3D plot 'view' settings e.g. [-6 40]
rmeddis@38 26 % method.axes (handle) where to plot (overules all others)
rmeddis@38 27 % method.maxPixels maximum number of pixels (used to speed plotting)
rmeddis@38 28 % method.blackOnWhite =1; inverts display for 2D plots
rmeddis@38 29 % method.forceLog positive values are put on log z-scale
rmeddis@38 30 % method.rasterDotSize min value is 1
rmeddis@38 31 % method.defaultFontSize deafult= 12
rmeddis@38 32 % method.timeStart default= dt
rmeddis@38 33 % method.defaultTextColor default ='k'
rmeddis@38 34 % method.defaultAxesColor default ='k'
rmeddis@38 35 % method.nCols default = 1 (layout for subplots)
rmeddis@38 36 % method.nRows default=method.numPlots (layout for subplots
rmeddis@38 37 % method.segmentNumber plot only this segment while 'hold on'
rmeddis@0 38 %
rmeddis@38 39 % e.g.
rmeddis@0 40 % UTIL_plotMatrix(toPlot, method)
rmeddis@0 41
rmeddis@0 42 dt=method.displaydt;
rmeddis@38 43 [r cols]=size(toPlot);
rmeddis@38 44 if cols==1
rmeddis@38 45 % toPlot should be a wide matrix or a long vector
rmeddis@38 46 toPlot=toPlot';
rmeddis@38 47 end
rmeddis@38 48
rmeddis@38 49 if ~isfield(method,'numPlots') || isempty(method.numPlots)
rmeddis@38 50 method.numPlots =1;
rmeddis@38 51 method.subPlotNo =1;
rmeddis@38 52 end
rmeddis@38 53
rmeddis@0 54 if ~isfield(method,'figureNo') || isempty(method.figureNo)
rmeddis@0 55 method.figureNo=99;
rmeddis@0 56 end
rmeddis@38 57
rmeddis@0 58 % if ~isfield(method,'zValuesRange') || isempty(method.zValuesRange)
rmeddis@0 59 % method.zValuesRange=[-inf inf];
rmeddis@0 60 % end
rmeddis@0 61
rmeddis@0 62 % set some defaults
rmeddis@0 63 if ~isfield( method,'blackOnWhite') || isempty(method.blackOnWhite)
rmeddis@38 64 method.blackOnWhite=0;
rmeddis@0 65 end
rmeddis@0 66 if ~isfield(method,'timeStart')|| isempty(method.timeStart)
rmeddis@38 67 method.timeStart=dt;
rmeddis@0 68 end
rmeddis@0 69 if ~isfield(method,'objectDuration') || isempty(method.objectDuration)
rmeddis@0 70 [nRows nCols]=size(toPlot); method.objectDuration=dt*nCols;
rmeddis@0 71 end
rmeddis@0 72 if ~isfield(method,'defaultFontSize') || isempty(method.defaultFontSize)
rmeddis@38 73 method.defaultFontSize=12;
rmeddis@0 74 end
rmeddis@0 75 if ~isfield(method,'defaultTextColor') || isempty(method.defaultTextColor)
rmeddis@0 76 method.defaultTextColor='k';
rmeddis@0 77 defaultTextColor=method.defaultTextColor;
rmeddis@0 78 else
rmeddis@0 79 defaultTextColor='k';
rmeddis@0 80 end
rmeddis@0 81 if ~isfield( method,'defaultAxesColor') || isempty(method.defaultAxesColor)
rmeddis@38 82 method.defaultAxesColor=defaultTextColor;
rmeddis@0 83 end
rmeddis@0 84 defaultAxesColor=method.defaultAxesColor;
rmeddis@0 85
rmeddis@0 86 % arrangement of plots in rows and columns
rmeddis@0 87 if ~isfield(method,'nCols') || isempty(method.nRows)
rmeddis@0 88 method.nCols=1;
rmeddis@0 89 end
rmeddis@0 90 if ~isfield(method,'nRows') || isempty(method.nRows)
rmeddis@0 91 method.nRows= method.numPlots;
rmeddis@0 92 end
rmeddis@0 93
rmeddis@0 94 if ~isfield(method,'rasterDotSize') || isempty(method.rasterDotSize)
rmeddis@0 95 rasterDotSize=1;
rmeddis@0 96 else
rmeddis@0 97 rasterDotSize=method.rasterDotSize;
rmeddis@0 98 end
rmeddis@0 99
rmeddis@0 100 % user can specify either an independent axis
rmeddis@0 101 % or a subplot of the current figure
rmeddis@0 102 % if both are specified, 'axes' takes priority
rmeddis@0 103 figure(method.figureNo)
rmeddis@0 104 if isfield(method,'axes') && ~isempty(method.axes)
rmeddis@38 105 % user defines where to plot it
rmeddis@38 106 axes(method.axes);
rmeddis@38 107 method.numPlots =1;
rmeddis@38 108 method.subPlotNo =1;
rmeddis@38 109
rmeddis@0 110 else
rmeddis@0 111 % now using a regular figure
rmeddis@0 112 if method.subPlotNo>method.numPlots;
rmeddis@0 113 error('UTIL_plotMatrix: not enough subplots allocated in figure 1. Check method.numPlots')
rmeddis@0 114 end
rmeddis@0 115 % choose subplot
rmeddis@0 116 subplot(method.nRows,method.nCols,method.subPlotNo), % cla
rmeddis@0 117
rmeddis@0 118 if isfield(method,'segmentNumber') && ~isempty(method.segmentNumber)...
rmeddis@0 119 && method.segmentNumber>1
rmeddis@38 120 % in multi-segment mode do not clear the image
rmeddis@0 121 % from the previous segment
rmeddis@0 122 hold on
rmeddis@0 123 else
rmeddis@0 124 % otherwise a fresh image will be plotted
rmeddis@0 125 hold off
rmeddis@0 126 cla
rmeddis@0 127 end
rmeddis@0 128 end
rmeddis@0 129
rmeddis@0 130 [numYvalues numXvalues]=size(toPlot);
rmeddis@0 131 xValues=method.timeStart:dt:method.timeStart+dt*(numXvalues-1);
rmeddis@0 132
rmeddis@0 133 if isfield(method,'yValues') && ~isempty(method.yValues)
rmeddis@0 134 % yValues is normally a vector specifying channel BF
rmeddis@0 135 yValues=method.yValues;
rmeddis@0 136 else
rmeddis@0 137 yValues=1:numYvalues;
rmeddis@0 138 end
rmeddis@0 139
rmeddis@38 140 if round(numYvalues/length(yValues))>1
rmeddis@38 141 % case where the plot matrix is double height (e.g. LSR+HSR)
rmeddis@38 142 yValues=[yValues yValues];
rmeddis@38 143 method.plotDivider=1;
rmeddis@38 144 else
rmeddis@38 145 method.plotDivider=0;
rmeddis@38 146 end
rmeddis@38 147
rmeddis@0 148 % Now start the plot.
rmeddis@0 149 % 3D plotting for 4 or more channels
rmeddis@0 150 % otherwise special cases for fewer channels
rmeddis@0 151
rmeddis@0 152 if ~islogical(toPlot)
rmeddis@0 153 % continuous variables
rmeddis@0 154 switch numYvalues
rmeddis@0 155 case 1 % single vector (black)
rmeddis@0 156 if isfield(method,'bar') && ~isempty(method.bar)
rmeddis@0 157 % histogram
rmeddis@0 158 bar(xValues, toPlot,'k')
rmeddis@0 159 method.bar=[]; % avoid carry over between modules
rmeddis@0 160 else
rmeddis@0 161 % waveform
rmeddis@0 162 plot(xValues, toPlot,'k')
rmeddis@0 163 end
rmeddis@0 164 xlim([0 method.objectDuration])
rmeddis@0 165 if isfield(method,'zValuesRange') ...
rmeddis@0 166 && ~isempty(method.zValuesRange)
rmeddis@0 167 ylim(method.zValuesRange)
rmeddis@0 168 method.zValuesRange=[]; % avoid carry over between modules
rmeddis@0 169 end
rmeddis@0 170 if isfield(method,'yLabel') && ~isempty(method.yLabel)
rmeddis@0 171 ylabel(method.yLabel, 'color', defaultTextColor)
rmeddis@0 172 method.yLabel=[]; % avoid carry over between modules
rmeddis@0 173 end
rmeddis@0 174
rmeddis@0 175 case 2 % 2 x N vector (black and red)
rmeddis@0 176 plot(xValues, toPlot(1,:),'k'), % hold on
rmeddis@0 177 plot(xValues, toPlot(2,:),'r'), % hold off
rmeddis@0 178 xlim([0 method.objectDuration])
rmeddis@0 179 if isfield(method,'zValuesRange') ...
rmeddis@0 180 && ~isempty(method.zValuesRange)
rmeddis@0 181 ylim(method.zValuesRange)
rmeddis@0 182 method.zValuesRange=[]; % avoid carry over between modules
rmeddis@0 183 end
rmeddis@0 184 if isfield(method,'yLabel')&& ~isempty(method.yLabel)
rmeddis@0 185 ylabel(method.yLabel, 'color', defaultTextColor)
rmeddis@0 186 method.yLabel=[]; % avoid carry over between modules
rmeddis@0 187 end
rmeddis@0 188
rmeddis@0 189 case 3 % 3 x N vector (black red and green)
rmeddis@0 190 % this is used for 1 channel DRNL output
rmeddis@0 191 plot(xValues, toPlot(1,:),'k'), hold on
rmeddis@0 192 plot(xValues, toPlot(2,:),'r'), hold on
rmeddis@0 193 plot(xValues, toPlot(3,:),'g'), hold off
rmeddis@0 194 xlim([0 method.objectDuration])
rmeddis@0 195 if isfield(method,'zValuesRange') ...
rmeddis@0 196 && ~isempty(method.zValuesRange)
rmeddis@0 197 ylim(method.zValuesRange)
rmeddis@0 198 end
rmeddis@0 199 if isfield(method,'yLabel') && ~isempty(method.yLabel)
rmeddis@0 200 ylabel(method.yLabel, 'color', defaultTextColor)
rmeddis@0 201 end
rmeddis@0 202
rmeddis@0 203 otherwise % >3 channels: surface plot
rmeddis@38 204 % add line to separate HSR and LSR
rmeddis@0 205 if method.plotDivider && size(toPlot,1) > 2
rmeddis@0 206 [r c]=size(toPlot);
rmeddis@0 207 emptyLine=max(max(toPlot))*ones(2,c);
rmeddis@0 208 halfway=round(r/2);
rmeddis@0 209 toPlot=[toPlot(1:halfway,:); emptyLine; toPlot(halfway+1:end,:)];
rmeddis@0 210 end
rmeddis@0 211
rmeddis@0 212 % invert data for black on white matrix plotting
rmeddis@0 213 if method.blackOnWhite
rmeddis@0 214 toPlot=-toPlot;
rmeddis@0 215 end
rmeddis@0 216
rmeddis@0 217 % matrix (analogue) plot
rmeddis@0 218 if isfield(method,'forceLog') && ~isempty(method.forceLog)
rmeddis@0 219 % positive values are put on log z-scale
rmeddis@0 220 toPlot=toPlot+min(min(toPlot))+1;
rmeddis@0 221 toPlot=log(toPlot);
rmeddis@0 222 if isfield(method,'title')
rmeddis@0 223 method.title=[method.title ' (log scale)'];
rmeddis@0 224 else
rmeddis@0 225 method.title= '(log scale)';
rmeddis@0 226 end
rmeddis@0 227 end
rmeddis@0 228
rmeddis@0 229 % zValuesRange
rmeddis@0 230 if isfield(method,'zValuesRange') ...
rmeddis@0 231 && ~isempty(method.zValuesRange)
rmeddis@0 232 clims=(method.zValuesRange);
rmeddis@0 233 imagesc(xValues, yValues, toPlot, clims), axis xy; %NB assumes equally spaced y-values
rmeddis@0 234 else
rmeddis@0 235 % automatically scaled
rmeddis@0 236 imagesc(xValues, yValues, toPlot), axis xy; %NB assumes equally spaced y-values
rmeddis@0 237
rmeddis@0 238 if ~isfield(method,'zValuesRange')...
rmeddis@0 239 || isempty(method.zValuesRange)
rmeddis@0 240 method.zValuesRange=[-inf inf];
rmeddis@0 241 end
rmeddis@0 242
rmeddis@0 243 if method.blackOnWhite
rmeddis@0 244 % NB plotted values have negative sign for black on white
rmeddis@0 245 caxis([-method.zValuesRange(2) -method.zValuesRange(1)])
rmeddis@0 246 else
rmeddis@0 247 caxis(method.zValuesRange)
rmeddis@0 248 end
rmeddis@0 249 end
rmeddis@0 250
rmeddis@0 251 % xaxis
rmeddis@0 252 % NB segmentation may shorten signal duration
rmeddis@0 253 [r c]=size(toPlot);
rmeddis@0 254 imageDuration=c*method.displaydt;
rmeddis@38 255 xlim([0 imageDuration])
rmeddis@38 256
rmeddis@0 257 % yaxis
rmeddis@0 258 if isfield(method,'minyMaxy') && ~isempty(method.minyMaxy)
rmeddis@0 259 ylim(method.minyMaxy)
rmeddis@0 260 else
rmeddis@0 261 if max(yValues)>min(yValues)
rmeddis@0 262 ylim([min(yValues) max(yValues)])
rmeddis@0 263 end
rmeddis@0 264 end
rmeddis@38 265
rmeddis@38 266 % y-axis design yTickLabels
rmeddis@38 267 if min(yValues)>1
rmeddis@0 268 tickValues=[min(yValues) max(yValues)];
rmeddis@38 269 tickLabels=num2str(tickValues');
rmeddis@38 270 if method.plotDivider && size(toPlot,1) > 2
rmeddis@38 271 % show min/max yvalues with slight shift
rmeddis@38 272 yList=yValues;
rmeddis@38 273 yValues=1:length(yValues);
rmeddis@38 274 tickValues=[1 halfway-1 halfway+2 length(yValues)];
rmeddis@38 275 idx=[1 halfway halfway+1 length(yValues)];
rmeddis@38 276 tickLabels=num2str(yList(idx)');
rmeddis@38 277 imagesc(xValues, yValues, toPlot), axis xy;
rmeddis@38 278 end
rmeddis@38 279
rmeddis@0 280 set(gca,'ytick',tickValues)
rmeddis@38 281 set(gca,'ytickLabel', strvcat(tickLabels))
rmeddis@0 282 set(gca,'FontSize', method.defaultFontSize)
rmeddis@0 283 end
rmeddis@0 284
rmeddis@0 285 end
rmeddis@0 286
rmeddis@38 287 else % is logical
rmeddis@0 288 % logical implies spike array. Use raster plot
rmeddis@0 289 [y,x]=find(toPlot); %locate all spikes: y is fiber number ie row
rmeddis@0 290 x=x*dt+method.timeStart; % x is time
rmeddis@0 291 plot(x,y, 'o', 'MarkerSize', rasterDotSize, 'color', 'k')
rmeddis@0 292 if numYvalues>1
rmeddis@0 293 set(gca,'yScale','linear')
rmeddis@0 294 set(gca,'ytick', [1 numYvalues],'FontSize', method.defaultFontSize)
rmeddis@0 295 % show lowest and highest BF value only
rmeddis@0 296 set(gca,'ytickLabel', [min(yValues) max(yValues) ],'FontSize', method.defaultFontSize)
rmeddis@0 297 if method.plotDivider
rmeddis@0 298 % or use labels to identify fiber type
rmeddis@0 299 set(gca,'ytickLabel', {'LSR', 'HSR'},'FontSize', method.defaultFontSize)
rmeddis@0 300 end
rmeddis@0 301 ylim([0 numYvalues+1])
rmeddis@0 302 end
rmeddis@0 303 xlim([0 method.objectDuration])
rmeddis@0 304 if isfield(method,'yLabel') && ~isempty(method.yLabel)
rmeddis@0 305 ylabel(method.yLabel,'FontSize', method.defaultFontSize, 'color', defaultTextColor)
rmeddis@0 306 end
rmeddis@0 307
rmeddis@0 308 % add line to separate HSR and LSR
rmeddis@0 309 if method.plotDivider
rmeddis@0 310 [r c]=size(toPlot);
rmeddis@0 311 halfWayUp=round(r/2);
rmeddis@0 312 hold on
rmeddis@0 313 plot([0 c*method.displaydt],[halfWayUp halfWayUp], 'b')
rmeddis@0 314 hold off
rmeddis@0 315 end
rmeddis@38 316
rmeddis@0 317 end
rmeddis@0 318
rmeddis@0 319 set(gca, 'xcolor', defaultAxesColor)
rmeddis@0 320 set(gca, 'ycolor', defaultAxesColor)
rmeddis@0 321
rmeddis@0 322 % add title
rmeddis@0 323 if isfield(method,'title') && ~isempty(method.title)
rmeddis@0 324 title(method.title, 'FontSize', method.defaultFontSize, 'color', defaultTextColor)
rmeddis@0 325 end
rmeddis@0 326
rmeddis@0 327 % label axes
rmeddis@0 328 if ~isfield(method,'axes') || isempty(method.axes)
rmeddis@0 329 % annotate the x-axis only if it is the last plot on a figure created by this utility
rmeddis@0 330 set(gca,'xtick',[],'FontSize', method.defaultFontSize)
rmeddis@0 331 if method.subPlotNo==method.numPlots
rmeddis@0 332 if isfield(method,'xLabel') && ~isempty(method.xLabel)
rmeddis@38 333 % set(gca,'ActivePositionProperty','outerposition')
rmeddis@0 334 % xlabel(method.xLabel)
rmeddis@0 335 xlabel(method.xLabel, 'FontSize', method.defaultFontSize, 'color', defaultTextColor)
rmeddis@0 336 end
rmeddis@0 337 set(gca,'xtickmode','auto') % add timescale to the lowest graph
rmeddis@0 338 end
rmeddis@0 339 end
rmeddis@0 340
rmeddis@0 341 % add user labels to the y-axis if requested
rmeddis@0 342 if isfield(method,'yLabel') && ~isempty(method.yLabel)
rmeddis@0 343 ylabel(method.yLabel, 'color', defaultTextColor)
rmeddis@0 344 end
rmeddis@0 345
rmeddis@0 346 % define color
rmeddis@0 347 if method.blackOnWhite, colormap bone, else colormap jet
rmeddis@0 348 end
rmeddis@0 349
rmeddis@0 350 % drawnow