Search code examples
gnuplot

How to create a 2D contour plot for the density of scattered data in gnuplot?


The following script is based on an older topic (Gnuplot: Scatter plot and density). What I need is a contour plot of the scattered data. But there are some things that do not look as I expect. The scatter plot (1st figure) is correct and even after normalizing the third column, all values of this column are in the range [0.0, 1.0]. But the color bar on the right side of the contour plot (2nd figure) shows a different range [-0.2, 1.0]. How can this be corrected? The XY plot itself is also different in size. I would expect the same scaling for the same data set.

### 2D density color plot
reset session

# create some random rest data
set table $Data
    set samples 700
    plot '+' u (invnorm(rand(0))):(invnorm(rand(0))) w table
    set samples 500
    plot '+' u (invnorm(rand(0))+2):(invnorm(rand(0))+2) w table
unset table

# for each datapoint: how many other datapoints are within radius R
R = 0.5    # Radius to check
Dist(x0,y0,x1,y1) = sqrt((x1-x0)**2 + (y1-y0)**2)
set print $Density
    do for [i=1:|$Data|] {
        x0 = real(word($Data[i],1))
        y0 = real(word($Data[i],2))
        c  = 0
        stats $Data u (Dist(x0,y0,$1,$2)<=R ? c=c+1 : 0) nooutput
        d = c / (pi * R**2)             # density: points per unit area
        print sprintf("%g %g %f", x0, y0, d)
    }
set print

# Plot normalized z-values
set size ratio -1   # same screen units for x and y
set palette rgb 33,13,10

stats $Density u 3 nooutput

set table $Density_norm
plot $Density u 1:2:($3/STATS_max) w table
unset table

plot $Density_norm u 1:2:3 w p pt 7 lc palette z notitle

pause -1

# Plot 2D contours of created data points
set dgrid3d 100,100 splines
set contour surface
set cntrparam levels incremental 0.0, 0.1, 1.0
set view map
splot $Density_norm u 1:2:3 with lines lw 2 lc palette nosurface

### end of script

scatter plot of normalized data

contour plot of the same normalized data


Solution

  • You need to know:

    The following should do what you are looking for. Maybe in the meantime there are new features in gnuplot 6.x which I am not yet aware of. The following should work with gnuplot>=5.2.5 (maybe with minor modifications).

    Script:

    ### 2D density color and contour plot
    reset session
    
    # create some random test data
    set table $Data
        set samples 700
        plot '+' u (invnorm(rand(0))):(invnorm(rand(0))) w table
        set samples 500
        plot '+' u (invnorm(rand(0))+2):(invnorm(rand(0))+2) w table
    unset table
    
    # for each datapoint: how many other datapoints are within radius R
    R = 0.5    # Radius to check
    Dist(x0,y0,x1,y1) = sqrt((x1-x0)**2 + (y1-y0)**2)
    set print $Density
        do for [i=1:|$Data|] {
            x0 = real(word($Data[i],1))
            y0 = real(word($Data[i],2))
            c  = 0
            stats $Data u (Dist(x0,y0,$1,$2)<=R ? c=c+1 : 0) nooutput
            d = c / (pi * R**2)             # density: points per unit area
            print sprintf("%g %g %f", x0, y0, d)
        }
    set print
    
    # Plot normalized z-values
    set size ratio -1   # same screen units for x and y
    set palette rgb 33,13,10
    set key noautotitle
    
    stats $Density u 3 nooutput
    set table $Density_norm
        plot $Density u 1:2:($3/STATS_max) w table
    unset table
    plot $Density_norm u 1:2:3 w p pt 7 lc palette z
    
    pause -1
    
    # plot density as impulses in 3D
    set ztics 0.2
    set cbtics 0.2
    set xyplane 0
    stats $Density u 3 nooutput
    print STATS_max
    splot $Density u 1:2:($3/STATS_max) w impulses lc palette z
    
    pause -1
    
    # Plot surface and contours into datablock
    set table SURF_CONT="SO79472868_s_c.dat"
    set table $Surface_Contour
        set dgrid3d 50,50 gauss 0.1
        set contour surface
        set cntrparam levels incremental 0.0, 0.1, 1.0
        splot $Density_norm u 1:2:3
    set table $Contours
        splot $Density_norm u 1:2:3 nosurface
        unset dgrid3d
        unset contour
    unset table
    
    # plot contour lines
    set hidden3d
    splot $Surface_Contour index 0 u 1:2:3 w surface lc palette z, \
                        '' index 1:999 u 1:2:3 w lines lc "black"
    
    pause -1
    
    # plot 2D contour lines
    plot $Contours u 1:2:3 w l lw 2 lc palette z
    
    ### end of script
    

    Results:

    Ungridded data. Density as colored points. Normalized range [0:1]. enter image description here

    Ungridded data. Density as colored impules in "3D". Normalized z-range [0:1] enter image description here

    Gridded data. Density as surface with contour lines. The z-range might not be [0:1] depending on dgrid3d settings. If needed, you could normalize this data again. enter image description here

    Contour of gridded data. z-range same as above. It's a 2D-plot, not a 3D-splot with set view map and strange margins. Margins just like the first plot above. enter image description here