bugGNU Octave - Bugs: bug #59731, wrong colorbar length when aspect...

 
 

bug #59731: wrong colorbar length when aspect ratio is manual

Submitted by:  Hg200 <hg200>
Submitted on:  Sat 19 Dec 2020 04:05:33 PM UTC  
 
Category:  Plotting Severity:  3 - Normal
Priority:  5 - Normal Item Group:  Incorrect Result
Status:  Confirmed Assigned to:  None
Originator Name:  Hg200 Open/Closed:  Open
Release:  6.1.0 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)

Thu 31 Dec 2020 08:21:13 PM UTC, comment #8: 

I did further research on _actual_axis_position_ (). As guessed in comment #7, this function calculates the position and size of the "image of the axes after applying the aspect ratio". To understand why this is needed, one must understand how objects are plotted in the Octave opengl-renderer. In graphics.cc

void axes::properties::update_camera (void)

the view and projection matrices are composed as a function of the viewpoint, target, up vector and the bounding box. The aspect ratio of the data is taken into account in the view matrix "x_gl_mat1". In a second step, the FOV is fitted into the bounding box. In simplified terms, this is basically controlled by the projection "x_gl_mat2".

A color bar must now be scaled based on the actual visible "image of the axes" in the figure after all those transformations. Therefore it is necessary to know the position of the axes after the projection (aspect ratio, rotation). IMO, the correct way to do this would be to create an internal variable in graphics.cc that specifies the final image size after projection. Now, the code in _actual_axis_position_ () also tries to calculate what the aspect ratio does to the image. For 2D this is easy, but for 3D it is a nightmare.

The code is not only messy, but also vulnerable. For example, it generates wrong color bar lengths when the unit is set to pixels before calling colorbar. The following test code produces color bars with two different lengths:

hax = axes ();
sombrero;
view(2)
daspect ([1,1,1]);
set (hax, 'units', 'normalized');
colorbar('south');
figure;
hax = axes ();
sombrero;
view(2)
daspect ([1,1,1]);
set (hax, 'units', 'pixels');
colorbar('south');

This is due to line 54, where axis_obj.outerposition depends on the current unit setting of the axes. If the unit is "pixels", this conversion is wrong:

pos_in_pixels = axis_obj.outerposition .* fig_position([3, 4, 3, 4]);

I think, based on what we know now, I can try to create a fix for colorbar.m under the prerequisites that are mentioned in comment #7. -> colorbar length calculation is omitted in 3D / manual mode, but is taken into account for 2D plots. 

Hg200 <hg200>
Mon 28 Dec 2020 03:44:55 PM UTC, comment #7: 

I have attached a file to make a colorbar investigation. It is advisable to run the file once under Octave and then with Matlab and then compare the output. Danger, many files will be generated!

Some conclusions are:

i.) In Matlab, in a view(3) plot the colorbar is almost as high as the window size. The colorbar does not seem to depend on the visible image size of the axes in the plot window. It also looks like it does not depend on whether the aspect ratio is "auto" or "manual". If we remove the "messy code" from colorbar.m (see comment #4 and comment #5) then everything becomes better in Octave. Example code:

figure ('position', [50, 100, 300, 600]);
hax = axes ();
[xx, yy] = meshgrid (linspace (-8, 8, 41));
r = sqrt ((xx).^2 + (yy).^2);
zz =  sin (r) ./ r;
surf (xx, yy, zz, 'edgecolor', 'none');
set (gcf, 'color', 'c');
view (3);
daspect ([1, 1, 1]);
hcb = colorbar ('east');

ii.) For view(2) plots in Matlab, the colorbar is scaled based on the width/height of the visible image of the axes in the plot window.  When the color bar is at the "outside" position, the length exactly matches the size of the image of the axes. Currently Octave's colorbar.m more or less honors this behavior. However, this feature breaks if we delete the "messy code" from colorbar.m. Example plot:

figure ('position', [50, 100, 600, 200]);
hax = axes ();
[xx, yy] = meshgrid (linspace (-8, 8, 41));
r = sqrt ((xx).^2 + (yy).^2);
zz =  sin (r) ./ r;
surf (xx, yy, zz, 'edgecolor', 'none');
set (gcf, 'color', 'c');
view (2);
daspect ([1, 1, 1]);
hcb = colorbar('south');

iii.) Difficulties: Currently, the Octave colobar algorithm calculates the position and length of the colorbar based on the bounding box (= hax, 'position'). The problem with this approach is that we cannot easily obtain the actual width/height of the visible axes image in the plot window, especially when we are in 3D: The actual aspect ratio of the image is determined by the opengl projection and view transformation, while the bounding box size is unaffected, even if we rotate the image. Example: The following code sequence returns the same bounding box coordinates, regardless of whether the aspect ratio is set to "manual" or "auto":

figure;
hax = axes ();
[xx, yy] = meshgrid (linspace (-8, 8, 41));
r = sqrt ((xx).^2 + (yy).^2);
zz =  sin (r) ./ r;
surf (xx, yy, zz, 'edgecolor', 'none');
set (gcf, 'color', 'c');
set (hax, "units", "pixels");
get (hax, 'position')
daspect ([1, 1, 1]);
get (hax, 'position')

References:
https://wiki.octave.org/User:Hg200

iv.) If we switch the aspect ratio in the toolkit gnuplot to "manual", then we obtain only garbage in the plot window even when there is no colorbar:

graphics_toolkit('gnuplot');
sombrero;
daspect ([1, 1, 1]);

I would vote to not maintain gnuplot any more, at least concerning this bug report.

If we want to keep feature ii.), we need some minimal corrections regarding the "aspect ratio" in "manual mode" when a view(2) plot is created. So we need to merge some of the "messy code". However, I still don't understand what exactly happens in "_actual_axis_position_.m".

Anyway, so far my evaluations.

(file #50582)

Hg200 <hg200>
Tue 22 Dec 2020 04:08:37 PM UTC, comment #6: 

I wonder if all the fiddling with placement was done to support gnuplot?

If eliminating the code produces reasonable results then we should just do that.

Rik <rik5>
Project Administrator
Mon 21 Dec 2020 11:12:03 PM UTC, comment #5: 

It would be helpful to know the original purpose behind "_actual_axis_position_.m" and also the variable "off" in "calc_cbar_position". In the first part of "_actual_axis_position_.m" the position and size of the axes is determined in pixel coordinates. But then a lots of calculations follow that depend on whether the aspect ratio mode is set to "manual" or not.

I plotted the code in the OP for colorbar variants (north, west, ..., northoutside, westoutside, ...) with and without aspect ratio set to [1,1,1] in Matlab R2018. The color bar is always at the same position, regardless of whether the aspect ratio is set to "manual" or "auto". Can't we just always position the colorbar as when the aspect ratio is set to "auto"? If I remove all the code in colorbar.m that does the calculations for the manual case, and if I set the variable "off" to zero, the result doesn't look so bad. Maybe some fine tuning necessary. But probably there are cases i don't see yet ;-)

Hg200 <hg200>
Mon 21 Dec 2020 09:15:31 PM UTC, comment #4: 

More debugging shows that the root of the problem seems to be in _actual_axis_position_.m which is its own script in plot/utils.  The code in that function has a very messy exception for when the aspect ratio is "manual" and there is a FIXME note that it hasn't been tested for all cases.

Rik <rik5>
Project Administrator
Mon 21 Dec 2020 05:02:03 PM UTC, comment #3: 

The colorbar created by the

colorbar ('southoutside');

command crosses out the whole image ;-) So not only the length but also the position doesn't seem to be quite right in some cases. I don't have any idea about it yet though. In this code section there are also conditions from gnuplot added. Why these strange position calculations? It would be interesting to know if that ever worked.

Hg200 <hg200>
Mon 21 Dec 2020 04:15:50 PM UTC, comment #2: 

Also confirmed that the place to resolve this is in the calc_cbar_position subfunction within colorbar.m.

Rik <rik5>
Project Administrator
Mon 21 Dec 2020 05:18:19 AM UTC, comment #1: 

Confirmed.  Changing OS to Any since this also happens on Linux.

Rik <rik5>
Project Administrator
Sat 19 Dec 2020 04:05:33 PM UTC, original submission:  

Run following code and compare with Matlab. I have attached also a screenshot for comparison.

hax = axes ();
[xx, yy] = meshgrid (-20:.1:20, -20:.1:20);
r = sqrt ((xx).^2 + (yy).^2);
zz =  sin (r) ./ r;
surf (xx, yy, zz, 'edgecolor', 'none');
daspect ([1, 1, 1]);
hcb = colorbar;
get (hcb, 'position')

The Matlab output for "hcb" is

0.8338    0.1100    0.0381    0.8150

I suspect the code in "calc_cbar_position" around line 600 but haven't had a closer look at this.

Hg200 <hg200>

 

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

Attach Files:
   
   
Comment:
   

Attached Files
file #50582:  colbartest.m added by hg200 (2KiB - text/x-objcsrc)
file #50521:  mat_vs_oct.jpg added by hg200 (33KiB - image/jpeg)

 

Depends on the following items: None found

Items that depend on this one: None found

 

Carbon-Copy List
  • -email is unavailable- added by rik5 (Posted a comment)
  • -email is unavailable- added by hg200 (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 4 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2020-12-28 hg200 Attached File- => Added colbartest.m, #50582
    2020-12-21 rik5 StatusNone => Confirmed
        Operating SystemMicrosoft Windows => Any
    2020-12-19 hg200 Attached File- => Added mat_vs_oct.jpg, #50521

    Back to the top


    Powered by Savane 3.5