]> Creatis software - CreaPhase.git/blob - octave_packages/m/plot/plotyy.m
update packages
[CreaPhase.git] / octave_packages / m / plot / plotyy.m
1 ## Copyright (C) 2007-2012 David Bateman
2 ##
3 ## This file is part of Octave.
4 ##
5 ## Octave is free software; you can redistribute it and/or modify it
6 ## under the terms of the GNU General Public License as published by
7 ## the Free Software Foundation; either version 3 of the License, or (at
8 ## your option) any later version.
9 ##
10 ## Octave is distributed in the hope that it will be useful, but
11 ## WITHOUT ANY WARRANTY; without even the implied warranty of
12 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 ## General Public License for more details.
14 ##
15 ## You should have received a copy of the GNU General Public License
16 ## along with Octave; see the file COPYING.  If not, see
17 ## <http://www.gnu.org/licenses/>.
18
19 ## -*- texinfo -*-
20 ## @deftypefn  {Function File} {} plotyy (@var{x1}, @var{y1}, @var{x2}, @var{y2})
21 ## @deftypefnx {Function File} {} plotyy (@dots{}, @var{fun})
22 ## @deftypefnx {Function File} {} plotyy (@dots{}, @var{fun1}, @var{fun2})
23 ## @deftypefnx {Function File} {} plotyy (@var{h}, @dots{})
24 ## @deftypefnx {Function File} {[@var{ax}, @var{h1}, @var{h2}] =} plotyy (@dots{})
25 ## Plot two sets of data with independent y-axes.  The arguments @var{x1} and
26 ## @var{y1} define the arguments for the first plot and @var{x1} and @var{y2}
27 ## for the second.
28 ##
29 ## By default the arguments are evaluated with
30 ## @code{feval (@@plot, @var{x}, @var{y})}.  However the type of plot can be
31 ## modified with the @var{fun} argument, in which case the plots are
32 ## generated by @code{feval (@var{fun}, @var{x}, @var{y})}.  @var{fun} can be
33 ## a function handle, an inline function or a string of a function name.
34 ##
35 ## The function to use for each of the plots can be independently defined
36 ## with @var{fun1} and @var{fun2}.
37 ##
38 ## If given, @var{h} defines the principal axis in which to plot the @var{x1}
39 ## and @var{y1} data.  The return value @var{ax} is a two element vector with
40 ## the axis handles of the two plots.  @var{h1} and @var{h2} are handles to
41 ## the objects generated by the plot commands.
42 ##
43 ## @example
44 ## @group
45 ## x = 0:0.1:2*pi;
46 ## y1 = sin (x);
47 ## y2 = exp (x - 1);
48 ## ax = plotyy (x, y1, x - 1, y2, @@plot, @@semilogy);
49 ## xlabel ("X");
50 ## ylabel (ax(1), "Axis 1");
51 ## ylabel (ax(2), "Axis 2");
52 ## @end group
53 ## @end example
54 ## @end deftypefn
55
56 function [Ax, H1, H2] = plotyy (varargin)
57
58   ## Don't use __plt_get_axis_arg__ here as ax is a two vector for plotyy
59   if (nargin > 1 && length (varargin{1}) == 2 && ishandle(varargin{1}(1))
60       && ishandle(varargin{1}(2))
61       && all (floor (varargin{1}) != varargin{1}))
62     obj1 = get (varargin{1}(1));
63     obj2 = get (varargin{1}(2));
64     if (strcmp (obj1.type, "axes") || strcmp (obj2.type, "axes"))
65       ax = [obj1, obj2];
66       varargin(1) = [];
67       if (isempty (varargin))
68         varargin = {};
69       endif
70     else
71       error ("plotyy: expecting first argument to be axes handle");
72     endif
73     oldh = gca ();
74   else
75     f = get (0, "currentfigure");
76     if (isempty (f))
77       f = figure ();
78     endif
79     ca = get (f, "currentaxes");
80     if (isempty (ca))
81       ax = [];
82     elseif (ishandle (ca) && isprop (ca, "__plotyy_axes__"))
83       ax = get (ca, "__plotyy_axes__");
84     else
85       ax = ca;
86     endif
87     if (length (ax) > 2)
88       for i = 3 : length (ax)
89         delete (ax (i));
90       endfor
91       ax = ax(1:2);
92     elseif (length (ax) == 1)
93       ax(2) = axes ();
94     elseif (isempty (ax))
95       ax(1) = axes ();
96       ax(2) = axes ();
97       ca = ax(2);
98     endif
99     if (nargin < 2)
100       varargin = {};
101     endif
102     oldh = ca;
103   endif
104
105   if (nargin < 4)
106     print_usage ();
107   endif
108
109   unwind_protect
110     [ax, h1, h2] = __plotyy__ (ax, varargin{:});
111   unwind_protect_cleanup
112     ## Only change back to the old axis if we didn't delete it
113     if (ishandle(oldh) && strcmp (get (oldh, "type"), "axes"))
114       axes (oldh);
115     endif
116   end_unwind_protect
117
118   if (nargout > 0)
119     Ax = ax;
120     H1 = h1;
121     H2 = h2;
122   endif
123
124 endfunction
125
126 function [ax, h1, h2] = __plotyy__ (ax, x1, y1, x2, y2, varargin)
127   if (nargin > 5)
128     fun1 = varargin{1};
129   else
130     fun1 = @plot;
131   endif
132   if (nargin > 6)
133     fun2 = varargin{2};
134   else
135     fun2 = fun1;
136   endif
137
138   xlim = [min([x1(:); x2(:)]), max([x1(:); x2(:)])];
139
140   if (ishandle(ax(1)) && strcmp (get (ax(1), "type"), "axes"))
141     axes (ax(1));
142   else
143     ax(1) = axes ();
144   endif
145   newplot ();
146   h1 = feval (fun1, x1, y1);
147
148   set (ax(1), "ycolor", getcolor (h1(1)));
149   set (ax(1), "xlim", xlim);
150   set (ax(1), "color", "none");
151
152   cf = gcf ();
153   set (cf, "nextplot", "add");
154
155   if (ishandle(ax(2)) && strcmp (get (ax(2), "type"), "axes"))
156     axes (ax(2));
157   else
158     ax(2) = axes ();
159   endif
160   newplot ();
161
162   colors = get (ax(1), "colororder");
163   set (ax(2), "colororder", [colors(2:end,:); colors(1,:)]);
164
165   if (strcmp (get (ax(1), "autopos_tag"), "subplot"))
166     set (ax(2), "autopos_tag", "subplot");
167   else
168     set (ax, "activepositionproperty", "position");
169   endif
170
171   h2 = feval (fun2, x2, y2);
172   set (ax(2), "yaxislocation", "right");
173   set (ax(2), "ycolor", getcolor (h2(1)));
174
175
176   if (strcmp (get(ax(1), "activepositionproperty"), "position"))
177     set (ax(2), "position", get (ax(1), "position"));
178   else
179     set (ax(2), "outerposition", get (ax(1), "outerposition"));
180     set (ax(2), "looseinset", get (ax(1), "looseinset"));
181   endif
182
183   set (ax(2), "xlim", xlim);
184   set (ax(2), "color", "none");
185   set (ax(2), "box", "off");
186
187   ## Add invisible text objects that when destroyed,
188   ## also remove the other axis
189   t1 = text (0, 0, "", "parent", ax(1), "tag", "plotyy",
190              "handlevisibility", "off", "visible", "off",
191              "xliminclude", "off", "yliminclude", "off");
192   t2 = text (0, 0, "", "parent", ax(2), "tag", "plotyy",
193              "handlevisibility", "off", "visible", "off",
194              "xliminclude", "off", "yliminclude", "off");
195
196   set (t1, "deletefcn", {@deleteplotyy, ax(2), t2});
197   set (t2, "deletefcn", {@deleteplotyy, ax(1), t1});
198
199   addlistener (ax(1), "position", {@update_position, ax(2)});
200   addlistener (ax(2), "position", {@update_position, ax(1)});
201   addlistener (ax(1), "outerposition", {@update_position, ax(2)});
202   addlistener (ax(2), "outerposition", {@update_position, ax(1)});
203   addlistener (ax(1), "looseinset", {@update_position, ax(2)});
204   addlistener (ax(2), "looseinset", {@update_position, ax(1)});
205   addlistener (ax(1), "view", {@update_position, ax(2)});
206   addlistener (ax(2), "view", {@update_position, ax(1)});
207   addlistener (ax(1), "plotboxaspectratio", {@update_position, ax(2)});
208   addlistener (ax(2), "plotboxaspectratio", {@update_position, ax(1)});
209   addlistener (ax(1), "plotboxaspectratiomode", {@update_position, ax(2)});
210   addlistener (ax(2), "plotboxaspectratiomode", {@update_position, ax(1)});
211
212   ## Store the axes handles for the sister axes.
213   if (ishandle (ax(1)) && ! isprop (ax(1), "__plotyy_axes__"))
214     addproperty ("__plotyy_axes__", ax(1), "data", ax);
215   elseif (ishandle (ax(1)))
216     set (ax(1), "__plotyy_axes__", ax);
217   else
218     error ("plotyy.m: This shouldn't happen. File a bug report.")
219   endif
220   if (ishandle (ax(2)) && ! isprop (ax(2), "__plotyy_axes__"))
221     addproperty ("__plotyy_axes__", ax(2), "data", ax);
222   elseif (ishandle (ax(2)))
223     set (ax(2), "__plotyy_axes__", ax);
224   else
225     error ("plotyy.m: This shouldn't happen. File a bug report.")
226   endif
227 endfunction
228
229 %!demo
230 %! clf
231 %! x = 0:0.1:2*pi;
232 %! y1 = sin (x);
233 %! y2 = exp (x - 1);
234 %! ax = plotyy (x, y1, x - 1, y2, @plot, @semilogy);
235 %! xlabel ("X");
236 %! ylabel (ax(1), "Axis 1");
237 %! ylabel (ax(2), "Axis 2");
238 %! axes (ax(1))
239 %! text (0.5, 0.5, "Left Axis", ...
240 %!       "color", [0 0 1], "horizontalalignment", "center")
241 %! axes (ax(2))
242 %! text (4.5, 80, "Right Axis", ...
243 %!       "color", [0 0.5 0], "horizontalalignment", "center")
244
245 %!demo
246 %! clf
247 %! x = linspace (-1, 1, 201);
248 %! subplot (2, 2, 1)
249 %! plotyy (x, sin(pi*x), x, 10*cos(pi*x))
250 %! subplot (2, 2, 2)
251 %! surf (peaks (25))
252 %! subplot (2, 2, 3)
253 %! contour (peaks (25))
254 %! subplot (2, 2, 4)
255 %! plotyy (x, 10*sin(2*pi*x), x, cos(2*pi*x))
256 %! axis square
257
258 %!demo
259 %! clf
260 %! x = linspace (-1, 1, 201);
261 %! subplot (1, 1, 1);
262 %! hax = plotyy (x, sin(pi*x), x, cos(pi*x));
263 %! ylabel ("Blue and on the Left")
264 %! ylabel (hax(2), "Green and on the Right")
265 %! xlabel ("xlabel")
266
267 function deleteplotyy (h, d, ax2, t2)
268   if (ishandle (ax2) && strcmp (get (ax2, "type"), "axes")
269       && (isempty (gcbf()) || strcmp (get (gcbf(), "beingdeleted"),"off"))
270       && strcmp (get (ax2, "beingdeleted"), "off"))
271     set (t2, "deletefcn", []);
272     delete (ax2);
273   endif
274 endfunction
275
276 function update_position (h, d, ax2)
277   persistent recursion = false;
278
279   ## Don't allow recursion
280   if (! recursion)
281     unwind_protect
282       recursion = true;
283       view = get (h, "view");
284       oldview = get (ax2, "view");
285       plotboxaspectratio = get (h, "plotboxaspectratio");
286       oldplotboxaspectratio = get (ax2, "plotboxaspectratio");
287       plotboxaspectratiomode = get (h, "plotboxaspectratiomode");
288       oldplotboxaspectratiomode = get (ax2, "plotboxaspectratiomode");
289
290       if (strcmp (get(h, "activepositionproperty"), "position"))
291         position = get (h, "position");
292         oldposition = get (ax2, "position");
293         if (! (isequal (position, oldposition) && isequal (view, oldview)))
294           set (ax2, "position", position, "view", view);
295         endif
296       else
297         outerposition = get (h, "outerposition");
298         oldouterposition = get (ax2, "outerposition");
299         if (! (isequal (outerposition, oldouterposition) && isequal (view, oldview)))
300           set (ax2, "outerposition", outerposition, "view", view);
301         endif
302       endif
303
304       if (! (isequal (plotboxaspectratio, oldplotboxaspectratio)
305              && isequal (plotboxaspectratiomode, oldplotboxaspectratiomode)))
306         set (ax2, "plotboxaspectratio", plotboxaspectratio);
307         set (ax2, "plotboxaspectratiomode", plotboxaspectratiomode);
308       endif
309     unwind_protect_cleanup
310       recursion = false;
311     end_unwind_protect
312   endif
313 endfunction
314
315 function color = getcolor (ax)
316   obj = get (ax);
317   if (isfield (obj, "color"))
318     color = obj.color;
319   elseif (isfield (obj, "facecolor") && ! ischar (obj.facecolor))
320     color = obj.facecolor;
321   elseif (isfield (obj, "edgecolor") && !  ischar (obj.edgecolor))
322     color = obj.edgecolor;
323   else
324     color = [0, 0, 0];
325   endif
326 endfunction
327