Plotting squares, triangles and circles when using smooth bezier with gnuplot - plot

I am usually using smooth bezier when plotting my data. It makes then easier to understand and also nicer to see. However, I would also like to plot circles, triangles and squares in the right place i.e. where I've got real data. How could I do that?
I'll give an example of what I do:
p "times" u 1:2 w lp smooth bezier title "Time 1", "" u 1:3 w lp smooth bezier title "Time 2"
set xtics("0" 0,"1" 1, "2" 2,"4" 4 ,"8" 8)
getting:
Now I want to set triangles in the green line to the right point corresponding to x=1, x=2,x=4 and x=8. Same for the red line, but instead triangles, circles, for example.

You can just plot the data again without smoothing:
CIRCLEPT = 6
TRIANGLEPT = 9
set xtics("0" 0,"1" 1, "2" 2,"4" 4 ,"8" 8)
plot "times" u 1:2 w lp lt 1 smooth bezier title "Time 1", \
"" u 1:2 w p lt 1 pt CIRCLEPT notitle , \
"" u 1:3 w lp lt 2 smooth bezier title "Time 2", \
"" u 1:3 w p lt 2 pt TRIANGLEPT notitle
As far as getting triangles and circles, you'll need to select the proper point type for your terminal. To figure out which point type to use, you'll need to do something like:
set terminal <whatever>
set output <whatever> #only for non-interactive terminals
test
Now you can look at whatever output was generated by test and along the right side will be a bunch of points of different types. Just pick the type you want (e.g. 7 is often a circle) and put it in the script

Related

GNUplot - draw line using window coordinate system

I try to plot two horizontal lines in a coordinate system using GNUPlot. The two lines represent average values in two datasets. Each dataset has the following constants: max, min and average. The same logic is to be applied to both datasets, so we can simply focus at one of them.
The output should be a 800 x 800 PNG image. They share the X axis, but their Y axis is different from each other in terms of the ranges' values and unit of measurement. Naturally, the numerical values of the two lines can vary arbitrarily. More precisely, I need to plot the two lines at, say, y = 300 and y = 500 in pixel coordinates, regardless of the value of average.
As far I as can tell, there is no way to tell GNUPlot to plot something at a specific pixel coordinate. However, I do believe it is possible to to it indirectly by adjusting the ranges to appropriate values. After poking around in GNUPlot, I managed to find proper values. When the proper range values are set, I think the datapoints in the set should be plotted nicely such that they fit into the graph. Now I need a general approach for any values.
I have the following GNUPlot script with arbitrary values for two horizontal lines:
set term png size 800, 800
set multiplot layout 1, 1
# Green line
min_green = 0
max_green = 50
set size 1,1
set ytics 20
set yrange [min_green : max_green]
avg_green = 22
plot avg_green linecolor rgb "green"
# Blue line
min_blue = 10
max_blue = 70
set size 1,1
set ytics 20
set yrange [min_blue : max_blue]
avg_blue = 14
plot avg_blue linecolor rgb "blue"
Use it like this: gnuplot -p script > plot.png
I need two procedure that looks something like this:
range_min = get_new_min_range(pixel_target_y, min, max, avg)
range_max = get_new_max_range(pixel_target_y, min, max, avg)
The ranges is put into set yrange in GNUPlot. The green line must be at y = 500 and the blue line must be at y = 300 (this is the pixel_target_y patameter). Any help is greatly appreciated!
Let me try to repeat in my words if I understood your question correctly:
You want to plot two datasets where the average (or mean) of each datasets have a fixed y-pixel-(or screen) position within the output graph (independent of data values and graph margins), correct?
For this you need the gnuplot variables GPVAL_TERM_YMIN and GPVAL_TERM_YMAX. In order to get these values you have to plot a dummy graph first. Then you need to do some calculations to get the proper range.
As you can see in the result from 3 different plots: the green and blue lines are independent of x-labels or graph titles.
Code:
### have average lines at fixed pixel position within the plot
reset session
myTermSizeX = 800
myTermSizeY = 800
set term pngcairo size myTermSizeX, myTermSizeY
myOutputFile = "Output.png"
set output myOutputFile
myFixY1 = 500
myFixY2 = 300
set title "Some graph title"
set xlabel "x-Axis title"
# create some test data
set table $Data1
plot '+' u 1:(rand(0)*50+40) smooth bezier
unset table
set table $Data2
plot '+' u 1:(rand(0)*40+10) smooth bezier
unset table
stats $Data1 u 2 name 'Data1' nooutput
stats $Data2 u 2 name 'Data2' nooutput
print Data1_min, Data1_mean, Data1_max
print Data2_min, Data2_mean, Data2_max
# dummy plot to get GPVAL_TERM_YMIN, GPVAL_TERM_YMAX
plot x
R_grph1 = real(myFixY1 - GPVAL_TERM_YMIN)/(GPVAL_TERM_YMAX - GPVAL_TERM_YMIN)
R_grph2 = real(myFixY2 - GPVAL_TERM_YMIN)/(GPVAL_TERM_YMAX - GPVAL_TERM_YMIN)
R_data1 = (Data1_mean - Data1_min)/(Data1_max-Data1_min)
R_data2 = (Data2_mean - Data2_min)/(Data2_max-Data2_min)
if (R_data1 > R_grph1) {
Y1min = Data1_min
Y1max = (Data1_mean - Data1_min)/R_grph1 + Data1_min
}
else {
Y1max = Data1_max
Y1min = Data1_max - (Data1_max - Data1_mean)/(1-R_grph1)
}
print Y1min,Y1max
if (R_data2 > R_grph2) {
Y2min = Data2_min
Y2max = (Data2_mean - Data2_min)/R_grph2 + Data2_min}
else {
Y2max = Data2_max
Y2min = Data2_max - (Data2_max - Data2_mean)/(1-R_grph2)
}
print Y2min,Y2max
set yrange [Y1min:Y1max]
set ytics nomirror
set y2range [Y2min:Y2max]
set y2tics nomirror
set output myOutputFile # it seems you have to specify the output again
set key top center
plot \
$Data1 u 1:2 axes x1y1 w lp pt 7 lc rgb "red" ti "Data1", \
Data1_mean axes x1y1 w l lw 2 lc rgb "green" ti "Data1 mean", \
Data1_min axes x1y1 lt 0 not, \
Data1_max axes x1y1 lt 0 not, \
$Data2 u 1:2 axes x1y2 w lp pt 7 lc rgb "orange" ti "Data2", \
Data2_mean axes x1y2 w l lw 2 lc rgb "blue" ti "Data2 mean", \
Data2_min axes x1y2 lt 0 not, \
Data2_max axes x1y2 lt 0 not
set output
### end of code
Result:

Gnuplot - Weighted point size

I have an unsorted data set of two columns with most of the points aligning diagonally along y=x, however some points misalign.
I would like to show that most of the points actually do align along the function, however just pointplotting would just overlap the over-represented points to one. The viewer would then get the impression that the data points are actually scattered randomly because there is no weight to the occurrence count.
Is there a way to implement a weight to the points that occur more than once - maybe through point size? Couldnt find anything on this topic.
Thanks a lot!
You don't show data so I assumed something from your description. As #Christoph already mentioned you could use jitter or transparency to indicate that there are many more datapoints more or less at the same location. However, transparency is limited to 256 values (actually, 255 because fully transparent you won't see). So, in extreme case, if you have more than 255 points on top of each other you won't see a difference to 255 points on top of each other.
Basically, you're asking for displaying the density of points. This reminds me to this question: How to plot (x,y,z) points showing their density
In the example below a "pseudo" 2D-histogram is created. I'm not aware of 2D-histograms in gnuplot, so you have to do it as 1D-histogram mapping it onto 2D. You divide the plot into fields and count the occurrence of point in each field. This number you use either for setting the point variable color via palette or for variable pointsize.
The code example will generate 5 ways to plot the data:
solid points
empty points
transparent points
colored points
sized points (your question)
I leave it up to you to judge which way is suitable. Certainly it will depend pretty much on the data and your special case.
Code:
### different ways to show density of datapoints
reset session
# create some random test data
set print $Data
do for [i=1:1000] {
x=invnorm(rand(0))
y=x+invnorm(rand(0))*0.05
print sprintf("%g %g",x,y)
}
do for [i=1:1000] {
x=rand(0)*8-4
y=rand(0)*8-4
print sprintf("%g %g",x,y)
}
set print
Xmin=-4.0; Xmax=4.0
Ymin=-4.0; Ymax=4.0
BinXSize = 0.1
BinYSize = 0.1
BinXCount = int((Xmax-Xmin)/BinXSize)+1
BinYCount = int((Ymax-Ymin)/BinYSize)+1
BinXNo(x) = floor((x-Xmin)/BinXSize)
BinYNo(y) = floor((y-Ymin)/BinYSize)
myBinNo(x,y) = (_tmp =BinYNo(y)*BinXCount + BinXNo(x), \
_tmp < 0 || _tmp > BinXCount*BinYCount-1 ? NaN : int(_tmp+1))
# get data into 1D histogram
set table $Bins
plot [*:*][*:*] $Data u (myBinNo($1,$2)):(1) smooth freq
unset table
# initialize array all values to 0
array BinArr[BinXCount*BinYCount]
do for [i=1:BinXCount*BinYCount] { BinArr[i] = 0 }
# get histogram values into array
set table $Dummy
plot myMax=NaN $Bins u ($2<myMax?0:myMax=$2, BinArr[int($1)] = int($2)) w table
unset table
myBinValue(x,y) = (_tmp2 = myBinNo(x,y), _tmp2>0 && _tmp2<=BinXCount*BinYCount ? BinArr[_tmp2] : NaN)
# point size settings
myPtSizeMin = 0.0
myPtSizeMax = 2.0
myPtSize(x,y) = myBinValue(x,y)*(myPtSizeMax-myPtSizeMin)/myMax*myPtSizeMax + myPtSizeMin
set size ratio -1
set xrange [Xmin:Xmax]
set yrange [Ymin:Ymax]
set key top center out opaque box
set multiplot layout 2,3
plot $Data u 1:2 w p pt 7 lc "red" ti "solid points"
plot $Data u 1:2 w p pt 6 lc "red" ti "empty points"
plot $Data u 1:2 w p pt 7 lc "0xeeff0000" ti "transparent points"
set multiplot next
plot $Data u 1:2:(myBinValue($1,$2)) w p pt 7 ps 0.5 palette z ti "colored points"
plot $Data u 1:2:(myPtSize($1,$2)) w p pt 7 ps var lc "web-blue" ti "sized points"
unset multiplot
### 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.

Lines Between Datapoints of different columns

I have these example-data saved in test.txt
1 2
2 3
3 5
4 5
5 6
I can easily plot them by
plot "test.txt" u 0:1,"" u 0:2
the result is
just the data plotted
but what i want is some lines between the datapoints to illustrate the difference and which points belong to the same x-value. (photoshopped scribble below)
same image with lines between datapoints
Is there any way i could achieve this with gnuplot?
Use the vectors style
plot "test.txt" u 0:1,"" u 0:2, "" u 0:1:(0):($2-$1) with vectors nohead
The vectors style expects 4 values which are the x and y coordinates, the x change (0 in this case), and the y change (the difference between your 2 columns). The nohead option removes the arrow head that is normally added.
You can style the vector using most line style specifications, and if necessary, can adjust coordinates to add some spacing. For example, setting the lines black and padding the lines by 0.1 in both directions by
plot "test.txt" u 0:1, "" u 0:2, "" u 0:($1+0.1):(0):($2-$1-0.2) with vectors nohead lc "black"
gives
I manually set ranges with set xrange and set yrange to match your images, as mine was using slightly different defaults.
See help vectors for more information on the vectors style.

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.

Resources