Search code examples
gnuplotscatter-plot

Gnuplot: Scatter plot and density


I have x- and y-data points representing a star cluster. I want to visualize the density using Gnuplot and its scatter function with overlapping points.

I used the following commands:

 set style fill transparent solid 0.04 noborder
 set style circle radius 0.01
 plot "data.dat" u 1:2 with circles lc rgb "red"

The result:

enter image description here

However I want something like that

enter image description here

Is that possible in Gnuplot? Any ideas?


Solution

  • (edit: revised and simplified)

    Probably a much better way than my previous answer is the following: For each data point check how many other data points are within a radius of R. You need to play with the value or R to get some reasonable graph.

    Indexing the datalines requires gnuplot>=5.2.0 and the data in a datablock (without empty lines). You can either first plot your file into a datablock (check help table) or see here: gnuplot: load datafile 1:1 into datablock

    The time for creating this graph will increase with number of points O(N^2) because you have to check each point against all others. I'm not sure if there is a smarter and faster method. The example below with 1200 datapoints will take about 4 seconds on my laptop. You basically can apply the same principle for 3D.

    Addition: (contour plot)

    • once you have the density data (x:y:density), you can either create a "3D"-splot or a 2D-contour plot
    • gnuplot has the feature dgrid3d for this and you need to play with the dgrid3d options (check help dgrid3d), e.g. gauss <number>
    • a disadvantage of using splot and set view map is the arrangement/alignment of the margins. Better would be plot, but then you have to plot your generated contours first into another datablock.

    Script: requires gnuplot>=5.2.5, Oct. 2018 (because of splot ... nosurface)

    ### 2D density color and contour plot
    reset session
    
    # create some random test data
    t0 = time(0.0)
    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
    print sprintf("Data creation: %.3f sec",(t1=time(0.0))-t0,t0=t1)
    
    stats $Data u 0 nooutput   # get number of datalines
    Rows = STATS_records
    R    = 0.7                 # Radius to check
    
    # for each datapoint: how many other datapoints are within radius R
    distance(x0,y0,x1,y1) = sqrt((x1-x0)**2 + (y1-y0)**2)
    set print $Density
        do for [i=1:Rows] {
            x0 = real(word($Data[i],1))
            y0 = real(word($Data[i],2))
            c  = 0
            stats $Data u (distance(x0,y0,$1,$2)<=R ? c=c+1 : 0) nooutput
            d = c / (pi * R**2)
            print sprintf("%g %g %d", x0, y0, d)
        }
    set print
    print sprintf("Density check: %.3f sec",(t1=time(0.0))-t0,t0=t1)
    
    set size ratio -1
    set palette rgb 33,13,10
    set cblabel "points per unit area"
    
    set multiplot layout 1,2
        plot $Density u 1:2:3 w p pt 7 lc palette z notitle
    
        set dgrid3d 100,100 gauss 0.2
        set contour
        set cntrparam levels 10
        set view map
        set size ratio -1
        set grid x,y
        set key noautotitle out samplen 1
        unset colorbox
        set margins 0,0,0,0
        splot $Density u 1:2:3 w l palette z nosurface
        print sprintf("Contour plot:  %.3f sec",(t1=time(0.0))-t0,t0=t1)
    unset multiplot
    ### end of script
    

    Result:

    Data creation: 0.079 sec
    Density check: 4.620 sec
    Contour plot:  0.889 sec
    

    enter image description here