[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Octave-task-tracker] [task #14243] Rewrite legend.m
From: |
Rik |
Subject: |
[Octave-task-tracker] [task #14243] Rewrite legend.m |
Date: |
Mon, 11 Nov 2019 19:17:50 -0500 (EST) |
User-agent: |
Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko |
Follow-up Comment #13, task #14243 (project octave):
I'm starting to recall that legend is a very intricate function with lots of
small behavior deviations. The good news is that the second patch is much
faster, and about the same timing as what we have today when used on ordinary
plots.
Some additional corner cases that I discovered.
Corner case #1 (incorrectly handling multiple text strings)
x = linspace (0, 2*pi, 100);
plot (x, sin (x), 'o-', x, cos (x), '*-')
legend ("sine", "cosine");
error: binary operator '/' not implemented for 'cell' by 'scalar' operations
error: called from
legend>__legend_textitem_array__ at line 841 column 14
legend>__legend_update_layout__ at line 632 column 31
legend at line 201 column 5
/tmp/oct-tKWrbi at line 3 column 6
Corner case #2 (labeling more than 20 data objects)
The behavior quoted below is from the existing legend implementation. Like
Matlab, if the default number of labels is greater than 20 then it issues a
warning and only labels the first 20. This behavior is no longer present in
the patch.
octave:2> plot (rand (30));
octave:3> legend ()
warning: legend: labeling only first 20 data objects
warning: called from
legend at line 450 column 11
Corner case #3 (doesn't accept a numeric value for "location")
This could be behavior that we just drop. Specifying location with a numeric
value has been deprecated for a very long time, and is no longer supported in
Matlab either.
octave:1> plot (1:10, 'o-')
octave:2> legend ('abc', 'location', 3)
error: set: invalid value for radio property "location"
error: called from
legend at line 195 column 5
Corner case #3 (legend object created even when function fails)
This is a problem because it creates an axes object with tag "legend" which
leaves a white rectangle on the plot. If input validation fails there should
be no object created. Maybe you want to surround the construction of the axes
object with a try/catch block, and if there is an error delete the created
axes legend object and then re-throw the error.
octave:5> plot (1:10, 'o-')
octave:6> h = legend ('abc', 'location', 'foobar')
error: invalid value = foobar
error: called from
legend at line 195 column 5
octave:7> findall (gcf, 'tag', 'legend')
ans = -5.6867
Corner case #4 ("bestoutside" location property not implemented)
Current legend.m implements "bestoutside" so we shouldn't regress on that
behavior.
octave:10> plot (1:10, 'o-')
octave:11> h = legend ('abc', 'location', 'bestoutside')
error: invalid value = bestoutside
error: called from
legend at line 195 column 5
Corner case #5 ("none" location property not implemented)
"none" turns off the default positioning algorithm and allows the user to set
the location directly with the "position" property of the legend object.
octave:10> plot (1:10, 'o-')
octave:11> h = legend ('abc', 'location', 'none')
error: invalid value = none
error: called from
legend at line 195 column 5
Comment #6 (Octave prefers no Camel Case properties)
The following properties should probably be all lower case to match Octave's
other properties.
AutoUpdate = off
NumColumns = 1
NumColumnsMode = auto
Corner case #7 (listener on "numcolumns"?)
The "numcolumns" property works correctly when the legend is created, but
subsequent changes to the property don't re-format the legend.
x = linspace(0,pi);
y1 = cos(x);
plot(x,y1)
hold on
y2 = cos(2*x);
plot(x,y2)
y3 = cos(3*x);
plot(x,y3)
y4 = cos(4*x);
plot(x,y4)
hold off
hl =
legend({'cos(x)','cos(2x)','cos(3x)','cos(4x)'},'Location','northwest','NumColumns',2);
set (hl, 'numcolumns', 1)
Corner case #8 (legend show)
When called with the argument "show", legend should display a legend as if it
was called with no arguments. This produces "data1", "data2", etc. Instead,
the new legend code is treating "show" as a text label rather than a command.
legend ("toggle") produces the same behavior.
octave:106> plot (rand (3,2))
octave:107> legend show
warning: legend: ignoring extra objects.
warning: called from
legend>__legend_parse_opts__ at line 555 column 9
legend at line 125 column 8
Corner case #9 (horizontal spacing)
Try
demo legend 6
and you will see that the text and keys are crowded when compared to the
current version of legend.
Corner case #10 (property "textcolor" not implemented?)
Try
demo legend 9
The text should be magenta color rather than black.
Corner case #11 (demo #15, #16 produce warnings when they shouldn't)
legend example 15:
clf;
x = linspace (0, 10);
plot (x, x);
hold on;
stem (x, x.^2, "g");
title ("First created object gets first label");
legend ("linear");
hold off;
warning: legend: ignoring extra objects.
warning: called from
legend>__legend_parse_opts__ at line 555 column 9
legend at line 125 column 8
__demo__ at line 9 column 2
demo at line 147 column 7
Corner case #12 (demo #22 produces only one label)
Try
demo legend 22
It should produce a legend with "sin (x)" and "cos (x)" as labels.
Corner case #13 (callback execution error when running demo #28)
This occurred while running all of the demos in legend.m
Press <enter> to continue:
execution error in graphics callback function
legend example 28:
clf;
x = 0:10;
y1 = rand (size (x));
y2 = rand (size (x));
[ax, h1, h2] = plotyy (x, y1, x, y2);
ylabel (ax(1), {"Blue", "Y", "Axis"});
title ('plotyy legend test #2: "westoutside" adjusts to ylabel');
drawnow ();
legend ([h1, h2], {"Blue", "Orange"}, "location", "westoutside");
Corner case #14 (demo #29 fails)
Try
legend demo 29
The rightside axes is messed up.
Corner case #15 (demo #30)
In the new legend code, the subplots are all set to the same size which
accommodates the largest of the text strings. In previous versions of Octave,
in Matlab, each subplot is re-sized to fit the length of the label it is
paired with.
Try
legend demo 30
Comment #16 (demo #36 missing)
Demo #36 is missing in the new code. I think it is correct to include it
because it shows that the problem has now been fixed. If there is a
regression in behavior this demo will show it.
Comment #17 (performance measure)
I used demo #14 which does not include subplots to show that the new code can
be significantly slower even in an ordinary case.
tic; demo ("legend", 14); toc
Old code: 0.5 seconds
New code: 2.3 seconds
Comment #18 (length of lines in legend key)
I used
demo legend 3
and then measured the length of the lines in the legend key. In the old code
it is about 20 pixels and in the new code it is about 27 pixels. I like the
shorter length. Matlab uses long line lengths and I think it is ugly.
Comment #19 (hide __appdata__ property?)
The __appdata__ property is for internal use only. It should probably be a
hidden property so that users don't have to see all the guts of the
implementation.
octave:149> plot (1:10, 'o-')
octave:150> hl = legend ('abc')
hl = -102.66
octave:151> get (hl)
ans =
scalar structure containing the fields:
__appdata__ =
scalar structure containing the fields:
__axes_handle__ = -108.94
__next_label_index__ = 1
__peer_objects__ = -103.14
__updating_layout__ = 0
__original_looseinset__ =
0.130000 0.110000 0.095000 0.075000
__original_units__ = normalized
__peer_axes_position__ =
54.587 34.641 325.420 256.662
__listeners__ =
{
[1,1] =
{
[1,1] = 1
[1,2] = position
[1,3] =
{
[1,1] = @__maybe_update_layout__
[1,2] = -102.66
}
}
[1,2] =
{
[1,1] = -108.94
[1,2] = position
[1,3] =
{
[1,1] = @__maybe_update_layout__
[1,2] = -102.66
}
}
[1,3] =
{
[1,1] = -108.94
[1,2] = tightinset
[1,3] =
{
[1,1] = @__maybe_update_layout__
[1,2] = -102.66
}
}
[1,4] =
{
[1,1] = -108.94
[1,2] = colormap
[1,3] =
@(hax) set (hl, "colormap", get (hax, "colormap"))
}
[1,5] =
{
[1,1] = -108.94
[1,2] = fontsize
[1,3] =
@(hax) set (hl, "fontsize", 0.9 * get (hax, "fontsize"))
}
[1,6] =
{
[1,1] = -108.94
[1,2] = children
[1,3] =
{
[1,1] = @__legend_autoupdate__
[1,2] = -102.66
}
}
}
AutoUpdate = off
edgecolor =
0.1500 0.1500 0.1500
interpreter = tex
itemhitfcn = [](0x0)
location = northeast
NumColumns = 1
NumColumnsMode = auto
orientation = vertical
string =
{
[1,1] = abc
}
Corner case #20 ("EdgeColor" not implemented?)
Using this property doesn't seem to work anymore.
plot (1:10, 'o-');
hl = legend ('abc');
set (hl, 'edgecolor', 'r')
_______________________________________________________
Reply to this item at:
<https://savannah.gnu.org/task/?14243>
_______________________________________________
Message sent via Savannah
https://savannah.gnu.org/
- [Octave-task-tracker] [task #14243] Rewrite legend.m, Rik, 2019/11/09
- [Octave-task-tracker] [task #14243] Rewrite legend.m, Rik, 2019/11/09
- [Octave-task-tracker] [task #14243] Rewrite legend.m, Pantxo Diribarne, 2019/11/11
- [Octave-task-tracker] [task #14243] Rewrite legend.m,
Rik <=
- [Octave-task-tracker] [task #14243] Rewrite legend.m, Pantxo Diribarne, 2019/11/12
- [Octave-task-tracker] [task #14243] Rewrite legend.m, Pantxo Diribarne, 2019/11/12
- [Octave-task-tracker] [task #14243] Rewrite legend.m, Pantxo Diribarne, 2019/11/12
- [Octave-task-tracker] [task #14243] Rewrite legend.m, Pantxo Diribarne, 2019/11/12
- [Octave-task-tracker] [task #14243] Rewrite legend.m, Rik, 2019/11/12
- [Octave-task-tracker] [task #14243] Rewrite legend.m, Pantxo Diribarne, 2019/11/13
- [Octave-task-tracker] [task #14243] Rewrite legend.m, Rik, 2019/11/14
- [Octave-task-tracker] [task #14243] Rewrite legend.m, Pantxo Diribarne, 2019/11/18
- [Octave-task-tracker] [task #14243] Rewrite legend.m, Philip Nienhuis, 2019/11/18
- [Octave-task-tracker] [task #14243] Rewrite legend.m, Philip Nienhuis, 2019/11/18