I am making a gnuplot animation of a satellite going around a planet. My task is to display it's XY trajectory and associated values of velocity and energy versus time. I know how to plot the path, but I've been having problems displaying velocity etc.
the code below does the following:
satellite track and time steps -- column 3:4;
satellite position -- column 3:4;
planet position -- column 6:7.
do for [n=0:int(STATS_records)] {
plot "sat.dat" u 3:4 every ::0::n w lp ls 2 t sprintf("steps=%i", n), \
"sat.dat" u 3:4 every ::n::n w lp ls 4 notitle, \
"sat.dat" u 6:7 every ::0::n w lp ls 3 notitle , \
}
How do I display the associated velocity values for each sprintf ? The velocity values are in column 5. Thank you everyone in advance.
It seems that you want to put everything in the "key" (legend), but another option is to use labels, which can be easily placed arbitrarily. There are labels you can place one at a time (with set label) and with labels for plotting with actual labels. Don't get them confused.
Your main issue seems to be how to pull out the velocity value from column 5. My first instinct (which is quite hacky) is to use some external program, like awk:
v = system(sprintf("awk 'NR==%d{print $5}' '%s'", n+1, infile))
set label 1 sprintf("v=%.3f", v+0) at screen 0.2,0.9
This is also an example of a label (named 1). The screen keyword means screen-relative rather than graph-relative. Putting this inside your for loop will reassign label 1 every iteration, so it overwrites the label from the previous iteration. Not using this 1 will just plop another label on top of the last one, so it would get messy.
Using an external command line like this isn't very portable. (I don't think it would work on Windows.) I saw this question that shows how to pull a value from a specific row and column of a file. The problem I had with using this is that stats implicitly filters according to whatever xrange is set. When making animations like this, I've noticed that the camera can jump around too much from autoranging, so it's nice to have tight control over the plotting range. Defining an xrange at the top of the file interfered with a subsequent stats command to read a velocity value.
You can, however, specify a range for stats (before the file name, such as stats [*:*] infile). But I had issues using this in combination with a predefined xrange based for position. I found that it did work if I specify the desired plotting range on the plot line instead of a set xrange. Here is another (full script) version using only gnuplot:
set terminal pngcairo
infile = 'anim.dat'
stats infile using 3:4 name 'data' nooutput
set key font 'Courier'
do for [n=0:data_records-1] {
set output sprintf('frame-%03d.png', n)
stats [*:*] infile every ::n::n using 5 name 'velocity' nooutput
plot [data_min_x:1.1*data_max_x][data_min_y:1.1*data_max_y] \
infile u 3:4 every ::0::n w linespoints ls 2 t \
sprintf("steps =%6d\nvelocity =%6.3f", n, velocity_min), \
'' u 3:4 every ::n::n w points pt 7 ps 3 notitle
}
Notice that you could easily change this to a set label if you want. Another option is to plot
'' u (x):(y):5 every ::n::n w labels
to place a label at graph position (x,y).
I don't have your data, but I made my own file with what I hope is a similar format to yours:
anim.dat
0 0.0 0.0 0.0 1.11803398875 0.625
1 0.05 0.05 0.02375 1.09658560997 0.625
2 0.1 0.1 0.045 1.07703296143 0.625
3 0.15 0.15 0.06375 1.05948100502 0.625
4 0.2 0.2 0.08 1.04403065089 0.625
5 0.25 0.25 0.09375 1.0307764064 0.625
6 0.3 0.3 0.105 1.01980390272 0.625
7 0.35 0.35 0.11375 1.01118742081 0.625
8 0.4 0.4 0.12 1.00498756211 0.625
9 0.45 0.45 0.12375 1.00124921973 0.625
10 0.5 0.5 0.125 1.0 0.625
11 0.55 0.55 0.12375 1.00124921973 0.625
12 0.6 0.6 0.12 1.00498756211 0.625
13 0.65 0.65 0.11375 1.01118742081 0.625
14 0.7 0.7 0.105 1.01980390272 0.625
15 0.75 0.75 0.09375 1.0307764064 0.625
16 0.8 0.8 0.08 1.04403065089 0.625
17 0.85 0.85 0.06375 1.05948100502 0.625
18 0.9 0.9 0.045 1.07703296143 0.625
19 0.95 0.95 0.02375 1.09658560997 0.625
Related
I am trying to display a function which is a linear function f(x)=a*x+b with different coefficients in each range. My file (output.txt) looks like this but without the header:
a b range
-0.0645991 0.439102 0 0.25
-0.230142 0.480488 0.25 0.5
-0.438559 0.584697 0.5 0.75
-0.66962 0.757993 0.75 1
-0.898603 0.986975 1 1.25
-1.09846 1.2368 1.25 1.5
-1.24232 1.45259 1.5 1.75
-1.30601 1.56404 1.75 2
I have tried these lines but none of them worked:
plot "output.txt" using 1:2 with lines, set xrange using 3:4
plot "output.txt" [($3):($4)] ($1)*x+($2)
plot "output.txt" $3<=x<=$4 ? ($1)*x+($2) : 0
It's my first time using Gnuplot and I couldn't find any example of pulling range from a file.
Welcome to StackOverflow! You can simply use the plotting style with vectors.
Check help vectors.
The plotting command looks complicated but it is straightforward.
The four values you need are: x, y, delta x, and delta y, i.e.
in your example
x: 3rd column
y: f(x,a,b) where x is 3rd column and a and b are from 1st and 2nd columns, respectively.
dx: 4th column less 3rd column
dy: f(x,a,b) where x is from 4th column less f(x,a,b) where x is from 3rd column and a,b as above.
You can skip the arrow heads if you specify nohead in the plot command. Check help arrow.
Code:
### plotting style with vectors
reset session
$Data <<EOD
a b range
-0.0645991 0.439102 0 0.25
-0.230142 0.480488 0.25 0.5
-0.438559 0.584697 0.5 0.75
-0.66962 0.757993 0.75 1
-0.898603 0.986975 1 1.25
-1.09846 1.2368 1.25 1.5
-1.24232 1.45259 1.5 1.75
-1.30601 1.56404 1.75 2
EOD
f(x,a,b) = a*x + b
plot $Data u 3:(f($3,$1,$2)):($4-$3):(f($4,$1,$2)-f($3,$1,$2)) w vectors lc "red" head title "my function"
### end of code
Result:
I am trying to set line colors in gnuplot. I have a file with several datablocks in the usual format, separated by two empty lines. Is there a way I can set the color of each line in the plot to different colors. My graph looks like this right now
and my file like:
1 0.1 0.5
1 0.2 0.6
1 0.3 0.7
1 0.4 0.8
2 0.1 0.7
2 0.2 0.8
2 0.3 0.9
2 0.4 0.95
3 0.1 0.6
3 0.2 0.7
3 0.3 0.8
3 0.4 0.9
You can plot the lines block by block like this:
filename = "filename.dat" # need the same file several times
stats filename # get number of blocks
show variables # check STATS_blocks
plot for [b=0:STATS_blocks-1] filename u 2:3 index b title ''.(b+1) w lp ps 1
See help stats which counts the blocks in your file, help for which loops over all available blocks, and help index which selects one specific block.
When I separate the data blocks in your example file by two lines as you have written, I get this result:
If you want some control over the color, you might want to read help linecolor variable.
I have a set of data points I plot with gnuplot. Know I calculate a value for x and want to find the corresponding y value within the data.
Does anybody know how to manage this with gnuplot?
I found kind of a solution here on StackOverflow
Basically you have to invert the function you use to calculate y (or x in the case of the link) and then, thanks to the sprintf function, you gate the corresponding value.
NOTE
Have a look also here if you did not find the solution at the first link!
Although this is a rather old question, the following solution for interpolation might still be of interest to others.
The code can be simplified depending on whether you are just interested in nearest datapoint or in the interpolated value or whether you want to plot the value as point and/or label.
Code:
### interpolate between datapoints
reset session
$Data <<EOD
0 0
0.30 0.20
0.60 0.40
0.80 0.80
1 1
EOD
$Data2 <<EOD
1 0
0.80 0.15
0.50 0.30
0.50 0.50
0.30 0.80
0 1
EOD
InterpolY(x,x0,x1,y0,y1) = (x-x0)*(x-x1)<0 || x1-x0==0 ? x1-x0==0 ? (y0+y1)/2 : (y1-y0)/(x1-x0)*(x-x0) +y0 : NaN
set key noautotitle
array Point[1] # dummy array for plotting a single datapoint
# x-value for interpolation is defined in xp
plot x1=y1=yp=(xp=0.7,NaN) $Data u (x0=x1,x1=$1):(y0=y1,y1=$2, yp==yp ? NaN : yp=InterpolY(xp,x0,x1,y0,y1),y1) w lp pt 7, \
Point u (xp):(yp) w p pt 7 lc "red", \
Point u (xp):(yp):(sprintf("(%.2g|%.2g)",xp,yp)) w labels right offset -1,0 lc "red", \
x1=y1=yp=(xp=0.5,NaN) $Data2 u (x0=x1,x1=$1):(y0=y1,y1=$2, yp==yp ? NaN : yp=InterpolY(xp,x0,x1,y0,y1),y1) w lp pt 7, \
Point u (xp):(yp) w p pt 7 lc "green", \
Point u (xp):(yp):(sprintf("(%.2g|%.2g)",xp,yp)) w labels right offset -1,0 lc "green", \
### end of code
Result: (interpolated values at x=0.7 and x=0.5)
I have a data file with schema as "object parameter output1 output2 ...... outputk". For eg.
A 0.1 0.2 0.43 0.81 0.60
A 0.2 0.1 0.42 0.83 0.62
A 0.3 0.5 0.48 0.84 0.65
B 0.1 0.1 0.42 0.83 0.62
B 0.2 0.1 0.82 0.93 0.61
B 0.3 0.5 0.48 0.34 0.15
...
I want to create multiple plots, each plot corresponding to an object, with x axis being the parameter and series being the outputs. Currently, I've written a python script which dumps the rows for each object in different files and then calls gnuplot. Is there a more elegant way to plot it?
You are looking for this:
plot 'data.txt' using (strcol(1) eq "A" ? $2 : 1/0):4 with line
which results to:
If you would like to create plots for every object use:
do for [object in "A B"] {
reset
set title sprintf("Object %s",object)
plot 'data.txt' using (strcol(1) eq object ? $2 : 1/0):4 notitle with line
pause -1
}
Just press Enter for next plot.
Of course you can export these plots in files, too.
I have a data set that uses the x-scale:
0.1 0.4 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
But I need the tics to line up evenly, not have 0.1 and 0.4 scrunched up into the corner. I currently use,
set xtics 1
set xtics add (0.1)(0.4)
But that spaces 0.1 and 0.4 respective to the rest of the scale. I've attached a link to a tinypic I uploaded of my dummy data set with my current problem.
http://tinypic.com/r/2zfolxf/7
Current State
As far as I know, you can do the following in gnuplot with tics (at least what is relevant to your question):
You can specify the start, increment and end of the tics displayed.
This would make sense to you, if you wish to simply set the tics after the value of 2 like
set xtics 2, 1
The other thing you can do, is add explicit tic labels to certain values like
set xtics add ("0.1" 0, "0.4" 1)
This would introduce the labels 0.1, and 0.4 to the x scale where the actual values are 0 and 1
However you cannot modify the actual plotting of the graph. If in you data it states
0.1 100
0.4 150
1 200
2 300
then gunplot will plot it correspondingly.
Possible workaround
A workaround could look like this:
Plot the normal graph from 2 upwards.
Do some hackery stuff to the first two values with this:
plot "Data.dat" every 1::2 w l, "" every 1::1::2 using ($1<magic>):($2)
magic specifies some algebraic operation you want to do with the first column.
Everything is allowed and if your values are constant you can specify a polynomial that goes through the points 0, 1 and 2 with the inputs 0.1, 0.4 and 1 like this polynomial:
y = -1.85*x^2 + 4.26*x - 1.4
Example
Suppose you have this data file:
0.1 0.41
0.4 0.03
1 0.97
2 0.74
3 0.05
4 0.15
5 0.11
6 0.60
7 0.76
8 0.25
Then you can "rearrange" the first two entries to the x-positions -1 and 0 like this:
plot "Data.dat" every 1::2 w l, \
"" every 1::0::2 using (-1.85*$1**2 + 4.26*$1 - 1.4):($2) w l
With some tic-labeling and line style settings it should look exactly like what you are after.
I hope I understood what you are after and that you can make some use of my suggestions.
Cherio
Woltan