Writing Fortran unformatted files with Python

前端 未结 2 826
北荒
北荒 2020-12-06 14:30

I have some single-precision little-endian unformatted data files written by Fortran77. I am reading these files using Python using the following commands:

i         


        
相关标签:
2条回答
  • 2020-12-06 15:19

    this is creating an unformatted sequential access file:

    open(out_file_id,FILE=out_file,form="unformatted")
    

    Assuming you are writing a single array real a(n,n,n) using simply write(out_file_id)a you should see a file size 4*n^3+8 bytes. The extra 8 bytes being a 4 byte integer (=4n^3) repeated at the start and end of the record.

    the second form:

    open (in_file_id,FILE=in_file,form='unformatted',access='direct',recl=4*n*n*n)
    

    opens direct acess, which does not have those headers. For writing now you'd have write(unit,rec=1)a. If you read your sequential access file using direct acess it will read without error but you'll get that integer header read as a float (garbage) as the (1,1,1) array value, then everything else is shifted. You say you can read with fortran ,but are you looking to see that you are really reading what you expect?

    The best fix to this is to fix your original fortran code to use unformatted,direct access for both reading and writing. This gives you an 'ordinary' raw binary file, no headers.

    Alternately in your python you need to first read that 4 byte integer, then your data. On output you could put the integer headers back or not depending on what your paraview filter is expecting.

    ---------- here is python to read/modify/write an unformatted sequential fortran file containing a single record:

    import struct
    import numpy as np
    f=open('infile','rb')
    recl=struct.unpack('i',f.read(4))[0]
    numval=recl/np.dtype('float32').itemsize
    data=np.fromfile(f,dtype='float32',count=numval)
    endrec=struct.unpack('i',f.read(4))[0]
    if endrec is not recl: print "error unexpected end rec"
    f.close()
    f=open('outfile') 
    f.write(struct.pack('i',recl))
    for i in range(0,len(data)):data[i] = data[i]**2  #example data modification
    data.tofile(f)
    f.write(struct.pack('i',recl)
    

    just loop for multiple records.. note that the data here is read as a vector and assumed to be all floats. Of course you need to know the actuall data type to make use if it.. Also be aware you may need to deal with byte order issues depending on platform.

    0 讨论(0)
  • 2020-12-06 15:27

    Have you tried using the .tofile method of the manipulated data array? It will write the array in C order but is capable of writing plain binary.

    The documentation for .tofile also suggests this is the same as:

    with open(outfile, 'wb') as fout:
        fout.write(manipulated_data.tostring())
    
    0 讨论(0)
提交回复
热议问题