Search code examples
gnuplot

How to display mouse coordinates in multiplots?


In interactive terminals, e.g. like wxt or qt, gnuplot can show the coordinates of the mouse cursor on the status line of the terminal window. This is helpful in many cases and works fine for a single plot but does not work for a multiplot. gnuplot documentation explicitely mentions (check help mouse)

Mousing is not available inside multiplot mode. When multiplot is completed using unset multiplot, then the mouse will be turned on again but acts only on the most recent plot within the multiplot (like replot does).

This is a pity, because if it would be very convenient to quickly read out some data values from different graphs in a multiplot environment.

Question: is there maybe nevertheless a way to show the coordinates in a multiplot environment?


Solution

  • Since gnuplot 5.4.0 there is the "experimental" option set mouse mouseformat function string_valued_function(x, y). Check help mouseformat. With this, you can create some special functions. What you need to do is:

    • memorize the GPVAL_... graph parameters for each plot by adding them to a string variable
    • calculate the coordinates for the corresponding plot starting from x,y of the last plot

    If you have overlapping plots, the script will show the coordinates of the later added plot (which is "on top").

    So, hopefully this will be also useful to others. No guarantee that the following script is free of bugs. Any simplifications and better ideas would be very welcome. Ideally, this multiplot mouse coordinates would be implemented in gnuplot itself.

    I noted that the conversion of the coordinates doesn't seem to be "perfect", although I guess the formulae are correct, e.g. converting x,y mouse coordinates into terminal pixel coordinates I got a range from (-1 to 639) and (0 to 379) in a wxt 640,480 terminal. Any explanations are welcome.

    Script: (requires gnuplot>=5.4.0)

    ### display mouse cursor coordinates in multiplot
    reset session
    set term wxt size 640,480
    
    set samples 11
    f(x) = x
    g(x) = exp(x)
    
    GraphParams = ''
    addGraphParams(logAxisX,logAxisY) = GraphParams.\
                sprintf(' "%g %g %g %g %g %g %g %g %g %g %g %g"', \
                GPVAL_X_MIN, GPVAL_X_MAX, GPVAL_TERM_XMIN, GPVAL_TERM_XMAX, \
                GPVAL_X_LOG, logAxisX, \
                GPVAL_Y_MIN, GPVAL_Y_MAX, GPVAL_TERM_YMIN, GPVAL_TERM_YMAX, \
                GPVAL_Y_LOG, logAxisY)
    
    getGraphParam(graphNo,paramNo) = real(word(word(GraphParams,graphNo),paramNo))
    getXmin(n)     = getGraphParam(n,1)
    getXmax(n)     = getGraphParam(n,2)
    getTXmin(n)    = getGraphParam(n,3)
    getTXmax(n)    = getGraphParam(n,4)
    getLogX(n)     = getGraphParam(n,5)
    getLogAxisX(n) = int(getGraphParam(n,6))
    getYmin(n)     = getGraphParam(n,7)
    getYmax(n)     = getGraphParam(n,8)
    getTYmin(n)    = getGraphParam(n,9)
    getTYmax(n)    = getGraphParam(n,10)
    getLogY(n)     = getGraphParam(n,11)
    getLogAxisY(n) = int(getGraphParam(n,12))
    
    getPlotIdx(x,y) = (plotIdx=NaN, sum [_i=1:words(GraphParams)] ( \
                       TermX(x)>=getTXmin(_i) && TermX(x)<=getTXmax(_i) && \
                       TermY(y)>=getTYmin(_i) && TermY(y)<=getTYmax(_i) ? plotIdx=_i : 0), plotIdx)
    GraphX(n,x,y)   = (n==n ? real(TermX(x)-getTXmin(n))/(getTXmax(n)-getTXmin(n)) : NaN)
    GraphY(n,x,y)   = (n==n ? real(TermY(y)-getTYmin(n))/(getTYmax(n)-getTYmin(n)) : NaN)
    
    FirstX(x,y) = (_n=getPlotIdx(x,y), _n==_n ? getLogAxisX(_n) ? \
                   getLogX(_n)**(GraphX(_n,x,y)*(log(getXmax(_n))/log(getLogX(_n)) - \
                   log(getXmin(_n))/log(getLogX(_n))) + log(getXmin(_n))/log(getLogX(_n))) : \
                   getXmin(_n) + GraphX(_n,x,y)*(getXmax(_n)-getXmin(_n)) : NaN)
    FirstY(x,y) = (_n=getPlotIdx(x,y), _n==_n ? getLogAxisY(_n) ? \
                   getLogY(_n)**(GraphY(_n,x,y)*(log(getYmax(_n))/log(getLogY(_n)) - \
                   log(getYmin(_n))/log(getLogY(_n))) + log(getYmin(_n))/log(getLogY(_n))) : \
                   getYmin(_n) + GraphY(_n,x,y)*(getYmax(_n)-getYmin(_n)) : NaN)
    
    # take GPVAL_... from last plot
    TermX(x) = GPVAL_TERM_XMIN + (x-GPVAL_X_MIN) * \
              (GPVAL_TERM_XMAX-GPVAL_TERM_XMIN)/(GPVAL_X_MAX-GPVAL_X_MIN)
    TermY(y) = GPVAL_TERM_YMIN + (y-GPVAL_Y_MIN) * \
              (GPVAL_TERM_YMAX-GPVAL_TERM_YMIN)/(GPVAL_Y_MAX-GPVAL_Y_MIN)
    
    mouse(x,y) = sprintf("%g, %g",FirstX(x,y),FirstY(x,y))
    set mouse mouseformat function mouse(x,y)
    
    set multiplot
    
        set size   0.5,1.0
        set origin 0.0,0.0
        set grid x,y
        set key bottom right samplen 2
        plot [0:10] '+' u 1:(g($1)) w lp pt 7 lw 2 lc rgb "red" ti " x^2"
        GraphParams = addGraphParams(0,0)
        
        set size 0.37,0.45
        set origin 0.07, 0.5
        set logscale y
        set obj 1 rect from graph 0,0 to graph 1,1 fc "white" behind
        plot [0:10] '+' u 1:(g($1)) w lp pt 7 lw 2 lc rgb "red" ti " x^2"
        unset obj 1
        GraphParams = addGraphParams(0,1)
        
        set size   0.5,0.5
        set origin 0.5,0.5
        set logscale x 2
        set logscale y
        plot [0.5:100] '+' u (g($1)):1 w lp pt 7 lw 2 lc rgb "web-green" ti "x" 
        GraphParams = addGraphParams(1,1)
    
        set size   0.5,0.5
        set origin 0.5,0.0
        unset logscale x
        unset logscale y
        plot [1:10] '+' u 1:(f($1)) w lp pt 7 lw 2 lc rgb "web-green" ti "x" 
        GraphParams = addGraphParams(0,0)
    
    unset multiplot
    ### end of code
    

    Result: (Screen capture from wxt terminal)

    Note the moving mouse cursor and the coordinates in the status line and that the coordinates are (NaN,NaN) between the individual graphs.

    enter image description here