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 ?
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:
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