source: MML/trunk/machine/SOLEIL/common/naff/naffutils/datalabel.m @ 4

Last change on this file since 4 was 4, checked in by zhangj, 11 years ago

Initial import--MML version from SOLEIL@2013

File size: 6.9 KB
Line 
1function datalabel(state,marker_color);
2%datalabel       Interactive labeling of data points on a plot
3%   datalabel with no arguments toggles the data tip state
4%   datalabel ON turns data tips on for the current figure
5%   datalabel OFF turns data tips off for the current figure
6%   datalabel('ON',S), where S is a character string specifying
7%     a marker and/or color will add the specified marker to
8%     the data tip.  Default is red circles: 'ro'
9%
10%     Click on a line to label the nearest data point.
11%     Click and drag on a data tip to move it.
12%     Right-Click on a data tip to delete it.
13%
14%         Example:
15%            t = 0:pi/50:2.5*pi;
16%            y = sin(t);
17%            plot(t,y);  %Try plot(y,t), too
18%            datalabel on
19%        %Click on lines to label values.
20%        %Click and drag to move.
21%        %Right click to delete.
22%            datalabel off
23%        %Existing data tips are locked in place; can't add more
24%            datalabel('on','.b');  %Add blue dots with next data tips
25%
26%   smh: 5/02:  Click on text to re-position text relative to data point
27%               Click on data point to move to a different value
28%
29% This function is provided as an example only.  It has not been
30% tested, and therefore, it is not officially supported by The
31% MathWorks, Inc.
32
33% Written by Scott Hirsch
34% shirsch@mathworks.com
35% Most of this code comes from MOVTEXT, by John Galenski III
36% (Mistakes are mine, though!)
37% Copyright (c) by The MathWorks, Inc. 1985-2002
38%
39
40
41if nargin == 0 | strcmp(state,'on') % Set the WindowButtonDownFcn
42    if nargin <2 ,
43        marker='o';  %none
44        color = 'r';
45    else
46        %Parse marker string
47        colors = 'bgrcmyk';
48        markers = '+o*.xsdv^><ph';
49        for ii=1:length(marker_color)
50            col_ind = strfind(colors,marker_color(ii));
51            if ~isempty(col_ind)        %It's a color
52                color = marker_color(ii);
53            else                        %Try a marker instead
54                mark_ind = strfind(markers,marker_color(ii));
55                if ~isempty(mark_ind)
56                    marker = marker_color(ii);
57                end;
58            end;
59        end;
60    end;
61    if ~exist('color','var'), color = 'r'; end; %set default
62    if ~exist('marker','var'), marker = '.'; end; %set default
63    %If the user specifies a color, but no marker, I use a dot.
64   
65    set(gcf,'WindowButtonDownFcn','datalabel down')
66    setappdata(gcf,'Marker',marker);
67    setappdata(gcf,'Color',color);
68    set(gcf,'DoubleBuffer','on');       %eliminate flicker
69   
70elseif strcmp(state,'down') % Execute the WindowButtonDownFcn
71    htype = get(gco,'Type');
72    tag = get(gco,'Tag');
73    marker = getappdata(gcf,'Marker');
74    color  = getappdata(gcf,'Color');
75   
76    if strcmp(htype,'line') & ~strcmp(tag,'Dot')     %Line - Add text object
77        %This is sloppy, but it works.  The marker is a line named 'Dot'
78       
79        %Look up nearest value on line.
80       
81        %User-selected point
82        cp = get(gca,'CurrentPoint');
83        x = cp(1,1);       %first xy values
84        y = cp(1,2);       %first xy values
85       
86        %Line data
87        xl = get(gco,'XData');
88        yl = get(gco,'YData');
89       
90        [xv,yv] = local_nearest(x,xl,y,yl);
91
92       
93        %For R13 or higher (MATLAB 6.5), use a background color on the text string
94        th = text(xv,yv,['  (' num2str(xv) ',' num2str(yv) ')']);
95        v=str2num(version('-release'));
96        if v>=6.5
97            set(th,'BackgroundColor','y');
98        end;
99       
100       
101        ph = line(xv,yv, ...
102            'Color',color, ...
103            'Marker',marker, ...
104            'Tag','Dot', ...
105            'UserData',[gco th], ...
106            'LineStyle','none');
107       
108        mh = uicontextmenu('Tag','DeleteObject', ...
109            'Callback','ud = get(gco,''UserData'');delete([gco ud(2)]);');
110       
111        set([th ph],'UIContextMenu',mh);
112       
113        set(th,'UserData',[gco ph]);     %Store handle to line
114    elseif strcmp(htype,'text') | strcmp(tag,'Dot')
115        set(gco,'EraseMode','xor')
116        set(gcf,'WindowButtonMotionFcn','datalabel move', ...
117            'WindowButtonUpFcn','datalabel up');
118    end
119   
120elseif strcmp(state,'move') % Execute the WindowButtonMotionFcn
121    htype = get(gco,'Type');
122    tag = get(gco,'Tag');
123    if ~isempty(gco)
124        %Is this the dot or the text
125        if strcmp(htype,'text')             %The text
126            th = gco;
127            handles = get(gco,'UserData');   
128            ph = handles(2);
129            slide = 0;      %Don't slide along line; just reposition text
130        else                                %The marker
131            ph = gco;
132            handles = get(gco,'UserData');   
133            th = handles(2);
134            slide = 1;      %Slide along line to next data point
135        end;
136       
137        cp = get(gca,'CurrentPoint');
138        pt = cp(1,[1 2]);
139       
140        %Constrain to Line
141        lh = handles(1);        %Line
142       
143        x = cp(1,1);       %first xy values
144        y = cp(1,2);       %first xy values
145       
146        if slide            %Move to new data value
147            xl = get(lh,'XData');
148            yl = get(lh,'YData');
149           
150            ax = axis;
151           
152            %Get nearest value
153            [xv,yv]=local_nearest(x,xl,y,yl);
154           
155            set(th,'Position', [xv yv 0],'String',['  (' num2str(xv) ',' num2str(yv) ')'])
156            set(ph,'XData',xv,'YData',yv);
157        else                %Just move text around.
158            set(th,'Position', [x y 0])
159        end;
160       
161       
162        drawnow
163    end;
164elseif strcmp(state,'up') % Execute the WindowButtonUpFcn
165    htype = get(gco,'Type');
166    tag = get(gco,'Tag');
167    if strcmp(htype,'text') | strcmp(tag,'Dot')
168        set(gco,'EraseMode','Normal')
169        set(gcf,'WindowButtonMotionFcn','')
170    end;
171elseif strcmp(state,'off') % Unset the WindowButton...Fcns
172    set(gcf,'WindowButtonDownFcn','','WindowButtonUpFcn','')
173end
174
175
176function [xv,yv]=local_nearest(x,xl,y,yl)
177%Inputs:
178% x   Selected x value
179% xl  Line Data (x)
180% y   Selected y value
181% yl  Line Data (y)
182%Find nearest value of [xl,yl] to (x,y)
183%Special Case: Line has a single non-singleton value
184if sum(isfinite(xl))==1
185    fin = find(isfinite(xl));
186    xv = xl(fin);
187    yv = yl(fin);
188else
189    %Normalize axes
190    xlmin = min(xl);
191    xlmax = max(xl);
192    ylmin = min(yl);
193    ylmax = max(yl);
194   
195    % xln = xl;
196    % xn = x;
197    %
198    % yln = yl;
199    % yn = y;
200    xln = (xl - xlmin)./(xlmax - xlmin);
201    xn = (x - xlmin)./(xlmax - xlmin);
202   
203    yln = (yl - ylmin)./(ylmax - ylmin);
204    yn = (y - ylmin)./(ylmax - ylmin);
205   
206    %Find nearest point using our friend Ptyhagoras
207    a = xln - xn;       %Distance between x and the line
208    b = yln - yn;       %Distance between y and the line
209    c = (a.^2 + b.^2);  %Distance between point and line
210    %Don't need sqrt, since we get same answer anyway
211    [junk,ind] = min(c);
212   
213    %Nearest value on the line
214    xv = xl(ind);
215    yv = yl(ind);
216end;
Note: See TracBrowser for help on using the repository browser.