|
From: Ethan M. <merritt@u.washington.edu> - 2007-05-07 23:51:34
Attachments:
f_assign.patch
|
The SourceForge end of the gnuplot-bugs mailing list is currently broken. I found this posting via gmane.org (under "bugs") but it doesn't really belong there, so I'm copying it to the developers list with a reply. Synopsis: The suggestion is to allow assignment to a variable inside an expression. This may be useful in order to collect statistics about data points as they are read in Response: I have attached a small patch that implements a new user-visible function: assign("VAR", <expression>) It assigns the current value of the expression to a variable named VAR. NB: this is the _name_ of the variable, not the variable itself. Example: MAX = -999 update_max(x) = assign("MAX", x > MAX ? x : MAX) plot <foo> using 1:($2 + 0. * update_max($2)) print "Maximum data value plotted was", MAX Comments: I'm not sure this will actually accomplish what you want, but please try it out and let us know. If you use this inside a "using" clause, it will slow down data input. For large data files the slowdown is likely to be noticeable. For the use above, it would probably be more convenient to have the update_max(x) function return the current value of x rather than the updated maximum. It's not clear to me how best to achieve that. %%%%%%%% begin forwarded message %%%%%%%%% From: <plotter <at> piments.com> Subject: feature request Newsgroups: gmane.comp.graphics.gnuplot.bugs I have been trying to trick gnuplot into doing some simple tasks it does not seem possible to do but which could be immensely useful. to judge by comp.graphics.apps.gnuplot it seems that there are certain basic tasks that are frequently requested and get a reply along the lines of "gnuplot is not for number crunching". Fine. Gnuplot is a plotting program, not a data processing package but there are an number of trivial tasks like calculating a mean or finding the max of values *calculated* by gnuplot that cant currently be done. Tasks like this are far less complex than function fitting do data or plotting with spline interpolation and would be very valuable in the context of outputting data to a graph. eg how to put a label at the max point of the data. Definately a plotting task and hardly "number crunching" but currently it seems I have do this simple task in an external script. Worse, if I do some fitting and expression evaluation in the plot command , I have to duplicate it all to a table, call an external script and then read in a new file to get the value of the max or mean value of y. all I really need is a means to assign one tiny little variable during plot (directly or from a within a fn ) consider the following that will plot a "sample and hold": xmax=0; max(x)=( (xmax<x)?(xmax=x):xmax ); plot "150tank-txC.data" using 1:(Th6($4)) with lines t "panel out" \ , "150tank-txC.data" using 1:(max(Th6($4))) with lines t "s/h" ; Currently not possible since function parser will not allow C style 'assignment returns a value'. A similar technique could find the min , max, mean or area under graph; in fact it opens a whole range of possibilities that are frequently requested on the list. So how much effort is it? Well without going to the extent of supporting procedure calls from with plot command , adding the above parsing of C style assignments would be simple to add and open the door to some very useful techniques. I hope you will find it worth considering. Kind regards. %%%%%%%% begin forwarded message %%%%%%%%% -- Ethan A Merritt |
|
From: <pl...@pi...> - 2007-05-08 07:20:30
|
On Tue, 08 May 2007 01:51:34 +0200, Ethan Merritt = <merritt@u.washington.edu> wrote: > The SourceForge end of the gnuplot-bugs mailing list is currently brok= en. > I found this posting via gmane.org (under "bugs") but it doesn't reall= y > belong there, so I'm copying it to the developers list with a reply. Hi Ethan, thanks very much for picking this up. That seems quite close to what I w= as = requesting. I extended your example to pick up the x value of the ymax a= s = well. The plot gives the sample-and-hold plot as expected. Proof of = principle. Nice one. It would be quite a simple extention to do a trapezoidal area under grap= h = or the mean. The nice thing is this can be limitted by setting the range before plot.= = This is a nice quick solution that avoids quite a bit of effort messing = = about with external scripts for simple stuff like this. A nice addition.= set xdata time set timefmt "%H:%M" set xr ["10:15":"18:30"] xmax=3D0;ymax=3D0; max(x,y)=3Dassign("ymax",(ymax<y)?y+0. * assign("xmax",x):ymax ); set label "max was here" at "11:00",ymax/10; plot datafile using 1:(P( Th4($3-2.0) - Th5($2) )) axes x1y2 with = lines s f t "useful power" \ , datafile using 1:(max(column(1),P( Th4($3-2.0) - Th5($2) ))) axes = x1y2 with lines s f t "s/hold" \ My initial task with this was to put a label on the graph at the max poi= nt. This presents me with some small issues remaining to be solved: 1. My xdata is time format , I imagine your patch does not try to fit al= l = cases but in assigning the x value it gets truncated to the nearest hour= , = 12:45 becomes 12.0 2. my inexperience with gnuplot, it seems that if I try to set a label = after the plot command (which I need to do for xmax,ymax) it does not = show. The same command before plot command does work but it's at (0,0). I'm sure gnuplot users (ingenious as they are) will find 101 neat tricks= = to do with the new command , it opens up all sorts of possibilities. Many thanks. >>>>>>>>>> Synopsis: The suggestion is to allow assignment to a variable inside an expression. This may be useful in order to collect statistics about data points as they are read in Response: I have attached a small patch that implements a new user-visible function: assign("VAR", <expression>) It assigns the current value of the expression to a variable named VAR. NB: this is the _name_ of the variable, not the variable itself. Example: MAX =3D -999 update_max(x) =3D assign("MAX", x > MAX ? x : MAX) plot <foo> using 1:($2 + 0. * update_max($2)) print "Maximum data value plotted was", MAX Comments: I'm not sure this will actually accomplish what you want, but please try it out and let us know. If you use this inside a "using" clause, it will slow down data input. For large data files the slowdown is likely to be noticeable. For the use above, it would probably be more convenient to have the update_max(x) function return the current value of x rather than the updated maximum. It's not clear to me how best to achieve that. %%%%%%%% begin forwarded message %%%%%%%%% From: <plotter <at> piments.com> Subject: feature request Newsgroups: gmane.comp.graphics.gnuplot.bugs I have been trying to trick gnuplot into doing some simple tasks it does= not seem possible to do but which could be immensely useful. to judge by comp.graphics.apps.gnuplot it seems that there are certain basic tasks that are frequently requested and get a reply along the line= s of "gnuplot is not for number crunching". Fine. Gnuplot is a plotting program, not a data processing package but there are an number of trivial tasks like calculating a mean or finding the max of values *calculated* by gnuplot that cant currently be done. Tasks like this are far less complex than function fitting do data or plotting with spline interpolation and would be very valuable in the context of outputting data to a graph. eg how to put a label at the max point of the data. Definately a plottin= g task and hardly "number crunching" but currently it seems I have do this= simple task in an external script. Worse, if I do some fitting and expression evaluation in the plot comman= d , I have to duplicate it all to a table, call an external script and the= n read in a new file to get the value of the max or mean value of y. all I really need is a means to assign one tiny little variable during plot (directly or from a within a fn ) consider the following that will plot a "sample and hold": xmax=3D0; max(x)=3D( (xmax<x)?(xmax=3Dx):xmax ); plot "150tank-txC.data" using 1:(Th6($4)) with lines t "panel out" \ , "150tank-txC.data" using 1:(max(Th6($4))) with lines t "s/h" ; Currently not possible since function parser will not allow C style 'assignment returns a value'. A similar technique could find the min , max, mean or area under graph; = in fact it opens a whole range of possibilities that are frequently request= ed on the list. So how much effort is it? Well without going to the extent of supporting procedure calls from with= plot command , adding the above parsing of C style assignments would be simple to add and open the door to some very useful techniques. I hope you will find it worth considering. Kind regards. %%%%%%%% begin forwarded message %%%%%%%%% |
|
From: <pl...@pi...> - 2007-05-08 10:16:55
|
On Tue, 08 May 2007 09:23:01 +0200, <pl...@pi...> wrote:
> Example:
> MAX =3D -999
> update_max(x) =3D assign("MAX", x > MAX ? x : MAX)
> plot <foo> using 1:($2 + 0. * update_max($2))
> print "Maximum data value plotted was", MAX
> Comments:
> I'm not sure this will actually accomplish what you want, but
> please try it out and let us know. If you use this inside a
> "using" clause, it will slow down data input. For large data files
> the slowdown is likely to be noticeable. For the use above, it
> would probably be more convenient to have the update_max(x) function
> return the current value of x rather than the updated maximum.
> It's not clear to me how best to achieve that.
shift the 'times zero' trick inside the funtion?
catch_max(y) =3D y+ 0. * assign("MAX", y > MAX ? y : MAX);
plot <foo> using 1:(catch_max($2))
pretty much the same thing but like you say a bit more convenient for pl=
ot.
;)
|
|
From: Ethan A M. <merritt@u.washington.edu> - 2007-05-08 15:57:57
|
On Monday 07 May 2007 23:56, pl...@pi... wrote:
>
> thanks very much for picking this up. That seems quite close to what I was
> requesting. I extended your example to pick up the x value of the ymax as
> well. The plot gives the sample-and-hold plot as expected. Proof of
> principle. Nice one.
>
> The nice thing is this can be limitted by setting the range before plot.
> This is a nice quick solution that avoids quite a bit of effort messing
> about with external scripts for simple stuff like this. A nice addition.
Please continue to play with it. We need to discover what limitations and
drawbacks this simple implementation may have before seriously considering
to add some variant to the program.
I hope we can come up with a nicer syntax, as it seems ugly to me to hide
this inside the 'using' clause. Thinking out loud.... what about a
parallel clause with a name like 'after'. The operations in the 'after'
clause would be carried out before passing the data through for actual
plotting:
plot <foo> using 1:2 after track_max($2) with lines
perhaps it should allow multiple operations:
plot <foo> using 1:2 after {track_max($2), track_min($2), sum($2)} with lines
More thoughts:
- (Pro) As compared to filtering through an external script, this mechanism
has the advantage that it can affect internal gnuplot user variables.
- (Con) This is incompatible with the revised zooming/refresh code
that I am working on. There the idea is to avoid re-reading the input
data if all you want to do is replot it. But the assign/after mechanism
is applied during data input, so it would be bypassed by any such shortcut.
- Having to use the name of the variable rather than the variable itself
may make sense to a low-level programmer, but is likely to be confusing
to many users. Suggestions for a syntax that hides this level of
complexity would be welcome. Or perhaps some additional cleverness in
the parset is possible. We have one such function already,
exists("VARNAME"), but that one is also confusing.
> This presents me with some small issues remaining to be solved:
>
> 1. My xdata is time format , I imagine your patch does not try to fit all
> cases but in assigning the x value it gets truncated to the nearest hour,
> 12:45 becomes 12.0
I have never understood the time-handling code. I suspect that the
whole special case time format mechanism is no longer needed, as the same
goal can be achieved using general string-handling functions.
In your case, you probably need to use some combination of stringcolumn()
strptime() strftime() rather than setting a time format.
> 2. my inexperience with gnuplot, it seems that if I try to set a label
> after the plot command (which I need to do for xmax,ymax) it does not
> show. The same command before plot command does work but it's at (0,0).
Of course. When you draw a new graph by issuing the command "plot" or
"splot", it uses the currently defined labels.
If you define a label afterwards, how could it possibly appear in the
already-drawn plot? If you don't mind reading the data a second time,
you could "replot" to pick up the new labels.
--
Ethan A Merritt
|
|
From: <pl...@pi...> - 2007-05-08 19:53:58
|
On Tue, 08 May 2007 17:57:54 +0200, Ethan A Merritt
<merritt@u.washington.edu> wrote:
> On Monday 07 May 2007 23:56, pl...@pi... wrote:
>>
>> thanks very much for picking this up. That seems quite close to what I
>> was
>> requesting. I extended your example to pick up the x value of the ymax
>> as
>> well. The plot gives the sample-and-hold plot as expected. Proof of
>> principle. Nice one.
>>
>> The nice thing is this can be limitted by setting the range before plot.
>> This is a nice quick solution that avoids quite a bit of effort messing
>> about with external scripts for simple stuff like this. A nice addition.
>
> Please continue to play with it. We need to discover what limitations
> and
> drawbacks this simple implementation may have before seriously
> considering
> to add some variant to the program.
>
> I hope we can come up with a nicer syntax, as it seems ugly to me to hide
> this inside the 'using' clause.
Yes it feels like a bit of a cludge but I'm happy to have a cludge rather
than an impasse. I think the 'after' syntax is seems much more integrated.
Thinking out loud.... what about a
> parallel clause with a name like 'after'. The operations in the 'after'
> clause would be carried out before passing the data through for actual
> plotting:
>
> plot <foo> using 1:2 after track_max($2) with lines
>
> perhaps it should allow multiple operations:
>
> plot <foo> using 1:2 after {track_max($2), track_min($2), sum($2)}
> with lines
>
>
> More thoughts:
>
> - (Pro) As compared to filtering through an external script, this
> mechanism
> has the advantage that it can affect internal gnuplot user variables.
>
> - (Con) This is incompatible with the revised zooming/refresh code
> that I am working on. There the idea is to avoid re-reading the input
> data if all you want to do is replot it. But the assign/after
> mechanism
> is applied during data input, so it would be bypassed by any such
> shortcut.
>
> - Having to use the name of the variable rather than the variable itself
> may make sense to a low-level programmer, but is likely to be confusing
> to many users. Suggestions for a syntax that hides this level of
> complexity would be welcome. Or perhaps some additional cleverness in
> the parset is possible. We have one such function already,
> exists("VARNAME"), but that one is also confusing.
>
Yes , it's a shame if you have to do it that way, I assumed you'd just
done that for speed to test the idea because it was simpler to code.
>> This presents me with some small issues remaining to be solved:
>>
>> 1. My xdata is time format , I imagine your patch does not try to fit
>> all
>> cases but in assigning the x value it gets truncated to the nearest
>> hour,
>> 12:45 becomes 12.0
>
> I have never understood the time-handling code. I suspect that the
> whole special case time format mechanism is no longer needed, as the same
> goal can be achieved using general string-handling functions.
> In your case, you probably need to use some combination of stringcolumn()
> strptime() strftime() rather than setting a time format.
>
>> 2. my inexperience with gnuplot, it seems that if I try to set a label
>> after the plot command (which I need to do for xmax,ymax) it does not
>> show. The same command before plot command does work but it's at (0,0).
>
> Of course. When you draw a new graph by issuing the command "plot" or
> "splot", it uses the currently defined labels.
> If you define a label afterwards, how could it possibly appear in the
> already-drawn plot? If you don't mind reading the data a second time,
> you could "replot" to pick up the new labels.
>
Redoing the whole job just to add a label seems a bit extravagant. I
thought there may be some trick with multiplot that I had not discovered
yet. Your reply suggests there is not.
This seems an illogical restriction from a users point of view even if it
makes sense in the way gnuplot stores label info.
maybe there should be some mechanism if there isn't , eg. set label ....
replot.
BTW I posted a bug to the bugs list about time data not being respected by
table mode . Although I noticed the cursor is now display time data
correctly, having gone to cvs, this does seem to be an area that still
needs implementing consistantly.
I'll try to do an trapezoidal A.U.G using your mod., I had to put this
out to awk which was an annoying waste of effort. It will be a good test.
Thanks for your interest.
|
|
From: <pl...@pi...> - 2007-05-08 21:30:46
|
On Tue, 08 May 2007 17:57:54 +0200, Ethan A Merritt =
<merritt@u.washington.edu> wrote:
>
> Please continue to play with it. We need to discover what limitations=
=
> and
> drawbacks this simple implementation may have before seriously =
> considering
> to add some variant to the program.
area=3D0; started=3D0;prev_x=3D0;prev_y=3D0;
add_aug(x,y)=3Dassign("area",(started)?area+(x-prev_x)*(y-prev_y)/2.+0.*=
assign("prev_x",x)+0.*assign("prev_y",y):(0.*assign("started",1)+0.*assi=
gn("prev_x",x)+0.*assign("prev_y",y)));
This should do a trapezoidal area under graph but I have not been able t=
o =
check it's result because of time trunkage.
Anyway, plotting the return value it seems to be doing the right thing.
;)
|
|
From: Juergen W. <wie...@fr...> - 2007-05-08 16:43:21
|
Am Dienstag, 8. Mai 2007 schrieb Ethan A Merritt: > plot <foo> using 1:2 after track_max($2) with lines [...] > - (Con) This is incompatible with the revised zooming/refresh code > that I am working on. There the idea is to avoid re-reading the input > data if all you want to do is replot it. But the assign/after mechanism > is applied during data input, so it would be bypassed by any such > shortcut. I think this is a feature. For compatibility, the refreshing should not be done with "replot" but with "redraw" (or similar). I would not expect "redraw" to go through this filter. > I have never understood the time-handling code. I suspect that the > whole special case time format mechanism is no longer needed, as the same > goal can be achieved using general string-handling functions. > In your case, you probably need to use some combination of stringcolumn() > strptime() strftime() rather than setting a time format. I don't think so. I see two problems (probably there are more): * Automatic tic generation is date/time aware. This could be adjusted manually, but the automatic tics wouldn't be too sensible. * Tic label generation. The command "set format" just takes a format string, which is used either for date/time or ordinary numbers. The functions strptime() and strftime() only work with a more flexible "set format" which takes a string valued expression, which is evaluated at plot time. Juergen |
|
From: Ethan M. <merritt@u.washington.edu> - 2007-05-08 18:01:12
|
On Tuesday 08 May 2007 09:43, Juergen Wieferink wrote: > > > I have never understood the time-handling code. I suspect that the > > whole special case time format mechanism is no longer needed, as the same > > goal can be achieved using general string-handling functions. > > In your case, you probably need to use some combination of stringcolumn() > > strptime() strftime() rather than setting a time format. > > I don't think so. I see two problems (probably there are more): > * Automatic tic generation is date/time aware. This could be > adjusted manually, but the automatic tics wouldn't be too sensible. Could be. As I said, I am not familiar with the time format options. > * Tic label generation. The command "set format" just takes a > format string, which is used either for date/time or ordinary > numbers. The functions strptime() and strftime() only work with a > more flexible "set format" which takes a string valued expression, which > is evaluated at plot time. Sure. But that could be a useful addition in its own right. I didn't mean to say that the time format options could be deprecated with no additional work; I just meant that the basic pieces are in place to replace them with a more general mechanism. Don't forget that we have several long-standing requests to extend the time format system so that it can handle intervals smaller than a second, and also to allow it to handle spherical coordinate systems deg/min/sec/fractional-sec One could write a lot of special-purpose code to handle these extensions, but I would rather see the effort spent on implementing a generic mechanism of which the existing time formats and the proposed geographic variants are just user-configurable examples. -- Ethan A Merritt Courier Deliveries: 1959 NE Pacific Dept of Biochemistry Health Sciences Building University of Washington - Seattle WA 98195-7742 |
|
From: <pl...@pi...> - 2007-05-12 14:13:30
|
Hi again,
just found a bit of time to have another look at this. A couple of small=
=
probs, one with assign() , the other with strptime you suggested I look =
at.
On Tue, 08 May 2007 20:01:06 +0200, Ethan Merritt =
<merritt@u.washington.edu> wrote:
> On Tuesday 08 May 2007 09:43, Juergen Wieferink wrote:
>>
>> > I have never understood the time-handling code. I suspect that the=
>> > whole special case time format mechanism is no longer needed, as th=
e =
>> same
>> > goal can be achieved using general string-handling functions.
>> > In your case, you probably need to use some combination of =
>> stringcolumn()
>> > strptime() strftime() rather than setting a time format.
>>
I tried using strptime with the same time format that works with my data=
=
but found I had to divide by 3600 just to get it on the plot. However it=
=
did get around the trucation to the nearest hour I was seeing when passi=
ng =
the result of timecolumn().
So it seems that strptime() does not always parse the data in the same w=
ay =
as with timefmt as the help suggests.
It seems that this time feature has been somewhat tacked on to fullfil =
requests for this format but that it has not been implement, or at least=
=
implemented in the same way through out.
If you are working on the code to deal with this in a more structured wa=
y =
I think that would be very benefitial, current behavious seems to vary =
somewhat depending on where and how time format is used.
>> I don't think so. I see two problems (probably there are more):
>> * Automatic tic generation is date/time aware. This could be
>> adjusted manually, but the automatic tics wouldn't be too sensible.=
>
> Could be. As I said, I am not familiar with the time format options.
>
>> * Tic label generation. The command "set format" just takes a
>> format string, which is used either for date/time or ordinary
>> numbers. The functions strptime() and strftime() only work with a
>> more flexible "set format" which takes a string valued expression, =
=
>> which
>> is evaluated at plot time.
>
> Sure. But that could be a useful addition in its own right.
> I didn't mean to say that the time format options could be deprecated
> with no additional work; I just meant that the basic pieces are in pla=
ce
> to replace them with a more general mechanism.
>
> Don't forget that we have several long-standing requests to extend
> the time format system so that it can handle intervals smaller than
> a second, and also to allow it to handle spherical coordinate systems
> deg/min/sec/fractional-sec
>
> One could write a lot of special-purpose code to handle these
> extensions, but I would rather see the effort spent on implementing
> a generic mechanism of which the existing time formats and the
> proposed geographic variants are just user-configurable examples.
>
>
My other problem is that the code snip I posted seems to be correctly =
calculating the areas of the increamental trapezoidal segements but fail=
s =
to add the existing value of my area variable.
area=3D0; started=3D0;prev_x=3D0;prev_y=3D0;
add_aug(x,y)=3Dassign("area",(started)?\
area + (x-prev_x)*(y-prev_y)/2.0 =
+ 0.0*assign("prev_x",x) + 0.0*assign("prev_y",y) \
:( 0.0*assign("started",1) =
+ 0.0*assign("prev_x",x) + 0.0*assign("prev_y",y) ) \
);
plot datafile using =
1:(add_aug(strptime("%H:%M",stringcolumn(1))/3600*2,P( Th4($3-2.0) =
-(Th7($5)-0.52) ))) axes x1y2 with lines s f t "aug" \
So referencing area inside assign("area", ) seems to return zero, wherea=
s =
the other calls to assign() work and references to the other variables =
inside assign() produces expected results.
Can you confirm that bug and hopefully correct it?
Many thanks.
|
|
From: Ethan M. <merritt@u.washington.edu> - 2007-05-14 18:15:44
|
On Saturday 12 May 2007 07:13, pl...@pi... wrote:
> My other problem is that the code snip I posted seems to be correctly
> calculating the areas of the increamental trapezoidal segements but fails
> to add the existing value of my area variable.
>
>
> area=0; started=0;prev_x=0;prev_y=0;
> add_aug(x,y)=assign("area",(started)?\
> area + (x-prev_x)*(y-prev_y)/2.0
> + 0.0*assign("prev_x",x) + 0.0*assign("prev_y",y) \
> :( 0.0*assign("started",1)
> + 0.0*assign("prev_x",x) + 0.0*assign("prev_y",y) ) \
> );
>
>
> plot datafile using
> 1:(add_aug(strptime("%H:%M",stringcolumn(1))/3600*2,P( Th4($3-2.0)
> -(Th7($5)-0.52) ))) axes x1y2 with lines s f t "aug" \
>
>
>
> So referencing area inside assign("area", ) seems to return zero, whereas
> the other calls to assign() work and references to the other variables
> inside assign() produces expected results.
>
> Can you confirm that bug and hopefully correct it?
Too complicated for my poor brain.
Please try to reduce this to a much simpler test script
that demonstrates an error.
The obvious test:
sum(x) = assign("sum",x+sum)
plot <foo> using 1:($2+0*sum($2))
seems to work just fine
--
Ethan A Merritt Courier Deliveries: 1959 NE Pacific
Dept of Biochemistry
Health Sciences Building
University of Washington - Seattle WA 98195-7742
|