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