Search code examples
gnuplot

gnuplot: rotate line title and set offset


I'm trying to plot hs-diagram from csv files.

To plot lines I use

plot 'it175.csv' using 7:6 with lines lc rgb 'green' title '175K' at begin, \
'ib50.csv' using 7:6 with lines lc rgb 'red' title '50MPa' at end

It gives nice isotherm titles,

enter image description here

but worse isobaric

enter image description here

How can I rotate line titles and set offset to the end of the line using 'title "title" at end' without using labels, because there are over 430 lines, and it is very difficult to adjust label coordinates for each line by hand


Solution

  • Let me summarize: you want to print the key/legend/title at the end of the curve rotated by a suitable angle.

    If you check help plot title and although it is linked to help key for further parameters, I couldn't find any statement about rotated keys (gnuplot 5.4.1). So, it looks like you have to rotate them yourself, at least, with some effort you can do it automatically.

    • there is the plotting style with labels which has variable rotation (check help labels)
    • the rotation angle of the text should be equal to the angle of the last segment of the curve
    • you need to determine the angle of the last segment of each curve, however, you cannot simply take the coordinates of your plot, but you need to take the "pixel coordinates" of the screen to get the proper "visual" angle.

    What the following script does:

    • generates input files for illustration, like your files which contain the value of the labels already in the filename
    • get a list of all files obeying a certain pattern, e.g. it*.dat
    • create a "preliminary" plot in order to get the relationships between plot coordinates and pixel coordinates via the gnuplot variables GPVAL_... which you only get after plotting.
    • plot your data again with lines and labels and at the same time extract the "visual" angle of the last segment of each curve and rotate the label (key/title) accordingly.

    I hope you can follow the script below and adapt it to your data. If you need more explanations, let me know. Maybe there is a simpler solution which I am currently not aware of.

    Script:

    ### rotate title at end of curve
    reset session
    
    # create some test data files
    do for [t=0:5] {
        set print sprintf("it%d.dat",t*5+370)
            do for [x=0:100:5] {
                print sprintf("%g %g",x,(t/3.+0.2)*x**2+t*2000)
            }
        set print
    }
    do for [t=0:6] {
        set print sprintf("ib%d.dat",t*5+20)
            do for [x=0:100:5] {
                print sprintf("%g %g",x*(t+1)/10.,x**3/35.)
            }
        set print
    }
    
    # get a file list
    
    GetFileList(path,expr) = GPVAL_SYSNAME[1:7] eq "Windows" ? \
                             sprintf('dir /b "%s%s"', path, expr) : \
                             sprintf('ls "%s%s"',     path, expr)     # Linux/MacOS
    FILES_it = system(GetFileList('','it*.dat'))
    FILES_ib = system(GetFileList('','ib*.dat'))
    
    set key noautotitle
    set offset 0, graph 0.05, graph 0.05, 0
    
    # plot to get the GPVAL_ ... values
    plot for [FILE in FILES_it] FILE u 1:2 w l lc "red", \
         for [FILE in FILES_ib] FILE u 1:2 w l lc "green"
    
    # store GPVAL parameters after plot in variables
    txmin = GPVAL_TERM_XMIN; txmax = GPVAL_TERM_XMAX; tymin = GPVAL_TERM_YMIN; tymax = GPVAL_TERM_YMAX
    xmin  = GPVAL_X_MIN;     xmax  = GPVAL_X_MAX;     ymin  = GPVAL_Y_MIN;     ymax  = GPVAL_Y_MAX
    
    # x,y to pix and pix to x,y coordinate conversion
    XtoPix(x)    = txmin + real(x-xmin)    *(txmax-txmin)/( xmax- xmin)
    YtoPix(y)    = tymin + real(y-ymin)    *(tymax-tymin)/( ymax- ymin)
    
    # angle from -180° to +180°
    set angle degrees
    Angle(x0,y0,x1,y1) = (_dx=x1-x0, _dy=y1-y0, _L=sqrt(_dx**2 + _dy**2), _L==0 ? NaN : \
                         (_dy>=0 ? acos(_dx/_L) : -acos(_dx/_L) ))
    # angle for screen coordinates
    AngleScr(x0,y0,x1,y1) = Angle(XtoPix(x0),YtoPix(y0),XtoPix(x1),YtoPix(y1))
    
    myLabel(fname,unit) = sprintf(" %s %s",fname[3:strstrt(fname,'.')-1],unit)   # extract number from filename
    
    plot for [FILE in FILES_it] FILE u (last=$0,$1):2 w l lc "red", \
         for [FILE in FILES_it] x1=y1=NaN FILE u (x0=x1,x1=$1,$0==1?x1:NaN):(y0=y1,y1=$2,$0==1?y1:NaN):\
             (myLabel(FILE,"K")):(AngleScr(x0,y0,x1,y1)) every ::last-1::last w labels rotate var left font ",11", \
         for [FILE in FILES_ib] FILE u (last=$0,$1):2 w l lc "green", \
         for [FILE in FILES_ib] x1=y1=NaN FILE u (x0=x1,x1=$1,$0==1?x1:NaN):(y0=y1,y1=$2,$0==1?y1:NaN):\
             (myLabel(FILE,"MPa")):(AngleScr(x0,y0,x1,y1)) every ::last-1::last w labels rotate var left font ",11"
    ### end of script
    

    Result:

    enter image description here