gnuplot pm3d plot triangle data - plot

i'm trying to plot an heatmap on a triangular surface, the coordinates and "heat values" are obtained with the methog shown on page staff.aist.go.jp/a.noda/programs/ternary/ternary-en.html.
so, i process the data and obtain a data file in the form:
x y val
where x and y are values between 0 and 1, and val is an integer representing the frequency i need to show.
the data file is this: http://tinyurl.com/lqsqtvv
and the plot script is this:
#!/usr/bin/gnuplot
reset
set terminal pngcairo size 640,480
set output 'heat_map_triangle.png'
set border linewidth 0
unset tics
set bmargin 3
set lmargin 3
set rmargin 3
set tmargin 3
set dgrid3d
set pm3d map
#set pm3d ftriangles
set pm3d interpolate 0,0
set pm3d at bs
set label 'Y' at 0, -0.03 center
set label 'Z' at 1, -0.03 center
set label 'X' at 0.5, 0.886 center
set style line 1 lt 1 lw 3 pt -1 ps 1
# x
set arrow 1 from 0,0 to 1, 0.0 nohead linestyle 1
# z
set arrow 11 from 1, 0 to 0.50, 0.866 nohead linestyle 1
# y
set arrow 21 from 0.50, 0.866 to 0,0 nohead linestyle 1
splot "./triangle.out" using 1:2:3
so, i'm getting out this plot
that is not exactly what i wanted...
i can't understand how to tell pm3d not to fill zones that are not in the data file (e.g. outside the triangle) and why the triangle top edge is taller than the heatmap.
it there a way to plot the data the way i want it?
in pm3d documentation it says that it can leave empty spaces, but how?
thanks

Ultimately, for pm3d to work, gnuplot requires that the data be on some sort of grid "mesh". The mesh needs to composed of quadrillaterals, but that is the only stipulation. e.g., your gridpoints could be arranged like this:
1
2
3
4 5 6 10
9
8
7
In this case, gnuplot will create a quadrilateral from points 1-2-4-5 and points 2-3-5-6, etc. etc. Gnuplot will color the quadrilateral depending on the corners2color option of pm3d. By default, it uses the average of the 4 values on the corners of the cells.
To put this in a datafile, you'd want to the datafile coordinates like this:
x1 y1 z1
x2 y2 z2
x3 y3 z3
x10 y10 z10
x4 y4 z4
x5 y5 z5
x6 y6 z6
x10 y10 z10
x7 y7 z7
x8 y8 z8
x9 y9 z8
x10 y10 z10
Notice how I left a blank line between horizontal "scans" across the data. (Of course, we could have structured the datafile to take vertical "scans" across the data as well). I also repeated a point at the right vertex of my triangle to give it a sharp point. This isn't strictly necessary, but I wanted to demonstrate it was possible.
Your data isn't in that form and normally, gnuplot would give you an error complaining that your data wasn't gridded. however, you've added the line set dgrid3d which tells gnuplot that your data isn't on a grid and that gnuplot should use an inverse distance weighting function to interpolate your data onto a grid. Unfortunately, gnuplot creates a regular (rectangular) grid and there is no way to tell it to create some other kind of grid. Ultimately, you need to figure out how to beat your data into this form.

If you were prepared to use R, and the ggtern library, the following could be achieved:
Which was done with the following code:
#Load library
library(ggtern)
#Load the data
df <- read.table("./data.txt")
colnames(df) = c("x","y","Value")
#Put in ternary coordinates
df.new <- data.frame(transform_cart_to_tern(data=df),Value=df$Value)
df.new <- df.new[order(df.new$Value),]
df.new <- df.new[which(df.new$Value > 0),]
#Plot the diagram
ggtern(data=df.new,aes(y=T,x=L,z=R)) +
geom_point(aes(color=Value,alpha=Value)) +
scale_color_gradient(low="transparent",high="red") +
guides(alpha="none") +
theme_rgbw() +
theme(legend.position=c(0,1),legend.justification=c(0,1)) +
labs(title="Example Density Plot",color="Frequency")

Related

How to make `set offsets` apply to certain axis?

The gnuplot doc for set offsets is extremely terse and I cannot find how offsets interact with multiple x-axes or y-axes.
I have 2 plots and they use x1y1 and x1y2, so there are 2 y-axes one on the left one on the right. Right now, when I add some top offset it applies to the plot which uses y1. How can I make it affect the plot which uses y2?
That's what gnuplot help offsets says:
Offsets provide a mechanism to put an empty boundary around the data
inside an autoscaled graph. The offsets only affect the x1 and y1
axes, and only in 2D plot commands.
So it looks like, it's not (directly) possible.
By the way, do you want offsets affecting...
only y2 axis or
y1 and y2 axes in the same way or
y1 and y2 axes differently?
Maybe you can edit your question and add an example for illustration.
Addition:
Maybe the following is helpful. As you already did, you can use the GPVAL_ variables.
Important to know, that these values are only set after plotting.
So, you have to plot, then modify your y1 and y2 ranges as desired and then replot. You could also use the variables GPVAL_Y_MIN, GPVAL_Y_MAX, GPVAL_Y2_MIN, and GPVAL_Y2_MAX which gnuplot's autoscaling algorithm suggests as ranges.
Code:
### different "offsets" for y1 and y2 axes
reset session
set xlabel "x1-axis"
set ylabel "y1-axis"
set ytics nomirror
set y2label "y2-axis"
set y2tics nomirror
plot 100*(sin(x)+1) axes x1y1 w l, \
10*cos(x) axes x1y2 w l
Y1FromBottom = 0.40 # y1 data will use 40% space from bottom
Y2FromBottom = 0.80 # y2 data will use 80% space from bottom
set yrange[:(GPVAL_DATA_Y_MAX-GPVAL_DATA_Y_MIN)/Y1FromBottom+GPVAL_DATA_Y_MIN]
set y2range[:(GPVAL_DATA_Y2_MAX-GPVAL_DATA_Y2_MIN)/Y2FromBottom+GPVAL_DATA_Y2_MIN]
replot
### end of code
Result:

gnuplot - using line color as third variable does not generate the required output

Using gnuplot, I am trying to make a 2D plot with points where the point color is represented by the third column of a data file(file has 3 columns)
Here is the link to the file
I am using the following command to generate the graph:
pl "outPhaseDiff_b1_dScan.dat" u 1:2:3 w p pt 7 ps 2 lc variable
The desired output should contain 5 colors but it is only plotting 2 colors, which is really strange because I have been using this command for a long time and did not encounter such issue before. I guess it has to do something with the plotting algorithm but I have no clue.
Check your data, it contains many line pairs with the following pattern:
0.0000 0.0060 3
0.0000 0.0060 5
One line with x, y, color1, another line with identical x and y, but different color2. So the points from the second line hide the points from the first one.
If you plot it 3d with several layers, it looks like this:
z = 0
y = 0
splot "outPhaseDiff_b1_dScan.dat" \
u 1:2:($2 == y ? (z = z+1) : (z = 0, y=$2), z):3 \
w p pt 7 ps 2 lc variable
A 2d plot looks from top, only two colors are visible.

join points with arrow and label

My data file is like this:
x1 y1 x2 y2 id1 id2 value
x1 y1 x2 y2 id1 id2 value
x1 y1 x2 y2 id1 id2 value
.
.
.
I would like to joint the two points (x1,y1) and (x2,y2) with an arrow goes from 1 to 2.
Also i would like to:
add near the point 1 "id1" and near the point 2 "id2"
add a label with value in the middle of the arrow.
Use the vectors plotting style for the arrows and label to add all the labels:
plot 'data.txt' using 1:2:($3-$1):($4-$2) with vectors t '', \
'' using 1:2:5 with labels offset char 0,1 t '',\
'' using 3:4:6 with labels offset char 0,1 t '',\
'' using (0.5*($1+$3)):(0.5*($2+$4)):7 with labels offset char 0,1 t ''
Plotting with vectors requires the starting point an the arrow length, $1 accesses the values of the first column for calculations, ($3-$1) is the x-length of the arrow.
offset char 0,1 puts the label at a vertical offset of one character height above the given point. For more help see help vectors and help labels.

Plot points linked with edges using gnuplot

I have a file of points (x, y) that I plot using gnuplot. If I have another file that shows which point is linked with which other point by an edge (e.g. (3.8, 6) linked to (4,7)), is it possible to visualise/plot this edges between points ?
depending on how your data is organized, you may want to look into plotting with vectors.
For example, if your datafile looks like:
#x1 y1 x2 y2
1 1 3 3
You can plot this using:
set style arrow 1 nohead
plot "my_arrows.dat" using 1:2:($3-$1):($4-$2) with vectors arrowstyle 1
EDIT
Assuming all the points in your datafile are repeated, you can do the following:
set style arrow 1 nohead
plot "my_arrows.dat" using 1:2:($3-$1):($4-$2) with vectors arrowstyle 1,\
"my_arrows.dat" using 1:2 w points
If they're not repeated, you can do:
set style arrow 1 nohead
plot "my_arrows.dat" using 1:2:($3-$1):($4-$2) with vectors arrowstyle 1,\
"my_arrows.dat" using 1:2 w points ls 1 lc rgb "red" pt 1,\
"my_arrows.dat" using 3:4 w points ls 1 lc rgb "red" pt 1
Note that you can play around with the linestyles (linecolor or lc, pointtype or pt, linewidth or lw etc. to make the points appear the same.)
You might not be able to read the line positions in without using a separate utility to generate your plotscript, but the command to draw a line from point to point is
set arrow [X] from first x1,y1 to first x2,y2 nohead
where X is an optional tag number for the arrow, and (x1,y1) and (x2,y2) are points in the graph's coordinate system.

3d grid adapted to non rectangular data in gnuplot

I would like to plot points in a 3d plot and create a mesh that could handle non rectangular data. To be more specific my data is
data.dat
-1 0 0
-1 1 0
0 -1 0
0 0 0
0 1 0
1 -1 0
1 0 0
and my gnuplot file
plot.plt
set dgrid3d 3,3
splot 'data.dat' w l
pause -1
Unfortunately dgrid3d seems to make my data rectangular and a rectangular grid (actually a square grid) is plotted. Is there a way to plot a restricted envelope of my data ? Ideally I would like to plot the orthogonal convex hull of my set of points.
You have a few options for doing something like this -- unfortunately they all require some work on your part.
First, it is important to note that gnuplot can handle non-rectangular meshes for surface plotting (even though you only need a rectangular surface for this example). For surface plotting, the datafile looks like (Notice the blank records):
x11 y11 z11
x21 y21 z21
x31 y31 z31
...
x12 y12 z12
x22 y22 z22
x23 y23 z23
...
It then forms quadrilaterals. In this case, the first quadrilateral would be formed from the points (x11,y11),(x21,y21),(x12,y12),(x22,y22). The second quadrilateral would be formed from (x21,y21),(x31,y31),(x22,y22),(x23,y23) and so forth. So, given your set of points, you can easily create a "rectangular mesh" which will hold all of your datapoints. It won't be evenly spaced, but that's no problem as all. Now we need to figure out how to remove points so that gnuplot won't plot them. This is the "trick". You can mark a particular string as "missing data" in the datafile (set datafile missing "string"). In that case, gnuplot won't plot that point, but it will still keep track of the coordinates of the missing data for the sake of generating the surface.
So at the end of the day, your datafile will look something like:
x11 y11 ?
x21 y21 ?
x31 y31 z31
...
x12 y12 ?
x22 y22 z22
x23 y23 z23
...
and the script to plot it would be:
set datafile missing '?'
set surf
set view map #Not sure about this...depends on the view you want
splot "mydata.dat" u 1:2:3 w lines
If you want gnuplot to compute the "orthogonal convex hull", I think you're out of luck there.
THE EASY WAY
Also note that if you want a solid colored object in 2d space (like the picture on the wikipedia link you posted), this problem becomes significantly easier. If you can create a datafile with just the vertices of the object you want to draw (in order such that (x1,y1) connects to (x2,y2) connects to (x3,y3)...), then you can plot that datafile as:
set fillstyle #However you want the object to appear
plot "datafile.dat" u 1:2 with filledcurves closed

Resources