Menu

#1881 Error in axis range results in mouse stuck in coordinate mode

None
closed-fixed
nobody
None
2016-12-12
2016-12-11
Dan Sebald
No

I wish I had a simple example to illustrate the following problem, but I can't seem to find one. The app I'm seeing this problem with is a big bunch of commands and data. There are actually a couple problems which I will summarize at the end.

Basically, I'm using multiaxes that utilize data and when zooming too closely one of the axes has no data within it's borders. So, it produces the following error message:

line 2824: Can't plot with an empty x2 range!

But after the other axes plots just fine, the mouse is stuck showing a coordinate and from there doesn't behave as it should. Rather, if I click the left mouse button, gnuplot attempts to plot again and displays the message above once again.

Here's the hunk of code where I think the problem arises:

    /* check that xmin -> xmax is not too small */
    axis_checked_extend_empty_range(FIRST_X_AXIS, "x range is invalid");

    if (axis_array[SECOND_X_AXIS].linked_to_primary) {
        clone_linked_axes(axis_array[SECOND_X_AXIS].linked_to_primary, &axis_array[SECOND_X_AXIS]);
        /* FIXME: This obsoletes OUTRANGE/INRANGE for secondary axis data */
    } else if (uses_axis[SECOND_X_AXIS] & USES_AXIS_FOR_DATA) {
        /* check that x2min -> x2max is not too small */
        axis_checked_extend_empty_range(SECOND_X_AXIS, "x2 range is invalid");
    } else if (axis_array[SECOND_X_AXIS].autoscale) {

The error happens in axis.c function axis_checked_extend_empty_range:

    if (dmax - dmin == 0.0) {
    /* empty range */
    if (this_axis->autoscale) {
        /* range came from autoscaling ==> widen it */
        double widen = (dmax == 0.0) ?
        FIXUP_RANGE__WIDEN_ZERO_ABS
        : FIXUP_RANGE__WIDEN_NONZERO_REL * fabs(dmax);
        if (!(axis == FIRST_Z_AXIS && !mesg)) /* set view map */
        fprintf(stderr, "Warning: empty %s range [%g:%g], ",
            axis_name(axis), dmin, dmax);
        /* HBB 20010525: correctly handle single-ended
         * autoscaling, too: */
        if (this_axis->autoscale & AUTOSCALE_MIN)
        this_axis->min -= widen;
        if (this_axis->autoscale & AUTOSCALE_MAX)
        this_axis->max += widen;
        if (!(axis == FIRST_Z_AXIS && !mesg)) /* set view map */
        fprintf(stderr, "adjusting to [%g:%g]\n",
            this_axis->min, this_axis->max);
    } else {
        /* user has explicitly set the range (to something empty)
               ==> we're in trouble */
        int_error(NO_CARET, "Can't plot with an empty %s range!",
              axis_name(axis));
    }

and I'm using no autoscale...the second alternative above. It must be that at the point of this error, the mouse hasn't yet had its icon changed back to the normal pointer.

So, that's one error. The second error concerns why gnuplot can't figure out the proper scaling regardless of whether there is any data within the border as a result of zooming when I've used "set x2range"?

So that's

1) Mouse state stuck at coordinate when the "int_error" path is followed during a plot.
2) Gnuplot should be able to figure out the scaling easy enough even though no data is within the border.

Regarding #2, perhaps I'm not understanding the way this works, as I see in the code this

    if (axis_array[SECOND_X_AXIS].linked_to_primary) {

case. I'll look through the documentation about whether I can do that in this case, because all I really want is to have the same data but the axis scale represented differently.

Discussion

  • Dan Sebald

    Dan Sebald - 2016-12-11

    The x11 terminal mouse cursor reverts back to the normal cross (even though Qt terminal doesn't). So, the restoration takes place before the plot:

        } else {
    
            /* complete zoom (any button
             * finishes zooming.) */
    
    [snip]
            if (term->set_cursor) {
            term->set_cursor(0, 0, 0);
            if (mouse_setting.annotate_zoom_box && term->put_tmptext) {
                term->put_tmptext(1, "");
                term->put_tmptext(2, "");
            }
            }
    

    However, the x11 terminal also gets in a state for which conventional mouse behavior is lost. I think the issue there is that Qt doesn't restore the mouse cursor immediately because of it's event loop construct.

    Anyway, the way I see it, if a command line generates a proper plot, gnuplot should be set up that no matter what it does to replot via the mouse it can't cause an error. Either the error should be disallowed or perhaps the data needs to be set up correctly.

    In static mouse.c is this routine apply_zoom(). It seems to makes sense. The mouse code figures out what the new zoom boundary should be, and in apply_zoom is:

        /* If we are zooming, we don't want to autoscale the range.
         * This wasn't necessary before we introduced "refresh".  Why?
         */
        if (zoom_now == zoom_head && z != zoom_head) {
        axis_array[FIRST_X_AXIS].autoscale = AUTOSCALE_NONE;
        axis_array[FIRST_Y_AXIS].autoscale = AUTOSCALE_NONE;
        axis_array[SECOND_X_AXIS].autoscale = AUTOSCALE_NONE;
        axis_array[SECOND_Y_AXIS].autoscale = AUTOSCALE_NONE;
        }
    

    So, zooming always has no autoscale... so why the error about no value x2 range? (And what is quandry in the comment of the code above?)

     
  • Dan Sebald

    Dan Sebald - 2016-12-11

    Here's an example of another warning that does appear upon issuing the command, but after doing a zoom, the pressing 'u' the message "warning: x axis range undefined or overflow" appears:

    gnuplot> plot '-' with lines axis x2y1
    input data ('e' ends) > -10 1
    input data ('e' ends) > 10 -1
    input data ('e' ends) > end
    gnuplot>          warning: x axis range undefined or overflow
    

    Again, as I see it, mouse actions shouldn't cause any warnings/errors regarding plot range.

     
  • Ethan Merritt

    Ethan Merritt - 2016-12-11

    dunno about the rest of it, but this bit seems dubious:
    "Mouse state stuck at coordinate when the "int_error" path is followed during a plot"
    You're using the x11 terminal, right? So the mousing is controlled by a separate process. int_error() in the main process cannot affect it. Heck you can kill the main process with "killall gnuplot" and the x11 window will still do mousing. So I think you may have misdiagnosed this.

     
    • Dan Sebald

      Dan Sebald - 2016-12-11

      Both Qt and x11 get stuck in the coordinate state. I'm not referring to the mouse cursor getting stuck at one position, as in freeze. I'm referring to the appearance of the mouse cursor and its subsequent behavior. The cursor goes from a cross-hair state to a coordinate state with a box outlining where the new border should be. It's when doing the second mouse botton click to select the second corner then gnuplot int_error when drawing results in Qt mouse cursor still having coordinates displayed next to the icon.

      Anyway, it is sort of a moot issue because there shouldn't be any int_error as a result of zooming or panning. I've explored that in one of the posts just before this one (chronologically...may be lower in the list visibly). Having made a small change so there are no int_error, it has uncovered more bugs as to the presensce and formatting of time data in the x2 tic annotation.

       
  • Dan Sebald

    Dan Sebald - 2016-12-11

    OK, I think I'm getting closer now. First, I don't necessarily agree with this conditional test:

        } else if (uses_axis[SECOND_X_AXIS] & USES_AXIS_FOR_DATA) {
            /* check that x2min -> x2max is not too small */
            axis_checked_extend_empty_range(SECOND_X_AXIS, "x2 range is invalid");
    

    Why should that be a problem? FIRST_X_AXIS doesn't behave that way. (Maybe it did at one time and nobody thought to change the behavior for SECOND_X_AXIS and SECOND_Y_AXIS.) For example:

    gnuplot> plot '-' with lines
    input data ('e' ends) > -10 -1
    input data ('e' ends) > 10 1
    input data ('e' ends) > end
    gnuplot> 
    

    works fine.

    But it turns out that via the mouse, the above code isn't run. Instead, it goes through

        if (refresh_ok == E_REFRESH_OK_2D) {
        refresh_bounds(first_plot, refresh_nplots);
        do_plot(first_plot, refresh_nplots);
        update_gpval_variables(1);
    

    then

    /* Helper function for refresh command.  Reexamine each data point and update the
     * flags for INRANGE/OUTRANGE/UNDEFINED based on the current limits for that axis.
     * Normally the axis limits are already known at this point. But if the user has
     * forced "set autoscale" since the previous plot or refresh, we need to reset the
     * axis limits and try to approximate the full auto-scaling behaviour.
     */
    void
    refresh_bounds(struct curve_points *first_plot, int nplots)
    

    and that route doesn't seem to have the same sorts of logic tests:

        this_plot = first_plot;
        for (iplot = 0;  iplot < nplots; iplot++, this_plot = this_plot->next) {
    
        /* handle 'reverse' ranges */
        axis_revert_range( this_plot->x_axis );
        axis_revert_range( this_plot->y_axis );
    
        /* Make sure the bounds are reasonable, and tweak them if they aren't */
    fprintf(stderr, "HERE 1\n");
        axis_checked_extend_empty_range(this_plot->x_axis, NULL);
        axis_checked_extend_empty_range(this_plot->y_axis, NULL);
        }
    

    This refresh_bounds() routine is used only one other place I see, which is the cumulative average family of plots.

    Anyway, when the mouse is setting the x1,y1,x2,y2 boundaries for the plot, there is no reason to call refresh_bounds(). How should we go about addressing this? Something like:

        if (refresh_ok == E_REFRESH_OK_2D) {
        IF (!MOUSE_CODE_SET_VARIABLE_NOT_TO_REFRESH)
        refresh_bounds(first_plot, refresh_nplots);
        do_plot(first_plot, refresh_nplots);
        update_gpval_variables(1);
    

    or something like the diff file I'm attaching? The patch I attached works for me, but whether it breaks the cumulative average family of features, I don't know. Beyond that, with the attached patch--though the plot for both axes now works fine--when I zoom the plot or move the mouse wheel the time tic annotation disappears on the x2 axis. Also, there's a big space between the time tic annotation and top border crowding out the title. There's too many issues here to make this functional, so I think I'm going to drop the dual-scale plot idea.

     
  • Dan Sebald

    Dan Sebald - 2016-12-11

    I've managed my original goal by plotting a function 1/0 on one of the axes. So, you can mark this one "won't fix", if you think the zooming code with data is too fragile. I turns out that the tic annotation behavior isn't related to the int_error, so I'm going to post a different bug report for that.

     
  • Ethan Merritt

    Ethan Merritt - 2016-12-12
    • status: open --> closed-fixed
    • Group: -->
    • Priority: -->
     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.