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