2
votes

I have a file of data where the first column is time in seconds. The start of time is 0, and onward from there.

I want to plot the data with an x-axis formatted as days:hours:minutes:seconds. T=0 should map to 00:00:00:00. I can't figure out how to get days to start at 00 instead of 01. I have tried the below. I also tried setting xrange to [-86400:173000], but that maps to day 365, not 0. Shouldn't it be common to plot some time-sampled data, that may span days, starting with T=0?

It seems that GnuPlot needs a different set of time format characters for zero-based time plotting, instead of date-based. Unless it already has it and I have missed it.

data

0 0
3600 10
7200 30
21600 50
160000 100

GnuPlot script

set xdata time
set format x "%02j:%H:%M:%S"
set timefmt "%s"
set xrange [0:173000]
plot "data" using 1:2 with lines

Plot

2
How many days do you need to plot? Less or more than 7 days? If less than 7, then I would see a workaround.theozh
Hah :). I guess you mean this. set format x "%02w:%H:%M:%S" set xrange [-345600:173000]Myles Prather
That's a long walk. I might consider using it. I was hoping to just modify my existing code with a new format and not have to add any logic. But at least there is a work-around. Thanks @theozh.Myles Prather
To answer your question. I am tracking the results of a long simulation. Some will go longer than a week, but most won't. So this is a decent work-around. So surprising this is a "novel" approach to plotting that I am taking. Seems it would be fairly commonplace. Like a v1.1 feature. Not v5.5.Myles Prather

2 Answers

3
votes

I can get you part way there. Gnuplot has a separate set of time formats for relative time. Zero-based and handles positive and negative intervals. It's hard to find in the documentation, but here is a section from "help time_specifiers".

   Format       Explanation
   %tH          +/- hours relative to time=0 (does not wrap at 24)
   %tM          +/- minutes relative to time=0
   %tS          +/- seconds associated with previous tH or tM field

Examples of time format:

The date format specifiers encode a time in seconds as a clock time on a particular day. So hours run only from 0-23, minutes from 0-59, and negative values correspond to dates prior to the epoch (1-Jan-1970). In order to report a time value in seconds as some number of hours/minutes/seconds relative to a time 0, use time formats %tH %tM %tS. To report a value of -3672.50 seconds

   set format x                 # default date format "12/31/69 \n 22:58"
   set format x "%tH:%tM:%tS"   # "-01:01:12"
   set format x "%.2tH hours"   # "-1.02 hours"
   set format x "%tM:%.2tS"     # "-61:12.50"

Using these relative time formats with your sample data I can get as far as:

$data << EOD
0 0
3600 10
7200 30
21600 50
160000 100
EOD

set xtics time format "%tH:%tM:%tS"
set title 'set xtics time format "%tH:%tM:%tS"'
set xrange [0:173000]
plot $data using 1:2 with lp

enter image description here

Now the problem is that there is no equivalent relative day format. Call that a bug or at least a missing feature. Let's take a stab at adding days to the format by hand.

secperday = 3600*24
days(t) = gprintf("%02g:", int(t)/secperday)
hours(t) = strftime("%02tH:%tM:%tS", int(t)%secperday)

# Create ten days worth of tic labels
# Every six hours with no label; once a day with full label
set xtics 6*3600 format "" 
do for [i=0:10] {
    T = day * secperday
    set xtics add ( days(T).hours(T) T )
}
plot $data using 1:2 with lp

enter image description here

1
votes

As mentioned in the comments above, one workaround would be using week days, which however would limit you to 7 days. Since 0 seconds correspond to Thursday, 01.01.1970 00:00:00 you have to subtract 4 days = 24*3600*4 seconds to make it a Sunday (=0).

Another strange workaround would be to use multiplot and plot twice, just for the day labels. You have to set a bottom margin to exactly "overplot" the previous plot. There would be still room for fine tuning.

By the way: If the scale is several days then the question is if seconds in the label are actually relevant?

Code:

### timedate days starting from zero
reset session

$Data <<EOD
0 0
3600 10
7200 30
21600 50
160000 100
450000 222
500000 333
EOD

set multiplot layout 2,1

    # first workaround, limited to 7 days
    set format x "day %1w\n%H:%M:%S" timedate
    plot $Data u ($1-24*3600*4):2 w lp pt 7 notitle
    
    # second workaround, using multiplot
    set format x "\n%H:%M:%S" timedate
    set bmargin 3
    plot $Data u 1:2 w lp pt 7 notitle
    
    set multiplot previous
    set format x "day %s"
    set xrange[GPVAL_X_MIN/86400:GPVAL_X_MAX/86400]
    plot $Data u ($1/86400):2 w p ps 0 notitle  # point size zero, i.e. invisible

unset multiplot
### end of code

Result:

enter image description here