Search code examples
gnuplot

A simple gnuplot digitizer?


Sometimes it might be useful to digitize scanned graphs to get the data and redraw a plot. I'm aware that there are dedicated tools with a lot of features, e.g. see miscellaneous links on the gnuplot home page: http://gnuplot.info/links.html

However, is there maybe a way using gnuplot only? Maybe with a few lines of code you can implement a simple version of a digitizer? Which should already be sufficient for some cases having a limited number of datapoints.

(edit: part of original question now put as answer)


Solution

  • In case this might be useful to someone... this gnuplot version is just for fun, sharing and for demonstration of gnuplot capabilities. Improvements are welcome, e.g.

    • logarithmic axes, time axes, multiple curves, tilted images, etc.

    How it works:

    • an image is imported into a graph. gnuplot supports e.g. GIF, JPG, PNG. To see the list of filetypes show datafile binary filetype.
    • the first 3 mouseclicks have to be on 1) end of y-axis, 2) origin, and 3) end of x-axis
    • further mouseclicks draw datapoints

    The following key bindings are implemented:

    • 0: (re-)define the axes from end of y-axis to origin to end of x-axis
    • x: remove all datapoints
    • c: clear only last datapoint
    • s: save data to file

    Script: (works with gnuplot>=5.2.0)

    ### a simple gnuplot digitizer
    reset session
     
    IMAGE    = 'Superconductivity.png'
    DATAFILE = 'Superconductivity.dat'
     
    AxisXStart = 4.00
    AxisXEnd   = 4.40
    AxisYStart = 0.00
    AxisYEnd   = 0.15
    
    DataHeader = "# x-value y-value
    set print $Data
        print DataHeader
    set print
    
    AxesHeader = "# axes mouse coordinates
    set print $Axes
        print AxesHeader
    set print
    
    set margins 0,0,0,0
    set key noautotitle
    
    fx(point) = (word(point,1)-word($Axes[3],1))/(word($Axes[4],1)-word($Axes[3],1))*(AxisXEnd - AxisXStart) + AxisXStart
    fy(point) = (word(point,2)-word($Axes[3],2))/(word($Axes[2],2)-word($Axes[3],2))*(AxisYEnd - AxisYStart) + AxisYStart
    
    # get point
    bind Button1 'if (|$Axes|<4) { set print $Axes append } else { set print $Data append }; \
                  print MOUSE_X, MOUSE_Y; set print; replot'
    
    # reset axis points
    bind 0 'set print $Axes; print AxesHeader; set print; replot'
    
    # remove all data points
    bind x 'set print $Data; print DataHeader; set print; replot'
    
    # remove last data point
    bind c 'if (|$Data|>2) {array A[|$Data|]; do for [i=2:|$Data|-1] { A[i]=$Data[i] }; \
            set print $Data; do for [i=1:|A|-1] { print A[i] }; } \
            else {set print $Data; print DataHeader; }; set print; replot'
    
    # save data to file
    bind s 'set print DATAFILE; print $Data[1]; \
            do for [i=2:|$Data|] { print sprintf("%g %g", fx($Data[i]), fy($Data[i])) }; \
            set print; pause -1 sprintf("Data saved to: %s",DATAFILE)'
    
    plot IMAGE binary filetype=auto origin=(0,0) dx=1 dy=1 with rgbimage, \
         $Axes u 1:2 w l lw 2 lc "blue" noautoscale, \
         $Data u 1:2 w p pt 7 lc "red" noautoscale
    ### end of script
    

    Input: Superconductivity.png

    enter image description here

    Procedure: (Screen capture from wxt terminal)

    enter image description here

    Result: Superconductivity.dat

    # Temperature Resistance
    4.3696 0.130726
    4.3328 0.126117
    4.232 0.113966
    4.20241 0.00157884
    4.19248 0.000406976
    4.18307 0.000751641