Home > bioelectromagnetism > crosshair.m

crosshair

PURPOSE ^

CROSSHAIR: A gui interface for reading (x,y) values from a plot.

SYNOPSIS ^

function [Xpoint,Ypoint,XYhist] = crosshair(action);

DESCRIPTION ^

  CROSSHAIR:  A gui interface for reading (x,y) values from a plot.
  
  [Xpoint,Ypoint,XYhist] = crosshair(action);
  
  A set of mouse driven crosshairs is placed on the current axes,
  and displays the current (x,y) values of the line plot.  There is an
  option to provide data specific values or interpolated values.  The
  resolution of the data specific values depends on both the data
  resolution and the GUI interface (mainly mouse movement resolution).
  The interpolated values appear to provide a more continuous function,
  however they too depend on the GUI interface resolution.  There are 
  no options for extrapolation.
  
  For multiple traces, plots with the same length(xdata) are
  tracked. Each mouse click returns Xpoint,Ypoint values and selecting 
  'done' will remove the GUI and restore the mouse buttons to previous 
  values.  Selecting 'exit' will remove the GUI and close the figure.
  
  In this version (Dec 2002), there are new options to define functions
  of X/Y and monitor their results.  There is also a new STORE button 
  that creates and updates an XYhist struct in the base workspace, which
  contains value labels and values.  This version has better controls 
  of X/Y movements, including better interpolation movement options.  
  This version attempts to respond correctly to keyboard entries also.
  
  Some further help is given in the tool tips of the GUI.

  Note: crosshair always updates the Xpoint,Ypoint in the base 
  workspace. Here is an example of how to get return values within
  a script/function after pressing the exit button of crosshair:
       function [X,Y] = crosshair_returnXY
        x = [1:10]; y(1,:) = sin(x); y(2,:) = cos(x);
        figure; plot(x,y); crosshair;
        uiwait
        X = evalin('base','Xpoint');
        Y = evalin('base','Ypoint');
        return
  Copy this text to a function .m file and then call it from the
  base workspace with [X,Y] = crosshair_returnXY
  
  Useage:  x = [1:10]; y(1,:) = sin(x); y(2,:) = cos(x); x2 = x.^2;
           figure; plot(x2,y); crosshair

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SUBFUNCTIONS ^

SOURCE CODE ^

0001 function [Xpoint,Ypoint,XYhist] = crosshair(action);
0002 %  CROSSHAIR:  A gui interface for reading (x,y) values from a plot.
0003 %
0004 %  [Xpoint,Ypoint,XYhist] = crosshair(action);
0005 %
0006 %  A set of mouse driven crosshairs is placed on the current axes,
0007 %  and displays the current (x,y) values of the line plot.  There is an
0008 %  option to provide data specific values or interpolated values.  The
0009 %  resolution of the data specific values depends on both the data
0010 %  resolution and the GUI interface (mainly mouse movement resolution).
0011 %  The interpolated values appear to provide a more continuous function,
0012 %  however they too depend on the GUI interface resolution.  There are
0013 %  no options for extrapolation.
0014 %
0015 %  For multiple traces, plots with the same length(xdata) are
0016 %  tracked. Each mouse click returns Xpoint,Ypoint values and selecting
0017 %  'done' will remove the GUI and restore the mouse buttons to previous
0018 %  values.  Selecting 'exit' will remove the GUI and close the figure.
0019 %
0020 %  In this version (Dec 2002), there are new options to define functions
0021 %  of X/Y and monitor their results.  There is also a new STORE button
0022 %  that creates and updates an XYhist struct in the base workspace, which
0023 %  contains value labels and values.  This version has better controls
0024 %  of X/Y movements, including better interpolation movement options.
0025 %  This version attempts to respond correctly to keyboard entries also.
0026 %
0027 %  Some further help is given in the tool tips of the GUI.
0028 %
0029 %  Note: crosshair always updates the Xpoint,Ypoint in the base
0030 %  workspace. Here is an example of how to get return values within
0031 %  a script/function after pressing the exit button of crosshair:
0032 %       function [X,Y] = crosshair_returnXY
0033 %        x = [1:10]; y(1,:) = sin(x); y(2,:) = cos(x);
0034 %        figure; plot(x,y); crosshair;
0035 %        uiwait
0036 %        X = evalin('base','Xpoint');
0037 %        Y = evalin('base','Ypoint');
0038 %        return
0039 %  Copy this text to a function .m file and then call it from the
0040 %  base workspace with [X,Y] = crosshair_returnXY
0041 %
0042 %  Useage:  x = [1:10]; y(1,:) = sin(x); y(2,:) = cos(x); x2 = x.^2;
0043 %           figure; plot(x2,y); crosshair
0044 %
0045 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0046 
0047 % Copyright (C) 2002  Darren L. Weber
0048 %
0049 % This program is free software; you can redistribute it and/or
0050 % modify it under the terms of the GNU General Public License
0051 % as published by the Free Software Foundation; either version 2
0052 % of the License, or (at your option) any later version.
0053 %
0054 % This program is distributed in the hope that it will be useful,
0055 % but WITHOUT ANY WARRANTY; without even the implied warranty of
0056 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0057 % GNU General Public License for more details.
0058 %
0059 % You should have received a copy of the GNU General Public License
0060 % along with this program; if not, write to the Free Software
0061 % Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
0062 
0063 %  History: 03/96, Richard G. Cobb <cobbr@plk.af.mil>
0064 %           08/01, Darren.Weber@flinders.edu.au
0065 %                  replaced obsolete 'table1' with 'interp1'; fixed bug
0066 %                  with number of 'traces'; rationalized calculations into
0067 %                  a common subfunction for x,y point calc in 'down','up',
0068 %                  & 'move' button functions; added option to turn on/off
0069 %                  interpolation and the exit button; simplified updates
0070 %                  to graphics using global GUI handle structure.
0071 %           11/01, Darren.Weber@flinders.edu.au
0072 %                  added tooltips for several GUI handles
0073 %                  added multiple interpolation methods
0074 %                  added GUI for data matrix indices (given no interpolation)
0075 %                  added option to select trace nearest to mouse click point
0076 %                  reversed order of lines in data matrix to be consistent
0077 %                    with the value returned from the nearest trace subfunction
0078 %                  create crosshair lines after finding all plot lines to
0079 %                    avoid confusing them with the plot lines
0080 %           01/02, Darren.Weber@flinders.edu.au
0081 %                  should now work across multiple plot figures, given
0082 %                    that all gui handles and data are now stored in the
0083 %                    plot figure 'userdata' handle.
0084 %                  added functionality to move smoothly from interpolation
0085 %                    back to the delimited data via the "next/previous"
0086 %                    buttons.
0087 %           06/02, Darren.Weber@flinders.edu.au
0088 %                  learned how to get values back to a script/function with
0089 %                    evalin command and updated help above.
0090 %           12/02, Darren.Weber@flinders.edu.au
0091 %                  added Store uicontrol and associated XYhist variable
0092 %                   updates in base workspace to provide storage of
0093 %                   consecutive XY values (thanks to C.A.Swenne@lumc.nl &
0094 %                   H.van_de_Vooren@lumc.nl for their suggestion/assistance).
0095 %                  added keyboard controls to left/right arrow and return.
0096 %                  added prev/next X interpolation interval.
0097 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0098 
0099 
0100 
0101 if ~exist('action','var') 
0102     action = 'init';
0103 elseif isempty(action)
0104     action = 'init';
0105 end
0106 
0107 XHR_HANDLES = get(gcbf,'userdata');
0108 
0109 
0110 % Check for specific keys and assign reasonable actions
0111 if strcmp(action, 'keypress'),
0112     
0113     CC = get(XHR_HANDLES.gui,'CurrentCharacter');
0114     cc = double(CC);
0115     if cc,
0116         switch cc,
0117         case 27, action = 'done';  % ESC
0118         case 28, action = 'prevx'; % left
0119         case 29, action = 'nextx'; % right
0120         case 30, action = 'ygt';   % up
0121         case 31, action = 'ylt';   % down
0122         case 13, action = 'store'; % return/enter
0123         otherwise, action = 'up';  % all other keys
0124         end
0125     end
0126 end
0127 
0128 action = lower(action);
0129 
0130 switch action,
0131 
0132 case 'init',
0133     
0134     % Paint GUI
0135     XHR_HANDLES = INIT;
0136     
0137     % Update and return values
0138     XHR_HANDLES = updateDATA(XHR_HANDLES);
0139     Xpoint = get(XHR_HANDLES.xvalue,'Value');
0140     Ypoint = get(XHR_HANDLES.yvalue,'Value');
0141     %updateXYhistory(Xpoint,Ypoint);
0142     
0143 % Mouse Click Down
0144 case 'down',
0145     
0146     set(XHR_HANDLES.gui,'WindowButtonMotionFcn','crosshair(''move'');');
0147     set(XHR_HANDLES.gui,'WindowButtonUpFcn','[Xpoint,Ypoint] = crosshair(''up'');');
0148     
0149     XHR_HANDLES = updateDATA(XHR_HANDLES);
0150     Xpoint = get(XHR_HANDLES.xvalue,'Value');
0151     Ypoint = get(XHR_HANDLES.yvalue,'Value');
0152     %updateXYhistory(Xpoint,Ypoint);
0153     
0154 % Mouse Drag Motion
0155 case 'move',
0156     
0157     XHR_HANDLES = updateDATA(XHR_HANDLES);
0158     Xpoint = get(XHR_HANDLES.xvalue,'Value');
0159     Ypoint = get(XHR_HANDLES.yvalue,'Value');
0160     %updateXYhistory(Xpoint,Ypoint);
0161     
0162 % Mouse Click Up
0163 case 'up',
0164     
0165     set(XHR_HANDLES.gui,'WindowButtonMotionFcn',' ');
0166     set(XHR_HANDLES.gui,'WindowButtonUpFcn',' ');
0167     
0168     XHR_HANDLES = updateDATA(XHR_HANDLES);
0169     Xpoint = get(XHR_HANDLES.xvalue,'Value');
0170     Ypoint = get(XHR_HANDLES.yvalue,'Value');
0171     %updateXYhistory(Xpoint,Ypoint);
0172     
0173 % Next or Previous X point
0174 case {'nextx','prevx','changex','nexty','prevy','changey','ylt','ygt'}, % Change X/Y
0175     
0176     XHR_HANDLES = moveXY(XHR_HANDLES,action);
0177     Xpoint = get(XHR_HANDLES.xvalue,'Value');
0178     Ypoint = get(XHR_HANDLES.yvalue,'Value');
0179     %updateXYhistory(Xpoint,Ypoint);
0180     
0181 % Store XY values into a history array
0182 case 'store',
0183     
0184     Xpoint = get(XHR_HANDLES.xvalue,'Value');
0185     Ypoint = get(XHR_HANDLES.yvalue,'Value');
0186     updateXYhistory(XHR_HANDLES);
0187     
0188 % Exit crosshairs GUI
0189 case {'done','exit'},
0190     
0191     XHR_HANDLES = get(gcbf,'userdata');
0192     
0193     Xpoint = get(XHR_HANDLES.xvalue,'Value');
0194     Ypoint = get(XHR_HANDLES.yvalue,'Value');
0195     %updateXYhistory(Xpoint,Ypoint);
0196     
0197     handles = fieldnames(XHR_HANDLES);
0198     for i=1:length(handles),
0199         switch handles{i},
0200         case {'axis','datalines','gui'},
0201         otherwise,
0202             h = getfield(XHR_HANDLES,handles{i});
0203             if ishandle(h), delete(h); end
0204         end
0205     end
0206     
0207     if strcmp(action,'exit');
0208         if ishandle(XHR_HANDLES.gui),
0209             close(XHR_HANDLES.gui);
0210         end
0211     else
0212         
0213         set(XHR_HANDLES.gui,'WindowButtonUpFcn','');
0214         set(XHR_HANDLES.gui,'WindowButtonMotionFcn','');
0215         set(XHR_HANDLES.gui,'WindowButtonDownFcn',XHR_HANDLES.button);
0216         
0217         refresh(XHR_HANDLES.gui);
0218     end
0219     
0220     clear XHR_HANDLES;
0221     return;
0222     
0223 end
0224 
0225 set(gcf,'userdata',XHR_HANDLES);
0226 if ishandle(XHR_HANDLES.gui),
0227     figure(XHR_HANDLES.gui);
0228 end
0229 
0230 return;
0231 
0232 
0233 
0234 
0235 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0236 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0237 function updateXYhistory(H),
0238     
0239     Ch = get(H.yindex,'Value');
0240     X  = get(H.xvalue,'Value');
0241     Y  = get(H.yvalue,'Value');
0242     fX = get(H.fxvalue,'Value');
0243     fY = get(H.fyvalue,'Value');
0244     
0245     fXeq = get(H.fxeq,'String');
0246     fYeq = get(H.fyeq,'String');
0247     
0248     XY.labels = {'Channel','X','Y',['f(x) = ',fXeq],['f(y) = ',fYeq]};
0249     XY.data   = [Ch,X,Y,fX,fY];
0250     
0251     if evalin('base','exist(''XYhist'',''var'');'),
0252         XYhist = evalin('base','XYhist');
0253         % get the current history set
0254         set = getfield(XYhist,['set',num2str(XYhist.set)]);
0255         if isequal(set.labels,XY.labels),
0256             set.data(end+1,:) = XY.data;
0257             XYhist = setfield(XYhist,['set',num2str(XYhist.set)],set);
0258             assignin('base','XYhist',XYhist);
0259         else
0260             fprintf('\nWarning: creating new set of XYhist in base workspace.\n\n');
0261             XYhist.set = XYhist.set + 1;
0262             XYhist = setfield(XYhist,['set',num2str(XYhist.set)],XY);
0263             assignin('base','XYhist',XYhist);
0264         end
0265     else
0266         XYhist.set = 1;
0267         XYhist.set1 = XY;
0268         assignin('base','XYhist',XYhist);
0269     end
0270     
0271 return
0272 
0273 
0274 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0275 function [H] = moveXY(H,move)
0276     
0277     interp  = get(H.interp,'Value');
0278     xinterp = get(H.xinterp,'Value');
0279     
0280     if (xinterp > 0) & (interp > 1),
0281         
0282         % Use incremental interpolation of x values
0283         switch move,
0284         case 'nexty', H.data.yindex = H.data.yindex + 1;
0285         case 'prevy', H.data.yindex = H.data.yindex - 1;
0286         case 'ygt',
0287             ydata = interpYall(H);
0288             [ysort,yi] = sort(ydata);
0289             currYI = find(ysort > H.data.ypoint);
0290             if min(currYI),
0291                 H.data.yindex = yi(min(currYI));
0292             end
0293         case 'ylt',
0294             ydata = interpYall(H);
0295             [ysort,yi] = sort(ydata);
0296             currYI = find(ysort < H.data.ypoint);
0297             if max(currYI),
0298                 H.data.yindex = yi(max(currYI));
0299             end
0300         case 'nextx',
0301             H.data.xpoint = H.data.xpoint + xinterp;
0302         case 'prevx',
0303             H.data.xpoint = H.data.xpoint - xinterp;
0304         end
0305         H = checkdatarange(H);
0306         H = interpY(H);
0307         updateGUI(H);
0308         return
0309     end
0310     
0311     
0312     % No interpolation of x values...
0313     
0314     if (interp > 1)
0315         xdata = H.data.xdata(:,H.data.yindex);
0316         [H.data.xindex] = NearestXYArrayPoint( xdata, H.data.xpoint, move );
0317     end
0318     
0319     switch move,
0320     case 'nextx',
0321         % Increase current xindex by one
0322         if(interp == 1), H.data.xindex = H.data.xindex + 1; end
0323     case 'prevx',
0324         % Decrease current xindex by one
0325         if(interp == 1), H.data.xindex = H.data.xindex - 1; end
0326     case 'nexty', H.data.yindex = H.data.yindex + 1;
0327     case 'prevy', H.data.yindex = H.data.yindex - 1;
0328     case 'ygt',
0329         ydata = H.data.ydata(H.data.xindex,:);
0330         [ysort,yi] = sort(ydata);
0331         currYI = find(ysort == H.data.ypoint);
0332         if currYI < length(yi),
0333             H.data.yindex = yi(currYI+1);
0334         end
0335     case 'ylt',
0336         ydata = H.data.ydata(H.data.xindex,:);
0337         [ysort,yi] = sort(ydata);
0338         currYI = find(ysort == H.data.ypoint);
0339         if currYI > 1,
0340             H.data.yindex = yi(currYI-1);
0341         end
0342     otherwise
0343     end
0344     
0345     H = checkdatarange(H);
0346     
0347     % Get x/y value at new x/y index
0348     H.data.xpoint = H.data.xdata(H.data.xindex,H.data.yindex);
0349     H.data.ypoint = H.data.ydata(H.data.xindex,H.data.yindex);
0350     
0351     set(H.interp,'Value',1);
0352     H = updateGUI(H);
0353     
0354 return
0355 
0356 
0357 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0358 function [ H ] = checkdatarange(H),
0359 
0360     % Ensure that x/y index is within data range
0361     s = size(H.data.xdata,1);
0362     if( H.data.xindex < 1 ),
0363         H.data.xindex = 1;
0364     elseif( H.data.xindex >= s ),
0365         H.data.xindex = s;
0366     end
0367     s = size(H.data.ydata,2);
0368     if( H.data.yindex < 1 ),
0369         H.data.yindex = 1;
0370     elseif( H.data.yindex >= s ),
0371         H.data.yindex = s;
0372     end
0373 
0374 return
0375 
0376 
0377 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0378 function [ H ] = updateDATA( H )
0379 
0380     % Only update if mouse pointer is in the
0381     % axis limits
0382     set(H.gui,'units','normalized');
0383     axpos = get(H.axis,'position');
0384     figcp = get(H.gui,'Currentpoint');
0385     axlim = axpos(1) + axpos(3);
0386     aylim = axpos(2) + axpos(4);
0387     if or(figcp(1) > (axlim+.01), figcp(1) < (axpos(1)-.01)),
0388         return;
0389     elseif or(figcp(2) > (aylim+.01), figcp(2) < (axpos(2)-.01)),
0390         return;
0391     end
0392     
0393     CurrentPoint  = get(H.axis,'Currentpoint');
0394     H.data.xpoint = CurrentPoint(1,1);
0395     H.data.ypoint = CurrentPoint(1,2);
0396     
0397     doNearTrace   = get(H.traceNearest,'Value');
0398     
0399     if (doNearTrace > 0)
0400         
0401         % Get new yindex for nearest trace
0402         [ H.data.xpoint, ...
0403           H.data.xindex, ...
0404           H.data.ypoint, ...
0405           H.data.yindex ] = NearestXYMatrixPoint( H.data.xdata,...
0406                                                   H.data.ydata,...
0407                                                   H.data.xpoint,...
0408                                                   H.data.ypoint);
0409     else
0410         H.data.yindex = get(H.trace,'Value');
0411     end
0412     
0413     CurrentPoint  = get(H.axis,'Currentpoint');
0414     H.data.xpoint = CurrentPoint(1,1);
0415     H.data.ypoint = CurrentPoint(1,2);
0416     
0417     H = interpY(H);
0418     H = updateGUI(H);
0419 
0420 return
0421 
0422 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0423 function [ H ] = updateGUI( H )
0424 
0425     InterpMethod = get(H.interp,'Value');
0426     if (InterpMethod > 1)
0427         % There is no specific matrix x-index for
0428         % an interpolated point, but the nearest xindex
0429         % is always returned from the interp function below
0430         % so that next/prev move function works correctly
0431         set(H.xindex,'String','interp');
0432     else
0433         set(H.xindex,'String',num2str(H.data.xindex));
0434     end
0435     set(H.xindex,'Value',H.data.xindex);
0436     
0437     tracestr = sprintf('%d',H.data.yindex);
0438     set(H.yindex,'String',tracestr,'Value',uint16(H.data.yindex));
0439     set(H.trace,'Value',uint16(H.data.yindex));
0440     
0441     % Create the crosshair lines on the figure, crossing at the x,y point
0442     x_rng  = get(H.axis,'Xlim');
0443     y_rng  = get(H.axis,'Ylim');
0444     set(H.xline,'Xdata',[H.data.xpoint H.data.xpoint],'Ydata',y_rng);
0445     set(H.yline,'Ydata',[H.data.ypoint H.data.ypoint],'Xdata',x_rng);
0446     
0447     % Update the x,y values displayed for the x,y point
0448     xstring = sprintf('%g',H.data.xpoint);
0449     ystring = sprintf('%g',H.data.ypoint);
0450     set(H.xvalue,'String',xstring,'Value',H.data.xpoint);
0451     set(H.yvalue,'String',ystring,'Value',H.data.ypoint);
0452     
0453     % Calculate the f(x) function
0454     fyeq = get(H.fyeq,'string');
0455     fyval = eval(strrep(fyeq,'y',ystring));
0456     fystr = sprintf('%g',fyval);
0457     set(H.fyvalue,'String',fystr,'Value',fyval);
0458     
0459     % Calculate the f(y) function
0460     fxeq = get(H.fxeq,'string');
0461     fxval = eval(strrep(fxeq,'x',xstring));
0462     fxstr = sprintf('%g',fxval);
0463     set(H.fxvalue,'String',fxstr,'Value',fxval);
0464     
0465 return
0466 
0467 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0468 function [ H ] = interpY( H )
0469     
0470     % In this function, xdata & ydata are arrays, not matrices
0471     xdata = H.data.xdata(:,H.data.yindex);
0472     ydata = H.data.ydata(:,H.data.yindex);
0473     
0474     if      H.data.xpoint >= max(xdata)                
0475             H.data.xpoint  = max(xdata);
0476             H.data.xindex  = find(xdata == max(xdata));
0477             H.data.ypoint  = ydata(H.data.xindex);
0478             return;
0479     elseif  H.data.xpoint <= min(xdata)
0480             H.data.xpoint  = min(xdata);
0481             H.data.xindex  = find(xdata == min(xdata));
0482             H.data.ypoint  = ydata(H.data.xindex);
0483             return;
0484     end
0485     
0486     % 'none|nearest|linear|spline|cubic'
0487     interp = get(H.interp,'Value');
0488     
0489     switch interp
0490     case 1
0491         % Given that xdata & ydata are the same length arrays,
0492         % we can find the ypoint given the nearest xpoint.
0493         [H.data.xindex, H.data.xpoint] = NearestXYArrayPoint( xdata, H.data.xpoint );
0494         H.data.ypoint = ydata(H.data.xindex);
0495     case 2
0496         H.data.ypoint = interp1( xdata, ydata, H.data.xpoint, 'nearest' );
0497     case 3
0498         H.data.ypoint = interp1( xdata, ydata, H.data.xpoint, 'linear' );
0499     case 4
0500         H.data.ypoint = interp1( xdata, ydata, H.data.xpoint, 'spline' );
0501     case 5
0502         H.data.ypoint = interp1( xdata, ydata, H.data.xpoint, 'cubic' );
0503     otherwise
0504         %use default (linear in matlabR12)
0505         H.data.ypoint = interp1( xdata, ydata, H.data.xpoint );
0506     end
0507 
0508 return
0509 
0510 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0511 function [ Yall ] = interpYall( H )
0512     
0513     xdata = H.data.xdata(:,H.data.yindex);
0514     Yall  = H.data.ydata;
0515     
0516     if      H.data.xpoint >= max(xdata),
0517             H.data.xpoint  = max(xdata);
0518             H.data.xindex  = find(xdata == max(xdata));
0519             Yall = ydata(:,H.data.xindex);
0520             return;
0521     elseif  H.data.xpoint <= min(xdata),
0522             H.data.xpoint  = min(xdata);
0523             H.data.xindex  = find(xdata == min(xdata));
0524             Yall = ydata(:,H.data.xindex);
0525             return;
0526     end
0527     
0528     % 'none|nearest|linear|spline|cubic'
0529     interp = get(H.interp,'Value');
0530     
0531     switch interp,
0532     case 1
0533         % do nothing in this case
0534     case 2
0535         Yall = interp1( xdata, Yall, H.data.xpoint, 'nearest' );
0536     case 3
0537         Yall = interp1( xdata, Yall, H.data.xpoint, 'linear' );
0538     case 4
0539         Yall = interp1( xdata, Yall, H.data.xpoint, 'spline' );
0540     case 5
0541         Yall = interp1( xdata, Yall, H.data.xpoint, 'cubic' );
0542     otherwise
0543         %use default (linear in matlabR12)
0544         Yall = interp1( xdata, Yall, H.data.xpoint );
0545     end
0546 
0547 return
0548 
0549 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0550 function [ index, point ] = NearestXYArrayPoint( data_array, point, type )
0551     
0552     if ~exist('type','var') type = ''; end
0553 
0554     % In this function, input data_array is an array, not a matrix.
0555     % This function returns the data point in the array
0556     % that has the closest value to the value given (point).  In
0557     % the context of 'crosshair' the point is a mouse position.
0558     
0559     if      point >= max(data_array)
0560             point  = max(data_array);
0561             index  = find(data_array == point);
0562             return;
0563     elseif  point <= min(data_array)
0564             point  = min(data_array);
0565             index  = find(data_array == point);
0566             return;
0567     end
0568     
0569     data_sorted = sort(data_array);
0570     
0571     greater = find(data_sorted > point);
0572     greater_index = greater(1);
0573     
0574     lesser = find(data_sorted < point);
0575     lesser_index = lesser(length(lesser));
0576     
0577     greater_dif = data_sorted(greater_index) - point;
0578     lesser_dif  = point - data_sorted(lesser_index);
0579     
0580     if strcmp(type,'nextx'),
0581         index = greater_index;
0582     elseif strcmp(type,'prevx'),
0583         index = lesser_index;
0584     else
0585         if (greater_dif < lesser_dif)
0586             index = find(data_array == data_sorted(greater_index));
0587         else
0588             index = find(data_array == data_sorted(lesser_index));
0589         end
0590     end
0591     point = data_array(index);
0592     
0593 return
0594 
0595 
0596 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0597 function [ xpoint, xindex, ypoint, yindex ] = NearestXYMatrixPoint( Xdata, Ydata, xpoint, ypoint )
0598 
0599     % In this function, Xdata & Ydata are matrices of the same dimensions.
0600     % This function attempts to find the nearest values in Xdata & Ydata
0601     % to the mouse position (xpoint, ypoint).
0602     
0603     % It is assumed that Xdata has identical columns, so we only really
0604     % need the first column to find the nearest value to xpoint.
0605     
0606     [ xindex, xpoint ] = NearestXYArrayPoint( Xdata(:,1), xpoint );
0607     
0608     % Now, given the xpoint, we can select just that row of the
0609     % Ydata matrix corresponding to the xpoint.
0610     ydata = Ydata(xindex,:);
0611     
0612     % The ydata array is searched in same manner as the xdata
0613     % array for the nearest value.
0614     [ yindex, ypoint ] = NearestXYArrayPoint( ydata, ypoint );
0615     
0616 return
0617 
0618 
0619 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0620 function [H] = INIT
0621 
0622     H.gui  = gcf; % Get current figure handles
0623     H.axis = gca; % Get current axis handles
0624     
0625     H.axis = gca; % Get current axis handles
0626     H.ylim = get(H.axis,'ylim');
0627     
0628     % store current button fcn
0629     H.button = get(H.gui,'WindowButtonDownFcn');
0630     % set XHR button down fcn
0631     set(H.gui,'WindowButtonDownFcn','crosshair(''down'');');
0632     set(H.gui,'KeyPressFcn','crosshair(''keypress'');');
0633     
0634     % Match background figure colour
0635     bgcolor = get(H.gui,'Color');
0636     % Try to adapt the foreground colour a little
0637     black = find(bgcolor <= .6);
0638     fgcolor = [0 0 0]; %black text
0639     if length(black)>2, fgcolor = [1 1 1]; end
0640     
0641     
0642     Font.FontName   = 'Helvetica';
0643     Font.FontUnits  = 'Pixels';
0644     Font.FontSize   = 10;
0645     Font.FontWeight = 'normal';
0646     Font.FontAngle  = 'normal';
0647     
0648     H.yflip       =   uicontrol(H.gui,'Style','pushbutton','Units','Normalized',Font,...
0649                               'Position',[.00 .70 .08 .05],...
0650                               'Tag','YFLIP',...
0651                               'TooltipString','Flip Y Axis', ...
0652                               'String','Flip',...
0653                               'Callback',strcat('XHR = get(gcbf,''userdata'');',...
0654                                                 'ydir = get(XHR.axis,''YDir'');',...
0655                                                 'if isequal(ydir,''normal''),',...
0656                                                 '   set(XHR.axis,''YDir'',''reverse'');',...
0657                                                 'else,',...
0658                                                 '   set(XHR.axis,''YDir'',''normal'');',...
0659                                                 'end;',...
0660                                                 'set(gcbf,''userdata'',XHR); figure(XHR.gui); clear XHR;'));
0661     
0662     H.yreset      =   uicontrol(H.gui,'Style','pushbutton','Units','Normalized',Font,...
0663                               'Position',[.00 .65 .08 .05],...
0664                               'Tag','YRESET',...
0665                               'TooltipString','Reset Axis Limits', ...
0666                               'String','Reset',...
0667                               'Callback',strcat('XHR = get(gcbf,''userdata'');',...
0668                                                 'XHR.ylim = get(XHR.axis,''ylim'');',...
0669                                                 'set(XHR.ymin,''string'',sprintf(''%g'',XHR.ylim(1)));',...
0670                                                 'set(XHR.ymax,''string'',sprintf(''%g'',XHR.ylim(2)));',...
0671                                                 'set(gcbf,''userdata'',XHR); figure(XHR.gui); clear XHR;'));
0672     
0673     H.ymin        =   uicontrol(H.gui,'Style','edit','Units','Normalized',Font,...
0674                               'Position',[.00 .60 .08 .05],...
0675                               'HorizontalAlign','left',...
0676                               'Tag','YMIN',...
0677                               'TooltipString','Set Y min', ...
0678                               'String',sprintf('%g',H.ylim(1)),...
0679                               'Callback',strcat('XHR = get(gcbf,''userdata'');',...
0680                                                 'ymin = str2num(get(XHR.ymin,''string''));',...
0681                                                 'XHR.ylim(1) = ymin;',...
0682                                                 'set(XHR.axis,''ylim'',XHR.ylim);',...
0683                                                 'set(XHR.ymin,''string'',sprintf(''%g'',XHR.ylim(1)));',...
0684                                                 'set(gcbf,''userdata'',XHR); figure(XHR.gui); clear XHR ymin;'));
0685     
0686     H.ymax        =   uicontrol(H.gui,'Style','edit','Units','Normalized',Font,...
0687                               'Position',[.00 .55 .08 .05],...
0688                               'HorizontalAlign','left',...
0689                               'Tag','YMAX',...
0690                               'TooltipString','Set Y max', ...
0691                               'String',sprintf('%g',H.ylim(2)),...
0692                               'Callback',strcat('XHR = get(gcbf,''userdata'');',...
0693                                                 'ymax = str2num(get(XHR.ymax,''string''));',...
0694                                                 'XHR.ylim(2) = ymax;',...
0695                                                 'set(XHR.axis,''ylim'',XHR.ylim);',...
0696                                                 'set(XHR.ymax,''string'',sprintf(''%g'',XHR.ylim(2)));',...
0697                                                 'set(gcbf,''userdata'',XHR); figure(XHR.gui); clear XHR ymax;'));
0698     
0699     H.grid        =   uicontrol(H.gui,'Style','checkbox','Units','Normalized',Font,...
0700                               'Position',[.00 .50 .08 .05],...
0701                               'BackgroundColor',bgcolor,'ForegroundColor',fgcolor,...
0702                               'Tag','GRID',...
0703                               'TooltipString','Toggle plot grid on/off.', ...
0704                               'String','grid',...
0705                               'Callback',strcat('XHR = get(gcbf,''userdata'');',...
0706                                                 'grid(XHR.axis);',...
0707                                                 'set(gcbf,''userdata'',XHR); figure(XHR.gui); clear XHR;'));
0708     
0709     H.xvalue      = uicontrol(H.gui,'Style','edit','Units','Normalized',Font,...
0710                               'Position',[.13 .95 .15 .05],...
0711                               'BackGroundColor',[ 0 .9 0],'ForeGroundColor',[ 0 0 0],...
0712                               'Tag','XVALUE',...
0713                               'TooltipString','X value (Read Only)',...
0714                               'String',' ');
0715     H.yvalue      = uicontrol(H.gui,'Style','edit','Units','Normalized',Font,...
0716                               'Position',[.28 .95 .15 .05],...
0717                               'BackGroundColor',[ 0 0 .9],'ForeGroundColor',[ 1 1 1],...
0718                               'Tag','YVALUE',...
0719                               'TooltipString','Y value (Read Only)',...
0720                               'String',' ');
0721     
0722     
0723     H.fxeq        = uicontrol('Style','edit','Units','Normalized',...
0724                               'Position',[.45 .95 .10 .05],...
0725                               'Tag','FXDEFINE',...
0726                               'TooltipString','Define f(x) equation here',...
0727                               'BackGroundColor',[ 0 .9 0],...
0728                               'ForeGroundColor',[ 0 0 0],'String','x');
0729     H.fxvalue     = uicontrol('Style','edit','Units','Normalized',...
0730                               'Position',[.55 .95 .15 .05],...
0731                               'Tag','FYVALUE',...
0732                               'TooltipString','f(x) result',...
0733                               'BackGroundColor',[ 0 .9 0],...
0734                               'ForeGroundColor',[ 0 0 0],'String',' ');
0735     
0736     H.fyeq        = uicontrol('Style','edit','Units','Normalized',...
0737                               'Position',[.70 .95 .10 .05],...
0738                               'Tag','FYDEFINE',...
0739                               'TooltipString','Define f(y) equation here',...
0740                               'BackGroundColor',[ 0 0 .9],...
0741                               'ForeGroundColor',[ 1 1 1],'String','y');
0742     H.fyvalue     = uicontrol('Style','edit','Units','Normalized',...
0743                               'Position',[.80 .95 .15 .05],...
0744                               'Tag','FYVALUE',...
0745                               'TooltipString','f(y) result',...
0746                               'BackGroundColor',[ 0 0 .9],...
0747                               'ForeGroundColor',[ 1 1 1],'String',' ');
0748                               
0749     H.yindex      = uicontrol('Style','edit','Units','Normalized',Font,...
0750                               'Position',[.92 .87 .08 .05],...
0751                               'BackGroundColor',[ 0 0 .9],'ForeGroundColor',[ 1 1 1],...
0752                               'Tag','YINDEX',...
0753                               'TooltipString','Enter Y index into plot data matrix.  Same as trace number.',...
0754                               'String','1',...
0755                               'Value',1,...
0756                               'Callback',strcat('H = get(gcbf,''userdata'');',...
0757                                                 'yi = str2num(get(H.yindex,''String''));',...
0758                                                 'H.data.yindex = yi;',...
0759                                                 'set(H.gui,''userdata'',H); clear H yi; ',...
0760                                                 '[Xpoint,Ypoint] = crosshair(''changey'');'));
0761     H.yprev       = uicontrol('Style','Push','Units','Normalized',Font,...
0762                               'Position',[.92 .82 .04 .05],...
0763                               'String','<',...
0764                               'Tag','YPREV',...
0765                               'TooltipString','Goto Previous Y Index (channel).',...
0766                               'CallBack','[Xpoint,Ypoint] = crosshair(''prevy'');');
0767     H.ynext       = uicontrol('Style','Push','Units','Normalized',Font,...
0768                               'Position',[.96 .82 .04 .05],...
0769                               'String','>',...
0770                               'Tag','YNEXT',...
0771                               'TooltipString','Goto Next Y Index (channel).',...
0772                               'CallBack','[Xpoint,Ypoint] = crosshair(''nexty'');');
0773     H.yLT         = uicontrol('Style','Push','Units','Normalized',Font,...
0774                               'Position',[.92 .77 .04 .05],...
0775                               'String','LT',...
0776                               'Tag','YLT',...
0777                               'TooltipString','Goto next Y Less Than current Y.',...
0778                               'CallBack','[Xpoint,Ypoint] = crosshair(''yLT'');');
0779     H.yGT         = uicontrol('Style','Push','Units','Normalized',Font,...
0780                               'Position',[.96 .77 .04 .05],...
0781                               'String','GT',...
0782                               'Tag','YGT',...
0783                               'TooltipString','Goto next Y Greater Than current Y.',...
0784                               'CallBack','[Xpoint,Ypoint] = crosshair(''yGT'');');
0785     
0786     H.xindex      = uicontrol('Style','edit','Units','Normalized',Font,...
0787                               'Position',[.92 .70 .08 .05],...
0788                               'BackGroundColor',[ 0 .9 0],'ForeGroundColor',[ 0 0 0],...
0789                               'Tag','XINDEX',...
0790                               'TooltipString','Enter X index into plot data matrix.  Only available for interpolation = ''none''.',...
0791                               'String','1',...
0792                               'Value',1,...
0793                               'Callback',strcat('XHR = get(gcbf,''userdata'');',...
0794                                                 'xi = str2num(get(XHR.xindex,''String''));',...
0795                                                 'XHR.data.xindex = xi;',...
0796                                                 'set(XHR.xinterp,''value'',0); ',...
0797                                                 'set(XHR.xinterp,''string'',''0''); ',...
0798                                                 'set(XHR.interp, ''value'',1); ',...
0799                                                 'set(XHR.gui,''userdata'',XHR); clear XHR; ',...
0800                                                 '[Xpoint,Ypoint] = crosshair(''changex'');'));
0801     H.xprev       = uicontrol('Style','Push','Units','Normalized',Font,...
0802                               'Position',[.92 .65 .04 .05],...
0803                               'String','<',...
0804                               'Tag','XPREV',...
0805                               'TooltipString','Goto Previous X Index (no interpolation).',...
0806                               'CallBack','[Xpoint,Ypoint] = crosshair(''prevx'');');
0807     H.xnext       = uicontrol('Style','Push','Units','Normalized',Font,...
0808                               'Position',[.96 .65 .04 .05],...
0809                               'String','>',...
0810                               'Tag','XNEXT',...
0811                               'TooltipString','Goto Next X Index (no interpolation).',...
0812                               'CallBack','[Xpoint,Ypoint] = crosshair(''nextx'');');
0813     
0814     H.xinterp     = uicontrol('Style','Edit','Units','Normalized',...
0815                               'Position',[.92 .60 .08 .05],...
0816                               'String','0',...
0817                               'Value',0,....
0818                               'Tag','XINTERP',...
0819                               'TooltipString','Interpolation X increment (zero = nearest X).',...
0820                               'Callback',strcat('XHR = get(gcf,''userdata''); ',...
0821                                                 'xint = str2num(get(XHR.xinterp,''string'')); ',...
0822                                                 'set(XHR.xinterp,''value'',xint); figure(XHR.gui); clear XHR; '));
0823                                             
0824     interpstr     =   'none|nearest|linear|spline|cubic';
0825     H.interp      =   uicontrol('Style','popup','Units','Normalized',Font,...
0826                               'Position',[.92 .55 .08 .05],...
0827                               'Tag','INTERP',...
0828                               'TooltipString','INTERP1 methods (none = raw values).', ...
0829                               'String',interpstr,...
0830                               'Callback',strcat('XHR = get(gcbf,''userdata'');',...
0831                                                 'xint = get(XHR.xinterp,''Value''); ',...
0832                                                 'if xint == 0, ',...
0833                                                 '   xint = 0.5; ',...
0834                                                 '   set(XHR.xinterp,''value'',xint); ',...
0835                                                 '   set(XHR.xinterp,''string'',num2str(xint)); ',...
0836                                                 '   set(XHR.xindex, ''string'',''interp''); ',...
0837                                                 'end; ',...
0838                                                 'set(XHR.gui,''userdata'',XHR); figure(XHR.gui); clear XHR; '));
0839     
0840     H.store       = uicontrol('Style','Push','Units','Normalized',...
0841                               'Position',[.92 .40 .08 .05],...
0842                               'String','Store',...
0843                               'Tag','STORE',...
0844                               'TooltipString','Store current Channel & XY values into base XYhist array.', ...
0845                               'CallBack','crosshair(''store'');');
0846                           
0847     H.done        = uicontrol('Style','Push','Units','Normalized',...
0848                               'Position',[.80 .00 .10 .05],...
0849                               'BackgroundColor',[.8 .5 0],...
0850                               'ForegroundColor',[1 1 1],...
0851                               'FontWeight','bold',...
0852                               'String','Done',...
0853                               'Tag','DONE',...
0854                               'TooltipString','Close crosshair', ...
0855                               'CallBack','crosshair(''done'');');
0856     H.exit        = uicontrol('Style','Push','Units','Normalized',...
0857                               'Position',[.90 .00 .10 .05],...
0858                               'BackgroundColor',[.8 0 0],...
0859                               'ForegroundColor',[1 1 1],...
0860                               'FontWeight','bold',...
0861                               'String','Exit',...
0862                               'Tag','EXIT',...
0863                               'TooltipString','Close crosshair and Figure', ...
0864                               'CallBack','crosshair(''exit'');');
0865                           
0866     %%%%%%%%%%%%%%%%%%%%%%%%%
0867     % Get Line Data from Plot
0868     
0869     % Lines are referenced as axis children, among other
0870     % axis children; so first get all axis children
0871     sibs = get(H.axis,'Children');
0872     
0873     % Now search axis children for any line types.
0874     % Because the columns of the y data matrix in a plot
0875     % command seem to be reversed in the axis children,
0876     % count down from max sibs to the first sib.
0877     lines = 0;
0878     H.data.xdata = [];
0879     H.data.ydata = [];
0880     H.data.xpoint = [];
0881     H.data.ypoint = [];
0882     H.data.xindex = 1;
0883     H.data.yindex = 1;
0884     i = max(size(sibs));
0885     while i >= 1
0886         if strcmp(get(sibs(i),'Type'),'line')
0887             
0888             % OK, found a line among the axis children.
0889             lines = lines + 1;
0890             
0891             % put line data into a column of DATA.xdata|DATA.ydata
0892             H.data.xdata(:,lines) = get(sibs(i),'XData').';
0893             H.data.ydata(:,lines) = get(sibs(i),'YData').';
0894         end
0895         i = i - 1;
0896     end
0897     
0898     % 'traces' string variable must be in ascending order
0899     traces  = '';
0900     i = 1;
0901     while i <= lines;
0902         if i < lines
0903             tracelabel = sprintf('Column %4d|',i);            
0904         else
0905             tracelabel = sprintf('Column %4d',i);
0906         end
0907         traces = strcat(traces,tracelabel);
0908         i = i + 1;
0909     end
0910     
0911     % If more than one line, provide GUI for line selection
0912     
0913     % Switch off||on Trace Selection GUI
0914     Vis = 'Off';
0915     if lines > 1,
0916         Vis = 'On';
0917     elseif lines == 0
0918         error('No lines found in the current plot window\n');
0919     end
0920     
0921     % Create Trace Index GUI
0922     H.traceLabel   = uicontrol('Style','Edit', 'Units','Normalized',...
0923                                'Position',[.00 .00 .15 .05],...
0924                                'Tag','TRACELABEL',...
0925                                'Visible',Vis,'String','Select Trace :',...
0926                                'TooltipString','Select trace to follow with crosshairs.');
0927     H.trace        = uicontrol('Style','Popup','Units','Normalized',...
0928                                'Position',[.15 .00 .20 .05],...
0929                                'Tag','TRACESWITCH',...
0930                                'BackGroundColor','w','String',traces,...
0931                                'Visible',Vis,...
0932                                'CallBack','crosshair(''up'');');
0933     H.traceNearest = uicontrol('Style','checkbox', 'Units','Normalized',...
0934                                'Position',[.36 .00 .19 .05],...
0935                                'BackgroundColor',bgcolor,'ForegroundColor',fgcolor,...
0936                                'Tag','TRACENEAREST',...
0937                                'Visible',Vis,'String','Nearest Trace','Value',1,...
0938                                'TooltipString','Trace nearest to mouse click; switch off to keep trace constant.');
0939     
0940     
0941     % Set X,Y cross hair lines
0942     % Do this after finding all the line axis children
0943     % to avoid confusing these lines with those of the
0944     % plot itself (counted above).
0945     x_rng = get(H.axis,'Xlim');
0946     y_rng = get(H.axis,'Ylim');
0947     H.xline = line(x_rng,[y_rng(1) y_rng(1)]);
0948     H.yline = line(x_rng,[y_rng(1) y_rng(1)]);
0949     set(H.xline,'Color','r','EraseMode','xor','Tag','XLINE');
0950     set(H.yline,'Color','r','EraseMode','xor','Tag','YLINE');
0951     
0952 return

Generated on Mon 15-Aug-2005 15:36:19 by m2html © 2003