How to plot data without a separate file by specifying all points inside the Gnuplot script?

前端 未结 6 733
死守一世寂寞
死守一世寂寞 2020-12-02 20:19

My program generates bash scripts that call gnuplot. I don\'t want to have to make an extra file to store the data; is there any way I can explicitly call all of the values?

相关标签:
6条回答
  • 2020-12-02 20:56

    Gnuplot 5.0.1 datablocks

    main.gnuplot

    $data << EOD
    1 1
    2 4
    3 9
    4 16
    EOD
    
    plot "$data" \
      with linespoints \
      title "my data"
    

    Convert to PNG:

    gnuplot -e 'set terminal png' -e 'set output "main.png"' main.gnuplot
    

    Output:

    This method is a bit more versatile than '-' as it makes it easier to reuse the same data multiple times, including on the same plot command: How to embed multiple datasets in a gnuplot command script for a single plot command?

    Version 5 is available on Ubuntu 15.04, or compile from source with: https://askubuntu.com/a/684136/52975

    You may also be interested in the + and ++ special file names when plotting with functions.

    Tested on Ubuntu 18.10, gnuplot 5.2.

    0 讨论(0)
  • 2020-12-02 21:03

    10 years later...

    You can write something like this directly in gnuplot:

    plot "< ./format.sh '{(1,5),(2,10),(3,1)}'"
    

    where format.sh is a pretty simple script in a local file (remember to give it exec permissions):

    #!/bin/bash
    echo "$1" | sed 's:^..\(.*\)..$:\1:' | sed 's:),(:\n:g' | sed 's:,: :g'
    

    How does it works?

    The three sed commands do the following:

    1. drops the first and last two characters, respectively {( and })
    2. changes the sequence ),( to a newline
    3. changes the remaining , to spaces

    So:

    $ ./format.sh '{(1,5),(2,10),(3,1)}'
    1 5
    2 10
    3 1
    

    The gnuplot plot "< command" syntax levers on popen to run command in a shell, capture the output and plot it on the fly. It can be pretty useful also in other circumstances.

    0 讨论(0)
  • 2020-12-02 21:04

    You can use the syntax for inline data - filename '-'.

    The following example produces a simple plot in a GIF image (bash script):

    gnuplot << EOF
    set terminal gif
    set output 'plot1.gif'
    plot '-' using 1:2
            1 10
            2 20
            3 32
            4 40
            5 50
            e
    EOF
    
    0 讨论(0)
  • 2020-12-02 21:15

    Solution is using arrays and parametric lines.

    X="0.1 0.2 0.3 0.4 0.5"
    Y="-1  0   2   4   8"
    
    set parametric
    set trange [1:words(X)]; set samples words(X)
    plot (0+word(X,int(t))),(0+word(Y,int(t))) 
    

    output

    source: https://groups.google.com/d/msg/comp.graphics.apps.gnuplot/UdiiC2cBQNo/xEyj6i7Y910J

    0 讨论(0)
  • 2020-12-02 21:16

    bash One line ping graph with gnuplot

    Sorry, it's not light (361 characters):

    gnuplot -p -e "set xdata time;set timefmt '%s';set xrange [ '$(date +%s)' : '$(date -d 'now +30 seconds' +%s)' ];plot '-' using 1:2 with line title 'ping google';" < <(( ping -c 30 -n google.com| sed -u 's/^64.*time=\([0-9.]\+\) .*$/\1/p;d' | tee >(sed -u 's/.*/now/'| stdbuf -oL date -f - +d%s)) | sed -u 'N;s/\n/ /;s/\([0-9.]\+\) d\([0-9]\+\) */\2 \1/;s/d//')
    

    Running this line will hold your terminal for 30 seconds, than plot on screen a graph presenting ping delay to google.com on last 30 seconds.

    The same line could be splitted like this (workable too):

    gnuplot -p -e "
        set xdata time;
        set timefmt '%s';
        set xrange [ '$(
            date +%s
          )' : '$(
            date -d 'now +30 seconds' +%s
          )' ];
        plot '-' using 1:2 with line title 'ping google';
        " < <((
        ping -c 30 -n google.com |
            sed -u 's/^64.*time=\([0-9.]\+\) .*$/\1/p;d' |
            tee >(sed -u 's/.*/now/'| stdbuf -oL date -f - +d%s)) |
        sed -u 'N;s/\n/ /;s/\([0-9.]\+\) d\([0-9]\+\) */\2 \1/;s/d//'
    )
    

    But this don't print values!

    So i've added some few bytes:

    gnuplot -p -e "set xdata time;set timefmt '%s';set xrange [ '$(date +%s)' : '$(date -d 'now +30 seconds' +%s)' ];plot '-' using 1:2 with line title 'ping google';" < <(( ping -c 30 -n google.com| sed -u 's/^64.*time=\([0-9.]\+\) .*$/\1/p;d' | tee >(sed -u 's/.*/now/'| stdbuf -oL date -f - +d%s)  ) | sed -u 'N;s/\n/ /;s/\([0-9.]\+\) d\([0-9]\+\) */\2 \1/;s/d//' | tee >(printf "%(%T)T %s\n" $(</dev/stdin) | column -c $COLUMNS >&2 ))
    

    This may create a window like this:

    And simultaneously print on terminal:

    17:58:53 19.6   17:59:00 124    17:59:07 159    17:59:13 194    17:59:19 17.1
    17:58:54 18.7   17:59:02 19.4   17:59:08 20.3   17:59:14 16.8   17:59:20 20.0
    17:58:55 17.9   17:59:03 180    17:59:09 76.4   17:59:15 48.9   17:59:21 192
    17:58:57 115    17:59:04 186    17:59:10 226    17:59:16 221    17:59:22 17.1
    17:58:58 18.5   17:59:05 16.8   17:59:11 109    17:59:17 19.0
    17:58:59 17.0   17:59:06 184    17:59:12 18.8   17:59:18 18.7
    

    Re-written splitted:

    gnuplot -p -e "
        set xdata time;
        set timefmt '%s';
        set xrange [ '$(date +%s)' : '$(date -d 'now +30 seconds' +%s)' ];
        plot '-' using 1:2 with line title 'ping google';" < <(
      (
          ping -c 30 -n google.com |
            sed -u 's/^64.*time=\([0-9.]\+\) .*$/\1/p;d' |
            tee >(sed -u 's/.*/now/'| stdbuf -oL date -f - +d%s)
      ) | sed -u 'N;s/\n/ /;s/\([0-9.]\+\) d\([0-9]\+\) */\2 \1/;s/d//' |
      tee >(printf "%(%T)T %s\n" $(</dev/stdin) |
      column -c $COLUMNS >&2 )
    )
    
    0 讨论(0)
  • 2020-12-02 21:18

    Example from using shell with pipeline,

    gnuplot -p <(echo -e 'plot "-"\n1 1\ne')
    
    0 讨论(0)
提交回复
热议问题