Escribiendo archivos sin formato de Fortran con Python

Tengo algunos archivos de datos sin formato de little-endian de precisión simple escritos por Fortran77. Estoy leyendo estos archivos usando Python usando los siguientes comandos:

import numpy as np original_data = np.dtype('float32') f = open(file_name,'rb') original_data = np.fromfile(f,dtype='float32',count=-1) f.close() 

Después de un poco de manipulación de datos en Python, estoy (intentando) escribirlos de nuevo en el formato original usando Python usando los siguientes comandos:

 out_file = open(output_file,"wb") s = struct.pack('f'*len(manipulated_data), *manipulated_data) out_file.write(s) out_file.close() 

Pero no parece estar funcionando. ¿Alguna idea sobre cuál es la forma correcta de escribir los datos usando Python en el formato original sin formato de Fortran?

Detalles del problema:

Puedo leer el archivo final con datos manipulados de Fortran. Sin embargo, quiero visualizar estos datos utilizando un software (Paraview). Para ello, convierto los archivos de datos sin formato en el formato * h5. Puedo convertir tanto los datos originales como los manipulados en formato h5 utilizando las utilidades h5. Pero mientras Paraview puede leer los archivos * h5 creados a partir de datos originales, Paraview no puede leer los archivos * h5 creados a partir de los datos manipulados. Supongo que algo se está perdiendo en la traducción.

    Así es como abro el archivo escrito por Python en Fortran (datos de precisión simple):

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

    Y esto es lo que estoy escribiendo los datos originales sin formato de Fortran:

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

    ¿Es esta información suficiente?

    ¿Ha intentado usar el método .tofile de la matriz de datos manipulados? Escribirá la matriz en orden C, pero es capaz de escribir binarios simples.

    La documentación para .tofile también sugiere que esto es lo mismo que:

     with open(outfile, 'wb') as fout: fout.write(manipulated_data.tostring()) 

    esto es crear un archivo de acceso secuencial sin formato:

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

    Suponiendo que está escribiendo una única matriz real a(n,n,n) utilizando simplemente write(out_file_id)a , debería ver un tamaño de archivo 4 * n ^ 3 + 8 bytes. Los 8 bytes adicionales son un entero de 4 bytes (= 4n ^ 3) que se repite al principio y al final del registro.

    la segunda forma:

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

    Abre el acceso directo, que no tiene esos encabezados. Para escribir ahora tendrías que write(unit,rec=1)a . Si lees tu archivo de acceso secuencial mediante acceso directo , se leerá sin error, pero obtendrás el encabezado entero leído como un valor flotante (basura) como el valor de la matriz (1,1,1), entonces todo lo demás se desplaza. Usted dice que puede leer con Fortran, pero ¿está viendo que realmente está leyendo lo que espera?

    La mejor solución para esto es corregir su código fortran original para usar el acceso directo sin formato para lectura y escritura. Esto le da un archivo binario sin procesar ‘ordinario’, sin encabezados.

    Alternativamente, en tu python debes leer primero ese entero de 4 bytes, luego tus datos. En la salida, puede poner los encabezados de números enteros atrás o no dependiendo de lo que su filtro de paraview está esperando.

    ———- aquí está python para leer / modificar / escribir un archivo fortran secuencial sin formato que contiene un solo registro:

     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) 

    simplemente haga un bucle para múltiples registros … tenga en cuenta que los datos aquí se leen como un vector y se supone que son todos flotadores. Por supuesto, debe conocer el tipo de datos actuall para utilizarlo si … También tenga en cuenta que es posible que deba tratar los problemas de orden de bytes según la plataforma.