1

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 ?

2
  • 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/7295599 Commented May 28, 2021 at 14:12
  • 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. Commented May 28, 2021 at 14:26

2 Answers 2

3

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
Sign up to request clarification or add additional context in comments.

5 Comments

This works, in my local computer since i have gnuplot 5.4. However I use a cluster and they have gnuplot 5.0, so it doesn't work, is so sad. Thank you for the answer. i think i will resign using gnuplot and do things on python. Once i find things i like i will save them in a format gnuplot likes and plot them.
@Gundro hey, wait... with gnuplot usually you always find a workaround (sometimes pretty cumbersome). I will think about a 5.0 version. Why can't they update to gnuplot 5.2 or 5.4? gnuplot 5.0 is 4-6 years old. Yeah, well gnuplot wants to be a plotting tool and no data analysis tool. However, to my opinion basic operations like transposing data would not harm. If you have Python installed you could always write a Python procedure and use gnuplot again with the pre-processed data.
I don't know why they don't want to update gnuplot or other tools in that specific cluster. it has so many problems but i can't change it or use another cluster. I tried using gnuplot to do everything with only one software, and because i want my figures to be gnuplot-pretty. However I decided today to use python instead, at least to manipulate and test figures and data. Then once I'm happy, I will save the desired data and plot it with gnuplot, but at the end. I think that will be faster for me in case i need to do some weird data operations.
If I find a way, i will be back and write it here. Thank you
Maybe the first line of your plotting script could ssh to a more up-to-date machine? Or start a Docker image?
0

This is an example of plotting without changing the format.

First, let's consider just the first two lines:

$data <<EOD
0.0, 1.0, 2.0, 3.0, 4.0, 5.0
0.0, 0.0, 0.1, 0.2, 0.3, 0.4
EOD

If we treat this data as a 1-row, 5-column nonuniform matrix,
we can plot v and np using the following commands:

set datafile separator comma
plot $data nonuniform matrix every :::0::0 with lines

Next, let's prepare the input data as:

$data <<EOD
0.0, 1.0, 2.0, 3.0, 4.0, 5.0
0.0, 0.0, 0.1, 0.2, 0.3, 0.4
1.0, 1.0, 2.0, 3.0, 4.0, 5.0
1.0, 0.1, 0.2, 0.3, 0.4, 0.5
2.0, 1.0, 2.0, 3.0, 4.0, 5.0
2.0, 0.2, 0.3, 0.4, 0.5, 0.6
EOD

To plot the data at the time step 2 (counting offsets from 0),
you can use the skip option like this:

it = 2
plot $data skip 2*it nonuniform matrix every :::0::0 with lines

A script to plot the data for each time step on the same graph would look like this:

$data <<EOD
0.0, 1.0, 2.0, 3.0, 4.0, 5.0
0.0, 0.0, 0.1, 0.2, 0.3, 0.4
1.0, 1.0, 2.0, 3.0, 4.0, 5.0
1.0, 0.1, 0.2, 0.3, 0.4, 0.5
2.0, 1.0, 2.0, 3.0, 4.0, 5.0
2.0, 0.2, 0.3, 0.4, 0.5, 0.6
EOD

set xrange [0:6]
set yrange [-0.1:1]

set datafile separator comma

time = ""
stats $data skip 1 every 2 using (time = time.strcol(1)." ",0) nooutput

plot for [it=0:2] $data skip 2*it nonuniform matrix every :::0::0 \
                        with linespoints pt 7 ps 2 title "time=".word(time,it+1)

enter image description here

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.