1
votes

I have data file coming from a fortran code. The data are 2 arrays v and np of size 500 and a scalar time. Each time I append to a file the new time value and the 2 vectors in 2 new lines of the file, in this format:

time,  v(1),  v(2),  v(3), ...,  v(499),  v(500)
time, np(1), np(2), np(3), ..., np(499), np(500) 

For example:

0.0, 1.0, 2.0, 3.0, ..., 499.0, 500.0
0.0, 0.1, 0.2, 0.3, ..., 0.499, 0.500
1.0, 1.0, 2.0, 3.0, ..., 499.0, 500.0
1.0, 0.1, 0.2, 0.3, ..., 0.499, 0.500
2.0, 1.0, 2.0, 3.0, ..., 499.0, 500.0
2.0, 0.1, 0.2, 0.3, ..., 0.499, 0.500

What i want, is to plot np as a function of v at an specific time (So in this case if i want time=2 i will plot lines 5 and 6 with ignoring the first row). However gnuplot doesn't like this format. I made it work using python, however i must do it with gnuplot.

I searched online and found that i can output my data in another format but this doesn't work properly either. This format looks like this:

0.0   0.0
1.0   0.1
2.0   0.2
3.0   0.3
4.0   0.4
...   ...
499.0 0.499
500.0 0.500


1.0   1.0
1.0   0.1
2.0   0.2
3.0   0.3
4.0   0.4
...   ...
499.0 0.499
500.0 0.500


2.0   2.0
1.0   0.1
2.0   0.2
3.0   0.3
4.0   0.4
...   ...
499.0 0.499
500.0 0.500

This format plots everything including the time and even using for loops and every function it doesn't work.

I also searched if I could format my data in columns in fortran, however i couldn't find any solution to that. The problem i have is that at each time, the arrays v and np are erased from memory. And for reasons I can't explain, I can't save v and np in a matrix and save them for later.

Is there a way i can format my data on fortran to read it on gnuplot and be able to plot only one time ?

Or is there a way i can read this format using only gnuplot ?

1
As far as I understand, it might boil down to how to plot a certain row with gnuplot, correct? Maybe this helps: stackoverflow.com/a/67592510/7295599theozh
Oh thanks. I never saw that post previously. It might work with the first output format. I have to see how to ignore first value now.Gundro

1 Answers

3
votes

gnuplot doesn't like data in rows. You could transpose your data with an external tool and simply plot it as columns with gnuplot. Unfortunately, gnuplot has no transpose function itself, although, in principle you could also transpose with gnuplot (https://stackoverflow.com/a/65576405/7295599), but it's probably highly inefficient for large datasets.

Actually, here is an awkward gnuplot solution to plot data from two rows. The values of the rows of interest are stored in arrays (hence requires gnuplot >=5.2.0) using a dummy table. The option every ::SkipCols skips the first SkipCols columns. In your case SkipCols=1 which skips the time values. Maybe somebody can simplify this approach further.

Code:

### plotting a row versus another row (requires gnuplot >=5.2.0)
reset session

$Data <<EOD
0.0   0.1  0.2  0.3  0.4  0.5  0.6  0.7
0.0   1.1  1.2  1.3  1.4  1.5  1.6  1.7
1.0   2.1  2.2  2.3  2.4  2.5  2.6  2.7
1.0   3.1  3.2  3.3  3.4  3.5  3.6  3.7
2.0   4.1  4.2  4.3  4.4  4.5  4.6  4.7
2.0   5.1  5.2  5.3  5.4  5.5  5.6  5.7
EOD

myXrow = 2      # counting starts from 0
myYrow = 3      #
SkipCols = 1    # skip number of columns from the beginning

stats $Data u 0 nooutput            # get the number of columns
array X[STATS_columns-SkipCols]     # define array size
array Y[STATS_columns-SkipCols]     #
myX(row) = ($2==row ? X[$1-SkipCols+1]=$3 : NaN)
myY(row) = ($2==row ? Y[$1-SkipCols+1]=$3 : NaN)

# put the x,y rows into arrays
set table $Dummy
    plot $Data matrix u (myX(myXrow),myY(myYrow)) every :myYrow-myXrow:SkipCols:myXrow::myXrow+myYrow w table
unset table
undef $Dummy

set key noautotitle
plot X u 2:(Y[$1]) w lp pt 7
### end of code

Result:

enter image description here

Addition: (Version for gnuplot 5.0)

Here is a version for gnuplot 5.0. Although datablocks have been introduced in gnuplot 5.0 you cannot address them via index as you can do in gnuplot 5.2. So, this workaround uses strings to store the rows and then printing it back into a datablock. Not very elegant and probably not efficient, but it seems to work. Unless there would be a limit of the string length, it should also work for your 500 columns. Actually, you have comma as separator, so you have set datafile separator comma and later set datafile separator whitespace. The code can probably still be optimized.

Code: (Result same as above)

### plotting a row versus another row (working for gnuplot 5.0)
reset session

$Data <<EOD
0.0,   0.1,  0.2,  0.3,  0.4,  0.5,  0.6,  0.7
0.0,   1.1,  1.2,  1.3,  1.4,  1.5,  1.6,  1.7
1.0,   2.1,  2.2,  2.3,  2.4,  2.5,  2.6,  2.7
1.0,   3.1,  3.2,  3.3,  3.4,  3.5,  3.6,  3.7
2.0,   4.1,  4.2,  4.3,  4.4,  4.5,  4.6,  4.7
2.0,   5.1,  5.2,  5.3,  5.4,  5.5,  5.6,  5.7
EOD

myXrow = 2                 # counting starts from 0
myYrow = 3

set datafile separator comma
X = Y = ''
AddValue(S,row) = S.($2==row ? sprintf(" %g",$3) : '')
set table $Dummy
    plot $Data matrix u (X=AddValue(X,myXrow),Y=AddValue(Y,myYrow)) every :myYrow-myXrow:1:myXrow::myXrow+myYrow
unset table
undef $Dummy

set print $DataNew
    do for [i=1:words(X)] { print sprintf("%s %s",word(X,i),word(Y,i)) }
set print

set datafile separator whitespace
set key noautotitle

plot $DataNew u 1:2 w lp pt 7
### end of code