Search code examples
gnuplot

How can I plot a sublevel set?


I wish to create a 2d plot which includes the sublevel set of a two variable function. The plot would also include other single variable functions. I am able to plot the region from a saved splot of the two variable function as points, but I have not been able to figure out how to just have the sublevel set as a shaded region. Thank you for any suggestions.

set table 'sublevel.dat'
splot f(x,y)
unset table

plot g(x), sublevel.dat using 1:($3\< value ? $2 : 1/0)

with points # works but not really just shading

or

with filledcurves (various other stuff none satisfactory)

or

set table 'sublevel.dat'
set contour ; set cntrparam levels discrete value
unset surface ; set view map
splot f(x,y)
unset table

plot g(x), sublevel.dat using 1:($3\< value ? $2 : 1/0)

with filledcurves xy=clever_x,clever_y # sometimes works but definitely not always


Solution

  • The following probably doesn't fully answer your exact question, but maybe helps to find a solution. If you want to fill a contour line up to (or from) a certain level you could simply set the color palette accordingly, e.g.

    set palette defined (zmin c1, z0 c1, z0 c0, zmax c0)
    

    where zmin, zmax, z0 are the minimum, maximum and desired level and c0 and c1 the desired colors.

    First you plot your function into a table using set contour and set cntrparam level discrete z0 which will put the z-data into the first block (index 0) and the contour line(s) in following blocks (here: just one contour line in index 1). Plot this data ... index 0 with image and ... index 1 with lines.

    When using a function, the higher you set samples and isosamples (here: 250), the more precise/smoother the border will get, but it takes longer.

    Although I don't know how to plot your special function, but if you have your data already in a file or table x y z=f(x,y), you could use the same procedure.

    Script:

    ### fill contour above/below certain level
    reset session
    
    f(x,y) = sin(1.3*x)*cos(.9*y)+cos(.8*x)*sin(1.9*y)+cos(y*.2*x)
    
    z0 = 0
    set contour
    set cntrparam levels discrete z0
    set table $Data
        set samples    250
        set isosamples 250
        splot sample [x=-7:7][y=-7:7] '++' u 1:2:(f(x,y))
    unset table
    stats $Data u 3 nooutput   # get zmin,zmax
    zmin = STATS_min
    zmax = STATS_max
    set xrange noextend
    set yrange noextend
    set tics out
    set key out noautotitle
    set cbrange[zmin:zmax]
    set style fill solid border lt -1
    unset colorbox
    
    c0 = "0xffffff"   # fillcolor 0
    c1 = "0xffcccc"   # fillcolor 1
    set palette defined (zmin c1, z0 c1, z0 c0, zmax c0)
    
    plot $Data index 0 u 1:2:3 w image, \
            keyentry w boxes fc rgb c1 ti "z < ".z0, \
            '' index 1 u 1:2 w l lc "black" ti "z = ".z0, \
            keyentry w boxes fc rgb c0 ti "z > ".z0
    ### end of script
    

    Result: (output from wxt terminal)

    enter image description here

    Addition: (transparent "fill")

    As far as I know, you cannot set a transparent fillcolor (at least not in gnuplot 5.4), but you can use the ternary operator (check help ternary) and set the values z>0 to NaN. If you then use, e.g. the terminal pngcairo with option transparent you will get a PNG with transparent areas and background.

    You need to change the first plotting line to

    plot $Data index 0 u 1:2:($3>z0 ? NaN : $3) w image
    

    and add the following lines at the end:

    set term pngcairo transparent
    set output "SO79103168.png"
        replot
    set output
    

    Output: (Screenshot of generated PNG imported into Inkscape with checkerboard background)

    enter image description here