Reputation: 329
I have recently picked up GNUplot, and am plotting some 3D data sets using the "matrix" data format. After a mashup of some command files I found on the web, it's working pretty well, however I haven't found anything on how to do the following:
I'd like to plot my data as a 3D surface with solid/opaque surfaces in the xy plane at the z-minimum and the xz and yz planes at the x and y data limits. For instance, my plot currently looks like this:
http://audio.claub.net/temp/waterfall__plot_normalized_to_on-axis.JPG
I would prefer that it has opaque planes like the image below:
http://www.musicanddesign.com/images/NOTE_Polar_surface_SE_Datadata.gif
(Sorry for not posting the actual images, but I am too new to this forum and don't have that privilage yet).
I'm guessing that I need to manually add the planes as additional 3D surfaces with their own matrix data structure, but I am not sure how to do that.
I am currently plotting the data using the commands:
reset
set xrange [100:20000]
#set yrange [-60:60]
#set zrange [-25:3]
set logscale x
set cntrparam levels increment GPVAL_DATA_Z_MAX-2,-2,-30
# GPVAL_DATA_Z_MAX above contains the max z value in the data set
set surface
set contour surface
set style data lines
set ticslevel 0
set xlabel 'frequency [Hz]' #offset 0,2.25
set xtics add ("200" 200,"500" 500,"2000" 2000,"5000" 5000,"20000" 20000)
set mytics 4
set ylabel "angle\n[deg]" offset -12,0
set view 60,20
set clabel
set tics out
set key at 120000,-20 noautotitle title "SPL level"
set hidden3d offset 3
set isosamples 200,100
splot 'data.dat' nonuniform matrix using 2:1:3 lt 9
Can someone suggest how I can generate the opaque surfaces in the plot?
Thanks for any help on this.
.
Upvotes: 4
Views: 4913
Reputation: 48390
Here is how you can draw these planes (first the code and the result, then the explanation):
reset
set terminal pngcairo size 1000,800
set output 'test.png'
set xrange [100:20000]
set logscale x
set cntrparam levels increment -2,-2,-30
set contour surface
set style data lines
set ticslevel 0
set xlabel 'frequency (in Hz)' #offset 0,2.25
set xtics add ("200" 200,"500" 500,"2000" 2000,"5000" 5000,"20000" 20000)
set mytics 4
set ylabel "angle (in deg)" rotate parallel
set view 60,20
set tics out
set key at screen 0.94, screen 0.5 noautotitle title "SPL level"
set hidden3d offset 3
splot 'data.dat' nonuniform matrix using 2:1:3 lt 9, \
'' nonuniform matrix using 2:(-60):($1 == -60 ? $3-0.02 : ($1 == -50 ? -40 : 1/0)) lt -3 nocontour,\
'' nonuniform matrix using (20000):1:(($2 > 18500 && $2 < 20000) ? -40 : ($2 == 20000 ? $3-0.02 : 1/0)) lt -3 nocontour
This gives:
To create the xz
-plane (2nd row in the splot
command), I did the following:
If the y
value equals to the first value (-60
), then the z
-value of the file are used (the -0.02
is only for cosmetics, just remove that to see the difference). If the y
-value equals to the second value (-50
), then the z
-value is set to the minimum (-40
). For all other points of the surface 1/0
is used, which generates undefined data points which are skipped.
The lt -3
means that no surface lines are drawn.
nocontour
omits the contours for this plane
The yz
-plane is generated accordingly, but now the x
-values must be checked. This assumes, that you known the limits and increments of your data files. I you don't, or if these change often, some more tricking is required.
As you may have noted, I also changed some other parts of your file:
GPVAL_DATA_Z_MAX
is available only after plotting, so you cannot use it to set the increment. (Only if you call the script twice, without the reset
). You could use the stats
command to extract minimum and maximum data values.
You can use screen
coordinates to position the key
.
The ylabel
can be positioned parallel to the axis with rotate parallel
.
Here is the code:
reset
set terminal pngcairo size 1000,800
set output 'test.png'
set xrange [100:20000]
# added following block:
set yrange [-60:60]
set zrange [-40:5]
set lmargin screen 0.2
set tmargin screen 0.8
set rmargin screen 0.8
set bmargin screen 0.2
set logscale x
set cntrparam levels increment -2,-2,-30
set contour surface
set style data lines
set ticslevel 0
set xlabel 'frequency (in Hz)' #offset 0,2.25
set xtics add ("200" 200,"500" 500,"2000" 2000,"5000" 5000,"20000" 20000)
set mytics 4
set ylabel "angle (in deg)" rotate parallel
set view 60,20
set tics out
unset key
set hidden3d nooffset
set multiplot
splot 'data.dat' nonuniform matrix using 2:1:3 lt 9,\
'' nonuniform matrix using 2:(-60):($1 == -60 ? $3-0.02 : ($1 == -50 ? -40 : 1/0)) lt -3 nocontour, \
'' nonuniform matrix using (20000):1:(($2 > 18500 && $2 < 20000) ? -40 : ($2 == 20000 ? $3-0.02 : 1/0)) lt -3 nocontour
unset tics
unset xlabel
unset ylabel
unset border
unset surface
unset hidden3d
splot 'data.dat' nonuniform matrix using 2:(-60):($1 == -60 ? $3-0.02 : ($1 == -50 ? -40 : 1/0)) lt 9,\
'' nonuniform matrix using (20000):1:(($2 > 18500 && $2 < 20000) ? -40 : ($2 == 20000 ? $3-0.02 : 1/0)) lt 9
unset multiplot
which gives:
I did the following additions compared to the first example:
I added explicit margins and set manual yrange
and zrange
. This is required because the contour lines of the planes are drawn with a second splot
command in multiplot
mode, but after unsetting border, tics and labels (otherwise the plot might lock jagged because of different anti-aliasing).
Draw only the contours of the planes. I need to unset surface
before plotting them, because the contour line types are taken relative the the surface line type. So I need to use lt 9
, but don't want the surface itself to be drawn.
Upvotes: 5
Reputation: 329
Thanks to the great answer by Christoph I am now able to see how to add the "sides" to the plot so that the result looks like a 3D object.
I modified the commands a bit. Now that I can add sides, it would be nice to also have the contour lines run from the z-axis tics across the "side" and meet the falling edge of the surface. Doing that means that I do not need the key, since the viewer can read off the position of the line from its z-axis intersection. The code I am using, and a link to the resulting plot, are given below. I want all mesh surfaces to be the same color and the contour lines must have the same color on the surface and the sides. If I used the multi-color countour lines, the color was always different on each face. So I have come up with this method that uses only one color for all contour lines, but that should be OK for my needs.
Here is the code:
reset
set terminal pngcairo size 1000,800 #I use a ported windows version, so I use the win term
set output 'test.png'
set xrange [100:20000]
set logscale x
set cntrparam levels increment 0,-5,-40
set contour surface
set style data lines
set ticslevel 0
set xlabel 'frequency (in Hz)' #offset 0,2.25
set xtics add ("200" 200,"500" 500,"2000" 2000,"5000" 5000,"20000" 20000)
set mytics 4
set ylabel "angle (in deg)"
set view 60,20
set tics out
unset key
unset clabel
set hidden3d offset 3
splot 'test.dat' nonuniform matrix using 2:1:3 w l lt 1 lc rgb "#3D59AB", \
'' nonuniform matrix using 2:(-60):($1 == -60 ? $3-0.02 : ($1 == -50 ? -40 : 1/0)) w l lt 1 lc rgb "#3D59AB" ,\
'' nonuniform matrix using 2:(60):($1 == 60 ? $3-0.02 : ($1 == 50 ? -40 : 1/0)) w l lt 1 lc rgb "#3D59AB" ,\
'' nonuniform matrix using (20000):1:(($2 > 18500 && $2 < 20000) ? -40 : ($2 == 20000 ? $3-0.02 : 1/0)) lt -999
.
Finally, here is the resulting plot:
Upvotes: 1
Reputation: 408
Try to change the last line by
set pm3d
splot 'data.dat' nonuniform matrix using 2:1:3 lt 9 with pm3d at s
to change the color add
set palette rgbformulae 33,13,10
before splot
Upvotes: 0