Home > vbmeg > functions > gui > vb_data_pick_tool.m

vb_data_pick_tool

PURPOSE ^

selectdata: graphical selection of data points on a plot using the mouse

SYNOPSIS ^

function [pointslist,xselect,yselect] = vb_data_pick_tool(varargin)

DESCRIPTION ^

 selectdata: graphical selection of data points on a plot using the mouse
 usage: pointslist = vb_data_pick_tool         % uses all default options
 usage: pointslist = vb_data_pick_tool(prop1,val1,prop2,val2,...)

 vb_data_pick_tool allows the user to select data points on a given plot
 using the mouse, in a variety of modes. 'Lasso' mode allows the
 selection by a user directed lasso around the points. 'Brush' mode
 selects points as you brush over them with the mouse. 'Rect' mode
 draws a rectangle, selecting any points inside the rectangle.
 'Closest' mode looks for a aingle mouse click, finding the closest
 point to the mouse.

 Returned is a list of the point indexes selected, additionally you
 can specify that the points be deleted from the plot.

 Arguments: (input)
  The input arguments to vb_data_pick_tool are all property/value pairs.
  (See PARSE_PV_PAIRS for more details.)
  http://www.mathworks.com/matlabcentral/fileexchange/loadFile.do?objectId=9082&objectType=FILE
 
  Property names and character values can be shortened as long as
  the shortening is unambiguous. Capitalization is ignored.

  Valid Properties: 'Action', 'Axes', 'BrushSize', 'Identify',
           'Ignore' , 'Pointer', 'SelectionMode'

  'Action' - {'list', 'delete'}
           'delete' causes the selected points to be deleted from
           the figure after their selection is final.

           DEFAULT VALUE: 'List'

  'Axes' - denotes the axes from which to select points

           DEFAULT VALUE: gca
  
  'BrushShape' - {'rect', 'circle'}

           DEFAULT VALUE: 'circle'

           Sets the shape of the brush to be used. Both brush
           shapes are relative to the figure axes, so a nominally
           "circular" brush is actually elliptical if the axis
           units/lengths are unequal.

           Only used when SelectionMode is 'brush'.

  'BrushSize' - Only used when SelectionMode is 'brush'.

           DEFAULT VALUE: 0.05

           The default value will specify a rectangular brush
           that has dimensions of 5% of the current axes. Note
           that on a set of square axes, the brush will always
           look square, even if the axes have very different
           units.

           0 < brushsize <= 0.25

  'Identify' - {'on', 'off'}
           Causes the selected points to be temporarily over-plotted
           with a new filled red marker ('o') as they are selected.

           Points selected with a lasso, or rect may be deselected
           as the tool is modified. Brush selections are cumulative.

           DEFAULT VALUE: 'on'

  'Ignore' - a data handle, or []

           A list of data handles to be ignored. This allows you to
           use selectdata on only some sets of points, while others
           in the same figure are ignored. This is a useful option
           when you may have plotted some data points but also a
           curve fit through your data. You can then cause the plotted
           curve to be ignored by selectdata.

           DEFAULT VALUE: []

  'Target' - a data handle
           A list of data handles of target.

  'Label' - {'off', 'on'}

           Causes text labels with their (x,y) coordinates to appear
           next to each point selected.

           Beware that selecting large numbers of points and creating
           and displaying the label for them can be time consuming.
           This option is a great one for single point selection,
           but I have seen system-related problems when rapidly
           selecting & deselecting large numbers of points with the
           rect tool.

           DEFAULT VALUE: 'off'

  'Pointer' - {'crosshair' | 'fullcrosshair' | 'arrow' | 'ibeam' |
           'watch' | 'topl' | 'topr' | 'botl' | 'botr' | 'left' |
           'top' | 'right' | 'bottom' | 'circle' | 'cross' | 'fleur' |
           'hand' }

           Changes the cursor pointer while selection is active.
           After selection terminates, the figure pointer is
           restored to its old setting.

           DEFAULT VALUE: 'crosshair'

  'Return' - {'selected' | 'unselected' }

           Selection of data points, perhaps if used to indicate
           outliers in data, would normally return that set of 
           points selected. But some users may prefer to see the
           list of points returned to be those points which were
           NOT selected.

           DEFAULT VALUE: 'selected'

  'SelectionMode' - {'Lasso', 'Brush', 'Rect', 'Closest'}

           DEFAULT VALUE: 'Lasso'

           If 'Brush' is used, then the brush will be a rectangular
           brush, with a size as defined by the 'BrushSize' property. 
           The brush will be centered at the current mouse coordinates.
           Brush size will be a fraction of the axis limits for the
           current axes. Click inside the axes, then drag the "brush"
           around. Any points the brush crosses over will be selected.

           If 'Lasso' is chosen, then click inside the axes to define
           one end of the lasso, then drag with the mouse still down,
           causing the mouse to define a general curvilinear region.
           The polygon will close automatically when the mouse button
           is released. A point is "inside" the lasso if inpolygon
           identifies it as so. BEWARE of convoluted lassos that
           intersect themselves.

           If 'Rect' is chosen, then click inside the axes to define
           one corner of the rect, dragging to specify the opposite
           corner, just as rbbox would do.

           If 'Closest' was chosen, then a single mouse click in the
           figure window is used, then that point which is closest in
           in Euclidean distance (in window units) is chosen. You
           can move the cursor around (don't release the mouse until
           you are done) and the currently selected point will be
           highlighted.

  'Verify' - { 'off' | 'on' }

           If set to 'on', this causes a dialog box to pop up after
           selection. The user can then acccept the selection, redo
           it, or cancel out, causing no points to be selected.

           Note, if cancel is chosen from the dialog, and 'return'
           was specify to return those points 'unselected', then ALL
           the points will actually be returned.

           DEFAULT VALUE: 'off'


 Note: other properties are available for use, but I've chosen to
 leave them semi-hidden because they don't seem terribly useful to
 most users. These properties allow you to specify the colors of the
 selection tool itself, the colors of the selected point markers,
 the transparency of the selection tool, the marker itself, etc.
 Default values for these parameters are:

           FlagMarker    = 'o'
           FlagColor     = 'r'
           Fill          = 'on'
           FillColor     = 'y'
           FillEdgeColor = 'b'
           FillTrans     = 0.5
           MaxBrush      = 0.25
           RemoveTool    = 'on'
           RemoveFlagged = 'on'
           RemoveLabels  = 'on'

 Further documentation on these parameters can be found by editting
 selectdata.m itself.


 Arguments: (output)
  pointslist - list of points that were selected. If only one
           dataset was found, then points list is a simple vector.
           If multiple sets of points were found in the axes, then
           points list will be a cell array.

           NOTE: Each set of points is peeled off the stach in the
           matlab stores it.

  xselect - array (or cell array) containing the x coordinates of
           those points identified in the selection

  yselect - array (or cell array) containing the y coordinates of
           those points identified in the selection


 Example:
  Plot a set of points, then select some with the mouse
  using a rectangular brush, return the indices of those
  points selected. (Note: user interaction on the plot
  will be necessary.)

    x = 0:.1:1;
    y = x.^2;
    h = plot(x,y,'o')
    waitforbuttonpress;
    pl = vb_data_pick_tool('selectionmode','brush', 'Target', h);
  
 Example:
  Select a single point with the mouse, then delete that
  selected point from the plot.

    pl = vb_data_pick_tool('selectionmode','closest','action','delete');

 Example:
  Select some points using a rect(rbbox) tool, also return
  the (x,y) coordinates from multiple curves plotted. Use
  shortened versions of the properties and values.
  
    h = plot(rand(5,2),rand(5,2),'o');
    waitforbuttonpress;
    [pl,xs,ys] = vb_data_pick_tool('sel','r', 'Target', h);
  
 Example:
  Plot a curve and some data points on one plot, select
  some points from the data plotted, but ignore the
  smooth curve, even if the lasso passes over it.
    x = 0:.01:1;
    y = exp(x);
    ynoisy = y + randn(size(y))/2;
    h1 = plot(x,y,'-');
    hold on
    h2 = plot(x,ynoisy,'o');
    waitforbuttonpress;
    [pl,xs,ys] = vb_data_pick_tool('sel','lasso','Target',h2);

 See also:


 Author: John D'Errico
 E-mail: woodchips@rochester.rr.com
 Release: 3.0
 Release date: 2/19/07

 Copyright (c) 2007, John D'Errico
 All rights reserved.

 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are
 met:

     * Redistributions of source code must retain the above copyright
       notice, this list of conditions and the following disclaimer.
     * Redistributions in binary form must reproduce the above copyright
       notice, this list of conditions and the following disclaimer in
       the documentation and/or other materials provided with the distribution

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 POSSIBILITY OF SUCH DAMAGE.

 [History]
   2016-02-01 rhayashi Added some options and not to use waitforbuttonpress

 [Note]
   Please specify 'Target' option implicitly.

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SUBFUNCTIONS ^

SOURCE CODE ^

0001 function [pointslist,xselect,yselect] = vb_data_pick_tool(varargin)
0002 % selectdata: graphical selection of data points on a plot using the mouse
0003 % usage: pointslist = vb_data_pick_tool         % uses all default options
0004 % usage: pointslist = vb_data_pick_tool(prop1,val1,prop2,val2,...)
0005 %
0006 % vb_data_pick_tool allows the user to select data points on a given plot
0007 % using the mouse, in a variety of modes. 'Lasso' mode allows the
0008 % selection by a user directed lasso around the points. 'Brush' mode
0009 % selects points as you brush over them with the mouse. 'Rect' mode
0010 % draws a rectangle, selecting any points inside the rectangle.
0011 % 'Closest' mode looks for a aingle mouse click, finding the closest
0012 % point to the mouse.
0013 %
0014 % Returned is a list of the point indexes selected, additionally you
0015 % can specify that the points be deleted from the plot.
0016 %
0017 % Arguments: (input)
0018 %  The input arguments to vb_data_pick_tool are all property/value pairs.
0019 %  (See PARSE_PV_PAIRS for more details.)
0020 %  http://www.mathworks.com/matlabcentral/fileexchange/loadFile.do?objectId=9082&objectType=FILE
0021 %
0022 %  Property names and character values can be shortened as long as
0023 %  the shortening is unambiguous. Capitalization is ignored.
0024 %
0025 %  Valid Properties: 'Action', 'Axes', 'BrushSize', 'Identify',
0026 %           'Ignore' , 'Pointer', 'SelectionMode'
0027 %
0028 %  'Action' - {'list', 'delete'}
0029 %           'delete' causes the selected points to be deleted from
0030 %           the figure after their selection is final.
0031 %
0032 %           DEFAULT VALUE: 'List'
0033 %
0034 %  'Axes' - denotes the axes from which to select points
0035 %
0036 %           DEFAULT VALUE: gca
0037 %
0038 %  'BrushShape' - {'rect', 'circle'}
0039 %
0040 %           DEFAULT VALUE: 'circle'
0041 %
0042 %           Sets the shape of the brush to be used. Both brush
0043 %           shapes are relative to the figure axes, so a nominally
0044 %           "circular" brush is actually elliptical if the axis
0045 %           units/lengths are unequal.
0046 %
0047 %           Only used when SelectionMode is 'brush'.
0048 %
0049 %  'BrushSize' - Only used when SelectionMode is 'brush'.
0050 %
0051 %           DEFAULT VALUE: 0.05
0052 %
0053 %           The default value will specify a rectangular brush
0054 %           that has dimensions of 5% of the current axes. Note
0055 %           that on a set of square axes, the brush will always
0056 %           look square, even if the axes have very different
0057 %           units.
0058 %
0059 %           0 < brushsize <= 0.25
0060 %
0061 %  'Identify' - {'on', 'off'}
0062 %           Causes the selected points to be temporarily over-plotted
0063 %           with a new filled red marker ('o') as they are selected.
0064 %
0065 %           Points selected with a lasso, or rect may be deselected
0066 %           as the tool is modified. Brush selections are cumulative.
0067 %
0068 %           DEFAULT VALUE: 'on'
0069 %
0070 %  'Ignore' - a data handle, or []
0071 %
0072 %           A list of data handles to be ignored. This allows you to
0073 %           use selectdata on only some sets of points, while others
0074 %           in the same figure are ignored. This is a useful option
0075 %           when you may have plotted some data points but also a
0076 %           curve fit through your data. You can then cause the plotted
0077 %           curve to be ignored by selectdata.
0078 %
0079 %           DEFAULT VALUE: []
0080 %
0081 %  'Target' - a data handle
0082 %           A list of data handles of target.
0083 %
0084 %  'Label' - {'off', 'on'}
0085 %
0086 %           Causes text labels with their (x,y) coordinates to appear
0087 %           next to each point selected.
0088 %
0089 %           Beware that selecting large numbers of points and creating
0090 %           and displaying the label for them can be time consuming.
0091 %           This option is a great one for single point selection,
0092 %           but I have seen system-related problems when rapidly
0093 %           selecting & deselecting large numbers of points with the
0094 %           rect tool.
0095 %
0096 %           DEFAULT VALUE: 'off'
0097 %
0098 %  'Pointer' - {'crosshair' | 'fullcrosshair' | 'arrow' | 'ibeam' |
0099 %           'watch' | 'topl' | 'topr' | 'botl' | 'botr' | 'left' |
0100 %           'top' | 'right' | 'bottom' | 'circle' | 'cross' | 'fleur' |
0101 %           'hand' }
0102 %
0103 %           Changes the cursor pointer while selection is active.
0104 %           After selection terminates, the figure pointer is
0105 %           restored to its old setting.
0106 %
0107 %           DEFAULT VALUE: 'crosshair'
0108 %
0109 %  'Return' - {'selected' | 'unselected' }
0110 %
0111 %           Selection of data points, perhaps if used to indicate
0112 %           outliers in data, would normally return that set of
0113 %           points selected. But some users may prefer to see the
0114 %           list of points returned to be those points which were
0115 %           NOT selected.
0116 %
0117 %           DEFAULT VALUE: 'selected'
0118 %
0119 %  'SelectionMode' - {'Lasso', 'Brush', 'Rect', 'Closest'}
0120 %
0121 %           DEFAULT VALUE: 'Lasso'
0122 %
0123 %           If 'Brush' is used, then the brush will be a rectangular
0124 %           brush, with a size as defined by the 'BrushSize' property.
0125 %           The brush will be centered at the current mouse coordinates.
0126 %           Brush size will be a fraction of the axis limits for the
0127 %           current axes. Click inside the axes, then drag the "brush"
0128 %           around. Any points the brush crosses over will be selected.
0129 %
0130 %           If 'Lasso' is chosen, then click inside the axes to define
0131 %           one end of the lasso, then drag with the mouse still down,
0132 %           causing the mouse to define a general curvilinear region.
0133 %           The polygon will close automatically when the mouse button
0134 %           is released. A point is "inside" the lasso if inpolygon
0135 %           identifies it as so. BEWARE of convoluted lassos that
0136 %           intersect themselves.
0137 %
0138 %           If 'Rect' is chosen, then click inside the axes to define
0139 %           one corner of the rect, dragging to specify the opposite
0140 %           corner, just as rbbox would do.
0141 %
0142 %           If 'Closest' was chosen, then a single mouse click in the
0143 %           figure window is used, then that point which is closest in
0144 %           in Euclidean distance (in window units) is chosen. You
0145 %           can move the cursor around (don't release the mouse until
0146 %           you are done) and the currently selected point will be
0147 %           highlighted.
0148 %
0149 %  'Verify' - { 'off' | 'on' }
0150 %
0151 %           If set to 'on', this causes a dialog box to pop up after
0152 %           selection. The user can then acccept the selection, redo
0153 %           it, or cancel out, causing no points to be selected.
0154 %
0155 %           Note, if cancel is chosen from the dialog, and 'return'
0156 %           was specify to return those points 'unselected', then ALL
0157 %           the points will actually be returned.
0158 %
0159 %           DEFAULT VALUE: 'off'
0160 %
0161 %
0162 % Note: other properties are available for use, but I've chosen to
0163 % leave them semi-hidden because they don't seem terribly useful to
0164 % most users. These properties allow you to specify the colors of the
0165 % selection tool itself, the colors of the selected point markers,
0166 % the transparency of the selection tool, the marker itself, etc.
0167 % Default values for these parameters are:
0168 %
0169 %           FlagMarker    = 'o'
0170 %           FlagColor     = 'r'
0171 %           Fill          = 'on'
0172 %           FillColor     = 'y'
0173 %           FillEdgeColor = 'b'
0174 %           FillTrans     = 0.5
0175 %           MaxBrush      = 0.25
0176 %           RemoveTool    = 'on'
0177 %           RemoveFlagged = 'on'
0178 %           RemoveLabels  = 'on'
0179 %
0180 % Further documentation on these parameters can be found by editting
0181 % selectdata.m itself.
0182 %
0183 %
0184 % Arguments: (output)
0185 %  pointslist - list of points that were selected. If only one
0186 %           dataset was found, then points list is a simple vector.
0187 %           If multiple sets of points were found in the axes, then
0188 %           points list will be a cell array.
0189 %
0190 %           NOTE: Each set of points is peeled off the stach in the
0191 %           matlab stores it.
0192 %
0193 %  xselect - array (or cell array) containing the x coordinates of
0194 %           those points identified in the selection
0195 %
0196 %  yselect - array (or cell array) containing the y coordinates of
0197 %           those points identified in the selection
0198 %
0199 %
0200 % Example:
0201 %  Plot a set of points, then select some with the mouse
0202 %  using a rectangular brush, return the indices of those
0203 %  points selected. (Note: user interaction on the plot
0204 %  will be necessary.)
0205 %
0206 %    x = 0:.1:1;
0207 %    y = x.^2;
0208 %    h = plot(x,y,'o')
0209 %    waitforbuttonpress;
0210 %    pl = vb_data_pick_tool('selectionmode','brush', 'Target', h);
0211 %
0212 % Example:
0213 %  Select a single point with the mouse, then delete that
0214 %  selected point from the plot.
0215 %
0216 %    pl = vb_data_pick_tool('selectionmode','closest','action','delete');
0217 %
0218 % Example:
0219 %  Select some points using a rect(rbbox) tool, also return
0220 %  the (x,y) coordinates from multiple curves plotted. Use
0221 %  shortened versions of the properties and values.
0222 %
0223 %    h = plot(rand(5,2),rand(5,2),'o');
0224 %    waitforbuttonpress;
0225 %    [pl,xs,ys] = vb_data_pick_tool('sel','r', 'Target', h);
0226 %
0227 % Example:
0228 %  Plot a curve and some data points on one plot, select
0229 %  some points from the data plotted, but ignore the
0230 %  smooth curve, even if the lasso passes over it.
0231 %    x = 0:.01:1;
0232 %    y = exp(x);
0233 %    ynoisy = y + randn(size(y))/2;
0234 %    h1 = plot(x,y,'-');
0235 %    hold on
0236 %    h2 = plot(x,ynoisy,'o');
0237 %    waitforbuttonpress;
0238 %    [pl,xs,ys] = vb_data_pick_tool('sel','lasso','Target',h2);
0239 %
0240 % See also:
0241 %
0242 %
0243 % Author: John D'Errico
0244 % E-mail: woodchips@rochester.rr.com
0245 % Release: 3.0
0246 % Release date: 2/19/07
0247 %
0248 % Copyright (c) 2007, John D'Errico
0249 % All rights reserved.
0250 %
0251 % Redistribution and use in source and binary forms, with or without
0252 % modification, are permitted provided that the following conditions are
0253 % met:
0254 %
0255 %     * Redistributions of source code must retain the above copyright
0256 %       notice, this list of conditions and the following disclaimer.
0257 %     * Redistributions in binary form must reproduce the above copyright
0258 %       notice, this list of conditions and the following disclaimer in
0259 %       the documentation and/or other materials provided with the distribution
0260 %
0261 % THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0262 % AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0263 % IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0264 % ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0265 % LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0266 % CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0267 % SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0268 % INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0269 % CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0270 % ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0271 % POSSIBILITY OF SUCH DAMAGE.
0272 %
0273 % [History]
0274 %   2016-02-01 rhayashi Added some options and not to use waitforbuttonpress
0275 %
0276 % [Note]
0277 %   Please specify 'Target' option implicitly.
0278 
0279 
0280 pointslist = [];
0281 xselect = [];
0282 yselect = [];
0283 
0284 % defaults for the parameters
0285 params.Axes = gca;
0286 params.SelectionMode = 'lasso';
0287 params.Action = 'list';
0288 params.BrushShape = 'circle';
0289 params.BrushSize = .05;
0290 params.Identify = 'on';
0291 params.Ignore = [];
0292 params.Target = [];
0293 params.Pointer = 'cross';
0294 params.Return = 'selected';
0295 params.Verify = 'off';
0296 params.Label = 'off';
0297 
0298 % Undocumented options, also unchecked for validity.
0299 % These parameters control the marker used to identify
0300 % those points which are currently selected.
0301 % FlagMarker must be a valid plot marker, FlagColor
0302 % must be a valid color spec. The default values are...
0303 params.FlagMarker = 'o';
0304 params.FlagColor = 'r';
0305 params.FlagEdgeColor = [];
0306 
0307 % More (unchecked) options that are yours to fiddle with
0308 % (or not.) These control the fill color to be applied
0309 % to the interior of the lasso, rect, and brush. Also
0310 % controlled are the degree of transparency to be applied.
0311 params.Fill = 'on';
0312 params.FillColor = 'y';
0313 params.FillEdgeColor = 'b';
0314 params.FillTrans = 0.5; % must be in the interval [0,1]
0315 
0316 % The maximum relative brushsize allowed is also
0317 % controlled here, just in case I ever wanted to allow
0318 % the brush to be a bit larger.
0319 params.MaxBrush = 0.25;
0320 
0321 % After selection has been accomplished, the flagged points
0322 % and the selection tool itself are normally deleted. But
0323 % in some circumstances it may be useful to not delete
0324 % those objects. 'off' will cause these objects to remain.
0325 params.RemoveTool = 'on';
0326 params.RemoveFlagged = 'on';
0327 params.RemoveLabels = 'on';
0328 
0329 % save this to restore later
0330 axissize = axis;
0331 
0332 % process any Property/value pairs.
0333 if nargin>0
0334   params = parse_pv_pairs(params,varargin);
0335 end
0336 
0337 % check the supplied parameters for validity
0338 params = check_params(params);
0339 
0340 % bring the focus to the figure containing the
0341 % designated axes
0342 fighandle = get(params.Axes,'parent');
0343 wbmf = get(fighandle,'WindowButtonMotionFcn');
0344 wbup = get(fighandle,'WindowButtonUpFcn');
0345 set(fighandle,'WindowButtonUpFcn',@selectdone);
0346 figure(fighandle);
0347 
0348 % User input thread sometime changes application status to 'Stop'
0349 % before running this program.(e.g. very short mouse click)
0350 % if strcmpi(get_app_status(fighandle), 'Stop')
0351 %     set_app_status(fighandle, 'Idle');
0352 %     % emergency stop code
0353 %     return;
0354 % end
0355 
0356 % get the current figure pointer, so we can
0357 % restore it later on
0358 oldpointer = get(fighandle,'Pointer');
0359 
0360 % extract xdata and ydata from the specified axes
0361 % get the children of the axes
0362 hc = get(params.Axes,'children');
0363 
0364 % are any of the data handles to be ignored?
0365 if ~isempty(params.Ignore) && ~isempty(params.Target)
0366   hc = setdiff(hc,params.Ignore);
0367 else
0368   hc = params.Target;
0369 end
0370 
0371 % strip out xdata and ydata
0372 xdata = get(hc,'xdata');
0373 ydata = get(hc,'ydata');
0374 
0375 % if we must highlight the points as they are
0376 % selected, then for efficiency we need to know
0377 % how many we may expect.
0378 flaghandle = [];
0379 if ~iscell(xdata)
0380   xdata = xdata(:);
0381   ydata = ydata(:);
0382   % total number of data points
0383   npoints = length(xdata);
0384 else
0385   for i = 1:length(xdata)
0386     xdata{i} = xdata{i}(:);
0387     ydata{i} = ydata{i}(:);
0388   end
0389   % total number of data points
0390   npoints = cellfun('length',xdata);
0391 end
0392 
0393 % for textlabels if desired
0394 texthandles = [];
0395 
0396 % set up a while loop in case we need to verify
0397 % satisfaction
0398 selectionflag = true;
0399 
0400 while selectionflag
0401   % and the total number currently selected
0402   nsel = 0;
0403   
0404 
0405   % what SelectionMode was specified
0406   switch params.SelectionMode
0407     case 'closest'
0408       % Find the single closest point (in Euclidean distance)
0409       % to the mouse click
0410       
0411       % set the figure pointer
0412       if ~isempty(params.Pointer)
0413         set(fighandle,'Pointer',params.Pointer)
0414       end
0415       
0416       % Button Motion and Button Up
0417       set(fighandle,'WindowButtonMotionFcn',@CPmotion);
0418       
0419       % dx, dy to scale the distance
0420       dx = (axissize(2) - axissize(1));
0421       dy = (axissize(4) - axissize(3));
0422       
0423       % current closest point is
0424       cc = get(gca,'CurrentPoint');
0425       xy = cc(1,1:2);
0426       
0427       % what point was closest?
0428       [pointslist,xselect,yselect] = closestpoint(xy,xdata,ydata,dx,dy);
0429       nsel = 1;
0430       
0431       % identify any points?
0432       if strcmp(params.Identify,'on')
0433         flagpoints
0434       end
0435       
0436       % label them?
0437       if strcmp(params.Label,'on')
0438         maketextlabels
0439       end
0440       
0441       % selecthandle is not needed for this mode op operation
0442       selecthandle = [];
0443       
0444       
0445       % resume.
0446       
0447       % all we need to do here is restore the figure pointer
0448       % if we changed it before
0449       if ~isempty(params.Pointer)
0450         set(fighandle,'Pointer',oldpointer)
0451       end
0452       
0453     case 'rect'
0454       % Selection rect as a polygon
0455 
0456       % mouse click?
0457 %      waitforbuttonpress;
0458 
0459       % set the figure pointer
0460       if ~isempty(params.Pointer)
0461         set(fighandle,'Pointer',params.Pointer)
0462       end
0463 
0464       % button down detected
0465       cc = get(gca,'CurrentPoint');
0466       rectxy1 = cc(1,1:2);
0467       rectxy2 = rectxy1 + eps(rectxy1);
0468 
0469       % make a polygon of the box, initially of nil area
0470       xv = [rectxy1(1), rectxy2(1), rectxy2(1), rectxy1(1), rectxy1(1)];
0471       yv = [rectxy1(2), rectxy1(2), rectxy2(2), rectxy2(2), rectxy1(2)];
0472 
0473       % no points should been selected
0474       [pointslist,xselect,yselect,nsel] = testpoly(xv,yv,xdata,ydata);
0475 
0476       % and plot it, filled or not
0477       hold on
0478       if strcmp(params.Fill,'on')
0479         % filled
0480         selecthandle = fill(xv,yv,params.FillColor);
0481         set(selecthandle,'facealpha',params.FillTrans, ...
0482           'linestyle','--','edgecolor',params.FillEdgeColor)
0483       else
0484         % unfilled
0485         selecthandle = plot(xv,yv,'r:');
0486       end
0487 
0488       % we can undo the hold now
0489       hold off
0490 
0491       % Button Motion and Button Up
0492       set(fighandle,'WindowButtonMotionFcn',@rectmotion);
0493 
0494 
0495       % ....
0496 
0497       % resume.
0498 
0499       % The rect already is a polygon, stored in (xv,yv)
0500 
0501     case 'lasso'
0502       % Selection lasso as a polygon
0503 
0504       % mouse click?
0505 %      waitforbuttonpress;
0506 
0507       % set the figure pointer
0508       if ~isempty(params.Pointer)
0509         set(fighandle,'Pointer',params.Pointer)
0510       end
0511 
0512       % button down detected
0513       cc = get(gca,'CurrentPoint');
0514       xlasso = cc(1,1);
0515       ylasso = cc(1,2);
0516 
0517       % form the polygon
0518       xv = xlasso;
0519       yv = ylasso;
0520 
0521       % and plot it, filled or not
0522       hold on
0523       if strcmp(params.Fill,'on')
0524         % filled
0525         selecthandle = fill(xv,yv,params.FillColor);
0526         set(selecthandle,'facealpha',params.FillTrans, ...
0527           'linestyle','--','edgecolor',params.FillEdgeColor)
0528       else
0529         % unfilled
0530         selecthandle = plot(xv,yv,'r:');
0531       end
0532 
0533       % we can undo the hold now
0534       hold off
0535 
0536       % Button Motion and Button Up
0537       set(fighandle,'WindowButtonMotionFcn',@lassomotion);
0538 
0539       % ....
0540 
0541       % resume.
0542 
0543       % The lasso already is a polygon, stored in (xv,yv)
0544 
0545     case 'brush'
0546       % paint over the data, with a rectangular brush
0547 
0548       % mouse click?
0549 %      waitforbuttonpress;
0550 
0551       % set the figure pointer
0552       if ~isempty(params.Pointer)
0553         set(fighandle,'Pointer',params.Pointer)
0554       end
0555 
0556       % button down detected
0557       bc = get(gca,'CurrentPoint');
0558       brushcenter = bc(1,1:2);
0559 
0560       % dx, dy for the brush
0561       bdx = params.BrushSize*(axissize(2) - axissize(1));
0562       bdy = params.BrushSize*(axissize(4) - axissize(3));
0563 
0564       if strcmpi(params.BrushShape,'rect')
0565         % make the brush polygon as a fixed size rectangle
0566         % that we can slide around
0567         xv = brushcenter(1) + [-1, 1, 1, -1, -1]*bdx/2;
0568         yv = brushcenter(2) + [-1, -1, 1, 1, -1]*bdy/2;
0569       else
0570         % a circle was specified
0571         theta = linspace(0,2*pi,100);
0572         xv = cos(theta)*bdx/2 + brushcenter(1);
0573         yv = sin(theta)*bdy/2 + brushcenter(2);
0574       end
0575 
0576       % draw the initial brush polygon, filled or not
0577       hold on
0578       if strcmp(params.Fill,'on')
0579         % filled
0580         selecthandle = fill(xv,yv,params.FillColor);
0581         set(selecthandle,'facealpha',params.FillTrans, ...
0582           'linestyle','-','edgecolor',params.FillEdgeColor)
0583       else
0584         % unfilled
0585         selecthandle = plot(xv,yv,'r:');
0586       end
0587       hold off
0588 
0589       % have any points been selected?
0590       [pointslist,xselect,yselect,nsel] = testpoly(xv,yv,xdata,ydata);
0591 
0592       % identify any points?
0593       if strcmp(params.Identify,'on') && (nsel>0)
0594         flagpoints
0595       end
0596       
0597       % label them?
0598       if strcmp(params.Label,'on') && (nsel>0)
0599         maketextlabels
0600       end
0601       
0602       % Button Motion and Button Up
0603       set(fighandle,'WindowButtonMotionFcn',@brushmotion);
0604       
0605       % resume.
0606 
0607   end
0608   
0609   % wait until the selection is done
0610   InputWait(fighandle);
0611 
0612   % Finished selection
0613   selectdone;
0614   
0615   % verify?
0616   if strcmpi(params.Verify,'on')
0617     % pop up a dialog
0618     ButtonName = questdlg( ...
0619       'Are you satisfied with the points selected?','???', ...
0620       'Yes','Redo Selection','Cancel Selection','Yes');
0621     
0622     switch ButtonName
0623       case 'Yes'
0624         % we can drop through
0625         selectionflag = false;
0626         
0627       case 'Cancel Selection'
0628         % drop out, with nothing selected
0629         if ~iscell(xdata)
0630           pointslist = [];
0631           xselect = [];
0632           yselect = [];
0633         else
0634           for i = 1:numel(xdata);
0635             pointslist{i} = [];
0636             xselect{i} = [];
0637             yselect{i} = [];
0638           end
0639         end
0640         
0641         % we can drop through
0642         selectionflag = false;
0643         
0644       case 'Redo Selection'
0645         % or try again. The while loop will cycle
0646         % until happy or canceled
0647         
0648     end
0649   
0650   else
0651     % no verification was requested, so we want to
0652     % terminate the while loop after only one pass through.
0653     selectionflag = false;
0654   end
0655   
0656 end
0657 
0658 % pointslist and xselect, yselect are already complete.
0659 % Do we delete the selected points?
0660 if strcmpi(params.Action,'delete')
0661   if ~iscell(xdata)
0662     % only one set, so xdata and ydata are not cell arrays
0663     
0664     % Which points from the data fall in the selection polygon?
0665     xdata(pointslist) = [];
0666     ydata(pointslist) = [];
0667     
0668     % drop those points from the plot
0669     set(hc,'xdata',xdata,'ydata',ydata)
0670   else
0671     % it was a cell array, so there were multiple sets.
0672     for i = 1:numel(xdata);
0673       
0674       xdata{i}(pointslist{i}) = [];
0675       ydata{i}(pointslist{i}) = [];
0676       
0677       % drop those points from the plot
0678       set(hc(i),'xdata',xdata{i},'ydata',ydata{i})
0679     end
0680   end
0681 end
0682 
0683 % was 'return' set to be the selected list or the unselected one?
0684 % Do nothing if 'selected', we are already done.
0685 if strcmpi(params.Return,'unselected')
0686   if ~iscell(xdata)
0687     % only one set, so xdata and ydata are not cell arrays
0688     pointslist = setdiff((1:npoints)',pointslist);
0689     xselect = xdata(pointslist);
0690     yselect = ydata(pointslist);
0691   else
0692     % it was a cell array, so there were multiple sets.
0693     for i = 1:numel(xdata);
0694       pointslist{i} = setdiff((1:npoints(i))',pointslist{i});
0695       
0696       xselect{i} = xdata{i}(pointslist{i});
0697       yselect{i} = ydata{i}(pointslist{i});
0698     end
0699   end
0700 end
0701 set(fighandle,'WindowButtonMotionFcn', wbmf);
0702 set(fighandle,'WindowButtonUpFcn', wbup);
0703 
0704 % =====================================================
0705 %     begin nested functions
0706 % =====================================================
0707 function brushmotion(src,evnt) %#ok
0708   % nested function for motion of the brush
0709   
0710   % get the new mouse position
0711   mousenew = get(params.Axes,'CurrentPoint');
0712   mousenew = mousenew(1,1:2);
0713   
0714   % make sure the axes are fixed
0715   axis(axissize)
0716   
0717   % how far did it move
0718   brushoffset = mousenew - brushcenter;
0719   brushcenter = mousenew;
0720   
0721   xv = xv + brushoffset(1);
0722   yv = yv + brushoffset(2);
0723   
0724   % did we brush over any new points
0725   [pl,xselect,yselect,nsel] = testpoly(xv,yv,xdata,ydata);
0726   
0727   % for a brush, we need to append any selected points to
0728   % the already selected list
0729   if ~iscell(xdata)
0730     % only one set, so xdata and ydata are not cell arrays
0731     pointslist = union(pointslist,pl);
0732     xselect = xdata(pointslist);
0733     yselect = ydata(pointslist);
0734     nsel = length(pointslist);
0735   else
0736     % it was a cell array, so there were multiple sets.
0737     for j = 1:numel(pointslist);
0738       pointslist{j} = union(pointslist{j},pl{j});  %#ok
0739       pointslist{j} = pointslist{j}(:); %#ok
0740       
0741       if ~isempty(pointslist{j})
0742         xselect{j} = xdata{j}(pointslist{j});
0743         yselect{j} = ydata{j}(pointslist{j});
0744       end
0745     end
0746     
0747     % total of points selected
0748     nsel = sum(cellfun('length',pointslist));
0749   end
0750   
0751   % identify any points?
0752   if strcmp(params.Identify,'on')
0753     flagpoints
0754   end
0755   
0756   % label them?
0757   if strcmp(params.Label,'on')
0758     maketextlabels
0759   end
0760   
0761   % replot the brush in its new position
0762   set(selecthandle,'xdata',xv,'ydata',yv)
0763   
0764 end
0765 % =====================================================
0766 
0767 % =====================================================
0768 function CPmotion(src,evnt) %#ok
0769   % nested function to select the closest point
0770   
0771   % get the new mouse position
0772   mousenew = get(params.Axes,'CurrentPoint');
0773   xy = mousenew(1,1:2);
0774   
0775   % make sure the axes stay fixed
0776   axis(axissize)
0777   
0778   % what point was closest?
0779   [pointslist,xselect,yselect] = closestpoint(xy,xdata,ydata,dx,dy);
0780   nsel = 1;
0781     
0782   % identify any points?
0783   if strcmp(params.Identify,'on')
0784     flagpoints
0785   end
0786   
0787   % label them?
0788   if strcmp(params.Label,'on')
0789     maketextlabels
0790   end
0791   
0792 end
0793 % =====================================================
0794 
0795 % =====================================================
0796 function rectmotion(src,evnt) %#ok
0797   % nested function for expansion or contraction of the rect
0798   
0799   % get the new mouse position
0800   mousenew = get(params.Axes,'CurrentPoint');
0801   rectxy2 = mousenew(1,1:2);
0802   
0803   % make sure the axes are fixed
0804   axis(axissize)
0805   
0806   % update the rect polygon of the box, changing the second corner
0807   xv = [rectxy1(1), rectxy2(1), rectxy2(1), rectxy1(1), rectxy1(1)];
0808   yv = [rectxy1(2), rectxy1(2), rectxy2(2), rectxy2(2), rectxy1(2)];
0809     
0810   % did we brush over any new points
0811   [pointslist,xselect,yselect,nsel] = testpoly(xv,yv,xdata,ydata);
0812   
0813   % identify any points?
0814   if strcmp(params.Identify,'on')
0815     flagpoints
0816   end
0817 
0818   % label them?
0819   if strcmp(params.Label,'on')
0820     maketextlabels
0821   end
0822     
0823   % replot the rect in its new position
0824   set(selecthandle,'xdata',xv,'ydata',yv)
0825   
0826 end
0827 % =====================================================
0828 
0829 % =====================================================
0830 function lassomotion(src,evnt) %#ok
0831   % nested function for expansion of the lasso
0832   
0833   % get the new mouse position
0834   mousenew = get(params.Axes,'CurrentPoint');
0835   mousenew = mousenew(1,1:2);
0836 
0837   % append the new point on the end of the last lasso
0838   xlasso = [xlasso,mousenew(1,1)];
0839   ylasso = [ylasso,mousenew(1,2)];
0840   
0841   % and close it to form the polygon
0842   xv = [xlasso,xlasso(1)];
0843   yv = [ylasso,ylasso(1)];
0844 
0845   % replot the newly extended lasso
0846   set(selecthandle,'xdata',xv,'ydata',yv)
0847   
0848   % did we enclose any new points?
0849   [pointslist,xselect,yselect,nsel] = testpoly(xv,yv,xdata,ydata);
0850   
0851   % identify any points?
0852   if strcmp(params.Identify,'on')
0853     flagpoints
0854   end
0855 
0856   % label them?
0857   if strcmp(params.Label,'on')
0858     maketextlabels
0859   end
0860     
0861   % make sure the axes are maintained in size
0862   axis(axissize)
0863   
0864 end
0865 % =====================================================
0866 
0867 % =====================================================
0868 function selectdone(src,evnt) %#ok
0869   % nested function for mouse up
0870   
0871   % do we remove the selection tool?
0872   if strcmpi(params.RemoveTool,'on')
0873     % delete the selection object from the plot
0874     if exist('selecthandle', 'var') && ~isempty(selecthandle)
0875         delete(selecthandle);
0876         selecthandle = [];
0877     end
0878   end
0879   
0880   % do we remove the flagged points?
0881   if strcmpi(params.RemoveFlagged,'on')
0882     % also remove the flagged/plotted points
0883     if exist('flaghandle', 'var') && ~isempty(flaghandle)
0884       delete(flaghandle)
0885       flaghandle = [];
0886     end
0887   end
0888   
0889   % do we remove the flagged points?
0890   if strcmpi(params.RemoveLabels,'on')
0891     % also remove the labels
0892     if exist('texthandles', 'var') && ~isempty(texthandles)
0893         delete(texthandles);
0894         texthandles = [];
0895     end
0896   end
0897   
0898 %   % cancel the WindowButtonFcn's that we had set
0899 %   set(fighandle,'WindowButtonMotionFcn',[]);
0900 %   set(fighandle,'WindowButtonUpFcn',[]);
0901   
0902   % restore the figure pointer to its original setting
0903   if ~isempty(params.Pointer) && exist('oldpointer', 'var')
0904     set(fighandle,'Pointer',oldpointer)
0905   end
0906   
0907   % and resume execution, back in the mainline
0908   Exit(fighandle);
0909 
0910 end
0911 % =====================================================
0912 
0913 % =====================================================
0914 function flagpoints
0915   % nested function for flagging the selected points
0916   
0917   % Are these the first points flagged? If so,
0918   % we need to plot them and set the marker, etc.
0919   if isempty(flaghandle) && (nsel > 0)
0920     % hold the figure, so we can add the flagged points
0921     hold on
0922     if isempty(params.FlagEdgeColor)
0923         params.FlagEdgeColor = params.FlagColor;
0924     end
0925     if ~iscell(xselect)
0926       flaghandle = plot(xselect,yselect,params.FlagMarker);
0927       set(flaghandle,'Color',params.FlagColor,'MarkerFaceColor',params.FlagColor,...
0928                      'MarkerEdgeColor', params.FlagEdgeColor);
0929     else
0930       flaghandle = plot(vertcat(xselect{:}),vertcat(yselect{:}),params.FlagMarker);
0931       set(flaghandle,'Color',params.FlagColor,'MarkerFaceColor',params.FlagColor,...
0932                      'MarkerEdgeColor', params.FlagEdgeColor);
0933     end
0934     % now release the hold
0935     hold off
0936   elseif ~isempty(flaghandle)
0937     % otherwise, we just need to update xdata and ydata
0938     
0939     if nsel == 0
0940       set(flaghandle,'xdata',[],'ydata',[]);
0941       
0942     elseif ~iscell(xselect)
0943       set(flaghandle,'xdata',xselect,'ydata',yselect);
0944     else
0945       set(flaghandle,'xdata',vertcat(xselect{:}),'ydata',vertcat(yselect{:}));
0946     end
0947   end
0948 end
0949 % =====================================================
0950 
0951 % =====================================================
0952 function maketextlabels
0953   % nested function for generation of text labels
0954   % over each point selected
0955   
0956   % We need to remove the last set of text labels
0957   delete(texthandles)
0958   
0959   % creat a new set of handles
0960   if ~iscell(xselect)
0961     xtext = xselect;
0962     ytext = yselect;
0963   else
0964     xtext = vertcat(xselect{:});
0965     ytext = vertcat(yselect{:});
0966   end
0967   
0968   % anything selected?
0969   if ~isempty(xtext)
0970     textlabels = cell(1,nsel);
0971     for L = 1:nsel
0972       textlabels{L} = ['(',num2str(xtext(L)),',',num2str(ytext(L)),')'];
0973     end
0974     texthandles = text(xtext,ytext,textlabels);
0975   end
0976 end
0977 % =====================================================
0978 
0979 end % mainline end
0980 
0981 % ================================================
0982 %               end main function
0983 % ================================================
0984 
0985 % ================================================
0986 %                  subfunctions
0987 % ================================================
0988 function [pl,xsel,ysel,nsel] = testpoly(xv,yv,xdata,ydata)
0989 % checks which points are inside the given polygon
0990 
0991 % was there more than one set of points found in the plot?
0992 if ~iscell(xdata)
0993   % only one set, so xdata and ydata are not cell arrays
0994   
0995   % Which points from the data fall in the selection polygon?
0996   pl = find(inpolygon(xdata,ydata,xv,yv));
0997   nsel = length(pl);
0998   
0999   xsel = xdata(pl);
1000   ysel = ydata(pl);
1001 else
1002   % it was a cell array, so there were multiple sets.
1003   pl = cell(size(xdata));
1004   xsel = pl;
1005   ysel = pl;
1006   nsel = 0;
1007   for i = 1:numel(xdata);
1008     pl{i} = find(inpolygon(xdata{i},ydata{i},xv,yv));
1009     nsel = nsel + length(pl{i});
1010     
1011     if ~isempty(pl{i})
1012       xsel{i} = xdata{i}(pl{i});
1013       ysel{i} = ydata{i}(pl{i});
1014     end
1015     
1016   end
1017 end
1018 
1019 end % subfunction end
1020 
1021 % ================================================
1022 %                  subfunction
1023 % ================================================
1024 function [pointslist,xselect,yselect] = closestpoint(xy,xdata,ydata,dx,dy)
1025 % find the single closest point to xy, in scaled units
1026 if ~iscell(xdata)
1027   % just one set of points to consider
1028   D = sqrt(((xdata - xy(1))/dx).^2 + ((ydata - xy(2))/dy).^2);
1029   [junk,pointslist] = min(D(:)); %#ok
1030   xselect = xdata(pointslist);
1031   yselect = ydata(pointslist);
1032 else
1033   % there is more than one set of points
1034   Dmin = inf;
1035   pointslist = cell(size(xdata));
1036   for i = 1:numel(xdata);
1037     D = sqrt(((xdata{i} - xy(1))/dx).^2 + ((ydata{i} - xy(2))/dy).^2);
1038     [mind,ind] = min(D(:)); %#ok
1039     
1040     if mind < Dmin
1041       % searching for the closest point
1042       Dmin = mind;
1043       
1044       pointslist = cell(size(xdata));
1045       xselect = cell(size(xdata));
1046       yselect = cell(size(xdata));
1047       
1048       pointslist{i} = ind;
1049       xselect{i} = xdata{i}(ind);
1050       yselect{i} = ydata{i}(ind);
1051     end
1052   end
1053 end
1054 
1055 end % subfunction end
1056 
1057 % ================================================
1058 %                  subfunction
1059 % ================================================
1060 
1061 % ============================================
1062 % subfunction - check_params
1063 % ============================================
1064 function par = check_params(par)
1065 % check the parameters for acceptability
1066 %
1067 % Defaults
1068 %  Axes = gca;
1069 %  SelectionMode = 'lasso';
1070 %  Action = 'list';
1071 %  BrushSize = .05;
1072 
1073 % Axes == gca by default
1074 if isempty(par.Axes)
1075   par.Axes = gca;
1076 else
1077   if ~ishandle(par.Axes)
1078     error 'Axes must be the handle to a valid set of axes.'
1079   end
1080 end
1081 
1082 % SelectionMode == 'brush' by default
1083 if isempty(par.SelectionMode)
1084   par.SelectionMode = 'brush';
1085 else
1086   valid = {'rect', 'brush', 'lasso', 'closest'};
1087   if ~ischar(par.SelectionMode)
1088     error 'Invalid Style: Must be character'
1089   end
1090   
1091   ind = strmatch(lower(par.SelectionMode),valid); %#ok
1092   if isempty(ind) || (length(ind)>1)
1093     error(['Invalid SelectionMode: ',par.SelectionMode])
1094   end
1095   par.SelectionMode = valid{ind};
1096 end
1097 
1098 % BrushShape == 'circle' by default
1099 if isempty(par.BrushShape)
1100   par.BrushShape = 'circle';
1101 else
1102   valid = {'rect', 'circle'};
1103   if ~ischar(par.BrushShape)
1104     error 'Invalid Style: Must be character'
1105   end
1106   
1107   ind = strmatch(lower(par.BrushShape),valid); %#ok
1108   if isempty(ind) || (length(ind)>1)
1109     error(['Invalid SelectionMode: ',par.BrushShape])
1110   end
1111   par.BrushShape = valid{ind};
1112 end
1113 
1114 % Action == 'list' by default
1115 if isempty(par.Action)
1116   par.Action = 'list';
1117 else
1118   valid = {'list', 'delete'};
1119   if ~ischar(par.Action)
1120     error 'Invalid Action: Must be character'
1121   end
1122   
1123   ind = strmatch(lower(par.Action),valid); %#ok
1124   if isempty(ind) || (length(ind)>1)
1125     error(['Invalid Action: ',par.Action])
1126   end
1127   par.Action = valid{ind};
1128 end
1129 
1130 % Pointer == 'crosshair' by default, but
1131 % if empty, will not change the pointer.
1132 if ~isempty(par.Pointer)
1133   valid = {'crosshair', 'fullcrosshair', 'arrow', 'ibeam', ...
1134     'watch', 'topl', 'topr', 'botl', 'botr', 'left', 'top', ...
1135     'right', 'bottom', 'circle', 'cross', 'fleur', ...
1136     'custom', 'hand'};
1137   
1138   if ~ischar(par.Pointer)
1139     error 'Invalid Pointer: Must be character'
1140   end
1141   
1142   ind = strmatch(lower(par.Pointer),valid,'exact');
1143   if isempty(ind)
1144     ind = strmatch(lower(par.Pointer),valid); %#ok
1145     if isempty(ind) || (length(ind)>1)
1146       error(['Invalid Pointer: ',par.Pointer])
1147     end
1148   end
1149   par.Pointer = valid{ind};
1150 end
1151 
1152 % Identify == 'on' by default
1153 if isempty(par.Identify)
1154   par.Identify = 'on';
1155 else
1156   valid = {'on', 'off'};
1157   if ~ischar(par.Identify)
1158     error 'Value for Identify is invalid: Must be character'
1159   end
1160   
1161   ind = strmatch(lower(par.Identify),valid); %#ok
1162   if isempty(ind) || (length(ind)>1)
1163     error(['Invalid Action: ',par.Identify])
1164   end
1165   par.Identify = valid{ind};
1166 end
1167 
1168 % Label == 'off' by default
1169 if isempty(par.Label)
1170   par.Label = 'off';
1171 else
1172   valid = {'on', 'off'};
1173   if ~ischar(par.Label)
1174     error 'Value for Label is invalid: Must be character'
1175   end
1176   
1177   ind = strmatch(lower(par.Label),valid); %#ok
1178   if isempty(ind) || (length(ind)>1)
1179     error(['Invalid Action: ',par.Label])
1180   end
1181   par.Label = valid{ind};
1182 end
1183 
1184 % Return == 'selected' by default
1185 if isempty(par.Return)
1186   par.Return = 'selected';
1187 else
1188   valid = {'selected', 'unselected'};
1189   if ~ischar(par.Return)
1190     error 'Value for Return is invalid: Must be character'
1191   end
1192   
1193   ind = strmatch(lower(par.Return),valid); %#ok
1194   if isempty(ind) || (length(ind)>1)
1195     error(['Invalid Action: ',par.Return])
1196   end
1197   par.Return = valid{ind};
1198 end
1199 
1200 % Verify == 'off' by default
1201 if isempty(par.Verify)
1202   par.Verify = 'off';
1203 else
1204   valid = {'on', 'off'};
1205   if ~ischar(par.Verify)
1206     error 'Value for Verify is invalid: Must be character'
1207   end
1208   
1209   ind = strmatch(lower(par.Verify),valid); %#ok
1210   if isempty(ind) || (length(ind)>1)
1211     error(['Invalid Action: ',par.Verify])
1212   end
1213   par.Verify = valid{ind};
1214 end
1215 
1216 % BrushSize == 0.05 by default
1217 if isempty(par.BrushSize)
1218   par.BrushSize = 0.05;
1219 else
1220   if (length(par.BrushSize)>1) || (par.BrushSize<=0) || (par.BrushSize>par.MaxBrush) 
1221     error 'Brushsize must be scalar, and 0 < BrushSize <= 0.25'
1222   end
1223 end
1224 
1225 % Ignore == [] by default
1226 if ~isempty(par.Ignore) && any(~ishandle(par.Ignore))
1227   error 'Ignore must be empty, or a data handle'
1228 end
1229 
1230 end % check_params
1231 
1232 
1233 % ============================================
1234 % Included subfunction - parse_pv_pairs
1235 % ============================================
1236 function params=parse_pv_pairs(params,pv_pairs)
1237 % parse_pv_pairs: parses sets of property value pairs, allows defaults
1238 % usage: params=parse_pv_pairs(default_params,pv_pairs)
1239 %
1240 % arguments: (input)
1241 %  default_params - structure, with one field for every potential
1242 %             property/value pair. Each field will contain the default
1243 %             value for that property. If no default is supplied for a
1244 %             given property, then that field must be empty.
1245 %
1246 %  pv_array - cell array of property/value pairs.
1247 %             Case is ignored when comparing properties to the list
1248 %             of field names. Also, any unambiguous shortening of a
1249 %             field/property name is allowed.
1250 %
1251 % arguments: (output)
1252 %  params   - parameter struct that reflects any updated property/value
1253 %             pairs in the pv_array.
1254 %
1255 % Example usage:
1256 % First, set default values for the parameters. Assume we
1257 % have four parameters that we wish to use optionally in
1258 % the function examplefun.
1259 %
1260 %  - 'viscosity', which will have a default value of 1
1261 %  - 'volume', which will default to 1
1262 %  - 'pie' - which will have default value 3.141592653589793
1263 %  - 'description' - a text field, left empty by default
1264 %
1265 % The first argument to examplefun is one which will always be
1266 % supplied.
1267 %
1268 %   function examplefun(dummyarg1,varargin)
1269 %   params.Viscosity = 1;
1270 %   params.Volume = 1;
1271 %   params.Pie = 3.141592653589793
1272 %
1273 %   params.Description = '';
1274 %   params=parse_pv_pairs(params,varargin);
1275 %   params
1276 %
1277 % Use examplefun, overriding the defaults for 'pie', 'viscosity'
1278 % and 'description'. The 'volume' parameter is left at its default.
1279 %
1280 %   examplefun(rand(10),'vis',10,'pie',3,'Description','Hello world')
1281 %
1282 % params =
1283 %     Viscosity: 10
1284 %        Volume: 1
1285 %           Pie: 3
1286 %   Description: 'Hello world'
1287 %
1288 % Note that capitalization was ignored, and the property 'viscosity'
1289 % was truncated as supplied. Also note that the order the pairs were
1290 % supplied was arbitrary.
1291 
1292 npv = length(pv_pairs);
1293 n = npv/2;
1294 
1295 if n~=floor(n)
1296   error 'Property/value pairs must come in PAIRS.'
1297 end
1298 if n<=0
1299   % just return the defaults
1300   return
1301 end
1302 
1303 if ~isstruct(params)
1304   error 'No structure for defaults was supplied'
1305 end
1306 
1307 % there was at least one pv pair. process any supplied
1308 propnames = fieldnames(params);
1309 lpropnames = lower(propnames);
1310 for i=1:n
1311   p_i = lower(pv_pairs{2*i-1});
1312   v_i = pv_pairs{2*i};
1313   
1314   ind = strmatch(p_i,lpropnames,'exact');
1315   if isempty(ind)
1316     ind = find(strncmp(p_i,lpropnames,length(p_i)));
1317     if isempty(ind)
1318       error(['No matching property found for: ',pv_pairs{2*i-1}])
1319     elseif length(ind)>1
1320       error(['Ambiguous property name: ',pv_pairs{2*i-1}])
1321     end
1322   end
1323   p_i = propnames{ind};
1324   
1325   % override the corresponding default in params
1326   params = setfield(params,p_i,v_i); %#ok
1327   
1328 end
1329 
1330 end % parse_pv_pairs
1331 
1332 %
1333 % --- Application status
1334 %
1335 function InputWait(fighandle)
1336 set_app_status(fighandle, 'Selecting');
1337 while(1)
1338     status = get_app_status(fighandle);
1339     if strcmpi(status, 'Stop');
1340         set_app_status(fighandle, 'Idle');
1341         %disp('Exit');
1342         break;
1343     else
1344 %        fprintf('S...');
1345         pause(0.1);
1346     end
1347 end
1348 end
1349 
1350 function Exit(fighandle)
1351 %disp('Exit is called');
1352 set_app_status(fighandle, 'Stop');
1353 end
1354 
1355 function set_app_status(h, status)
1356 setappdata(h, 'selection_status', status);
1357 end
1358 
1359 function status = get_app_status(h)
1360 status = getappdata(h, 'selection_status');
1361 end
1362

Generated on Mon 22-May-2023 06:53:56 by m2html © 2005