I try to compare two data files that show the raise in memory consumption vs. time. The data stems from two tests that I executed on different times, I'm trying to make the difference (or equivalence) obvious by shifting the second plot in the x and y axes.
Here is my test.plt script (the plot line is wrapped for this question):
reset
set title "Memory consumtion of process"
set style data fsteps
set xlabel 'Zeit (HH:MM:\nSS.ddd)'
set timefmt '"%H:%M:%S"'
set xdata time
set xrange ['"10:00:00"' : '"13:00:00"']
set yrange [12000 : 20000]
set ylabel "Memory\nin KBytes"
set format x "%H:%M:\n%.3S"
set grid
set key left
plot 'mem-2015-11-26-1229.dat' using 1:2 with lines,
'mem-2015-11-26.dat' using 1:($2-1500) with lines
There is no problem with y since this is a normal scalar value. But I'm having difficulties to do the same with the x axis, this is how I tried to shift x (all with no success):
plot 'mem-2015-11-26-1229.dat' using 1:2 with lines,
'mem-2015-11-26.dat' using ($1-3600.0):($2-1500) with lines
Not even using the alias ($1) seems to work on time axis:
plot 'mem-2015-11-26-1229.dat' using 1:2 with lines,
'mem-2015-11-26.dat' using ($1):($2-1500) with lines
Both give the following warning (and no output for the second file):
"test.plt", line 15: warning: Skipping data file with no valid points
What am I doing wrong? Is it even possible to calculate time values at all? If yes, how?
Related
I've got a problem with read-in time values in gnuplot. I have a data file
#data.dat
00:50.254
00:50.435
00:51.356
00:53.245
00:54.730
...
with format '%M:%S'. So I'm reading it in with my gnuplot file:
set xdata time
set timefmt "%M:%S"
set xtics format "%M:%S"
set grid
set xrange [ 0:"01:30" ]
set yrange [0:10]
set xtics "00:00",10,"01:30"
set mxtics 2
set ytics 0,2,10
set mytics 2
p 'data.dat' u 1:1
Here I want to plot the data really 1:1 as a test. The result is: I will get just the value of '%M' as y-value. This can be corrected by using set ydata time. But I want to do some calculation with the time data and need the seconds (or seconds including minutes, sth. like %M*60+%S: 01:30->90). I want to pass it to a function, or in my special case: summing it up with smooth freq after some calculation in a function:
bin(x) = floor(x+0.5)
p 'data.dat' u (bin($1)):(1.0) smooth freq w boxes
How can I access the %S part of the time?
How can I convert a read-in time to a double/float?
Thank you for your help in advance!
edit: I got an idea right after posting: is the read-in data an array and I can read out this array? I'll try it out.
edit2: internal error : non-STRING argument... This did not work
In my special case, I could maybe use : as delimiter and just read out the mins and secs as two colums... I'll give it a try too. But this wont help, if there are more columns with other data that needs to be plotted...
edit3: Even setting the delimiter (separator) doesn't solve the problem yet, but an error message occurs:
Bad format character at my plot line.
Here my new gnuplot command file:
set datafile separator ':'
set timefmt "%M:%S"
set xtics format "%M:%S"
set grid
#set xrange [ 0:"01:30" ]
set xrange [0:90]
set yrange [0:92]
#set xtics "00:00",10,"01:30"
set xtics 0,10,90
set mxtics 2
set ytics 0,2,10
set mytics 2
p 'data.dat' #u 1:2 #($1*60+$2):($2)
Internally, gnuplot stores the time as the number of seconds since some epoch (the epoch is different between versions, but is the Unix epoch in the 5.0 line).
Normally, using the time format settings, gnuplot handles conversions itself. However, there are functions that can be used for processing the times manually as well, for example
strptime("%M:%S","50.254")
will process the time of your first line into a number of seconds. We can even use this in plotting commands, as long as we are careful to read columns as strings
plot "data.dat" u 0:(strptime("%M:%S",strcol(1)))
will plot your data file as seconds elapsed versus the line number. As you are not specifying date info in your time format, gnuplot defaults to the beginning of it's first day in the epoch, so we just get 50 some seconds (otherwise the numbers could be much larger).
In general, you can handle any time format like this. It may be a little difficult if you have spaces or such in your time format, as you won't be able to rely on gnuplot's ability to know how much to "chunk" into the column without setting a time format (but this can be handled by using a different separator or quoting times).
See help strptime for the function which converts the time format to the internal representation and help strftime for the function which converts one of these internal representations back to a date string.
I have file with many columns that I'd like to plot as follows:
plot for [i=1:30] 'test' using 1:i w lp
This gives the plot I want, but when I do set key, then the key I see has all lines labeled as 1:i:
How can I make this output more meaningful, by actually displayin the value of i?
If you don't set an explicit title, gnuplot selects an automatic title based on the plain plot command call. If you want a meaningful title, you must give it explicitly, like
plot for [i=1:30] 'test' using 1:i w lp title sprintf("column %d", i)
I'm getting confused with how to use for-loops in gnuplot.
The following code works fine:
plot for [quadIter=0:270:90] \
path using 1:(column(1 + quadIter))
It plots 4 curves on one graph.
I also want to plot 4 horizontal lines on the same graph. I have written the following script to do this:
plot for [quadIter=0:270:90] \
path using 1:(column(1 + quadIter)) , \
path_to_expt[1 + quadIter/3: 19] \
But it only plots one additional line on the graph, so it is not being included in the for-loop. Please can you tell me how to get the additional line included in the loop?
Also, the constant value that is plotted is not the value I was expecting it would plot. Please can you tell me how to print the value of quadIter to the screen, so that I can check it against the value in the file?
Finally, I tried just to plot the 4 horizontal lines with this script:
plot for [quadIter=0:270:90] \
path_to_expt[1 + quadIter/3: 19] \
But I got an error message, "Non-numeric string found where a numeric expression was expected". I find this strange, as I didn't get this error message when I ran the second script but, as the second script isn't working how I would like, hopefully by getting the second and third scripts to work, I will have a better understanding of how for-loops work in gnuplot.
Thank you for your help!
The for iteration applies only the the current plot expression. The line
plot for [i=1:4] i*x, i*x**2
creates five plots, whereas in order to get eight plots you must do
plot for [i=1:4] i*x, for [i=1:4] i*x**2
Concerning your last expression path_to_expt[1 + quadIter/3: 19]: array expressions aren't supported by gnuplot (however path_to_expt looks like one).
My question is pretty basic. I am plotting several functions at once using gnuplot, and I want to print out (in either a file or on the graph itself) the maximum y-values of every function. Any idea how I could do that?
I looked into STATS and GPVAL_DATA_Y_MAX but I can't really figure out how to make them work with several functions at the same time.
Without going into too much details, let's suppose that my file looks like that :
plot 'file1.dat' us 1:2 title "file1" w lines,\
'file2.dat' us 1:2 title "file2" w lines,\
'file3.dat' us 1:2 title "file3" w lines
You can use the name parameter of the stats option to save the maximum of every file in a different set of variables:
stats 'file1.dat' using 2 nooutput name 'file1'
stats 'file2.dat' using 2 nooutput name 'file2'
stats 'file3.dat' using 2 nooutput name 'file3'
Now you can either print the values to an external file
set print 'max.dat'
print file1_max
print file2_max
print file3_max
If you want to place a respective label near the maximum in your graph, you must also know the corresponding x-value where the data has its maximum. This data is not readily available from the first stats command, only its index in the data file. So you need an additional call to stats in order to get the x-value where the maximum y-value was:
stats 'file1.dat' using 1 every ::file1_index_max::file1_index_max name 'file1_x'
...
And then you can use
set label center at first file1_x_max,first file1_max sprintf('y = %.2f', file1_max) offset char 0,1
Unfortunately, most of the commands cannot be iterated properly with changing variable names.
I am plotting the creation times of a large batch of files in gnuplot to see if they are created linearly in time (they are not).
Here is my code:
#!/bin/bash
stat -c %Y img2/*png > timedata
echo "set terminal postscript enhanced colour
set output 'file_creation_time.eps'
plot 'timedata'" | gnuplot
The problem I have is that the y data are the creation time in seconds since unix start time, so the plot just has 1.333...e+09 on the y-axis. I would like to have the creation time of the first file scaled to zero so that the relative creation times are readable.
I encounter this problem in a number of data-plotting contexts, so I would like to be able to do this within gnuplot rather than resorting to awk or some utility to preprocess the data.
I know the first time will be the smallest since the files are named serially, so is there a way to access the first element in a file, something like
`plot 'data' using ($1-$1[firstelement])`
?
I think you can do something like that...(the following is untested, but I think it should work...). Basically, you have to plot the file twice -- the first time through gnuplot picks up statistics about the dataset. The second time through, you use what you found on the first run-through to plot what you actually want.
set terminal unknown
plot 'datafile' using 1:2
set terminal post enh eps color
set output 'myfile.eps'
YMIN=GPVAL_Y_MIN
plot '' u 1:($2-YMIN)
If you have gnuplot 4.6, you can do the same thing with the stats command.
http://www.gnuplot.info/demo/stats.html
EDIT It appears you want the first point to provide the offset (sorry, misread the question)...
If you want the first point to provide the offset, you may be able to do something like (again, untested -- requires gnuplot >= 4.3):
first=0;
offset=0;
func(x)=(offset=(first==0)?x:offset,first=1,x-offset)
plot 'datafile' using (func($1))
Gnuplot accepts unix commands, so you can say something like
gnuplot> plot "< tail -3 test.dat" using 1:2 with lines
in order to plot just the last three lines. You can use something like this for your purpose. Moreover, if you want to plot let's say from line 1000 to 2000
plot "<(sed -n '1000,2000p' filename.txt)" using 1:2 with lines
You can check this website, for more examples.
I found a related stackoverflow question here and exploited the awk script from one of the answers:
#!/bin/bash
stat -c %Y img2/*png > timedata
echo "set terminal postscript enhanced colour
set output 'file_creation_time.eps'
unset key
set xlabel 'file number'
set ylabel 'file creation time (after first)'
plot \"<awk '{if(NR==1) {shift = \$1} print (\$1 - shift)}' timedata\"" | gnuplot
The output looks like this (these are not the data I was talking about in my question, but similar):
So, gnuplot can do what I want but it does depend on the UNIX environment...
I also tried mgilson's method:
plot 'timedata'
YMIN=GPVAL_Y_MIN
plot '' u ($1-YMIN)
but gnuplot (my version is 4.4.2) did not find the minimum correctly. It came close; it looks like it plotted such that the minimum of the y range is 0: