• How to: Assign an array[7] variable (with scope local to just one plot

    From najevi@21:1/5 to All on Tue Sep 26 06:54:49 2023
    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.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From najevi@21:1/5 to najevi on Wed Sep 27 04:17:30 2023
    On Tuesday, September 26, 2023 at 11:54:51 PM UTC+10, najevi wrote:
    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.

    One satisfactory solution I have found is to use the so-called "comma operator" within the parenthesized 1st-term of a using-clause:

    using (x = $f($1), x[3]) : (x[4]) : (x[5]) : (x[6]) : (x[7])

    and

    using (x = $f($1), x[3] + x[5]/2) : (x[4]-0.4) : 1 : (-fixT * (x[3] + x[5]/2 + pi/2)) : (x[7])

    reduces the number of times $f() is called to just once per using-clause .. so this can still mean multiple times per plot command but this is nonetheless a significant improvement compared to the prior method I was using.

    Parentheses are important because without parentheses the enclosed expressions will not evaluate each time plot reads a data point/data record. So this helps me to better understand what 'triggers' plot to call $f($1). This solution seems robust viz a
    viz running replot - so that is an added benefit.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)