Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Looking at binary output from fortran on gnuplot

So, I created a binary file with fortran, using something similar to this:

open (3,file=filename,form="unformatted",access="sequential")
write(3) matrix(i,:)

The way I understand it, fortran pads the file with 4 bytes on either end of the file, and the rest is just the data that I want (in this case, a list of 1000 doubles).

I want to read this in with gnuplot, however, I don't know how to get gnuplot to skip the first and last 4 bytes, and read the rest in as doubles. The documentation isn't very helpful in this regard.

Thanks

like image 295
Andrew Spott Avatar asked Jan 05 '12 23:01

Andrew Spott


3 Answers

Andrew: I see no reason to make gnuplot handle those extra bytes before/after your data. Either Fortran does not do this padding, or it does and gnuplot handles it without a hassle.

I've had a similar problem, and Google searches always brought me back here. I figured I'd better post my solution in case the same happens to other people.

I've been trying to make a 2D colormap plot using gnuplot's "plot 'file.dat' matrix with image" command. My ASCII output files were too big, so I wanted to use binary files instead. What I did was something like the following:

in fortran:

implicit none
real, dimension(128,128) :: array
integer :: irec

! ... initialize array ...

inquire( iolength=irec ) array
open( 36, 'out.dat', form='unformatted', access='direct', recl=irec )
write( 36, rec=1 ) array
close( 36, status='keep' )

in gnuplot:

plot 'out.dat' binary array=128x128 format="%float" with image

Notes:

  • By default, gnuplot assumes single precision in binary files. If your fortran program outputs in double precision, simply change "%float" to "%double".

  • My program used double precision data in the array, but output files were too big. Since images based on double or single precision are indistinguishable to the eye, and double-precision data files are large, I converted my double-precision data to single-precision data before writing it to a file.

  • You may have to adapt the gnuplot command depending on what you want to do with the matrix, but this loads it in and plots it well. This did what I needed it to do, and I hope it helps anyone
    else who has a similar problem.

  • As you can see, if Fortran adds extra bytes before/after your data, gnuplot seems to read in the data without making you take those extra bytes into account.

like image 120
jvriesem Avatar answered Oct 19 '22 18:10

jvriesem


It might be easier to use direct I/O instead of sequential:

inquire (iolength = irec) matrix(1,:) !total record length for a row
open (3, file=filename, form="unformatted", access="direct", recl=irec)
write(3, rec=1) matrix(i,:)

The inquire statement gives you the length of the output list in 'recl' units. As such, the whole list fits in one record of length irec.

For writing a matrix to file column-wise you can then do:

inquire (iolength = irec) matrix(:,1)
open (3, file=filename, form="unformatted", access="direct", recl=irec)
do i=1,ncol
    write(3, rec=i) matrix(:,i)
end do

or row-wise:

inquire (iolength = irec) matrix(1,:)
open (3, file=filename, form="unformatted", access="direct", recl=irec)
do i=1,nrow
    write(3, rec=i) matrix(i,:)
end do

or element-wise:

inquire (iolength = irec) matrix(1,1)
open (3, file=filename, form="unformatted", access="direct", recl=irec)
do j=1,ncol
    do i=1,nrow
        write(3, rec=j+(ncol-1)*i) matrix(i,j)
    end do
end do

or dump the entire matrix:

inquire (iolength = irec) matrix
open (3, file=filename, form="unformatted", access="direct", recl=irec)
write(3, rec=1) matrix
like image 43
steabert Avatar answered Oct 19 '22 19:10

steabert


Testing with gnuplot 5.0, the following fortran unformatted data write of a double array x of size N,

open(FID,file='binaryfile')
do k = 1, N
  write(FID) x(k)
end do 
close(FID)

can be understood by gnuplot with the following:

plot 'binaryfile' binary format="%*1int%double%*1int"

The %*1int means, skip once a four byte integer, effectively skipping the header and footer data fortran wraps around output.

For more information and extrapolation for more complicated data, see the gnuplot 5.0 docs on binary and see the size of the formats with, show datafile binary datasizes. Note however that multi-column data (i.e. N doubles per write) can be accessed with the same format as above but as %Ndoubles where N is an integer. Then with using 1:3 for example, one would plot the first column against the 3rd.

like image 36
jyalim Avatar answered Oct 19 '22 17:10

jyalim