bugGNU Octave - Bugs: bug #40686, Incorrect colorbar size after...

 
 

bug #40686: Incorrect colorbar size after "axis tight" or "axis equal"

Submitted by:  Ben Abbott <bpabbott>
Submitted on:  Sun 24 Nov 2013 02:03:26 AM UTC  
 
Category:  Plotting with gnuplot Severity:  3 - Normal
Priority:  5 - Normal Item Group:  Incorrect Result
Status:  Fixed Assigned to:  None
Originator Name:  Ben Abbott Open/Closed:  Closed
Release:  6.0.90 Operating System:  Any

Add a New Comment (Rich Markup)
   

You are not logged in

Please log in, so followups can be emailed to you.

 

( Jump to the original submission)

Sat 12 Sep 2020 08:56:01 PM UTC, comment #20: 

Thanks, Rik!  Sorry I did not reply sooner; I appreciate you taking action while it was at the top of your mind rather than waiting on my dawdling.  :)

Next time I am working with this code, I'll try to compare the gnuplot tookit results with the qt toolkit results and see if there's a low-hanging tweak to make them more similar.

Anne Hanna <thebat137>
Sat 12 Sep 2020 08:51:25 PM UTC, comment #19: 

I went ahead and checked in the change.  Marking as fixed and closing report.

Rik <rik5>
Project Administrator
Thu 10 Sep 2020 12:43:53 AM UTC, comment #18: 

@Anne: Your change makes things look better.  It's still not identical to the output when using qt as the graphics toolkit, but it is better.

Do you want to be credited for this patch?  We use a name and an e-mail address so if there are any problems we can eventually contact the original coder.  Otherwise, I can check it in under my credentials.

Rik <rik5>
Project Administrator
Sat 27 Jun 2020 06:34:35 PM UTC, comment #17: 

I just got around to looking at this issue again as it started getting in my way again.  I communicated a little last year with the person who first introduced the relevant code into Gnuplot (Ethan Merritt), and I'm not sure there's a particularly good reason this is the way it is, but, in any case, "set size noratio" was his suggested fix.  It does seem logical to me that Octave should need to do   something to unset the "axis equal xy(z); view map" commands before proceeding with drawing subsequent features, even if the specific unset command needed in this case is a little weird due to a misfeature of Gnuplot.

I've attached a proposed patch below that seems to resolve things for me.

I did also file an official bug against Gnuplot in hopes of getting their part of the issue improved:

https://sourceforge.net/p/gnuplot/bugs/2287/

Anyway, thanks for your past help tracking this down, and here's hoping we can finally get it cleaned up now.

(file #49376)

Anne Hanna <thebat137>
Wed 06 Feb 2019 07:22:29 AM UTC, comment #16: 

It sorta seems like it was done deliberately, I just don't understand why.  But I can ask the Gnuplot maintainers.  I'll report back.

Anne Hanna <thebat137>
Tue 05 Feb 2019 06:45:17 AM UTC, comment #15: 

It could be a bug in gnuplot.  They show up once in a while for the less-used scenarios.  I'll have a look this weekend.  If it looks like a bug to you, create a changeset for gnuplot as well.  gnuplot is a fairly easy program to download and build.

Dan Sebald <sebald>
Mon 04 Feb 2019 09:41:05 AM UTC, comment #14: 

What you say about equal and square not being the same in Gnuplot is correct.  (They don't even belong to the same "set" subcommand --- view vs. size!)  However, Gnuplot does something very odd when "set view equal xy(z)" and "set view map" are run in that order, which it does not do when "set view map" doesn't follow "set view equal xy(z)", and which it does not undo when "set view noequal" is run (in any combination).   Specifically, it sets a locked 1:1 aspect ratio, as if you ran "set size ratio -1", and this is what distorts the colorbar.

If you read the code for Gnuplot's internal set_view function (in set.c), you can see this in action, although it's a little unclear why it's being done that way.  "set size nosquare" undoes the problematic aspect ratio lock, but if you test your proposed patch, you will (I believe) see that "set view noequal" does not.

Aside from that, I'm a little concerned about whether the location you've suggested for adding the correction will be side effect free.  If I'm reading the code correctly, this would insert the "set view noequal" line after quite a bit of the plot stream for the next piece of the figure may have already been generated.  Given the unexpected interaction we've already seen between "set view map" and "set view equal", and lacking a complete understanding of all the different kinds of settings one might have wanted to do by that point for all other types of figure components, I'm somewhat leery of sticking a new command in the middle there for every single plot type that's not the problematic one as opposed to just having a single "undo" command at the end of the one known-problematic plot type (the "axis equal" plot).  So that's why I suggested putting it where I did.

Does that seem reasonable to you?


I should also mention a couple of other small points:

1) For all that I'm not enthusiastic about the location you suggest for inserting the correction, it will work fine for the nd == 2 case (which is actually the one we need it to work for if we want the colorbar fixed!).  The nd == 3 test is part of the condition for the first branch, not a condition for entering into that code block at all, so all nd == 2 plots will go into the branch that inserts the undo command, as we would want.

2) Octave's "axis square" doesn't currently use Gnuplot's "set size square" command, so it won't have a similar closure problem (although it might have other ones, for all I know!).  So at least for the purposes of this bug, I don't think it's a problem.  The original test example no longer gives me bad results either with "axis tight" or with "axis square", so I suspect those issues were accidentally fixed sometime in the last five years without anyone noticing.

Anne Hanna <thebat137>
Mon 04 Feb 2019 08:53:49 AM UTC, comment #13: 

Oh, no actual gnuplot colorbox.  That sort of rings a bell.

Your logic seems correct, other than "equal" and "square" not being the same thing in gnuplot.  I think "equal" refers to the units being equal on all dimensions, whereas "square" means to make the plot square.  I see the use of "equal", but you are right that there is no counterpart, i.e., "noequal".

An alternative to where you placed "nosquare", is to put the counter-part where the "equal" is.  That is, rather than a strategy of undoing what's been done, set the appropriate setting at the point where that property is set.  Attached is an example, but I don't think it is 100% correct because nd == 3 restricts this to 3D plots, whereas it could be the successive plot is 2D and hence the "equal" would still not be undone.

Anyway, look into that; you're on the right path.  There is a "equal/noequal" and a "square/nosquare" to account for if both those settings are used.

(file #46175)

Dan Sebald <sebald>
Sun 03 Feb 2019 09:15:13 PM UTC, comment #12: 

My understanding is that, right now, Octave is not using the built-in Gnuplot colorbox tools at all.  There's a point very early on in __gnuplot_draw_axes__ where it simply inserts "unset colorbox" into the plot stream, turning off any colorboxes Gnuplot might create on its own.  Instead, Octave draws its own colorbar manually as a two-dimensional image (i.e., with "plot"), much like I did in my Gnuplot test script.  The image data is just two identical columns of numbers corresponding to the desired color labeling for the plot, and the palette is set in advance to give the right colors for each of those numbers.

It's possible (but I don't know enough to decide this) that it might be better in the long run to change Octave over to using Gnuplot's built-in colorbox, but I'm a little leery of making a change of that magnitude at my current level of understanding of the code, as I'm not sure whether it might break other things.  The problem for me is that there's not really a clearly specific "this bit draws the colorbar" section in the __gnuplot_draw_axes__ function.  Instead, all "2-d image" type children of the figure we're drawing are handled in the same way.  Since I don't know if there are other 2-d image components a figure might have, I'm not sure it's a good idea for me to mess with this at this stage.

However, in terms of addressing this particular bug rather than the Gnuplot colorbar as a whole, I suspect that the safest and most correct thing do might actually be to apply a correction to the code for drawing the main plot of an "axis equal" figure.  Right now, "set view equal xy(z)" is executed before the (s)plot command for the main plot, but the aspect ratio lock is never turned off afterwards and so it goes on to affect any subsequent figure components.  I would expect that this is not generally an intended behavior, so inserting "set size nosquare" at the end of the commands for the main plot might not have as many side effects as trying to change the colorbar plotting method.

If I am understanding things correctly, a good place to apply this correction might be to insert the following at line 1748 of __gnuplot_draw_axes__.m , after the plot command for the main plot has been completed:

  ## Prevent "axis equal"/"set view equal xy(z)" from deforming other parts of the figure
  if (nd == 3 &&
      strcmp (axis_obj.dataaspectratiomode, "manual") &&
      axis_obj.dataaspectratio(1) == axis_obj.dataaspectratio(2))
    fprintf (plot_stream, "set size nosquare;\n");
  endif

(This is the same test that is used to insert the "set view equal" command in the first place.)

Does this seem logical?

Anne Hanna <thebat137>
Sun 03 Feb 2019 05:45:51 PM UTC, comment #11: 

I don't have too much time to look at this right now.  I'll give some background, though, and if Anne is close to a solution perhaps she can come up with a changeset after having a bit more understanding.

In gnuplot, the colorbox has a dodgy history.  It was initially tacked onto 3D space (splot).  Maybe it was in 2D (plot) as well, but I think not because way back surfaces were the only place that color would have appeared; later some features in 2D with color appeared.  To add to that, the colorbox was drawn in the 3D space itself, as though it were another surface; it wasn't an entity by itself.  So, when the user would rotate a 3D plot in gnuplot, the colorbox would rotate along with the view.  It was silly, and someone eventually fixed that, but still the legacy colorbox was a really limited and confounding entity.  There is a newer alternative which improves on this.

What is needed in gnuplot is a very generic sort of colorbox/key treatment so there could be multiple keys, fine control, etc.  It's always been talked about, but there aren't the programming resources in gnuplot like other open source projects might have.

The colorbox control was improved, but one has to place the colorbox in what is called "user" mode.  There is a philosophy of backward compatibility in gnuplot to not break old scripts for users.  In some cases new features can be worked in with just some syntax extension.  In the case of colorbox, it appears the approach was to have a "default" or wow-this-is-lame mode and a newer "user" mode.  In user mode, from gnuplot's documentation:

 `origin x, y` and `size x, y` are used only in combination with the `user`
option. The x and y values are interpreted as screen coordinates by default,
and this is the only legal option for 3D plots. 2D plots, including splot with
`set view map`, allow any coordinate system to be specified.  Try for example:
     set colorbox horiz user origin .1,.02 size .8,.04
which will draw a horizontal gradient somewhere at the bottom of the graph.

I've searched the octave plotting scripts using grep and don't see much use of the "colorbox" keyword.  My guess is that the best approach is to modify things slightly so that Octave always uses "user" mode and places the position of the colorbar itself.  E.g., issue gnuplot commands like

set colorbox user
...
set colorbox origin screen 0.9,0.1 size screen 0.05,0.8

where the actual numbers would come from octave computations.

So, in summary, confirm whether Octave is using gnuplot's colorbox "user" mode.  If not, give that a try.

Dan Sebald <sebald>
Sun 03 Feb 2019 01:17:13 AM UTC, comment #10: 

Thanks, Rik.

I should also note a couple more bits of evidence supporting the explanation I suggested below.  First, the problem doesn't appear with the fltk graphics toolkit.  Second, reversing the plot order of the "main" plot and the pseudo-colorbar in my gnuplot example is another way to fix the problem in that example (instead of using "set size nosquare").

Anne Hanna <thebat137>
Sat 02 Feb 2019 06:34:36 AM UTC, comment #9: 

Adding Dan Sebald to the CC list since he understands the gnuplot interface.  Your suggestion seems correct to me.

Rik <rik5>
Project Administrator
Fri 01 Feb 2019 06:26:33 AM UTC, comment #8: 

I looked at this a bit more and found what I believe may be a solution.  I was able to construct an example Gnuplot script which seems to illustrate the same problem as is occuring in the Octave code.

set multiplot;
reset;

unset colorbox

#set size square
set tmargin screen 0.925;
set bmargin screen 0.11;
set lmargin screen 0.13;
set rmargin screen 0.75;
set xrange [-0.5:1.5]
set yrange [-0.5:3.5]
$map1 << EOD
1 2
3 4
5 6
7 8
EOD
set view equal xyz
set view map
splot '$map1' matrix with image

set tmargin screen 0.925;
set bmargin screen 0.11;
set lmargin screen 0.8275;
set rmargin screen 0.874;
#set view 0,0
$cb1 << EOD
1 10
2 20
3 30
4 40
5 50
6 60
7 70
8 80
EOD
set xrange [-0.5:1.5]
set yrange [-0.5:7.5]
unset xtics
#set size nosquare
plot '$cb1' matrix title '' with image

unset multiplot

This code draws a "main" plot and a pseudo-colorbar in a similar way to what Octave does, and results in the pseudo-colorbar being shorter in height than the main plot.  Uncommenting the "set size nosquare" command matches the pseudo-colorbar height to the main plot.

The thing I see happening here is that the combination of "set view equal xyz" and "set view map" in that order locks the scale ratio between the x and y axis units at 1:1 (as confirmed by "show size").  Since the pseudo-colorbar is drawn after the main plot, it picks up this setting.  (You can see that each of the 16 pseudo-colorbar "pixels" ends up square.)  So, since the pseudo-colorbar is very narrow in the x direction, it ends up very short in the y direction.

What we actually want is for the pseudo-colorbar to completely fill the tall, narrow region allocated for it, allowing its "pixels" to have whatever aspect ratio is needed for that task.  "set size nosquare" does this, and the pseudo-colorbar height now matches that of the main plot.

I tested this in Octave by editing the _gnuplot_draw_axes_ to insert a "set size nosquare" command right before the plot command for the colorbar, and it seems to fix the colorbar height without mucking up anything else.  Does this seem like a reasonable approach?

Anne Hanna <thebat137>
Mon 07 Jan 2019 06:31:06 PM UTC, comment #7: 

One more possible breadcrumb that I just found, and then I am definitely going to have to stop poking at this and defer to those more knowledgeable:

_actual_axis_position_ seems to be in charge of setting up the {rltb}margin values, and there's a note in there (lines 58-59) that:

 ## When using {rltb}margin, Gnuplot does not handle the specified
## aspect ratio properly, so handle it here.

At least for the "axis tight" case, this seems to be where we're getting the rlmargin distance halved, shrinking the graph.  Is it possible that Gnuplot has changed (i.e., fixed) how it handles this?  I noted that if I set:

aspect_ratio_2d = [1, 1];

on line 61 instead of letting the corrective calculation happen, it does fix the "axis tight" case without breaking the non-tight case.  It may break other things I don't know about, but it could also be a sign that the Gnuplot issue is actually corrected.

Anyway, if this is useful in addressing the bug, or if anyone has advice for me on how I can explore this on my own further, please let me know.

Anne Hanna <thebat137>
Mon 07 Jan 2019 05:44:38 PM UTC, comment #6: 

I should note that simply changing "set view map" to "set view 0,0" in _gnuplot_draw_axes_ is probably not an actual solution (at least not all by itself), because it breaks the "axis tight" graph.  If I change my code (the second example) to "axis equal; axis tight" with this edit in place, the graph ends up at half size, because "axis tight" cuts the lmargin to rmargin distance in half.  So presumably "set view 0,0" alone isn't fully compatible with the current method of computing tight margins, and some tweaks or an alternate approach are required.

Anne Hanna <thebat137>
Mon 07 Jan 2019 04:15:17 PM UTC, comment #5: 

I have recently been experiencing problems with colorbar lengths after "axis equal" on a pcolor plot in Octave 4.4.1 using the gnuplot graphics tookit (under Debian Linux).  I believe my problems are related to those discussed in this bug report, and I have some diagnostic information that may be useful in resolving it, after all these years.

In attempting to diagnose my issue, I dumped the plot stream to text files and played around with it in gnuplot.  I confirmed that the problematic part of the gnuplot stream is the same in my own code as in the MWE given in comment #4.  However, either the relevant parts of Octave have changed somewhat since #4 was written, or #4 was tested with a different graphics toolkit that might have different bugs in it.  With gnuplot 5.2 and Octave 4.4.1, "axis tight" is not required for the problem to manifest, and "axis square" does not cause it, with or without "axis tight".  So a current version of that MWE seems to be:

 clf;
[x, y, z] = peaks ();

pcolor (x, y, z);

axis equal
# axis normal       # Uncomment this line to make the problem go away.
cb(1) = colorbar ();

An even more egregious shrinking of the colorbar under "axis equal" occurs with my original test case, which was:

 clf
pcolor(round(rand([5, 3])))
axis equal
# axis normal       # Uncomment this line to make the problem go away.
colorbar

The only significant difference between the "axis equal" and "axis normal" plot streams in both MWEs is the presence of "set view equal xyz" near the beginning of the "axis equal" plot stream.  It seems that this use of "set view equal" does not play nicely with the later use of "set view map" to reorient the "three-dimensional" pcolor plot to be shown face-on.  If I change "set view map" to "set view 0,0" in my plot stream file and run it in gnuplot, the colorbar attains its correct height and the rest of the image seems (to my eye) to be correct.

We can see in the _gnuplot_draw_axes_ function that "set view map" is only used for "surface" type graphics objects, and then only under the following circumstance (line 1684):

 if (view_map && rot_x == 0 && rot_z == 0)

I don't think I understand the code well enough to see why graphs with these properties need map view rather than just an appropriate rotation (i.e., "set view 0,0"), but perhaps someone who understands this better than I can tease out
the reason and decide what the best fix is?

---------

The reason that "axis square" and "axis tight" are no longer relevant to this problem can also be seen in the _gnuplot_draw_axes_ function.  A "set view equal" command is inserted only under the following circumstance (lines 120-122):

  if (nd == 3 &&
      strcmp (axis_obj.dataaspectratiomode, "manual") &&
      axis_obj.dataaspectratio(1) == axis_obj.dataaspectratio(2))

Using "axis square" instead of "axis equal" currently causes axis_obj to fail this test (dataaspectratiomode is "auto"), so "set view equal xyz" is never set for the main plot and the problem does not occur.  "axis tight" doesn't affect the parameters checked by this test, so it doesn't help trigger the bug either.

Anyway, I hope this helps with the bug somewhat?  Not being able to have usable colorbars on these plots is making me crazy.  :D

Anne Hanna <thebat137>
Thu 24 Nov 2016 10:17:54 PM UTC, comment #4: 

I think the problem is either one of 'axis square' or 'axis equal' which affect change dataaspectratio and plotboxaspectratio.

 clf;
[x, y, z] = peaks ();

pcolor (x, y, z);
# axis square       # Uncomment this line or the next to see problem
axis equal
cb(1) = colorbar ();
axis tight

Rik <rik5>
Project Administrator
Wed 23 Nov 2016 10:25:09 PM UTC, comment #3: 

This issue might be FIXED in Octave 4.2.0.

When running the script from comment #0 in Octave 4.2.0, then I now get visually "too long" colorbars. But they go over the full height of the figure window, so probably that is "right height" and this last remaining issue is fixed, now. But I am not 100% sure how the "perfect plot result" should look like in this case.

Hartmut <hardy>
Wed 20 May 2015 03:30:16 PM UTC, comment #2: 

Item (1) is caused by the fact that surf produces 3-D output, but the command "view (0, 90)" is restricting it to 2-D.  For 2-D plots there is no need to take into account the Z-axis and that is why Octave doesn't bother to set the Z limits correctly.

This is a known issue and both Matlab and Octave have the pcolor() function for producing this sort of plot.  Replacing

surf (x,y,z)
view (0, 90)

with

pcolor (x,y,z)

correctly sets the zlim values.

Item (3), the size of the colorbar, still remains.  Re-titling the bug report to emphasize that issue.

Since colorbars, legends, and text objects are annotations.  It makes sense to add these only after the plot is visually the way you like it.  I know Octave should be able to handle the other ordering through callbacks, but at least for now there is a simple work around which is to have colorbar be the last command for a plot.

Rik <rik5>
Project Administrator
Mon 09 Feb 2015 11:04:19 PM UTC, comment #1: 

Hi,

After this changeset http://hg.savannah.gnu.org/hgweb/octave/rev/8064b5cdbc11 , axes sizes are consistent. Item (1) and (3) still remain.

Pantxo Diribarne <pantxo>
Project Member
Sun 24 Nov 2013 02:03:26 AM UTC, original submission:  

The demo below exhibits three problems

(1) The zlim() is not set correctly (the peaks are truncated)
(2) The axes plot boxes are not consistent in size
(3) The colorbar heights are short.

These problems only exist with "axes square; axes equal".

%!demo
%! clf;
%! [x, y, z] = peaks ();
%!
%! ax(1) = subplot (1, 3, 1);
%! surf (x, y, z)
%! view (0, 90)
%! axis square
%! axis equal
%! cb(1) = colorbar ();
%! axis tight
%!
%! ax(2) = subplot (1, 3, 2);
%! surf (x, y, z*10)
%! view (0, 90)
%! axis square
%! axis equal
%! cb(2) = colorbar ();
%! axis tight
%!
%! ax(3) = subplot (1, 3, 3);
%! surf (x, y, z/10)
%! view (0, 90)
%! axis square
%! axis equal
%! cb(3) = colorbar ();
%! axis tight
%!
%! set (gcf (), "position", get (gcf (), "position") .* [0.5 1 2 1])
%!
%! axes_positions = get (ax, 'position')
%! colorbar_positions = get (cb, 'position')

The resulting positions are below.

axes_positions =
{
  [1,1] =

     0.13000   0.11000   0.17072   0.81500

  [2,1] =

     0.43444   0.11000   0.15181   0.81500

  [3,1] =

     0.73889   0.11000   0.13289   0.81500

}
colorbar_positions =
{
  [1,1] =

     0.322065   0.403684   0.012804   0.227633

  [2,1] =

     0.605227   0.416295   0.011386   0.202409

  [3,1] =

     0.8883889   0.4289074   0.0099667   0.1771852

}

Ben Abbott <bpabbott>
Project Member

 

(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

Attach Files:
   
   
Comment:
   

Attached Files
file #49376:  __gnuplot_draw_axes__.m.patch added by thebat137 (795B - text/x-patch - proposed patch)
file #29695:  figure.png added by bpabbott (86KiB - image/png)

 

Depends on the following items: None found

Items that depend on this one: None found

 

Carbon-Copy List
  • -email is unavailable- added by sebald (Posted a comment)
  • -email is unavailable- added by rik5
  • -email is unavailable- added by thebat137 (Posted a comment)
  • -email is unavailable- added by hardy (Posted a comment)
  • -email is unavailable- added by rik5 (Posted a comment)
  • -email is unavailable- added by pantxo (Posted a comment)
  • -email is unavailable- added by bpabbott (Submitted the item)
  •  

    Do you think this task is very important?
    If so, you can add your encouragement to it.
    This task has 0 encouragements so far.

    Only project members can vote.

     

     

     

    Follow 12 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2020-09-12 rik5 StatusPatch Reviewed => Fixed
        Open/ClosedOpen => Closed
        Releasedev => 6.0.90
    2020-09-10 rik5 StatusConfirmed => Patch Reviewed
    2020-06-27 thebat137 Attached File- => Added __gnuplot_draw_axes__.m.patch, #49376
    2019-02-04 sebald Attached File- => Added octave-undo_equal-djs2019-01-04.diff, #46175
    2019-02-02 rik5 CategoryPlotting => Plotting with gnuplot
    2019-02-02 rik5 Carbon-Copy- => Added sebald
    2016-11-24 rik5 SummaryIncorrect colorbar size after "axis tight" => Incorrect colorbar size after "axis tight" or "axis equal"
    2015-05-20 rik5 StatusNone => Confirmed
        Summarytrouble with subplots and colorbar => Incorrect colorbar size after "axis tight"
    2013-11-24 bpabbott Attached File- => Added figure.png, #29695

    Back to the top


    Powered by Savane 3.5