System time and Gnuplot - gnuplot

I am constructing a normal X/Y data plot using column data from a .txt data file. The graph plots well (see general code below).
I am wondering if it is possible to extract and use a System time in conjunction with the logged data in the .txt file?
This is in order to produce an X/Y plot with Y being the data from column [x] from the .txt file and the x-axis being an extracted system time point ??
The system time is not part of the log file.
The data string contained within the text file looks like this and is ; delimited: 221.5;65.9;-22.9;0;22.1
Code to generate the plot:
set multiplot layout 5,1
set title "Plot 1"
unset key
plot "data.txt" using 1 with linespoints ls 1
set title "Plot 2"
unset key
plot "data.txt" using 2 with linespoints ls 2
......
unset multiplot
In other words, for each data .txt file column point I would like to attach a system time giving as "Plot 1" {sys.time[x],221.5} and for "Plot 2" {sys.time[x],65.9}.
The next row of file data points delimited by ; will have another system time attached to each of them.
Thanks

I am still a bit guessing, but your image made it a bit more clear.
Maybe we can use this for further tweaking.
Some random data: data.txt
0.713;0.725;0.579;0.485;0.271
0.861;0.882;0.128;0.772;0.475
0.524;0.076;0.420;0.583;0.068
0.429;0.114;0.907;0.679;0.842
0.684;0.077;0.752;0.165;0.062
0.916;0.865;0.368;0.380;0.843
0.291;0.460;0.272;0.279;0.632
0.908;0.832;0.556;0.259;0.744
0.763;0.735;0.624;0.277;0.520
0.735;0.690;0.145;0.148;0.734
0.041;0.398;0.353;0.764;0.065
0.765;0.049;0.603;0.215;0.636
0.613;0.271;0.770;0.030;0.449
0.512;0.583;0.956;0.994;0.832
0.222;0.061;0.471;0.085;0.880
0.259;0.071;0.065;0.391;0.043
0.077;0.356;0.377;0.590;0.562
0.706;0.343;0.312;0.993;0.659
0.826;0.103;0.908;0.135;0.048
0.393;0.012;0.192;0.017;0.233
The code:
### adding time data afterwards
reset session
FILE = "data.txt"
set datafile separator ";"
set xdata time
set timefmt "%d.%m.%Y %H:%M"
set format x "%d.%m."
TimeIntervalInSeconds = 3600*24
StartTime = "01.01.2019 12:00"
set ytics 0.5
set multiplot layout 5,1
do for [i=1:5] {
set title sprintf("Plot %d",i)
plot FILE using (StartTime+$0*TimeIntervalInSeconds):i w lp lt i notitle
}
unset multiplot
### end of code
Result:

Related

Is it possible to adjust the height of the boxes plot of gnuplot?

Following is the data.csv
#x,data
0,20
1,30
2,40
3,50
The following code uses gnuplot to plot the boxes plot and saves to png
import subprocess
proc = subprocess.Popen(['gnuplot','-p'],
shell=True,
stdin=subprocess.PIPE,
encoding='utf8'
)
proc.communicate(
f"""
set terminal png size 400,300; set output 'plot.png';
set boxwidth 1
set style fill solid 1.0
set xrange [-1:40]
set datafile separator comma
plot 'data.csv' using 1:2 with boxes notitle
"""
)
The output png image:
Is it possible to modify the height of each box and set it to 10?
Expected output:
Using this script adapted from Object placement using a data file, by the great Hagen Wierstorf.
reset
# The range has to be set manually
set xrange [-1:5]
set yrange [10:70]
set datafile separator comma
set style rectangle dashtype solid fc rgb "#0077ff" fillstyle solid noborder
# Rectangle dimensions
height = 10
width = 1
# --- Read placement from data file
# Set the output of the following plot to a table in order to achieve that it is
# not shown in the current terminal
set table '/dev/null'
# Function to create the right call function
add_rectangle(x,y,hgt,wdt) = sprintf(\
' set object rect from "%f", "%f" to "%f", "%f"; ',x,y,x+wdt,y+hgt)
# Initialize command string
CMD = ''
# Do a dummy plot to read the position data
plot 'data.csv' u 1:(CMD = CMD.add_rectangle($1,$2,height,width))
# Execute the drawing command
eval(CMD)
# Restore the terminal
unset table
# dummy empty plot to create the plot instance
plot x with line linecolor rgb"#ffffff" notitle
You can get this plot
As far has I know you can't circumvent setting the plot ranges manually, but since you are using a python script to invoke the plot maybe you can pass the min and max of the columns to the script and automate the setup.
By the way, there is the plotting style with boxxyerror, check help boxxyerror.
However, from your question and your sketch and your given data it is not fully clear whether you want
3 boxes; from one datapoint to the next (i.e. height = difference between two consecutive datapoints)
4 boxes; starting from the data value with fixed height 10.
Code: (second option)
### plot boxes with defined height
reset session
$Data <<EOD
#x,data
0,20
1,30
2,40
3,50
EOD
set xrange [-1:40]
set datafile separator comma
set style fill solid 1.0
plot $Data u 1:2:($1-0.5):($1+0.5):2:($2+10) w boxxyerror notitle
### end of code
Result:

GnuPlot: stacked histogram causes hovering bars

since two days I am trying to solve this problem. The bars of this stacked histogram are not printed above each other. They are floating freely around.
Secondly, I only want to print any 5th xtic-label. I am using GnuPlot v 4.6 patchlevel 6.hovering bars in stacked bargraph
Here are the first data rows (generated with libreoffice):
05.06,-,-,1
06.06,3,-,0
07.06,12,-,3
08.06,0,5,4
09.06,7,2,0
10.06,86,2,1
11.06,31,4,1
12.06,17,1,0
01.07,1,7,1
Here comes the command set:
gnuplot> set datafile separator ','
gnuplot> set style data histogram
gnuplot> set style histogram rowstacked
gnuplot> set style fill solid border -1
gnuplot> set xlabel "Zeit"
gnuplot> set ylabel "Anzahl"
gnuplot> set yrange [0:250]
gnuplot> plot 'test.csv' using 2:xtic(1) title "Menge A",''
gnuplot> using 3:xtic(1) title "Menge B",''
gnuplot> using 4:xtic(1) title "Menge C"
Gnuplot seems to get confused with - as only column content. Also a set datafile missing '-' doesn't help. You need a datafile with really empty fields, like
05.06,,,1
06.06,3,,0
07.06,12,,3
If you cannot get LibreOffice to save the data file properly you can use e.g. sed to process the file on-the-fly:
plot "< sed 's/-//g' test.csv" using 2:xtic(1), '' ...
(This works properly if you don't have negative values, which I suppose is the case).
To the second part: Instead of xtic(1) you can also put any expression which evaluates to a string inside of xtic, like
xtic(int($0)%5 == 0 ? strcol(1) : '')
This uses the string in the first column as xticlabel if the row number is a multiple of 5, otherwise an empty string:
set datafile separator ','
set style data histogram
set style histogram rowstacked
set style fill solid border -1
set xlabel "Zeit"
set ylabel "Anzahl"
set yrange [0:*]
plot '< sed "s/-//g" test.csv' using 2:xtic(int($0)%5 == 1 ? strcol(1) : '') title "Menge A",\
'' using 3 title "Menge B",\
'' using 4 title "Menge C"
As Christoph has already explained, the problem is caused by the - in your input data.
Therefore, the best and cleanest solution is to make LibreOffice display missing data differently.
However, everything worked fine for me when I mask the using COLUMNNUMBER part by using $COLUMNNUMBER. Hence, I changed the last line of your code to
plot 'test.csv' u ($2):xtic(1) t "Menge A", '' u ($3) t "Menge B", \
'' u ($4) t "Menge C"
As you see, you can shorten using to u and title to t. Moreover, you should use :xtic(1) only for the first data set.
Here is my outoput

Gnuplot - How do not plot a piece of line for non-contiguous date/time

I'm trying to plot last 24 hours from datafile. This data file has
date/time and value
Below are the contents of datafile.dat:
2015-12-17-21:07:41,74.30
2015-12-17-21:08:41,74.10
2015-12-17-21:08:41,74.10
2015-12-30-21:08:41,79.10
2015-12-30-21:09:41,79.10
....
below gnuplot script
set datafile separator ","
set terminal png font arial 12 size 1000,600
set xdata time
set timefmt "%Y-%m-%d-%H:%M:%S"
set format x "%d/%m\n%H:%Mh"
set xrange [ time(0) - 86400 : time(0) ] # 86400 sec = 1 day
set grid
set output "/data/weather/humidity.png"
plot "datafile.dat" using 1:2 with lines smooth bezier title ""
As I don't have data in the file for day 29, why does gnuplot draw a line from day 29 to day 30?
I don't have rows in the data file for day 29, and I'd like to not draw them.
If I don't have 24 hours of data in the the file, I would like to draw just what I have.
How can I do that?
Gnuplot has an option set clip which controls how lines connecting to points outside the given range are drawn: set clip one, which is the default, draws lines between two points if one of the points is in-range. The line is clipped at the plot border. set clip two would plot line parts even if both points are out-range, but the line goes through the plot area.
Use unset clip to plot only lines between points which are both in-range.
set datafile separator ","
set xdata time
set timefmt "%Y-%m-%d-%H:%M:%S"
set format x "%d/%m\n%H:%Mh"
set xrange [ time(0) - 86400 : time(0) ]
unset clip
plot "datafile.dat" using 1:2 with lines title ""
Unfortunately, that doesn't work properly with smoothing, because gnuplot first does the smoothing between all points (in-range and out-range), and then only applies the clipping rules. In order to have the smoothing handles properly you must filter the points before handling them to gnuplot, e.g. with awk:
set datafile separator ","
set xdata time
set timefmt "%Y-%m-%d-%H:%M:%S"
set format x "%d/%m\n%H:%Mh"
set xrange [time(0) - 86400 : time(0)]
filter = '< awk -F, -v d="$(date -d''24 hours ago'' +''%F-%T'')" ''$1>=d'' datafile.dat'
plot filter using 1:2 with lines smooth bezier title ""
Note, that the comparison $1 >= d in awk is a string comparison, but that is fine for the time format you are using.
As Christoph already mentioned, apparently smooth will smooth the data also outside the current plotting range. However, there is no need for awk or external tools, you can do it with gnuplot only (hence platform-independent).
Simply filter the data outside the range with gnuplot via:
myFilter(col,t) = t<t0 ? NaN : column(col)
The script creates some random test data with some missing data gap. When plotting only a part of the range you will get the unwanted (and unexpected) smoothing with data outside the plotting range, although you set unset clip.
Script:
### smooth filtered data
reset session
myTimeFmt = "%Y-%m-%d:%H:%M:%S"
set datafile separator ","
# create some random test data
set table $Data
set samples 50
SecPerDay = 3600*24
t0 = time(0)
y0 = 100
plot '+' u (sprintf("%s,%g", strftime(myTimeFmt,t0=t0-3600),y0=y0+rand(0)-0.5)) w table, \
t0 = t0 - 3*SecPerDay, \
'+' u (sprintf("%s,%g", strftime(myTimeFmt,t0=t0-3600),y0=y0+rand(0)-0.5)) w table
unset table
set format x "%b %d" timedate
set key out noautotitle
set grid x,y
N = 3 # N last days
t1 = time(0)
t0 = t1 - N*SecPerDay
myFilter(col,t) = t<t0 ? NaN : column(col)
set multiplot layout 3,1
set title "full data range"
plot $Data u (timecolumn(1,myTimeFmt)):2 w l ti "data", \
'' u (timecolumn(1,myTimeFmt)):2 smooth bezier w l ti "smooth"
set title "limited range with unwanted smoothing outside range"
unset clip
set xrange[t0:t1]
plot $Data u (timecolumn(1,myTimeFmt)):2 w l ti "data", \
'' u (timecolumn(1,myTimeFmt)):2 smooth bezier w l ti "smooth"
set title "limited range with filter"
set xrange[t0:t1]
plot $Data u (t=timecolumn(1,myTimeFmt)):(myFilter(2,t)) w l ti "data", \
'' u (t=timecolumn(1,myTimeFmt)):(myFilter(2,t)) smooth bezier w l ti "smooth"
unset multiplot
### end of script
Result:

Unexpected output GNUPlot

I am drawing a simple graph using GNUPlot but output is not what I expected order.
Here is my script :
set title 'cost function vs clusters'
set xlabel '#clusters'
set ylabel 'cost function'
set terminal postscript
set output '| ps2pdf - output.pdf'
plot filename using 1:2 title "x" with linesp
Data on which I am plotting the data is :
13 0.004945370902817711
8 0.06739505462909719
2 0.28378378378378377
17 0.004657849338700402
5 0.015181138585393904
20 0.0018401380103507763
And here is my ouput :
I want points to be joined in sequential order of x.
How I can achieve this?
For the data you showed, you can use smooth unique. This sorts the data and replaces the same x-values with a single point having the averaged y value. If you can be sure, that you'll never have two equal x-values, then you can use this:
set title 'cost function vs clusters'
set xlabel '#clusters'
set ylabel 'cost function'
set terminal pdfcairo
set output 'output.pdf'
plot filename using 1:2 smooth unique title "x" with lp
And call it with gnuplot -e 'filename="aboveFile"' plot.gpi.
The other variant using sort also works fine:
plot '< sort -n '.filename using 1:2 title "x" with lp

Junk in the terminal when trying to export .png

I have a file (called print_1012720.txt) that looks like the text shown below.
1133254688 5698771509078629376
1150031904 5698771509371165696
1150031904 5698771510035551232
4170258464 5698771510036082688
2895583264 5698771510036715520
1620908064 5698771510037202176
346232864 5698771510037665280 <----
3366459424 5698771510038193664
2091784224 5698771510332259072
817109024 5698771510332816128 <-----
3837335584 5698771510333344512
2562660384 5698771510339882240
1287985184 5698771510340411392
13309984 5698771510340939776 <-------
3033536544 5698771510348048896
1758861344 5698771510348577280
484186144 5698771510349228800
3504412704 5698771510632804864
2229737504 5698771510633441792
955062304 5698771510634390272
3975288864 5698771510638858496
2700613664 5698771510639347712
1425938464 5698771510642663168
134486304 5698771510643387136
3154712864 5698771510643808768
I am running the following commands in bash.
gnuplot
reset
set terminal png
set xdata time
set timefmt "%d/%m/%Y %H:%M:%S"
set format x "%H:%M"
set xlabel "time"
set ylabel "highest seq number"
set yrange [0:65535]
set title "seq number over time"
set key reverse Left outside
set grid
set style data linespoints
plot "print_1012720" using 1:2 title "Flow 1"
It gives garbage in my shell. I suspect that it is the spacing between the columns that is causing this. However if I correct the spacing then the file is correctly plotted. Any clue how this can be rectified?
I suspect your main problem is that you are not setting an output. After your set terminal command you should set an output file, otherwise gnuplot will spit out the .png to your terminal, which looks like gibberish. Try putting the following in a file (saved as 'plot.plt' for instance) and then run gnuplot plot.plt at the bash command line.
set terminal png
set output 'output.png'
set xdata time
set timefmt "%s"
set format x "%H:%M"
set xlabel "time"
set ylabel "highest seq number"
set title "seq number over time"
set key reverse Left outside
set grid
set style data linespoints
plot "print_1012720.txt" using 1:2 title "Flow 1"
Creating a plot file this way will save you a lot of time typing at the gnuplot command line.
A couple of other comments:
1) You set your yrange to be 0:65535 when your y values from the datafile are much larger.
2) It looks like you are trying to extract a time in UNIX format from the first column in your datafile. For this you would want the line set timefmt '%s' as I have above. However, the time data in the data file appear to be all over the place, as do the y data.
3) You do not need the reset command at the beginning, since running gnuplot this way will create a new instance of gnuplot, so there will be nothing to reset.
4) You also had 'print_1012720' without the '.txt' extension; I'm not sure this was an error on your part.

Resources