Home > NoiseTools > nt_plotxx.m

# nt_plotxx

## PURPOSE

nt_plotxx(fname,bounds,chans) - plot using index file

## SYNOPSIS

function nt_plotxx(fname,bounds,chans)

## DESCRIPTION

    nt_plotxx(fname,bounds,chans) - plot using index file

      fname: name of file to plot
      bounds: [start,stop] (s) range to plot [default: all]
      chans: channels to plot [default: all]

     Data are plotted using cheap data representation in index file.
     All channels are plotted unless specified.
     The entire file is plotted unless specified.
     The mean of each channel (over entire data) is removed before plotting.

     A limited form of zooming and navigation is available using the arrow keys.
     Multiple windows can be open, each pointing to a different file.

     NoiseTools

## CROSS-REFERENCE INFORMATION

This function calls:

- nt_double2int nt_double2int() - recode/decode double as integer to save space
- nt_greetings nt_greetings - display message the first time the toolbox is used
- nt_idxx nt_idxx(fname,iname,bsize,chunksize,nfft) - create an index file to summarize large data file
- nt_plotxx nt_plotxx(fname,bounds,chans) - plot using index file

This function is called by:

- nt_plotxx nt_plotxx(fname,bounds,chans) - plot using index file

## SUBFUNCTIONS

- function keyfunction(fig,eventDat)
- function y=dsmmx(mmx,dsr)

## SOURCE CODE

    0001 function nt_plotxx(fname,bounds,chans)
    0002 %nt_plotxx(fname,bounds,chans) - plot using index file
    0003 %
    0004 %  fname: name of file to plot
    0005 %  bounds: [start,stop] (s) range to plot [default: all]
    0006 %  chans: channels to plot [default: all]
    0007 %
    0008 % Data are plotted using cheap data representation in index file.
    0009 % All channels are plotted unless specified.
    0010 % The entire file is plotted unless specified.
    0011 % The mean of each channel (over entire data) is removed before plotting.
    0012 %
    0013 % A limited form of zooming and navigation is available using the arrow keys.
    0014 % Multiple windows can be open, each pointing to a different file.
    0015 %
    0016 % NoiseTools
    0017
    0018 nt_greetings;
    0019
    0020 assert(nargin>0, '!');
    0021 if nargin<2; bounds=[]; end
    0022 if nargin<3; chans=[]; end
    0023
    0024 if ~ 2==exist('get_axes_width');  % tbd: replicate to remove dependency
    0025     disp('get_axes_width() not found');
    0026     disp('Download https://www.mathworks.com/matlabcentral/fileexchange/40790-plot-big');
    0027     error;
    0028 end
    0029
    0030 if ischar(fname) % index file
    0031     [FILEPATH,NAME,EXT]=fileparts(fname);
    0032     iname=[FILEPATH,filesep,NAME,'.idxx'];
    0033     if 2~=exist(iname);
    0034         disp('No index file found.  Create one.');
    0035         if 2~=exist(fname);
    0036             error('No data file either...');
    0037         end
    0038         disp('This may take a while...');
    0039         tic;
    0040         nt_idxx(fname);
    0041         toc;
    0042     end
    0043     disp('read from file...'); tic;
    0044     load(iname, '-mat', 'bstats'); % ignores 'cstats' and 'sstats'
    0045     disp('done'); toc
    0046     i=bstats;
    0047 elseif isstruct(fname) %  index struct
    0048     i=fname;
    0049 else
    0050     error('!');
    0051 end
    0052
    0053 % decode from int structure
    0054 if isempty(chans); chans=1:i.nchans; end
    0055 mn=nt_double2int(i.min,{[],chans});
    0056 mx=nt_double2int(i.max,{[],chans});
    0057 mnn=nt_double2int(i.mean,{[],chans});
    0058
    0059 % remove mean from min and max for each channel
    0060 mn=bsxfun(@minus,mx,mean(mnn));
    0061 mx=bsxfun(@minus,mx,mean(mnn));
    0062
    0063 srr=i.sr/double(i.card(1));     % sampling rate
    0064
    0065 % select data within requested bounds (in seconds)
    0066 maxbound=(size(mn,1)-1)/srr;    % s, end of file
    0067 if isempty(bounds); bounds=[0,maxbound]; end
    0068 start=1+max(0,min(size(mn,1)-1, round(bounds(1)*srr)));
    0069 stop=1+max(0,min(size(mn,1)-1, round(bounds(2)*srr)));
    0070 mn=mn(start:stop,:);
    0071 mx=mx(start:stop,:);
    0072
    0073 % estimate how many pixels fit within a window
    0074 axes_width=get_axes_width(gca);
    0075
    0076 % plot the waveform
    0077 figure(gcf);    % bring latest figure foremost
    0078 clf; drawnow    % erase (just so user know's something's happening
    0079 %{
    0080 The ideal is to plot the min-max series using 'fill'.  Unfortunately that's
    0081 slow.
    0082 Coalescing the min-max index to fewer samples helps somewhat, but the
    0083 outcome is impredictable.
    0084 A solution is to first display the min and max series using 'plot' (fast)
    0085 then overwrite with 'fill' (slow). Aspect not quite right yet...
    0086 I hope there's a better solution
    0087 %}
    0088
    0089 % first display using 'plot'
    0090 if size(mx,1)<axes_width
    0091     % running into the limits of the resolution of the index, we should go
    0092     % to data file
    0093 end
    0094 if size(mx,1)>axes_width*50
    0095     % coalesce first if really big
    0096     dsr=round(size(mx,1)/(axes_width*50));
    0097     mmx=dsmmx(cat(3,mn,mx),dsr);
    0098     mn=mmx(:,:,1); mx=mmx(:,:,2);
    0099     srr=srr/dsr;
    0100 end
    0101 yy=[mn; flipud(mx)];
    0102 xx=[(0:size(mn,1)-1)' ; (size(mn,1)-1:-1:0)'];
    0103 plot(bounds(1)+xx/srr , yy); % plot min forward & max backward
    0104 xlabel('time (s)');
    0105 xlabel('s');
    0106 xlim(bounds);
    0107 a=min(mn(:));
    0108 b=max(mx(:));
    0109 ylim([a-(b-a)*0.1,b+(b-a)*0.1])
    0110
    0111 drawnow;
    0112 hold on;
    0113
    0114 if 0
    0115 % then write over with fill, better aspect but slow
    0116 if size(mx,1)>axes_width
    0117     dsr=round(size(mx,1)/(axes_width));
    0118     mmx=dsmmx(cat(3,mn,mx),dsr);
    0119     mn=mmx(:,:,1); mx=mmx(:,:,2);
    0120     srr=srr/dsr;
    0121 end
    0122 npoints=size(mn,1);
    0123 X=bounds(1)+(0:npoints-1)'/srr;
    0124 h=fill([X;flipud(X)],[mn;flipud(mx)], 'k', 'LineStyle', 'none');
    0125 colororder=get(gca,'colororder');
    0126 for iPatch=1:numel(h);
    0127     h(iPatch).FaceColor=colororder(1+rem(iPatch-1,7),:);
    0128     %h(iPatch).EdgeColor=colororder(1+rem(iPatch-1,7),:);
    0129 end
    0130 end
    0131
    0132 % if size(mx,1) > 8*axes_width
    0133 %     % use plot, fastest
    0134 %     if size(mx,1)>axes_width*50
    0135 %         dsr=round(size(mx,1)/(axes_width*50));
    0136 %         mmx=dsmmx(cat(3,mn,mx),dsr);
    0137 %         mn=mmx(:,:,1); mx=mmx(:,:,2);
    0138 %         srr=srr/dsr;
    0139 %     end
    0140 %     yy=[mn; flipud(mx)];
    0141 %     xx=[(0:size(mn,1)-1)' ; (size(mn,1)-1:-1:0)'];
    0142 %     plot(bounds(1)+xx/srr , yy); % plot min forward & max backward
    0143 %     xlabel('time (s)');
    0144 % else
    0145 %     % use fill, better aspect
    0146 %     if size(mx,1)>axes_width
    0147 %         % !!!!
    0148 %         % should plot from the data
    0149 %         % !!!!
    0150 %         dsr=round(size(mx,1)/(axes_width));
    0151 %         mmx=dsmmx(cat(3,mn,mx),dsr);
    0152 %         mn=mmx(:,:,1); mx=mmx(:,:,2);
    0153 %         srr=srr/dsr;
    0154 %     end
    0155 %     npoints=size(mn,1);
    0156 %     X=bounds(1)+(0:npoints-1)'/srr;
    0157 %     h=fill([X;flipud(X)],[mn;flipud(mx)], 'k');
    0158 %     colororder=get(gca,'colororder');
    0159 %     for iPatch=1:numel(h);
    0160 %         h(iPatch).FaceColor=colororder(1+rem(iPatch-1,7),:);
    0161 %         h(iPatch).EdgeColor=colororder(1+rem(iPatch-1,7),:);
    0162 %     end
    0163 % end
    0164
    0165 xlabel('s');
    0166 xlim(bounds);
    0167 a=min(mn(:));
    0168 b=max(mx(:));
    0169 ylim([a-(b-a)*0.1,b+(b-a)*0.1])
    0170
    0171 % GUI
    0172 userdata.i=i;
    0173 userdata.bounds=bounds;
    0174 set(gcf,'UserData',userdata);
    0175 set(gcf, 'KeyPressFcn',@keyfunction)
    0176 end
    0177
    0178 function keyfunction(fig,eventDat)
    0179 userdata=get(fig,'UserData');
    0180 b=userdata.bounds;
    0181 i=userdata.i;
    0182 fname=i.fname;
    0183 switch eventDat.Key
    0184     case 'rightarrow'
    0185         newbounds=[b(1)+(b(2)-b(1))*.5, b(1)+(b(2)-b(1))*1.5];
    0186         disp(round([newbounds, diff(newbounds)]))
    0187         nt_plotxx(i,newbounds);
    0188     case 'leftarrow'
    0189         newbounds=[b(1)-(b(2)-b(1))*.5, b(1)+(b(2)-b(1))*.5];
    0190          disp(round([newbounds, diff(newbounds)]))
    0191         nt_plotxx(i,newbounds);
    0192     case 'uparrow'
    0193         newbounds=[b(1)+(b(2)-b(1))*.25, b(1)+(b(2)-b(1))*.75];
    0194          disp(round([newbounds, diff(newbounds)]))
    0195        nt_plotxx(i,newbounds);
    0196     case 'downarrow'
    0197         newbounds=[b(1)-(b(2)-b(1))*.5, b(1)+(b(2)-b(1))*1.5];
    0198         disp(round([newbounds, diff(newbounds)]))
    0199         nt_plotxx(i,newbounds);
    0200     otherwise
    0201 end
    0202 end
    0203
    0204 function y=dsmmx(mmx,dsr) % downsample min-max array
    0205     assert(dsr<size(mmx,1), '!');
    0206     assert(size(mmx,3)==2, '!');
    0207     n=floor(size(mmx,1)/dsr);
    0208     xtra=mmx(n*dsr+1:end,:,:);
    0209     mmx=mmx(1:n*dsr,:,:);
    0210     [nsamples,nchans,~]=size(mmx);
    0211     mmx=permute(mmx,[3 1 2]); % --> 2 X nsamples X nchans
    0212     mmx=reshape(mmx, [dsr*2,nsamples/dsr, nchans]);
    0213     mn=min(mmx);
    0214     mx=max(mmx);
    0215     y=cat(3,shiftdim(mn,1),shiftdim(mx,1));
    0216     % process xtra tbd
    0217 end