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