gnuplot: how to correctly interpret negative times? - gnuplot

I have some issue with negative times in gnuplot.
Basically, I would like to write a negative time, e.g. as -00:01:00, but gnuplot is not interpreting it as -60 seconds, but as +60 seconds.
I can somehow understand why: because -00 hours is equal to +00 hours and then 01 minutes are counted positive.
Did I overlook something? Is there maybe an easy workaround?
More examples are given below. Let's convert some times in the format %H:%M:%S (actually %tH:%tM:%tS).
I'm fine with all lines, except line 6.
Line 7 will be interpreted as %tH:%tM without seconds that's why it is -3660 seconds.
Code:
### negative times
reset session
$Data <<EOD
1 01:00:00
2 01:00:01
3 -01:00:00
4 -01:00:01
5 00:01:01
6 -00:01:01
7 -01:01
8 00:-01:-01
9 00:-01:01
EOD
myTimeFmt = "%tH:%tM:%tS"
set table $Test
plot $Data u 1:(strcol(2)):(timecolumn(2,myTimeFmt)) w table
unset table
print $Test
### end of code
Result:
1 01:00:00 3600
2 01:00:01 3601
3 -01:00:00 -3600
4 -01:00:01 -3601
5 00:01:01 61
6 -00:01:01 61
7 -01:01 -3660
8 00:-01:-01 -61
9 00:-01:01 -61

The following is an attempt to include the possibility of entering negative times starting with -00 hours %tH:%tM:%tS (or minutes %tM:%tS).
It will handle cases 4 and 6 differently than gnuplot currently will do.
The workaround will handle cases which have negative or -00 hours and additionally negative minutes or seconds (cases 7-14 and 16-17) the same way as gnuplot will do. Well, the latter are strange formats anyway.
Code:
### workaround for handling negative times
reset session
$Data <<EOD
1 01:00:00
2 -01:00:00
3 00:01:00
4 -00:01:00
5 00:00:01
6 -00:00:01
7 00:00:-01
8 00:-00:01
9 00:-00:-01
10 00:-01:01
11 00:-01:-01
12 -00:-01:-01
13 -00:-01:01
14 -00:-01:-01
15 -01:01:01
16 -01:-01:-01
17 01:-01:-01
EOD
myTimeFmt = "%tH:%tM:%tS"
myTimeSigned(fmt,s) = s[1:1] eq '-' && strptime("%tH",s)==0 && strptime(fmt,s)>0 ? \
-strptime(fmt,s[2:]) : strptime(fmt,s)
myTime(n,fmt) = myTimeSigned(fmt,strcol(n))
set table $Test
plot $Data u 1:(strcol(2)):(timecolumn(2,myTimeFmt)):(myTime(2,myTimeFmt)) w table
unset table
print $Test
### end of code
Result:
input gnuplot workaround
1 01:00:00 3600 3600
2 -01:00:00 -3600 -3600
3 00:01:00 60 60
4 -00:01:00 60 -60 # different
5 00:00:01 1 1
6 -00:00:01 1 -1 # different
7 00:00:-01 -1 -1
8 00:-00:01 1 1
9 00:-00:-01 -1 -1
10 00:-01:01 -61 -61
11 00:-01:-01 -61 -61
12 -00:-01:-01 -61 -61
13 -00:-01:01 -61 -61
14 -00:-01:-01 -61 -61
15 -01:01:01 -3661 -3661
16 -01:-01:-01 -3661 -3661
17 01:-01:-01 3539 3539

Related

Missing Date xticks on chart for matplotlib on Python 3. Bug?

I am following this section, I realize this code was made using Python 2 but they have xticks showing on the 'Start Date' axis and I do not. My chart only shows Start Date and no dates are provided. I have attempted to convert the object to datetime but that shows the dates and breaks the graph below it and the line is missing:
Graph
# Set as_index=False to keep the 0,1,2,... index. Then we'll take the mean of the polls on that day.
poll_df = poll_df.groupby(['Start Date'],as_index=False).mean()
# Let's go ahead and see what this looks like
poll_df.head()
Start Date Number of Observations Obama Romney Undecided Difference
0 2009-03-13 1403 44 44 12 0.00
1 2009-04-17 686 50 39 11 0.11
2 2009-05-14 1000 53 35 12 0.18
3 2009-06-12 638 48 40 12 0.08
4 2009-07-15 577 49 40 11 0.09
Great! Now plotting the Difference versus time should be straight forward.
# Plotting the difference in polls between Obama and Romney
fig = poll_df.plot('Start Date','Difference',figsize=(12,4),marker='o',linestyle='-',color='purple')
Notebook is here

read many lines with specific position

Thank you for the time you soent reading it, maybe it is a nooby question
I have a file of 10081 lines, this is an example of the file (a nordic seismic bulletin):
2016 1 8 0921 21.5 L -22.382 -67.835 148.9 OSC 18 0.3 4.7LOSC 1
2016 1 8 1515 43.7 L -20.762 -67.475 188.7 OSC 16 .30 3.7LOSC 1
2016 1 9 0529 35.9 L -18.811 -67.278 235.9 OSC 16 0.5 3.9LOSC 1
2016 110 313 55.6 L -22.032 -67.375 172.0 OSC 14 .30 3.0LOSC 1
2016 110 1021 36.5 L -16.923 -66.668 35.0 OSC 16 0.4 4.5LOSC 1
I tried the following code to extract some information from the file and save them in a separate file.
awk 'NR==1 {print substr($0,24,7), substr($0,32,7), substr($0,40,5)}' select.inp > lat_lon_depth.xyz
substr($0,24,7) means that I take from the 24th position 7 characters which is
the latitude information (-22.382) and the same for the others (longitude from 32th place with 7 characters and depth on 4oth position with 5 characters).
So the question, is possible to go trought all the lines of file and have all latitude, longitude and depth.
Thank you for the time

How to generate 3 natural number that sum to 60 using awk

I am trying to write awk script that generate 3 natural numbers that sum to 60. I am trying with rand function but I`ve got problem with sum to 60
Here is one way:
awk -v n=60 'BEGIN{srand();a=int(rand()*n);b=int(rand()*(n-a));c=n-a-b;
print a,b,c}'
Idea is:
generate random number a :0=<a<60
generate random number b :0=<b<60-a
c=60-a-b
here, I set a variable n=60, to make it easy if you have other sum.
If we run this one-liner 10 times, we get output:
kent$ awk 'BEGIN{srand();for(i=1;i<=10;i++){a=int(rand()*60);b=int(rand()*(60-a));c=60-a-b;print a,b,c}}'
46 7 7
56 1 3
26 15 19
14 12 34
44 6 10
1 36 23
32 1 27
41 0 19
55 1 4
54 1 5

How can I swap numbers inside data block of repeating format using linux commands?

I have a huge data file, and I hope to swap some numbers of 2nd column only, in the following format file. The file have 25,000,000 dataset, and 8768 lines each.
%% Edited: shorter 10 line example. Sorry for the inconvenience. This is typical one data block.
# Dataset 1
#
# Number of lines 10
#
# header lines
5 11 3 10 120 90 0 0.952 0.881 0.898 2.744 0.034 0.030
10 12 3 5 125 112 0 0.952 0.897 0.905 2.775 0.026 0.030
50 10 3 48 129 120 0 1.061 0.977 0.965 3.063 0.001 0.026
120 2 4 5 50 186 193 0 0.881 0.965 0.899 0.917 3.669 0.000 -0.005
125 3 4 10 43 186 183 0 0.897 0.945 0.910 0.883 3.641 0.000 0.003
186 5 4 120 125 249 280 0 0.899 0.910 0.931 0.961 3.727 0.000 -0.001
193 6 4 120 275 118 268 0 0.917 0.895 0.897 0.937 3.799 0.000 0.023
201 8 4 278 129 131 280 0 0.921 0.837 0.870 0.934 3.572 0.000 0.008
249 9 4 186 355 179 317 0 0.931 0.844 0.907 0.928 3.615 0.000 0.008
280 10 4 186 201 340 359 0 0.961 0.934 0.904 0.898 3.700 0.000 0.033
#
# Dataset 1
#
# Number of lines 10
...
As you can see, there are 7 repeating header lines in the head, and 1 trailing line at the end of the dataset. Those header and trailing lines are all beginning from #. As a result, the data will have 7 header lines, 8768 data lines, and 1 trailing line, total 8776 lines per a data block. That one trailing line only contains sinlge '#'.
I want to swap some numbers in 2nd columns only. First, I want to replace
1, 9, 10, 11 => 666
2, 6, 7, 8 => 333
3, 4, 5 => 222
of the 2nd column, and then,
666 => 6
333 => 3
222 => 2
of the 2nd column. I hope to conduct this replacing for all repeating dataset.
I tried this with python, but the data is too big, so it makes memory error. How can I perform this swapping with linux commands like sed or awk or cat commands?
Thanks
Best,
This might work for you, but you'd have to use GNU awk, as it's using the gensub command and $0 reassignment.
Put the following into an executable awk file ( like script.awk ):
#!/usr/bin/awk -f
BEGIN {
a[1] = a[9] = a[10] = a[11] = 6
a[2] = a[6] = a[7] = a[8] = 3
a[3] = a[4] = a[5] = 2
}
function swap( c2, val ) {
val = a[c2]
return( val=="" ? c2 : val )
}
/^( [0-9]+ )/ { $0 = gensub( /^( [0-9]+)( [0-9]+)/, "\\1 " swap($2), 1 ) }
47 # print the line
Here's the breakdown:
BEGIN - set up an array a with mappings of the new values.
create a user defined function swap to provide values for the 2nd column from the a array or the value itself. The c2 element is passed in, while the val element is a local variable ( becuase no 2nd argument is passed in ).
when a line starts with a space followed by a number and a space (the pattern), then use gensub to replace the first occurrance of the first number pattern with itself concatenated with a space and the return from swap(the action). In this case, I'm using gensub's replacement text to preserve the first column data. The second column is passed to swap using the field data identifier of $2. Using gensub should preserve the formatting of the data lines.
47 - an expression that evaluates to true provides the default action of printing $0, which for data lines might have been modified. Any line that wasn't "data" will be printed out here w/o modifications.
The provided data doesn't show all the cases, so I made up my own test file:
# 2 skip me
9 2 not going to process me
1 1 don't change the for matting
2 2 4 23242.223 data
3 3 data that's formatted
4 4 7 that's formatted
5 5 data that's formatted
6 6 data that's formatted
7 7 data that's formatted
8 8 data that's formatted
9 9 data that's formatted
10 10 data that's formatted
11 11 data that's formatted
12 12 data that's formatted
13 13 data that's formatted
14 s data that's formatted
# some other data
Running the executable awk (like ./script.awk data) gives the following output:
# 2 skip me
9 2 not going to process me
1 6 don't change the for matting
2 3 4 23242.223 data
3 2 data that's formatted
4 2 7 that's formatted
5 2 data that's formatted
6 3 data that's formatted
7 3 data that's formatted
8 3 data that's formatted
9 6 data that's formatted
10 6 data that's formatted
11 6 data that's formatted
12 12 data that's formatted
13 13 data that's formatted
14 s data that's formatted
# some other data
which looks alright to me, but I'm not the one with 25 million datasets.
You'd also most definitely want to try this on a smaller sample of your data first (the first few datasets?) and redirect stdout a temp file perhaps like:
head -n 26328 data | ./script.awk - > tempfile
You can learn more about the elements used in this script here:
awk basics (the man page)
Arrays
User defined functions
String functions - gensub()
And of course, you should spend some quality time reviewing awk related questions and answers on Stack Overflow ;)

How to embed multiple datasets in a gnuplot command script for a single plot command?

I found out that in gnuplot one can obtain multiple curves / datasets from a single file:
splot "file.dat" using 1:2:3, splot "file.dat" using 1:4:5
Also one can embed data in a script like so:
splot "-" using 1:2:3
1 0 1
1 2 3
0.5 3 1.5
However, the following seems not to work:
splot "-" using 1:2:3, "-" using 1:4:5
1 0 1 4 4
1 2 3 3 4
0.5 3 1.5 2.5 -1
is this intentional, does a workaround exist or is it simply not possible?
Gnuplot 5.0.1 datablocks
main.gnuplot
$data << EOD
1 0.5 0.25 2 4
2 1 1 4 8
3 1.5 2.25 6 12
4 2 4 8 16
5 2.5 6.25 10 20
6 3 9 12 24
7 3.5 12.25 14 28
8 4 16 16 32
9 4.5 20.25 18 36
10 5 25 20 40
11 5.5 30.25 22 44
12 6 36 24 48
EOD
splot \
"$data" using 1:2:3 with linespoints title "y = x/2, z = y^2", \
"$data" using 1:4:5 with linespoints title "y = 2x, z = 2*y"
Convert to PNG:
gnuplot -e 'set terminal png' -e 'set output "main.png"' main.gnuplot
Output:
Ubuntu 15.04 has the gnuplot5-x11 package.
On Ubuntu 14.04, you can compile gnuplot from source easily with:
cvs -d:pserver:anonymous#gnuplot.cvs.sourceforge.net:/cvsroot/gnuplot login
cvs -z3 -d:pserver:anonymous#gnuplot.cvs.sourceforge.net:/cvsroot/gnuplot co -P gnuplot
cd gnuplot
cvs update -r Release_5_0_1
sudo apt-get build-dep gnuplot
sudo apt-get install lua5.2
./prepare
./configure
time make
sudo make install
gnuplot --version
Yes, the project uses CVS at the time of writing!
Tested on Ubuntu 18.10, gnuplot 5.2.
The following script works with Gnuplot 4.4 as expected. The output attached below
set terminal png
set output 'e.png'
splot "-" using 1:2:3, "" using 1:2:3
1 0 1 4 4
1 2 3 3 4
0.5 3 1.5 2.5 -1
e
1 4 4
1 3 4
0.5 2.5 -1
e
set output
splot "-" using 1:2:3, "" using 1:2:3
The workaround would be
splot "-" using 1:2:3
1 0 1
1 2 3
0.5 3
splot "-" using 1:2:3
1 4 4
1 3 4
0.5 2.5 -1
If you can put the 5-column data into a plotscript, you can preprocess it to be two 3-column data sets in a plotscript.
I can't get it to work in one line as you have tried. It may not be possible, since
splot 'dat.txt' using 1:2:3, '' using 1:3:4
works, but
splot '-' using 1:2:3, '' using 1:4:5
1 0 1 4 4
1 2 3 3 4
0.5 3 1.5 2.5 -1
does not.

Resources