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:
Related
How to turn the following tabular dataset into a simple 2D density plot to show a loc-number distribution?
I am new to gnuplot. Attempted a tutorial. A simple x,y plot with multiple columns of data, the plot is fine of course. Then tried this answer.. However I encountered the following issue, though x values are defined. I am guessing fundamentally my data set is lacking?(!).. what am I not doing right here? How to achieve a simple 2D contour from below data?
Updating based on recommended suggestions while OP aim remains intact.
Following is the input sample data used. File is single-space delimited. x = x, y=y, z1 = locid (1 to n) or z2=loctype (scuba, shower, swimming, restrooms, sushi, cafe, restaurant, etc)
input data :
ametype amename X(1000) Y1000) km-to-carpark
Scuba SCUB1 10.72 49.01
Scuba SCUB2 13.88 47.32
Scuba SCUB3 14.58 46.46
Scuba SCUB4 14.52 48.23
Scuba SCUB5 13.05 47.23
Scuba SCUB6 12.21 47.95
Scuba SCUB7 12.66 46.19
Cafe CAFE1 13.97 47.45
Cafe CAFE4 31.63 30.3
Playground PARK2 31.57 30.2
Playground PARK1 27.51 31.87
Cafe CAFE5 67.71 109.09
Scuba SCUB8 68.58 109.54
Scuba SCUB9 67.14 109.99
Cafe CAFE2 13.83 46.24
SUSHI SUSH1 79.59 41.22
SUSHI SUSHI2 73.81 54.14
SUSHI SUSHI3 72.87 55.47
SUSHI SUSHI4 75.05 56.51
RESTROOM RESTR1 74.1 56.05
RESTROOM RESTR2 74.96 57.9
RESTROOM RESTR3 75.06 55.59
RESTAURANT RESTAU1 76.57 56.33
RESTAURANT RESTAU1 76.95 55.1
RESTAURANT RESTAU2 77.75 54.69
RESTAURANT RESTAU2 76.15 54.34
code tried for a different dataset where x,y weren't coordinates;
set view map
set contour
set isosample 250, 250
set cntrparam level incremental 1, 0.1
set palette rgbformulae 33,13,10
splot 'data.dat' with lines nosurface
#splot for [col=1:10] ‘data.dat’ u ($1):(column(col) > 2 ? 1/0 : column(col)):3
errors:
1) All points x value undefined
2) Tabular output of this 3D plot style not implemented
updated:
a) increased data points
c) a possible chicken scratch to give simple impression.
Expecting a distribution density map like this.
This is an interesting plotting challenge.
The input data format is also straightforward, but needs some processing until the desired contour lines can be plotted with gnuplot.
Comments:
The data is all in one file. Data entries for the types can be random, no order necessary.
the example below will create some random test data with "Cafe, Scuba, Sushi" and 50 entries of each. Skip this part if you want to use your own file.
the further lines of the script, have no idea about the content of the test data file (i.e. how many types, type names, coordinates, etc.), all will be determined automatically.
create a unique list of types. The list will be in the order of first occurrence.
define a grid (here dx=0.2, dy=0.2, i.e. reasonable values within the data range) and count for each grid point the occurrences for each type within a certain radius (here: 0.5). Calculate the density by dividing the count by the unit area (area of the circle).
for each type create the contour lines via plotting to a file indexed by a two digit number. So far, I don't know how one would easily write this into indexed datablocks to avoid files on disk.
finally, plot the contour line files and the original data points by using a filter to get the right color.
One thing which I haven't figured out yet is set cntrparam level 2: I would like to have exactly 2 contour lines per type, but it seems gnuplot still uses the option set cntrparam level auto 2 and adjusts the number of levels itself.
As you can imagine this graph will probably look pretty confusing with 10 or more types.
For sure, there is room for improvement and no guarantee that there are no bugs in this script. Look at it as a starting point for further optimization. Suggestions for improvements are welcome!
Script:
### plot density contours from simple x,y location file
reset session
FILE = "SO73244095.dat"
# create some random test data
myTypes = "Cafe Scuba Sushi"
set print FILE
do for [p=1:words(myTypes)] {
a = word(myTypes,p)
x0 = rand(0)*5
y0 = rand(0)*5
do for [i=1:20] {
print sprintf("%s %s%d %.3g %.3g",a,a,i,invnorm(rand(0))+x0,invnorm(rand(0))+y0)
}
}
set print
# create a unique list of types
# and extract min, max data
addToList(list,col) = list.(_s='"'.strcol(col).'"', strstrt(list,_s)>0 ? '' : _s)
myTypes = ''
myType(i) = word(myTypes,i)
stats FILE u (myTypes=addToList(myTypes,1),$3):4 name "DATA" nooutput
Nt = words(myTypes)
print sprintf("%d types found: %s",Nt,myTypes)
# get densities for each type
dx = 0.2 # adjust the grid as you like...
dy = 0.2 # ... time for graph creation will increase with finer grid
Radius = 0.5 # adjust radius to a reasonable value
Nx = ceil((DATA_max_x-DATA_min_x)/dx)
Ny = ceil((DATA_max_y-DATA_min_y)/dy)
Dist(x0,y0,x1,y1) = sqrt((x1-x0)**2 + (y1-y0)**2)
print "Please wait..."
set print $Densities
do for [nt=1:Nt] {
do for [ny=0:Ny] {
do for [nx=0:Nx] {
c = 0
x = DATA_min_x+nx*dx
y = DATA_min_y+ny*dy
stats FILE u (Dist(x,y,$3,$4)<=Radius && (strcol(1) eq word(myTypes,nt)) ? c=c+1 : 0) nooutput
d = c / (pi * Radius**2) # density per unit area
print sprintf("%g %g %g",x,y,d)
}
print "" # empty line
}
print ""; print "" # two empty lines
}
set print
# get contour lines via splot into files
myContFile(n) = sprintf("%s.cont%02d",FILE,n)
unset surface
set contour
set cntrparam cubicspline levels 2 # cubicspline for "nice" round curves
do for [nt=1:Nt] {
set table myContFile(nt)
splot $Densities u 1:2:3 index nt-1
unset table
}
# set size ratio -1 # uncomment if equal x,y scale is important
set grid x,y
set key out noautotitle
set xrange[:] noextend
set yrange[:] noextend
set colorsequence classic
myFilter(colD,colF,valF) = strcol(colF) eq valF ? column(colD) : NaN
plot for [i=1:Nt] myContFile(i) u 1:2 w l lc i, \
for [i=1:Nt] FILE u 3:(myFilter(4,1,myType(i))) w p pt 7 lc i ti myType(i)
### end of script
Result: (a few random examples)
I am trying to plot a file of data along with 2 circles with gnuplot. The data file is here and the circle file is here. The circles are quite big compared to the dataset, and when I plot it on a large scale everything works fine. But when I try to zoom in, the circles disappear. Here are the gnuplot commands I use (v5.4.2):
plot 'data.txt' us (log($2)):(log($3)) w lp, 'circ.txt' us 1:2:3 w circles
Here is the result (looks ok):
Now if I try to zoom in a little (still ok):
set xrange [*:55]
replot
Trying to zoom in more (circles disappear!)
set xrange [*:8]
replot
Is this a bug in gnuplot, or is there a way to fix this and visualize the circles on a zoomed in view?
As #Ethan already explained, with the plotting style with circles if the center of a circle is not in the graph range anymore, the circle will not be plotted.
You can workaround this if you plot the circles yourself. Then you can zoom in as long as a datapoint of the circumference is still in the graph. For large zoom-in you could increase the number of samples, e.g. set samples 500.
However, in order to have the circle visually appear as a circle (not as an ellipse) you have to set size ratio -1 which will change the graph size.
Code:
### plot circles which "allow" zoom-in
reset session
set size ratio -1
$Circles <<EOD
50 0 50
100 0 100
220 0 220
EOD
CircX(x0,y0,r,t) = x0+r*cos(2*pi*t)
CircY(x0,y0,r,t) = y0+r*sin(2*pi*t)
x0(n) = word($Circles[n],1)
y0(n) = word($Circles[n],2)
r(n) = word($Circles[n],3)
set key noautotitle
set samples 100
set yrange[-100:100]
plot for [i=1:|$Circles|] [0:1] '+' u \
(CircX(x0(i),y0(i),r(i),$1)):(CircY(x0(i),y0(i),r(i),$1)) w l
### end of code
Result: (original plot)
(zoomed-in):
Gnuplot does not draw points that are out of range. You can think of a circle as a point defined by its center and radius. As soon as the center goes out of range, in this case xmin < xmax < center, the circle is no longer drawn.
Another solution using 'set object circle'
There is a way to display all circles defined in 'circ.txt' as objects using set object circle.
set table $DATA
plot "circ.txt" using 1:2:3 with table
unset table
do for [k=1:|$DATA|] {
line = $DATA[k]
xpos = word(line, 1)
ypos = word(line, 2)
r = word(line, 3)
set object circle at xpos, ypos radius r fill empty border lc black
}
set xrange [*:30]
set yrange [*:16]
plot "data.txt" using (log($2)):(log($3)) with lp
I try to plot contour with only one cntrlabel per line but I do not succeed. I tried
set cntrlabel onecolor start 50 interval 10000000
and
set cntrlabel onecolor start 50 interval -1
but it does not work. Is there a mean to force 1 label per line ?
Moreover, I would like to shift the cntrlabel in order to prevent them to be overlayed (as observed on the top-left of the graph with the label 45, 50, 55, and 60). How should I do ?
The code used to obtain this graph is the following:
FILE = "data_sensibilite_correlation_phiFR_Tpfr_fusion_ordre"
set contour base
set cntrparam level discrete 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 25, 30, 35, 40, 45, 50, 55, 60
#set cntrparam level incremental 2, 4, 60
set cntrlabel onecolor start 50 interval 10000000
set xrange [-10:10]
set yrange [0.55:0.95]
#set cbrange [0:20]
set style textbox opaque
unset key
set view map
set xlabel "{/Symbol e}_{/Symbol q} [%]"
set ylabel "T_b / T_{c} uncertainties on T_c"
set cblabel "{/Symbol e}_{{/Symbol F} cs} [%]"
set pm3d noborder
splot FILE u 1:2:3 w pm3d, \
FILE u 1:2:3 w l lc "black" nosurface, \
FILE with labels boxed
The data is available here: https://filesender.renater.fr/?s=download&token=c718b69b-1496-47db-9da4-21d48cf08aa4
Some time ago, I experienced the same issue.
Since your data is not accessible anymore, I am creating some test data in the script itself.
The problem is that you see too many labels although you are trying to limit them via
set cntrlabel {start <int>} {interval <int>}.
Let me try to explain: If you plot the contour line into a datablock you will notice that although some contour lines in the graph look like continuous lines, however, in fact, they are interrupted by empty lines in the data.
I guess this comes from the algorithm how gnuplot determines the contour lines. It seems, the more data points you have, the higher the probability that some contour lines are interrupted.
In the first graph below I made the interruptions visible by setting variable line color depending on pseudocolumn -1 (check help pseudocolumns). For the time being ignore the yellow line.
For example, the contour line for the level 8 consists of 5 pieces (i.e. 5 different colors).
This means when plotting the contour labels even if you set every 200 (or interval 10000000) you will get at least as many labels per contour line as many "broken" parts you have for that line.
Test Graph:
So, you could try to merge these interrupted lines which might be feasible, however, is not so easy because:
you have contour lines which should not be merged, e.g. level 15 on the left side and on the right side of the graph
you cannot easily connect the interrupted lines by simply removing the empty lines because the data points of the line parts are not in the right order
A different approach:
Hence, here is another "simple" idea, but not so simple to realize:
Define a parametric curve (yellow line in the above graph) which will intersect all the contour lines which you want to have labeled.
The script will determine the intersection points and will place a label at these positions.
The determination of the intersections is somewhat lengthy and the code is taken from here.
This procedure is certainly slow and not very efficient because it checks each yellow segment against all other segments.
Currently, the sampling of the yellow line needs to be high enough (here: N=21) such that each yellow segment will intersect with one contour line segment. The calculation time for the intersections can probably be shortened considerably if one yellow segment can intersect several contour line segments. Alternatively, the intersection lines could be filtered by level and then intersected. I will try these options asap.
If anyone has a more ideas to improve, please let me know.
Script:
### add contour labels nicely aligned
reset session
# create some test data
f(x,y) = ((4*x)**2 + (-y-5)**2)/10.
set samples 200
set isosamples 200
set table $Data
splot '++' u (x):(y):(f(x,y))
set table $Contours
unset surface
set contour
set cntrparam levels discrete 2,4,6,8,10,15,20,25,30,40
splot $Data u 1:2:3
unset table
set colorsequence classic
set style textbox opaque
set key noautotitle
set view map
# define parametric function for "line of labels"
xmin = -5.5
xmax = 5.5
N = 21
g(x) = 0.25*x**2 - 2
gx(t) = xmin + t*(xmax-xmin)/N
gy(t) = g(gx(t))
set table $LabelLine
plot '+' u (gx($0)):(gy($0)) every ::::N w table
unset table
set xrange [:] noextend
set yrange [:] noextend
# this plotting part can be skipped, it's just for illustration purpose
plot $Contours u 1:2:-1 w l lc var, \
'' u 1:2:3 every 200 w labels boxed, \
$LabelLine u 1:2 w lp pt 7 lc "yellow" noautoscale
pause -1
# some necessary functions
# orientation of 3 points a,b,c: -1=clockwise, 0=linear, +1=counterclockwise
Orientation(a,b,c) = sgn((word(b,1)-word(a,1))*(word(c,2)-word(a,2)) - \
(word(c,1)-word(a,1))*(word(b,2)-word(a,2)))
# check for intersection of segment a-b with segment c-d,
# 0=no intersection, 1=intersection
IntersectionCheck(a,b,c,d) = \
(Orientation(a,c,b)==Orientation(a,d,b)) || (Orientation(c,a,d)==Orientation(c,b,d)) ? 0 : 1
# calculate coordinates of intersection point, "" if identical points
M(a,b) = real(word(a,1)*word(b,2) - word(a,2)*word(b,1))
N(a,b,c,d) = (word(a,1)-word(b,1))*(word(c,2)-word(d,2)) - \
(word(a,2)-word(b,2))*(word(c,1)-word(d,1))
Intersection(a,b,c,d) = N(a,b,c,d) !=0 ? sprintf("%g %g", \
(M(a,b)*(word(c,1)-word(d,1)) - (word(a,1)-word(b,1))*M(c,d))/N(a,b,c,d), \
(M(a,b)*(word(c,2)-word(d,2)) - (word(a,2)-word(b,2))*M(c,d))/N(a,b,c,d)) : ""
# looping data segments for finding intersections
set print $Intersections
do for [i=1:|$LabelLine|-1] {
a = sprintf("%s %s", word($LabelLine[i], 1),word($LabelLine[i], 2))
b = sprintf("%s %s", word($LabelLine[i+1],1),word($LabelLine[i+1],2))
Line = ''
Intersection0 = ''
do for [j=1:|$Contours|-1] {
c = $Contours[j]
d = $Contours[j+1]
if (strlen(c)!=0 && strlen(d)!=0 && c[1:1] ne '#' && c[1:1] ne '#') {
if (IntersectionCheck(a,b,c,d)) {
Intersection1 = Intersection(a,b,c,d)
if ((Intersection0 ne Intersection1)) {
Level = word($Contours[j],3)
print sprintf("%s %s %s",Intersection0, Intersection1, Level)
}
Intersection0 = Intersection1
}
}
else {Intersection0 = ''}
}
}
set print
set palette rgb 33,13,10
plot $Data u 1:2:3 w image, \
$Contours u 1:2 w l lc "black", \
$Intersections u 1:2:3 w labels boxed
### end of script
Result:
Here is a much simpler solution resulting in only one label per level, however, depending on your data you won't know where exactly the labels will be positioned.
The contour lines per level are separated by two empty lines. The different pieces within a contour line of one specific level might be separated into (sub-)blocks separated by a single empty line.
Now, you can address specific rows and sub-blocks via every (check help every). For example, if you only want to plot each second row of each first sub-block you can specify every ::1:0:1:0 (indices are zero-based). You need to play with these numbers, depending on your data and how many contour line breaks you have. However, most likely the labels will not be nicely aligned as in my other (much more complicated) answer. Furthermore, the labeling will be only once per level, i.e. no labels on the left side of the plot in the example below.
Script:
### add contour labels, only one per level
reset session
# create some test data
f(x,y) = ((4*x)**2 + (-y-5)**2)/10.
set samples 200
set isosamples 200
set table $Data
splot '++' u (x):(y):(f(x,y))
set table $Contours
unset surface
set contour
set cntrparam levels discrete 2,4,6,8,10,15,20,25,30,40
splot $Data u 1:2:3
unset table
set colorsequence classic
set style textbox opaque
set key noautotitle
set view map
set xrange [:] noextend
set yrange [:] noextend
set tics out
set palette rgb 33,13,10
plot $Data u 1:2:3 w image, \
$Contours u 1:2 w l lc "black", \
$Contours u 1:2:3 every ::1:1:1:1 w labels boxed
### end of script
Result:
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:
I want to create a streamline like arrow lines in Gnuplot,I already have the data points that I needed, so I think my problem is not the same as this post says and different from this post because I have already obtain the data needed for stramlines.
What I have done is like this:
So the red lines are vectors show flow field and green line is streamlines to guide the readers the direction of the flux. And all the large blue arrows are my aim to be plotted in GNUPLOT. I have kown how to plot middle arrows as this post has shown but what code I need to do if I want to plot more arrows along the lines?
To be more detailed, How can I plot like this:
I supply my data file here :
velocity.txt is for vector flow field data as "index,X,Y,vx,vy,particle-numbers"
line.txt is for streamline data as "X,Y"
and My gnu file is bleow:
set terminal postscript eps size 108,16 enhanced font "Arial-Bold,100"
set output 'vector.eps'
unset key
set tics
set colorbox
set border 0
set xtics 2
#set xlabel 'x'
#set ylabel 'y'
set xrange [0:108]
set yrange [0:16]
#set cbrange [0:40]
set nolabel
set style line 4 lt 2 lc rgb "green" lw 2
plot 'velcoity.txt' u 2:3:(250*$4):(250*$5) with vectors lc 1,'line.txt' u 1:2 ls 4
Thank you!
To plot arrows along a line you can again use the vectors plotting style like you do already for the stream field.
But to get a proper plot you must consider several points:
Usually gnuplot limits the size of the arrow heads to a fraction of the arrow length. So, if you want to plot a continuous line with arrows heads, the arrows themselves should have a very short length. To avoid downscaling of the arrow heads, use the size ... fixed option, which is available only since version 5.0
You have only the trajectory, x and y values, of the line. To extract the arrow direction, the simplest approach would be to use the difference between two neighbouring points (or at a distance of two or three points).
You can extract these differences in the using statement. As pseudo code, one could do the following:
if rownumber modulo 10 == 0:
save x and y values
else if rownumber modulo 10 == 1:
draw arrow from previous point to current point, only with a head
else
ignore the point.
Putting this pseudo-code in the using statement gives the following:
ev = 10
avg = 1
sc = 0.1
plot 'line.txt' u (prev_x = (int($0)%ev == 0 ? $1 : prev_x), prev_y = (int($0)%ev == 0 ? $2 : prev_y), int($0)%ev == avg ? $1 : 1/0):2:(sc*(prev_x-$1)):(sc*(prev_y-$2)) w vectors backhead size 2,20,90 fixed ls 4
To make things more flexible, I introduced some variables: ev tells you the difference count between two arrows heads, avg the distance between two points used to calculate the arrow direction, and sc the length of the arrow shaft.
As further improvement you can use the length of the stream field arrows to colour the stream field vectors. This gives the following script
reset
unset key
set tics
set colorbox
set border 0
set xtics 2
set autoscale xfix
set autoscale yfix
set autoscale cbfix
set style line 4 lt 2 lc rgb "green" lw 2
ev=30
avg=3
sc=0.1
field_scale=500
plot 'velcoity.txt' u 2:3:(field_scale*$4):(field_scale*$5):(sqrt($4**2+$5**2)) with vectors size 1,15,45 noborder lc palette,\
'line.txt' u 1:2 ls 4 w l,\
'' u (prev_x = (int($0)%ev == 0 ? $1 : prev_x), prev_y = (int($0)%ev == 0 ? $2 : prev_y), int($0)%ev == avg ? $1 : 1/0):2:(sc*(prev_x-$1)):(sc*(prev_y-$2)) w vectors backhead size 2,20,90 fixed ls 4
With the result (qt terminal):