No BSD License  

Highlights from
scrollingplot

from scrollingplot by Jonathan Tinker
Simplifies despiking of data.

varargout=scrollingplot(varargin)
function varargout=scrollingplot(varargin)
% Creates a figure for assistance with data quality control. If there are
% several data sets with a common x axis (time for example), all the data
% can be plotted on separate axes, and when one is zoomed into or panned,
% the other axes adjust to have the same x limits. This allows the data on
% all axes to compared simultaneously. Data can be selected as being good
% or bad, and a logical array of the indexes of the data is returned (bad
% data is given a 1, such that "y(index) = nan;" may be executed). To
% select data, A key is pressed, and a rubberband box (rbbox) is
% initiallised. The data is selected with this box, and it is highlighted,
% with red dots in the current axes, and green circle in the other axes (at
% the same time, generally bad data in any sensor means data from all the
% sensor is discarded during that period).
%
% Data selection keys are
%       b (lowercase)       selects bad data
%       g (lowercase)       selects good data
%       s (lowercase)       inverts the selection
%       Q (uppercase)       quits the program
%
% By Default, everytime a selection is made, all the logical indexes are
% saved as tmpswi.mat in the current directory.
%
% A dialog box to accept a command has been developed. This allows a
% command to be executed by the program. The benefit of this is it allows
% all data point to be selected when a certain logical operation is true
% e.g. select all point as bad when the depth is below a certain value.
% Pressing C (upper case) brings up this dialog box.
% Internal Variable names:
%       x
%       y1
%       y2
%       y3...
%       y1sw
%       y2sw
%       y3sw... (selected values are 1).
%
%
% Syntax:
%   index = scrollingplot(x,y1,y2,y4,...)
%
%
% NB the matlab command LINKAXES 
%
%                           Jonathan Tinker


% clc
% ca
%
% clear ax
%
% X=dat(i).t;
% Y1=dat(i).p;
% Y2=dat(i).u;
% Y3=dat(i).v;
%
% varargin={X,Y1,Y2,Y3};
% nargin=4;
% %
% % % varargin={X,Y1,Y2};
% % % nargin=3;
% % %

% As the timer object and the function cannot see each other, variable used
% between them must be set as global variable. This clears any global
% varibale and timers that may not have been deleted if the script crashes.

clear global ax
clear ax
out = timerfind;
delete(out)


% set up the input variables - needs work

nys = 0;
x=varargin{1};
par=zeros(1,nargin);
for i=2:nargin
    if length(varargin{i})==length(varargin{1})
        eval(['y' num2str(i-1) '=varargin{i}(:,1);']);
        try
            eval(['yaux' num2str(i-1) '=varargin{i}(:,2:end);']);
        end
        param(i) = 0;
        nys=nys+1;
    else 
        par(i) = 1;
    end
end
% y2sw(yaux2<0.25)=1
yaux2;

% if sum(par)>1
%     params = varargin(logical(par));
%     
%     for i=1:length(params)
%         if strcmp(lower(params{i}),'crashed')
%             crashed=1;
%         end
%     end
% end

% max(x)
% max(y1)
% max(y2)
% max(y3)

tit=''

crashed=0;
if sum(par)>1
    params = varargin(logical(par));
    
    for i=1:length(params)
        if strcmp(lower(params{i}),'crashed')
            crashed=1;
        end
        if strcmp(lower(params{i}),'title')
            tit=params{i+1};
        end
        
        
    end
end


% x=varargin{1};
% 
% if nargin == 3
%     y1=varargin{2};
%     y2=varargin{3};
%     nys=2;
% end
% 
% if nargin == 4
%     y1=varargin{2};
%     y2=varargin{3};
%     y3=varargin{4};
%     nys=3;
% end
% 
% if nargin == 5
%     y1=varargin{2};
%     y2=varargin{3};
%     y3=varargin{4};
%     y4=varargin{5};
%     nys=4;
% end
% 
% crashed = 0;



% set up the switches for each set of data

for i=1:nys
    eval(['y' num2str(i) 'sw=logical(zeros(size(x)));']);
end


% if logical(crashed)
%     load tmpswi.mat
% end




% set axes "ax" as global so it can be seen by the timer
global ax


% Create the plot
figure
for i=1:nys
    ax(i)=subplot(nys,1,i);
    eval(['plot(x,y' num2str(i) ',''b'')'])
    hold on
    try
        eval(['plot(x,yaux' num2str(i) ',''y'')'])
    end
    % grid on
    xlabel('x')
    ylabel(['y' num2str(i)])

    if i==1
        title(tit)
        % text(min(xlim),min(ylim),'s =  switch, b = bad, g = good, C = command, Q = exit','VerticalAlignment','bottom')
    end
    hold on
end

coms='s =  switch, b = bad, g = good, C = command, Q = exit'
set(gcf,'name',coms)


% Create the code for the Timer to execute every period. This code gets the
% xlims from the current axes and applies it to all the other axes.
updatestr=[     'tmpax=get(gcf,''currentaxes'');' ...
    'tmpxlim=xlim;' ...
    'global ax;' ...
    'for i=1:' num2str(length(ax)) ';' ...
    'set(ax(i),''xlim'',tmpxlim);' ...
    'end'];

% Creates and starts the timer. This will execute the above code every 0.1
% seconds
Time=timer('Timerfcn',updatestr,'Period',0.1,'Executionmode','fixedrate');
start(Time);

% Creates a current character, ch, and plot handle p and bp for the inital
% loop.
set(gcf,'CurrentCharacter','a')
ch=0;
p=plot(ax(1),x(1),y1(1));
bp=plot(ax(1),x(1),y1(1));


% Main while loop, will keep executing until and upper case Q is pressed.
while ch~=double('Q')


    % To resolve an bug that was occuring when the shift key was being
    % pressed (or other "non-ascii" key), if the current character is "",
    % set ch to equal 1.
    if strcmp(get(gcf,'CurrentCharacter'),'')
        ch=1;
    else
        % ch is the numeric value of the current character
        ch=double(get(gcf,'CurrentCharacter'));
    end
    
    
%     if ismember(ch,double(['m' 'M']))
%         zoom on
%     end
%     
%     if ismember(ch,double(['p' 'P']))
%         pan on
%     end


    if ismember(ch,double(['d']))
        [gX,gY] = ginput(1)
        set(gcf,'name',['X = ' num2str(gX) '. Y = ' num2str(gY)])
        
        
        pause(1)
        set(gcf,'name',coms,'CurrentCharacter','a')
    end


    % if the current character is a selection value (s, g, b etc)
    if ismember(ch,double(['s' 'g' 'b']))

        %turn off the panning and zooming tools
        pan off
        zoom off


        % code for the rubberband box (see help rbbox)
        k = waitforbuttonpress;
        point1 = get(gca,'CurrentPoint');    % button down detected
        finalRect = rbbox;                   % return figure units
        point2 = get(gca,'CurrentPoint');    % button up detected
        point1 = point1(1,1:2);              % extract x and y
        point2 = point2(1,1:2);
        p1 = min(point1,point2);             % calculate locations
        offset = abs(point1-point2);         % and dimensions

        % Get the axes that the data was selected from
        actax=get(gcf,'currentaxes');


        % as there are a variable number of input datasets, this if
        % statement has been converted into a string, that is evaluated for
        % each of the datasets. The if command basically says any points in
        % the current axes that were selected, have their switch (y1sw etc)
        % changed to the on, off or inverted.

        for i=1:nys

            actstr=['ind=(x>p1(1)&x<p1(1)+offset(1))&(y' num2str(i) '>p1(2)&y' num2str(i) '<p1(2)+offset(2));' char(10) ...
                'if ch==double(''s'')' char(10) ...
                '    y' num2str(i) 'sw(ind)=~y' num2str(i) 'sw(ind);' char(10) ...
                'elseif ch==double(''b'')' char(10) ...
                '    y' num2str(i) 'sw(ind)=1;' char(10) ...
                'elseif ch==double(''g'')' char(10) ...
                '    y' num2str(i) 'sw(ind)=0;' char(10) ...
                'end'];

            if actax==ax(i)
                eval(actstr);
            end
        end

    end

    % If the "C" was pressed, a dialog box is triggered, and any string
    % entered will be evaluated (with a try set of commands to avoid
    % crashing the program if a mistake is entered).

    if ismember(ch,double(['C']))
        inputstr= inputdlg('Enter Command to be evaluated, e.g. y1sw(y1<0.15)=1','Commands',1,{'y1sw(y1<0.05)=1;y2sw(yaux2<0.2)=1;y3sw(yaux3<0.2)=1'})
        try
            eval([inputstr{1} ';']);
        catch
            msgbox([inputstr{1} ' is not a valid command'])
        end
    end


    % Updates all the plots for the change of selection.
    if ismember(ch,double(['s' 'g' 'b' 'C']))

        % first delete original selection off the plot
        try
            delete(p);
            clear p;
        end
        try
            delete(bp);
            clear bp;
        end

        % Create an index for all axes (if any point is bad on any plot,
        % say that all data at that sample is bad).
        totswarr=[];
        for i=1:(nys)
            eval(['totswarr=[totswarr y' num2str(i) 'sw];']);
        end

        totsw=any(totswarr,2);


        % Plot green circles on all axes for bad data irrespective of
        % dataset.
        for i=1:nys
            try
            eval(['p(' num2str(i) ')=plot(ax(' num2str(i) '),x(totsw),y' num2str(i) '(totsw),''go'');']);
            catch
                disp('Didn''t plot')
            end
        end

        % Plot bad data on respective plot as red
        for i=1:nys
            eval(['try' char(10) ...
                '   bp(' num2str(i) ')=plot(ax(' num2str(i) '),x(y' num2str(i) 'sw),y' num2str(i) '(y' num2str(i) 'sw),''r.'');' char(10) ...
                'end']);
        end

        % clear the index and set the current character to its default
        % value, 'a'
        clear ind
        set(gcf,'CurrentCharacter','a')
        
        % Save the current switches, incase the script crashes, the data
        % isn't lost
        save tmpswi.mat y*sw
    end
    pause(0.1)
end

% stop and delete the timer
stop(Time);
delete(Time);


% Prepare the output variables
outputsw=[];
for i=1:nys
    outputsw(:,i)=eval(['y' num2str(i) 'sw']);
end

varargout(1)={outputsw};

% Clear the global ax
clear global ax

clear i

Contact us at files@mathworks.com