Work at SourceForge, help us to make it a better place! We have an immediate need for a Support Technician in our San Francisco or Denver office.


#1388 Per-line ranges apply only to functions, not to data plots

Christoph Bersch

Today I observed, that "per-line" ranges, i.e. something like

set xrange [1:5]
plot x lc rgb 'black', [3:4] x lc rgb 'red' lw 5

works fine for function, the example above works fine. But for data the range settings of the second command are ignored:

$data <<EOF

set xrange [1:5]
set style data lines
plot $data u 1:1 lc rgb 'black', [3:4] $data u 1:1 lc rgb 'red' lw 2

I would expect this to work in the same manner as for functions.



  • Ethan Merritt
    Ethan Merritt

    I never intended the piecewise ranges to apply to data files. The idea was to allow independent sampling ranges. I guess the documentation could make that clearer.

    Even in older gnuplot versions you could filter the range of input data in the using spec. The lack of control only existed for functions, which don't have a using spec, and sampled functions done with '+', which otherwise have no provision for setting a range.

    I realize that this makes a range statement at the very start of a plot command different from ranges in the later positions. This is not ideal. The long-standing interpretation of an initial range has been that it was equivalent to a "set xrange" statement. My own preference would be to drop that interpretation altogether and have it be analogous to the later ranges. I.e. it would only apply to sampling the first plot segment. But I haven't made that change because I expect others to disagree with me on this point.

    Maybe I'm wrong and other people would generally agree with me that since we are not promising backward compatibility, internal consistency in version 5 is more important than retaining the old interpretation of the first range spec in a plot command. What do you think?

  • Karl Ratzsch
    Karl Ratzsch

    I´ve got one (possibly stupid) idea for this: Can´t the per-line ranges just be given after the function or file name? Then one could have both, e.g.

     plot [-11:11] "data" [-10:10], f(x) [1:6]

    and it´d be backward compatible, too.

    Last edit: Karl Ratzsch 2014-04-25
  • I was just surprised, that the piecewise ranges don't apply to data file. I would find that much more consistent, no matter if there other ways (using) to achieve the same result.

    What I also found non-intuitive was, that e.g. the plot

    plot [0:10] x, [10:20] x**2

    draws only the x part, because the xrange is set to [0:10]. However, using

    plot sample [0:10] x , [10:20] x**2

    uses the default range of [-10:10]. Only the command

    plot [0:20] sample [0:10] x, [10:20] x**2

    gives the "correct" result.

    Intuitively, I would expect the command

    `plot [0:10] x, [10:20] x**2

    to set xrange to [0:20] and plot the functions in their individual intervals. If one wants to specify a different overall xrange, one could use plot xrange [-10:30] [0:10] x, [10:20] x**2. But that would have other downsides. Expecially, when the yranges come into play...

    Don't know if there exists a better convention to properly combine the piecewise ranges and the total range. I guess one would have to make a lot of use cases and then consider if it makes sense to change the overall sense to change the overall syntax.

    But in any case, I would make the behavior equivalent for functions and data.

    • Ethan Merritt
      Ethan Merritt

      I would make the behavior equivalent for functions and data

      How would that be possible? They are intrinsically different. "data" has a self-defining natural axis range but has no associated sampling. "function" has no natural axis range (other than the program's arbitrary default [x=-10:10] but is strongly dependent on sampling. Remember that the sampling range may not coincide with the axis range.

      Your example "plot [0:10] x, [10:20] x**2" conflates xrange and sampling range because both functions use x. Consider instead:

        plot [0:10] x, [10:20] '+' using (cos($1/10)):(sin($1/10))

      Here you can see that the first bracketed expression [0:10] affects the axis range, while the second bracketed expression does not. I don't like this, but for me the better solution is to have neither expression affect the axis range. Both would affect sampling only, and the ranges would be controlled only by "set xrange".

  • Karl Ratzsch
    Karl Ratzsch

    I still say the ambiguity with the control of the axis range would be solved by changing the present (in gp50alpha) syntax (ranges given before function or filename) to expecting an additional sampling range after the function or filename, leaving only the axis range before the first function or file name, where it always was.

    See my posting above.

    The sampling range could then for datafiles just work as a filter, which is, i guess, what Christoph expected it to do in the first case.

    • expecting an additional sampling range after the function or filename,

      We have been on quite a long-term campaign to get rid of exactly that kind of position dependency in gnuplot's command syntax. Is this really sufficient reason to abandon that?

  • Ethan Merritt
    Ethan Merritt

    Karl: I think your range-comes-last suggestion is clever. But I also think it may be solving a problem that shouldn't exist in the first place.

    What is the argument that data files ever need an in-line range spec? It has always been possible to filter the data as it is read by putting a ternary test in the using spec. Why isn't that sufficient?

    That also applies to the very first range in the plot command. Why was it ever needed? I'm not impressed by the argument that it saves typing 8 additional characters, e.g.

      plot [min:max] 'foo.dat'


      set xr [min:max]; plot 'foo.dat'

    Perhaps there is an even more clever approach that makes it easier to place a filter in the using spec. For instance it is currently legal to say:

      plot [20:40][10:40][5:10] 'silver.dat' using 0:2:3 lc palette z

    That's ugly. It's also almost certainly wrong, since the 3rd range gets applied to the x2 axis rather than to z or to cb. What if this were

      plot 'silver.dat' using 0[20:40] : 2[10:40] : 3[5:10] lc palette z

    Better, although it's still hard to read and unclear whether the 3rd range is supposed to apply to z or to cb. I'd still prefer

      set xr [20:40]; set yr [10:10]; set cbr [5:10]
      plot 'silver.dat' using 0:2:3 lc palette z

    I can see an argument that putting the ranges in-line has no lasting effect, whereas putting them in a separate "set range" statement leaves the range in effect after the plot. But if that is the primary requirement maybe what we need is an easy save/restore command for ranges?

    • I'm not impressed by the argument that it saves typing 8 additional characters,

      That never actually was the argument for its existence. The argument has always been that sometimes you may want to override the range / autoscale settings temporarily, for the duration of a single plot, without losing them completely in the process. I.e. the use case is

      set xrange [0.2340985:0.2340987]
      plot 'data', f(x)
      #  hmmm... need to look at something else for a moment
      plot [5:20] 'some other data'
      # OK back to original plot, with the original range:
      plot 'data'

      That has been the general scheme of gnuplot since essentially forever: you have compile-time defaults which are changed until further notice by {un}set commands, and can be overridden on-the-fly for individual plots, or even individual curves in a plot command, by options right inside the plot command. I don't quite see why that's suddenly supposed to be such a bad idea.

      Last edit: Hans-Bernhard Broeker 2014-04-30
      • Ethan Merritt
        Ethan Merritt

        That was the point I raised in the final paragraph above. If the reason for allowing an initial in-line range is to overcome the lack of a save/restore for axis ranges, maybe the answer is to add save/restore of axis ranges.

        Heck, we even have code already for a LIFO stack of ranges settings - it's in the zoom/unzoom routines. What about making command line versions of the zoom/unzoom commands?

          zoom x [1:2] y [3:4]
          plot FOO ... title "with new ranges"

        I realize that your example was not a true "zoom" because it plotted some other bunch of data. So zoom/unzoom might not be the best choice of command names. Then again, if you plot a new data set after interactive zooming you get this same behavior. The new plot is in the "zoomed" state, and the "unzoom" hotkey will restore a previous set of range settings.

        Last edit: Ethan Merritt 2014-04-30
        • maybe the answer is to add save/restore of axis ranges.

          But why only axis ranges? A lot of settings are routinely overridden inside plot commands (dummy variable names, axis ranges, default plot styles, linestyle features, linetype features, surface meshing, pm3d, ...)

          OTOH, I really don't see that this would be worth breaking compatibility for.

    • Perhaps there is an even more clever approach that makes it easier to place a filter in the using spec.

      IMHO that would be a whole separate issue. Input filters are (or at least they should be) different things than ranges.

      Better, although it's still hard to read and unclear whether the 3rd range is supposed to apply to z or to cb.

      That's because it has nothing to do with any axis range. Those axis ranges are, first and foremost, properties of our output, not of input data handling. You're about to reinvent pretty much the same concept that you just called "stupid" regarding timecolumn(): trying to link axis settings to using specs.

      If a range were to be applied to a using specifier, the only thing it can possibly restrict is data input of exactly that one using spec. There's just no sane way it can change the range of whichever axis data from that spec is ultimately scaled by.

  • Ethan Merritt
    Ethan Merritt

    Maybe it is obvious, but a large part of what leads to confusion or unhappiness is the conflation of three separate things

    1 axis ranges for the complete plot
    2 inrange/outrange filtering of an input data file
    3 sampling range and interval for a function

    Unfortunately the initial bracketed entity in a "plot" command could mean any or all of these.

    We have survived this ambiguity for many years, so I don't think it is essential to change it. But if we are going to change it then the version 5 release candidate would be a good time to do so.

    If we do change it, my preference is to do so in a way that removes the ambiguity by separating these three operations.

    1 manipulate the axis ranges only in "set range" commands or zoom
    2 filter input data in the using spec
    3 use the brackets preceding a function or pseudofunction '+' to control the sampling range

    • Unfortunately the initial bracketed entity in a "plot" command could mean any or all of these.

      That same issue would have to be raised against 'set xrange' itself. This is in no way particular to the range overrides in 'plot'. It's a separate issue, which should probably be tracked in a separate feature request entry.

  • Karl Ratzsch
    Karl Ratzsch

    The sampling range just has no conceivable meaning for filed data. So why not use it for filtering the data? Christoph felt this was so obvious that he filed it as a bug, and he sort of is right there.

    We just need an unambigous syntax for this "overloading". My "before/after" scheme has the drawback of position dependance, but it is unambigous and (i think) makes up for the position dependance by it´s backward compatibility.

    Any ranges given before the first function or file name keep the same meaning as in 4.6, and every range after a function only controls the sampling. The filtering meaning for data files can then be added independently.

    I might add that i like how gnuplot lets me control most of anything except labels and other petty stuff in a single command. I´d like to keep that.