rmeddis@0: function UTIL_plotMatrix(toPlot, method) rmeddis@0: % UTIL_plotMatrix general purpose plotting utility for plotting the results rmeddis@0: % of the MAP auditory model. rmeddis@0: % All plots are placed in subplots of a figure (default figure 1). rmeddis@0: % Input arguments: rmeddis@0: % 'toPlot' is matrix (either numeric or logical) rmeddis@0: % 'method' is a structure containing plot instructions rmeddis@0: % rmeddis@0: % surface plots have log z-axis when all values are >1 rmeddis@0: % rmeddis@0: % when calling this function, always increment the subPlotNo in method rmeddis@0: % method.subPlotNo=method.subPlotNo+1; rmeddis@0: % method.subPlotNo=method.subPlotNo; rmeddis@0: % rmeddis@0: % mandatory parameters: rmeddis@0: % method.displaydt xValues spacing between data points rmeddis@0: % method.numPlots total number of subPlots in the figure rmeddis@0: % method.subPlotNo number of this plot rmeddis@0: % method.yValues mandatory only for 3D plots rmeddis@0: % rmeddis@0: % optional rmeddis@0: % method.figureNo normally figure(1) rmeddis@0: % method.zValuesRange [min max] value pair to define yaxis limits rmeddis@0: % method.zValuesRange [min max] CLIMS for 3-D plot rmeddis@0: % method.yLabel (string) y-axis label rmeddis@0: % method.xLabel (string) x-axis label rmeddis@0: % method.title (string) subplot title rmeddis@0: % method.bar =1, to force bar histogram (single channel only) rmeddis@0: % method.view 3D plot 'view' settings e.g. [-6 40] rmeddis@0: % method.axes (handle) used for writing to GUIs (specifies panel) rmeddis@0: % method.maxPixels maximum number of pixels (used to speed plotting) rmeddis@0: % method.blackOnWhite =1; % NB inverts display for 2D plots rmeddis@0: % method.forceLog positive values are put on log z-scale rmeddis@0: % method.rasterDotSize min value is 1 rmeddis@0: % method.defaultFontSize rmeddis@0: % method.timeStart default=dt rmeddis@0: % method.defaultTextColor default ='w' rmeddis@0: % method.defaultAxesColor default = 'w' rmeddis@0: % method.nCols default=1 rmeddis@0: % method.nRows default=method.numPlots rmeddis@0: % rmeddis@0: % useful paste for calling program rmeddis@0: % method.numPlots=method.numPlots; rmeddis@0: % method.subPlotNo=method.subPlotNo+1; rmeddis@0: % method.subPlotNo=method.subPlotNo; rmeddis@0: % dt=dt; rmeddis@0: % method.yValues=method.nonlinCF; % for 3D plots only rmeddis@0: % rmeddis@0: % method.figureNo=1; rmeddis@0: % method.yLabel='useThisLabel'; rmeddis@0: % method.xLabel='use this label'; rmeddis@0: % method.title='myTitle'; rmeddis@0: % rmeddis@0: % UTIL_plotMatrix(toPlot, method) rmeddis@0: rmeddis@0: dt=method.displaydt; rmeddis@0: if ~isfield(method,'figureNo') || isempty(method.figureNo) rmeddis@0: method.figureNo=99; rmeddis@0: end rmeddis@0: % if ~isfield(method,'zValuesRange') || isempty(method.zValuesRange) rmeddis@0: % method.zValuesRange=[-inf inf]; rmeddis@0: % end rmeddis@0: rmeddis@0: % set some defaults rmeddis@0: if ~isfield( method,'plotDivider') || isempty(method.plotDivider) rmeddis@0: method.plotDivider=0; rmeddis@0: end rmeddis@0: if ~isfield( method,'blackOnWhite') || isempty(method.blackOnWhite) rmeddis@0: method.blackOnWhite=0; rmeddis@0: end rmeddis@0: if ~isfield(method,'timeStart')|| isempty(method.timeStart) rmeddis@0: method.timeStart=dt; rmeddis@0: end rmeddis@0: if ~isfield(method,'objectDuration') || isempty(method.objectDuration) rmeddis@0: [nRows nCols]=size(toPlot); method.objectDuration=dt*nCols; rmeddis@0: end rmeddis@0: if ~isfield(method,'defaultFontSize') || isempty(method.defaultFontSize) rmeddis@0: method.defaultFontSize=12; rmeddis@0: end rmeddis@0: if ~isfield(method,'defaultTextColor') || isempty(method.defaultTextColor) rmeddis@0: method.defaultTextColor='k'; rmeddis@0: defaultTextColor=method.defaultTextColor; rmeddis@0: else rmeddis@0: defaultTextColor='k'; rmeddis@0: end rmeddis@0: if ~isfield( method,'defaultAxesColor') || isempty(method.defaultAxesColor) rmeddis@0: method.defaultAxesColor=defaultTextColor; rmeddis@0: end rmeddis@0: defaultAxesColor=method.defaultAxesColor; rmeddis@0: rmeddis@0: % arrangement of plots in rows and columns rmeddis@0: if ~isfield(method,'nCols') || isempty(method.nRows) rmeddis@0: method.nCols=1; rmeddis@0: end rmeddis@0: if ~isfield(method,'nRows') || isempty(method.nRows) rmeddis@0: method.nRows= method.numPlots; rmeddis@0: end rmeddis@0: rmeddis@0: if ~isfield(method,'rasterDotSize') || isempty(method.rasterDotSize) rmeddis@0: rasterDotSize=1; rmeddis@0: else rmeddis@0: rasterDotSize=method.rasterDotSize; rmeddis@0: end rmeddis@0: rmeddis@0: % user can specify either an independent axis rmeddis@0: % or a subplot of the current figure rmeddis@0: % if both are specified, 'axes' takes priority rmeddis@0: figure(method.figureNo) rmeddis@0: if isfield(method,'axes') && ~isempty(method.axes) rmeddis@0: % select an axis in some location other than 'figure' rmeddis@0: h=axes(method.axes); rmeddis@0: else rmeddis@0: % now using a regular figure rmeddis@0: if method.subPlotNo>method.numPlots; rmeddis@0: error('UTIL_plotMatrix: not enough subplots allocated in figure 1. Check method.numPlots') rmeddis@0: end rmeddis@0: % choose subplot rmeddis@0: subplot(method.nRows,method.nCols,method.subPlotNo), % cla rmeddis@0: rmeddis@0: if isfield(method,'segmentNumber') && ~isempty(method.segmentNumber)... rmeddis@0: && method.segmentNumber>1 rmeddis@0: % in multi-segment mode do not clear the image rmeddis@0: % from the previous segment rmeddis@0: hold on rmeddis@0: else rmeddis@0: % otherwise a fresh image will be plotted rmeddis@0: hold off rmeddis@0: cla rmeddis@0: end rmeddis@0: end rmeddis@0: rmeddis@0: [numYvalues numXvalues]=size(toPlot); rmeddis@0: xValues=method.timeStart:dt:method.timeStart+dt*(numXvalues-1); rmeddis@0: rmeddis@0: if isfield(method,'yValues') && ~isempty(method.yValues) rmeddis@0: % yValues is normally a vector specifying channel BF rmeddis@0: yValues=method.yValues; rmeddis@0: else rmeddis@0: yValues=1:numYvalues; rmeddis@0: end rmeddis@0: rmeddis@0: % Now start the plot. rmeddis@0: % 3D plotting for 4 or more channels rmeddis@0: % otherwise special cases for fewer channels rmeddis@0: rmeddis@0: if ~islogical(toPlot) rmeddis@0: % continuous variables rmeddis@0: switch numYvalues rmeddis@0: case 1 % single vector (black) rmeddis@0: if isfield(method,'bar') && ~isempty(method.bar) rmeddis@0: % histogram rmeddis@0: bar(xValues, toPlot,'k') rmeddis@0: method.bar=[]; % avoid carry over between modules rmeddis@0: else rmeddis@0: % waveform rmeddis@0: plot(xValues, toPlot,'k') rmeddis@0: end rmeddis@0: xlim([0 method.objectDuration]) rmeddis@0: if isfield(method,'zValuesRange') ... rmeddis@0: && ~isempty(method.zValuesRange) rmeddis@0: ylim(method.zValuesRange) rmeddis@0: method.zValuesRange=[]; % avoid carry over between modules rmeddis@0: end rmeddis@0: if isfield(method,'yLabel') && ~isempty(method.yLabel) rmeddis@0: ylabel(method.yLabel, 'color', defaultTextColor) rmeddis@0: method.yLabel=[]; % avoid carry over between modules rmeddis@0: end rmeddis@0: rmeddis@0: case 2 % 2 x N vector (black and red) rmeddis@0: plot(xValues, toPlot(1,:),'k'), % hold on rmeddis@0: plot(xValues, toPlot(2,:),'r'), % hold off rmeddis@0: xlim([0 method.objectDuration]) rmeddis@0: if isfield(method,'zValuesRange') ... rmeddis@0: && ~isempty(method.zValuesRange) rmeddis@0: ylim(method.zValuesRange) rmeddis@0: method.zValuesRange=[]; % avoid carry over between modules rmeddis@0: end rmeddis@0: if isfield(method,'yLabel')&& ~isempty(method.yLabel) rmeddis@0: ylabel(method.yLabel, 'color', defaultTextColor) rmeddis@0: method.yLabel=[]; % avoid carry over between modules rmeddis@0: end rmeddis@0: rmeddis@0: case 3 % 3 x N vector (black red and green) rmeddis@0: % this is used for 1 channel DRNL output rmeddis@0: plot(xValues, toPlot(1,:),'k'), hold on rmeddis@0: plot(xValues, toPlot(2,:),'r'), hold on rmeddis@0: plot(xValues, toPlot(3,:),'g'), hold off rmeddis@0: xlim([0 method.objectDuration]) rmeddis@0: if isfield(method,'zValuesRange') ... rmeddis@0: && ~isempty(method.zValuesRange) rmeddis@0: ylim(method.zValuesRange) rmeddis@0: end rmeddis@0: if isfield(method,'yLabel') && ~isempty(method.yLabel) rmeddis@0: ylabel(method.yLabel, 'color', defaultTextColor) rmeddis@0: end rmeddis@0: rmeddis@0: otherwise % >3 channels: surface plot rmeddis@0: % add white line to separate HSR and LSR rmeddis@0: if method.plotDivider && size(toPlot,1) > 2 rmeddis@0: [r c]=size(toPlot); rmeddis@0: % if isempty(method.zValuesRange), method.zValuesRange=0; end rmeddis@0: % mm=method.zValuesRange(2); rmeddis@0: emptyLine=max(max(toPlot))*ones(2,c); rmeddis@0: halfway=round(r/2); rmeddis@0: toPlot=[toPlot(1:halfway,:); emptyLine; toPlot(halfway+1:end,:)]; rmeddis@0: end rmeddis@0: rmeddis@0: % invert data for black on white matrix plotting rmeddis@0: if method.blackOnWhite rmeddis@0: toPlot=-toPlot; rmeddis@0: end rmeddis@0: rmeddis@0: % matrix (analogue) plot rmeddis@0: if isfield(method,'forceLog') && ~isempty(method.forceLog) rmeddis@0: % positive values are put on log z-scale rmeddis@0: toPlot=toPlot+min(min(toPlot))+1; rmeddis@0: toPlot=log(toPlot); rmeddis@0: if isfield(method,'title') rmeddis@0: method.title=[method.title ' (log scale)']; rmeddis@0: else rmeddis@0: method.title= '(log scale)'; rmeddis@0: end rmeddis@0: end rmeddis@0: rmeddis@0: % zValuesRange rmeddis@0: if isfield(method,'zValuesRange') ... rmeddis@0: && ~isempty(method.zValuesRange) rmeddis@0: % zValuesRange gives the max and min values rmeddis@0: % a=method.zValuesRange(1); rmeddis@0: % b=method.zValuesRange(2); rmeddis@0: % toPlot=(toPlot-a)/(b-a); rmeddis@0: % clims=[0 1]; rmeddis@0: clims=(method.zValuesRange); rmeddis@0: imagesc(xValues, yValues, toPlot, clims), axis xy; %NB assumes equally spaced y-values rmeddis@0: else rmeddis@0: % automatically scaled rmeddis@0: imagesc(xValues, yValues, toPlot), axis xy; %NB assumes equally spaced y-values rmeddis@0: rmeddis@0: % if ~isfield(method,'zValuesRange') rmeddis@0: % method.zValuesRange=[-inf inf]; rmeddis@0: % end rmeddis@0: % rmeddis@0: % if method.blackOnWhite rmeddis@0: % % NB plotted values have negative sign for black on white rmeddis@0: % caxis([-method.zValuesRange(2) -method.zValuesRange(1)]) rmeddis@0: % else rmeddis@0: % caxis(method.zValuesRange) rmeddis@0: % end rmeddis@0: rmeddis@0: if ~isfield(method,'zValuesRange')... rmeddis@0: || isempty(method.zValuesRange) rmeddis@0: method.zValuesRange=[-inf inf]; rmeddis@0: end rmeddis@0: rmeddis@0: if method.blackOnWhite rmeddis@0: % NB plotted values have negative sign for black on white rmeddis@0: caxis([-method.zValuesRange(2) -method.zValuesRange(1)]) rmeddis@0: else rmeddis@0: caxis(method.zValuesRange) rmeddis@0: end rmeddis@0: end rmeddis@0: rmeddis@0: % xaxis rmeddis@0: % NB segmentation may shorten signal duration rmeddis@0: [r c]=size(toPlot); rmeddis@0: imageDuration=c*method.displaydt; rmeddis@0: xlim([0 imageDuration]) rmeddis@0: % xlim([0 method.objectDuration]) rmeddis@0: rmeddis@0: % yaxis rmeddis@0: if isfield(method,'minyMaxy') && ~isempty(method.minyMaxy) rmeddis@0: ylim(method.minyMaxy) rmeddis@0: else rmeddis@0: if max(yValues)>min(yValues) rmeddis@0: ylim([min(yValues) max(yValues)]) rmeddis@0: end rmeddis@0: end rmeddis@0: if min(yValues)>1 % put channel array on a log scale rmeddis@0: tickValues=[min(yValues) max(yValues)]; rmeddis@0: set(gca,'ytick',tickValues) rmeddis@0: set(gca,'ytickLabel', strvcat(num2str(tickValues'))) rmeddis@0: set(gca,'FontSize', method.defaultFontSize) rmeddis@0: end rmeddis@0: rmeddis@0: end rmeddis@0: rmeddis@0: else % is logical rmeddis@0: rmeddis@0: % logical implies spike array. Use raster plot rmeddis@0: [y,x]=find(toPlot); %locate all spikes: y is fiber number ie row rmeddis@0: x=x*dt+method.timeStart; % x is time rmeddis@0: plot(x,y, 'o', 'MarkerSize', rasterDotSize, 'color', 'k') rmeddis@0: if numYvalues>1 rmeddis@0: set(gca,'yScale','linear') rmeddis@0: set(gca,'ytick', [1 numYvalues],'FontSize', method.defaultFontSize) rmeddis@0: % show lowest and highest BF value only rmeddis@0: set(gca,'ytickLabel', [min(yValues) max(yValues) ],'FontSize', method.defaultFontSize) rmeddis@0: if method.plotDivider rmeddis@0: % or use labels to identify fiber type rmeddis@0: set(gca,'ytickLabel', {'LSR', 'HSR'},'FontSize', method.defaultFontSize) rmeddis@0: end rmeddis@0: ylim([0 numYvalues+1]) rmeddis@0: end rmeddis@0: xlim([0 method.objectDuration]) rmeddis@0: if isfield(method,'yLabel') && ~isempty(method.yLabel) rmeddis@0: ylabel(method.yLabel,'FontSize', method.defaultFontSize, 'color', defaultTextColor) rmeddis@0: end rmeddis@0: rmeddis@0: % add line to separate HSR and LSR rmeddis@0: if method.plotDivider rmeddis@0: [r c]=size(toPlot); rmeddis@0: halfWayUp=round(r/2); rmeddis@0: hold on rmeddis@0: plot([0 c*method.displaydt],[halfWayUp halfWayUp], 'b') rmeddis@0: hold off rmeddis@0: end rmeddis@0: end rmeddis@0: rmeddis@0: set(gca, 'xcolor', defaultAxesColor) rmeddis@0: set(gca, 'ycolor', defaultAxesColor) rmeddis@0: rmeddis@0: % add title rmeddis@0: if isfield(method,'title') && ~isempty(method.title) rmeddis@0: title(method.title, 'FontSize', method.defaultFontSize, 'color', defaultTextColor) rmeddis@0: end rmeddis@0: rmeddis@0: % label axes rmeddis@0: if ~isfield(method,'axes') || isempty(method.axes) rmeddis@0: % annotate the x-axis only if it is the last plot on a figure created by this utility rmeddis@0: set(gca,'xtick',[],'FontSize', method.defaultFontSize) rmeddis@0: if method.subPlotNo==method.numPlots rmeddis@0: if isfield(method,'xLabel') && ~isempty(method.xLabel) rmeddis@0: % set(gca,'ActivePositionProperty','outerposition') rmeddis@0: % xlabel(method.xLabel) rmeddis@0: xlabel(method.xLabel, 'FontSize', method.defaultFontSize, 'color', defaultTextColor) rmeddis@0: end rmeddis@0: set(gca,'xtickmode','auto') % add timescale to the lowest graph rmeddis@0: end rmeddis@0: end rmeddis@0: rmeddis@0: % add user labels to the y-axis if requested rmeddis@0: if isfield(method,'yLabel') && ~isempty(method.yLabel) rmeddis@0: ylabel(method.yLabel, 'color', defaultTextColor) rmeddis@0: end rmeddis@0: rmeddis@0: % define color rmeddis@0: if method.blackOnWhite, colormap bone, else colormap jet rmeddis@0: end rmeddis@0: rmeddis@0: % drawnow