Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
876 views
in Technique[技术] by (71.8m points)

gnuplot: How to get correct contour line level values with "uneven" data?

I tried to get contour lines on data which is not "evenly" distributed within a rectangular bounding box. In order to get this I needed to play several tricks. I had to unset dgrid3d, otherwise I could not plot the data as it is. Furthermore, I had to plot the contour lines into a table to be able to plot the contour when dgrid3d is off. The code below is a bit cumbersome, but the result would be more or less ok, if the levels of the contour lines were correct. In the below example they levels should go up to 2500, not just to 1200.

Code:

### wrong contour line levels with "non-rectangular" data
reset session

# create some test data
set print $Data
do for [i=0:100] {
    do for [j=0:100-i:5] {
        print sprintf("%g %g %g",i,j,i*j)
    }
    print ""
}
set print

set pm3d
set view map

# get contour lines into table
set contour
set dgrid3d
set dgrid3d 20,20
set cntrparam levels auto 20
set table $Contour
    splot $Data u 1:2:3 
unset table
unset contour
unset dgrid3d

# only use the contourlines, skip grid data at index 0
set table $Contour2
    splot $Contour u 1:2:3 index 1::1
unset table

# convert one empty line into two empty lines, otherwise splot will connect the lines
set print $Contour   # overwrite datablock $Contour
    do for [i=1:|$Contour2|] {
        if ($Contour2[i] eq '') { print ""}
        print $Contour2[i]
    }
set print

stats $Contour2 u 0 nooutput   # get number of blocks = number of contour lines
ContourLineCount = STATS_blocks

# get contour line values into array
array ContValues[ContourLineCount]
set table $Dummy
    plot for [i=0:ContourLineCount-1] $Contour u (ContValues[i+1]=$3) index i every ::0::0 w table
unset table

set key noautotitle horizontal at screen 0.15,0.9
set size ratio -1
set lmargin screen 0.10
set rmargin screen 0.85
splot $Data u 1:2:3 w pm3d, 
      for [i=0:ContourLineCount-1] $Contour u 1:2:3:3 index i w l lw 1.5 lc i, 
      for [i=1:ContourLineCount] keyentry w l lw 1.5 lc i title sprintf("%g",ContValues[i])
### end of code

Result:

enter image description here

Checking the documentation, I assume that gnuplot needs more or less equally distributed data within a rectangular bounding box. So, in the above case, although the contour lines look somehow reasonable, but the levels are nonsense.

From help contour:

set contour enables contour drawing for surfaces. This option is available for splot only. It requires grid data, see grid_data for more details. If contours are desired from non-grid data, set dgrid3d can be used to create an appropriate grid.

From help dgrid3d:

When enabled, 3D data read from a file are always treated as a scattered data set. A grid with dimensions derived from a bounding box of the scattered data and size as specified by the row/col_size parameters is created for plotting and contouring. The grid is equally spaced in x (rows) and in y (columns); the z values are computed as weighted averages or spline interpolations of the scattered points' z values. In other words, a regularly spaced grid is created and the a smooth approximation to the raw data is evaluated for all grid points. This approximation is plotted in place of the raw data.

Questions:

Is there maybe nevertheless a way to get the correct contour line levels? I don't think I can simply multiply the levels by a factor of 2 (this would be more or less the expected levels). Maybe mirroring the data, getting the levels and removing the mirrored data again? Maybe someone can even simplify the code getting the desired result?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

I think all those extra steps to massage the data format and create a separate block of contour line data are totally unnecessary.

The fundamental problem here is that your data is not just "uneven"; it is dense over half the area being plotted but entirely missing for the other half. What are the "correct contour lines" for a region in which there is no data whatsoever?

What you need is either

  1. data, if only incomplete, for the missing region

or

  1. some way to plot only the region for which you have data

Gnuplot does not provide an easy way to produce a plot that is a triangle rather than a rectangle, but filling half the rectangle with background color is not hard.

# create some test data
set print $Data
do for [i=0:100] {
    do for [j=0:100-i:5] {
        print sprintf("%g %g %g",i,j,i*j)
    }
}
unset print

set dgrid3d 20,20 gauss

set view map
set size ratio -1
set key outside

set contour
set cntrparam levels auto 20
set cntrlabel format "%.0f"

set obj 1 polygon from graph 0,1 to graph 1,1 to graph 1,0
set obj 1 front fillstyle solid noborder fillcolor "white"

splot $Data u 1:2:3 w lines nosurface title '$Data'

enter image description here


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

56.8k users

...