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