najevi
2023-09-26 13:54:49 UTC
I am using gnuplot v6 rc1 as I am relying on a function block to implement a non-trivial algorithm.
I have a function block returning a 7 element array based on each data point in a dataset. The function, $f(), consumes just one data point ($1) and returns an array[7] value. So something like:
local array x[7] = $f($1)
The data set is not complex - being just one value per line in a file. The length of a dataset can be very large. Currently ~20,000,000 data points is the longest dataset but I test with datasets of fewer than 600 data points.
Ideally I'd assign the return value of the function to an array variable and then use references to that local array variable within a single plot command however I cannot see how to achieve such a local array variable assignment within the syntax of a plot command.
As you can see from the pseudo-code below, I use 5 elements of the returned array in a plot command and since I currently do so by calling the function 5 times I think it is terribly wasteful of CPU cycles. (NOTE: I currently use the other 2 elements of the returned array to dramatically skip over function block code whenever ARGV[1] and ARGC have not changed since the last time the function was called.)
I'd appreciate learning how to achieve the same result more efficiently.
pseudo code to illustrate:-
= = = start of pseudo code = = =
array lastFNvalue[7] = [0,0,0,0,0,0,0]
function $f << _EOFD
if ( (lastFNvalue[2] == ARGC) && (lastFNvalue[1] == ARGV[1]) ) { return lastFNvalue }
:
: # algorithm yielding 5 values from one input value
:
local array s[7] = [ ARGV[1], ARGC, azimuth, r, delTheta, delR, density ]
lastFNvalue = s
return s
_EOFD
:
:
plot @inFile \
using ($f($1)[3]) : ($f($1)[4]) : ($f($1)[5]) : ($f($1)[6]) : ($f($1)[7]) \
with sectors linecolor palette \
, @inFile \
using ($f($1)[3]+$f($1)[5]/2) : ($f($1)[4]-0.4) : 1 : (-fixT*( ($f($1)[3]+$f($1)[5]/3) + pi/2 ) ) : ($f($1)[7]) \
with labels nopoint center rotate variable textcolor palette font "Times,8" \
, '-' using 1:2:3:4:5 with sectors linecolor variable
0 0 2 @N 0
EOD
= = = end of pseudo code = = =
So you can see that elements 3,4,5,6 of the array are used to plot (annular) sectors and element 7 (the density) indexes a color palette to yield a meaningful color for each radius of this plot .. which clearly uses polar coordinates.
I'd imagined I could use one comma-delimited:
<plot-element>,
to assign the returned value of $f($1) to an array variable and thereby avoid calling $f() multiple times within the one plot command. When I could not discover a suitable syntax for doing so I capitulated and settled for calling $f() multiple times and simply inserted a conditional test (as shown above) to bypass the complex algorithm whenever the $1 data value being passed to $f() has not changed since the last time $f() was called.
** Do you know of a legitimate syntax that enables (what hopefully the reader will agree is) intuitive/expected behaviour from the pseudo-code I describe below:-
specifically that plot-element:
local array x[7] = $f($1) ,
= = =
plot @inFile \
local array x[7] = $f($1) \
, using (x[3]) : (x[4]) : (x[5]) : (x[6]) : (x[7]) \
with sectors linecolor palette \
, using (x[3]+x[5]/2) : (x[4]-0.4) : 1 : (-fixT*( (x[3]+x[5]/3) + pi/2 ) ) : (x[7]) \
with labels nopoint center rotate variable textcolor palette font "Times,8" \
, '-' using 1:2:3:4:5 with sectors linecolor variable
0 0 2 @N 0
EOD
= = =
The intent being that array x[7] has scope local to just that one plot command and therefore $f($1) is called only the once per data point in any data set.
Thank you for considering this specific application of gnuplot.
FWIW:
I did toy with having $f() return a string resembling the "using" syntax:
"using (azimuth) : (r) : (delTheta) : (delR) : (density) "
with a view to substitution of that string variable as a macro via:
@$f($1)
style of dereferencing but that was frustratingly unsuccessful.
I have a function block returning a 7 element array based on each data point in a dataset. The function, $f(), consumes just one data point ($1) and returns an array[7] value. So something like:
local array x[7] = $f($1)
The data set is not complex - being just one value per line in a file. The length of a dataset can be very large. Currently ~20,000,000 data points is the longest dataset but I test with datasets of fewer than 600 data points.
Ideally I'd assign the return value of the function to an array variable and then use references to that local array variable within a single plot command however I cannot see how to achieve such a local array variable assignment within the syntax of a plot command.
As you can see from the pseudo-code below, I use 5 elements of the returned array in a plot command and since I currently do so by calling the function 5 times I think it is terribly wasteful of CPU cycles. (NOTE: I currently use the other 2 elements of the returned array to dramatically skip over function block code whenever ARGV[1] and ARGC have not changed since the last time the function was called.)
I'd appreciate learning how to achieve the same result more efficiently.
pseudo code to illustrate:-
= = = start of pseudo code = = =
array lastFNvalue[7] = [0,0,0,0,0,0,0]
function $f << _EOFD
if ( (lastFNvalue[2] == ARGC) && (lastFNvalue[1] == ARGV[1]) ) { return lastFNvalue }
:
: # algorithm yielding 5 values from one input value
:
local array s[7] = [ ARGV[1], ARGC, azimuth, r, delTheta, delR, density ]
lastFNvalue = s
return s
_EOFD
:
:
plot @inFile \
using ($f($1)[3]) : ($f($1)[4]) : ($f($1)[5]) : ($f($1)[6]) : ($f($1)[7]) \
with sectors linecolor palette \
, @inFile \
using ($f($1)[3]+$f($1)[5]/2) : ($f($1)[4]-0.4) : 1 : (-fixT*( ($f($1)[3]+$f($1)[5]/3) + pi/2 ) ) : ($f($1)[7]) \
with labels nopoint center rotate variable textcolor palette font "Times,8" \
, '-' using 1:2:3:4:5 with sectors linecolor variable
0 0 2 @N 0
EOD
= = = end of pseudo code = = =
So you can see that elements 3,4,5,6 of the array are used to plot (annular) sectors and element 7 (the density) indexes a color palette to yield a meaningful color for each radius of this plot .. which clearly uses polar coordinates.
I'd imagined I could use one comma-delimited:
<plot-element>,
to assign the returned value of $f($1) to an array variable and thereby avoid calling $f() multiple times within the one plot command. When I could not discover a suitable syntax for doing so I capitulated and settled for calling $f() multiple times and simply inserted a conditional test (as shown above) to bypass the complex algorithm whenever the $1 data value being passed to $f() has not changed since the last time $f() was called.
** Do you know of a legitimate syntax that enables (what hopefully the reader will agree is) intuitive/expected behaviour from the pseudo-code I describe below:-
specifically that plot-element:
local array x[7] = $f($1) ,
= = =
plot @inFile \
local array x[7] = $f($1) \
, using (x[3]) : (x[4]) : (x[5]) : (x[6]) : (x[7]) \
with sectors linecolor palette \
, using (x[3]+x[5]/2) : (x[4]-0.4) : 1 : (-fixT*( (x[3]+x[5]/3) + pi/2 ) ) : (x[7]) \
with labels nopoint center rotate variable textcolor palette font "Times,8" \
, '-' using 1:2:3:4:5 with sectors linecolor variable
0 0 2 @N 0
EOD
= = =
The intent being that array x[7] has scope local to just that one plot command and therefore $f($1) is called only the once per data point in any data set.
Thank you for considering this specific application of gnuplot.
FWIW:
I did toy with having $f() return a string resembling the "using" syntax:
"using (azimuth) : (r) : (delTheta) : (delR) : (density) "
with a view to substitution of that string variable as a macro via:
@$f($1)
style of dereferencing but that was frustratingly unsuccessful.