To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.
The primary repository for this project is hosted at git://github.com/rmeddis/MAP.git .
This repository is a read-only copy which is updated automatically every hour.
root / utilities / UTIL_plotMatrix.m @ 0:f233164f4c86
History | View | Annotate | Download (13 KB)
| 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 |