From: Dima K. <gn...@di...> - 2020-09-09 09:08:14
Attachments:
gray.jpg
|
Hi. I vaguely recall mentioning this already, but I don't see it in my email. Apologies if this has already been reported. I have this script: set yrange [:] reverse set size ratio -1 plot "/tmp/gray.jpg" binary filetype=auto flipy with rgbimage,'-' using 1:2 notitle with points pt 3 ps 3 1854.0 1599.0 1596.0 1568.0 2170.0 1626.0 3649.0 1762.0 1937.0 1604.0 1243.0 1544.0 2412.0 1648.0 886.0 1508.0 141.0 1436.0 3088.0 1709.0 292.0 1455.0 2311.0 1639.0 647.0 1484.0 2662.0 1672.0 1105.0 1529.0 803.0 1499.0 4218.0 1811.0 731.0 1498.0 3743.0 1769.0 1371.0 1555.0 4100.0 1800.0 1446.0 1544.0 2092.0 1587.0 2863.0 1669.0 2930.0 1681.0 3197.0 1702.0 3341.0 1709.0 3483.0 1733.0 e I.e. we plot some points on top of the attached image. The contents of the image don't matter. Here we just have a gray field. I'm using the latest master branch, but I belive 5.4 does this too. 1. Running that script in an interactive terminal (I tried x11 and qt), the plot pops up just fine: the autoscale considered the image AND the points 2. We interactively zoom on any area with the mouse. This works too 3. We press 'u' to zoom out. The expectation is that we get back to the full view after step 1. Instead we get to a new view, zoomed-in on the points only, NOT on the image. Something about the reverse yrange is confusing I think. Have I reported this already? Thanks. |
From: Ethan A M. <me...@uw...> - 2020-09-09 16:36:21
|
On Wednesday, 9 September 2020 02:07:50 PDT Dima Kogan wrote: > Hi. I vaguely recall mentioning this already, but I don't see it in my > email. Apologies if this has already been reported. I have this script: > > set yrange [:] reverse > set size ratio -1 > plot "/tmp/gray.jpg" binary filetype=auto flipy with rgbimage,'-' using 1:2 notitle with points pt 3 ps 3 [snip] > e > > I.e. we plot some points on top of the attached image. The contents of > the image don't matter. Here we just have a gray field. I'm using the > latest master branch, but I belive 5.4 does this too. > > 1. Running that script in an interactive terminal (I tried x11 and qt), > the plot pops up just fine: the autoscale considered the image AND the > points > > 2. We interactively zoom on any area with the mouse. This works too > > 3. We press 'u' to zoom out. The expectation is that we get back to the > full view after step 1. Instead we get to a new view, zoomed-in on > the points only, NOT on the image. Hmm. But if you press 'p' for "previous" the unzoom works correctly. That is probably a clue. Also, if the inline data is replaced by a datablock the problem goes away. I think the issue is that because your example uses in-line data it cannot be re-read. The program tries to work around this by reusing the contents of the various internal data structures but in this case the workaround fails. Possibly fixable, but I think the primary lesson is that data blocks are much preferred to in-line data if you are going to be manipulating/re-drawing the plot. Ethan > Something about the reverse yrange is confusing I think. Have I reported > this already? > > Thanks. |
From: Dima K. <gn...@di...> - 2020-09-12 03:21:40
|
Ethan A Merritt <me...@uw...> writes: > I think the issue is that because your example uses in-line data it > cannot be re-read. The program tries to work around this by reusing > the contents of the various internal data structures but in this case > the workaround fails. Possibly fixable, but I think the primary lesson > is that data blocks are much preferred to in-line data if you are > going to be manipulating/re-drawing the plot. Hi. 100% of my fairly heavy usage of gnuplot uses inline data. The particular case in this report is fairly common too: when doing any sort of computer vision that annotates an image, you want to display the source image with a flipped y axis, since the origin pixel is at the top-left. In any case, this worked in 5.2. I just did a bisection, and I can now see why this seemed familiar. The commit that broke it: https://sourceforge.net/p/gnuplot/gnuplot-main/ci/36a2407e50/ The person who broke it was me! But despite what git says, I have very little recollection of any of this. Ethan: do you have a good sense of what's happening here, and can you easily fix it now? If not, I can poke at it, and figure it out. dima |
From: Dima K. <gn...@di...> - 2020-09-13 04:01:30
|
Ethan A Merritt <me...@uw...> writes: > And even after tracking it that far I still don't understand why > 'p' works and 'u' doesn't. If you can figure that out I'd be > happier with declaring it fixed. In my tests just now 'p' and 'u' both show this issue. Are you 100% sure that 'p' does NOT show the issue for you? |
From: Ethan A M. <me...@uw...> - 2020-09-12 05:52:22
Attachments:
refresh_volatile_reversed_axis.patch
|
On Friday, 11 September 2020 20:13:33 PDT Dima Kogan wrote: > In any case, this worked in 5.2. I just did a bisection, and I can now > see why this seemed familiar. The commit that broke it: > > https://sourceforge.net/p/gnuplot/gnuplot-main/ci/36a2407e50/ > > The person who broke it was me! But despite what git says, I have very > little recollection of any of this. Ethan: do you have a good sense of > what's happening here, and can you easily fix it now? If not, I can poke > at it, and figure it out. > > dima I am puzzled because I do not understand the difference between returning to the top level zoom state by pressing 'p' to step backwards through the stack of zoom operations and pressing 'u' to jump back to the top of the stack. Either way it should be applying the same state (confirmed in the debugger) but for some reason that I don't understand the former works correcly and the latter doesn't. I _think_ that the problem involves this macro in axis.h %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /* Simplest form of autoscaling (no check on autoscale constraints). * Used by refresh_bounds() and refresh_3dbounds(). * Used also by autoscale_boxplot. */ #define autoscale_one_point(axis, x) do {\ if (axis->set_autoscale & AUTOSCALE_MIN && x < axis->min) \ axis->min = x; \ if (axis->set_autoscale & AUTOSCALE_MAX && x > axis->max) \ axis->max = x; \ } while (0); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% as called from plot2d.c:refresh_bounds() when zooming volatile data. Note that the macro does not consider the case of reversed axes. Adding a test for (axis->min < axis->max) seems to make your test case work. See attached patch. The unpatched code does the wrong thing for reversed axes. The patched code does nothing at all for reversed axes, is it probably wrong also but for some case other than yours. A more complete fix for the macro is wanted. And even after tracking it that far I still don't understand why 'p' works and 'u' doesn't. If you can figure that out I'd be happier with declaring it fixed. Ethan -- Ethan A Merritt Biomolecular Structure Center, K-428 Health Sciences Bldg MS 357742, University of Washington, Seattle 98195-7742 |
From: Ethan A M. <me...@uw...> - 2020-09-12 06:19:08
Attachments:
refresh_volatile_reversed_axis.patch
|
On Friday, 11 September 2020 22:51:03 PDT Ethan A Merritt wrote: > I _think_ that the problem involves this macro in axis.h > > %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% > /* Simplest form of autoscaling (no check on autoscale constraints). > * Used by refresh_bounds() and refresh_3dbounds(). > * Used also by autoscale_boxplot. > */ > #define autoscale_one_point(axis, x) do {\ > if (axis->set_autoscale & AUTOSCALE_MIN && x < axis->min) \ > axis->min = x; \ > if (axis->set_autoscale & AUTOSCALE_MAX && x > axis->max) \ > axis->max = x; \ > } while (0); > %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% > > as called from plot2d.c:refresh_bounds() when zooming volatile data. > > Note that the macro does not consider the case of reversed axes. > Adding a test for (axis->min < axis->max) seems to make your > test case work. See attached patch. Better patch (but still not fully correct) Ethan |
From: Dima K. <gn...@di...> - 2020-09-13 04:08:14
|
Dima Kogan <gn...@di...> writes: > Ethan A Merritt <me...@uw...> writes: > >> And even after tracking it that far I still don't understand why >> 'p' works and 'u' doesn't. If you can figure that out I'd be >> happier with declaring it fixed. > > In my tests just now 'p' and 'u' both show this issue. Are you 100% sure > that 'p' does NOT show the issue for you? I just tried this with the x11, qt and wxt terminals, and in all 3 cases both 'u' and 'p' show this issue. I'm at the git HEAD as off a few days ago: commit 160d7511bcbdfd0d1943a624af5fc42504a9f84c Author: Ethan A Merritt <merritt@u.washington.edu> Date: Thu Sep 3 20:20:23 2020 -0700 new function (long)argb = rgbcolor("name") The test is: 1. start gnuplot 2. "load" the script in the first email in this thread 3. interactively zoom 4. 'u' or 'p' I'm on GNU/Linux. If I can reproduce the behavior you're seeing ('p' and 'u' work differently), then I'll be happy to debug it. |
From: Ethan A M. <me...@uw...> - 2020-09-13 17:37:00
|
On Saturday, 12 September 2020 21:07:58 PDT Dima Kogan wrote: > Dima Kogan <gn...@di...> writes: > > > Ethan A Merritt <me...@uw...> writes: > > > >> And even after tracking it that far I still don't understand why > >> 'p' works and 'u' doesn't. If you can figure that out I'd be > >> happier with declaring it fixed. > > > > In my tests just now 'p' and 'u' both show this issue. Are you 100% sure > > that 'p' does NOT show the issue for you? > > I just tried this with the x11, qt and wxt terminals, and in all 3 cases > both 'u' and 'p' show this issue. I'm at the git HEAD as off a few days > ago: > > commit 160d7511bcbdfd0d1943a624af5fc42504a9f84c > Author: Ethan A Merritt <merritt@u.washington.edu> > Date: Thu Sep 3 20:20:23 2020 -0700 > > new function (long)argb = rgbcolor("name") > > The test is: > > 1. start gnuplot > 2. "load" the script in the first email in this thread > 3. interactively zoom > 4. 'u' or 'p' > > I'm on GNU/Linux. If I can reproduce the behavior you're seeing ('p' and > 'u' work differently), then I'll be happy to debug it. Try this: 1) start gnuplot 2) load script 3) zoom 4) 'u' plot is now incorrectly scaled 5) 'n' shows zoom state from (3) 6) 'p' correctly unzooms to original plot Now that I try more sequences I notice that replacing 'p' with 'u' in step (6) also works correctly. So maybe the issue is whether the previous operation was 'n'? Or there's some parity issue with the count of operations? Regardless, I think autoscaling in the current HEAD now works correctly for your test case. I also think that it is incorrect for the unzoom operation to invoke autoscaling at all, but that would require additional code changes. Ethan |
From: Dima K. <gn...@di...> - 2020-09-13 20:18:11
|
Hi. I do observe your sequence work at you state: > 1) start gnuplot > 2) load script > 3) zoom > 4) 'u' > plot is now incorrectly scaled > 5) 'n' > shows zoom state from (3) > 6) 'p' > correctly unzooms to original plot Step 6 may be 'u' or 'p'. The reason things don't look the same after steps 4 and 6 is the value of { axis_array[FIRST_Y_AXIS].min, axis_array[FIRST_Y_AXIS].max } at the start of the refresh_bounds() call. This function assumes min<max. And if we're reversing some axis, this is done at the very end of refresh_bounds() with the axis_check_range() calls. In step 3, refresh_bounds() sees {min,max} = {4000,-500} In step 6, refresh_bounds() sees {min,max} = {1850,1400} This is dependent on the actual zoom bounds. Both of these have the unexpected min>max, obviously, but in step 6 we get lucky, and it ends up doing the right thing anyway, in this case. Specifically the diverging behavior comes from refresh_bounds() calls process_image() calls STORE_AND_UPDATE_RANGE() calls store_and_update_range() The logic in store_and_update_range() is effectively: if ( curval > axis->max && curval >= axis->min ) axis->max = curval; Which is correct only if axis->min < axis->max I'm not entirely sure what the values of axis->min, axis->max should be at the start of refresh_bounds(), but reordering them makes this thing work correctly. Patch (usable for this specific test case only): diff --git a/src/plot2d.c b/src/plot2d.c index b2877eb89..7e4e57259 100644 --- a/src/plot2d.c +++ b/src/plot2d.c @@ -299,6 +299,17 @@ refresh_bounds(struct curve_points *first_plot, int nplots) struct curve_points *this_plot = first_plot; int iplot; /* plot index */ + + if(axis_array[FIRST_Y_AXIS].min > axis_array[FIRST_Y_AXIS].max) + { + double t = axis_array[FIRST_Y_AXIS].min; + axis_array[FIRST_Y_AXIS].min = axis_array[FIRST_Y_AXIS].max; + axis_array[FIRST_Y_AXIS].max = t; + } + + + + for (iplot = 0; iplot < nplots; iplot++, this_plot = this_plot->next) { int i; /* point index */ struct axis *x_axis = &axis_array[this_plot->x_axis]; Applying this patch makes the test case work, even before any of your patches from yesterday. Clearly, this should be more general, but I'm hazy on the details, so it'd be better if you finish this, probably. Thanks! |
From: Ethan A M. <me...@uw...> - 2020-09-13 23:32:13
|
On Sunday, 13 September 2020 13:17:59 PDT Dima Kogan wrote: > Hi. I do observe your sequence work at you state: > > > 1) start gnuplot > > 2) load script > > 3) zoom > > 4) 'u' > > plot is now incorrectly scaled > > 5) 'n' > > shows zoom state from (3) > > 6) 'p' > > correctly unzooms to original plot > > Step 6 may be 'u' or 'p'. The reason things don't look the same after > steps 4 and 6 is the value of > > { axis_array[FIRST_Y_AXIS].min, axis_array[FIRST_Y_AXIS].max } > > at the start of the refresh_bounds() call. This function assumes > min<max. And if we're reversing some axis, this is done at the very end > of refresh_bounds() with the axis_check_range() calls. > > In step 3, refresh_bounds() sees {min,max} = {4000,-500} > In step 6, refresh_bounds() sees {min,max} = {1850,1400} > > This is dependent on the actual zoom bounds. Both of these have the > unexpected min>max, obviously, but in step 6 we get lucky, and it ends > up doing the right thing anyway, in this case. OK. But no autoscaling at all should be necessary during zoom or unzoom. That is true even for nonvolatile data, but is doubly true for volatile data. The whole point of zoom is that the bounds are being chosen interactively by the mouse, not by the content of the plot. My thought is to add a flag somewhere that zoom/unzoom is in progress, and skip all autoscaling operations if it is set. In fact there already is a flag "inside_zoom" but it isn't used for much. I have not yet inventoried all the places in the code that would need to be changed. Ethan |