1

I've got a file which has this structure:

Header 1
Header 2
config X Y
0.0 -5 -2
0.0 0 1
0.0 5 4
Header2
Config X Y
1.0 -5 -1
1.0 0 0
1.0 5 5
Header2
Config X Y
2.0 -5 0
2.0 0 1
2.0 5 6

Using gnuplot, I would like to plot columns 2:3 (Y as a function of X) with a few conditions:

  • Get rid of the headers and any line that's not filled with numbers
  • On the same graph, plot a new function (with a new label and a new color) each time the config changes. In the aforementioned case, you'd end up with three plots (one for config=0.0, one for config=1.0 and one for config=2.0)

Is there a one-liner for this in Gnuplot?

I tried to use the "every" keyword

p 'filename.txt' every ::3 u 2:3 w p

but to no avail

Thank you

  • Do yo have the possibility to change the data or is this given and fixed? For example add two blank lines before each header? How long are the 3 datasets? Different length or all the same length? – theozh Nov 28 '22 at 13:36
  • Hi @theozh, I would like not to modify the data since the script should be applied to different files the name of which is to be specified at the start of said script. The files will have the same length: exact same number of rows since the x-sampling should never change. – Bean_from_accounts Nov 28 '22 at 14:09
  • Just to confirm, Is it correct that you have first 3 text lines, N data lines, 2 text lines, N data lines, 2 text lines, N data lines? – theozh Nov 28 '22 at 14:49
  • That is correct. – Bean_from_accounts Nov 28 '22 at 15:03

1 Answers1

1

If you have a strict data structure and you insist on a one-liner you could do the following with every, check help every. However, then you need to know in advance that N=5 (here: 2 header lines and 3 data lines) and you have 3 blocks. You also skip the first 3 lines (check help skip).

You could use stats find out N automatically. Personally, I would prefer a solution with more than one line, which would robust against little changes in data, just in case.

Script:

### separate data into subblocks with different colors
reset session

$Data <<EOD
Header 1
Header 2
config X Y
0.0 -5 -2
0.0  0  1
0.0  5  4
Header2
Config X Y
1.0 -5 -1
1.0  0  0
1.0  5  5
Header2
Config X Y
2.0 -5  0
2.0  0  1
2.0  5  6
EOD

plot for [i=0:2] N=5 $Data u 2:3 every ::i*N::(i+1)*N-1 skip 3 w lp pt 7 lc i ti sprintf("Config%d",i)
### end of script

Result:

enter image description here

Addition:

Here is a more general (but maybe not too obvious) solution:

  • you don't need to know in advance how many blocks you have and how many datalines you have
  • you can have different number of data lines

What the script does:

  • during plotting, the script checks if the column 1 contains a valid number, valid(1) will return 1 if it is a valid number and 0 otherwise (check help valid).
  • the variable c1 is initialized to 0. During plotting line by line c0 is assigned the value of c1 and c1 gets the value of valid(1).
  • so, everytime column 1 changes from text to numbers (i.e. c1>c0) increment b by 1 and use it for setting the color (check help lc variable)
  • plot keyentries in a loop with the corresponding title.

So, it is a two-liner which also could be put into a single line.

Script:

### separate data into subblocks with different colors (more flexibility)
reset session

$Data <<EOD
Header 1
Header 2
Header 3
config X Y
0.0 -5 -2
0.0  0  1
0.0  5  4    # could be followed e.g. by an empty line

Header2
Config X Y
1.0 -5 -1
1.0  0  0
1.0  5  5
1.0  6  6   # 4 data entries
Header2
Config X Y
Some other text line added
2.0 -5  0
2.0  0  1
2.0  5  6
2.0  6  7
2.0  7  6.5   # 5 data entries
EOD

set key top left noautotitle

plot c1=b=0 $Data u (c0=c1,c1=valid(1),$2):($3):(c1>c0?b=b+1:b-1) w lp pt 7 lc var, \
     for [i=0:b-1] keyentry w lp pt 7 lc i ti sprintf("Config%d",i)
### end of script

Result:

enter image description here

theozh
  • 22,244
  • 5
  • 28
  • 72
  • Thank you very much! I didn't have enough time to test your more general solution but the first one works perfectly well for me, provided I place "N=5" before the plot command (probably a typo, otherwise gnuplot will return a "undefined variable: for" error). – Bean_from_accounts Nov 29 '22 at 15:02
  • 1
    @Bean_from_accounts You are right, sorry. Because I squeezed all into one line, but at the wrong position... `plot for [i=0:2] N=5 $Data u ...` is correct or alternatively `N=5` in a separate line before the plot command. I will edit the answer. Thanks for the feedback. – theozh Nov 29 '22 at 15:11