¿Cuál es el equivalente de ‘fread’ de Matlab en Python?

Prácticamente no tengo conocimiento de Matlab, y necesito traducir algunas rutinas de análisis a Python. Son para archivos grandes, que a su vez están divididos en ‘bloques’, y tengo dificultades desde el principio con la sum de comprobación en la parte superior del archivo.

¿Qué está pasando exactamente aquí en Matlab?

status = fseek(fid, 0, 'cof'); fposition = ftell(fid); disp(' '); disp(['** Block ',num2str(iBlock),' File Position = ',int2str(fposition)]); % ----------------- Block Start ------------------ % [A, count] = fread(fid, 3, 'uint32'); if(count == 3) magic_l = A(1); magic_h = A(2); block_length = A(3); else if(fposition == file_length) disp(['** End of file OK']); else disp(['** Cannot read block start magic ! Note File Length = ',num2str(file_length)]); end ok = 0; break; end 

fid es el archivo que se está viendo actualmente en iBlock es un contador para el cual se encuentra dentro del archivo

magic_l y magic_h tienen que ver con las sums de comprobación más adelante, aquí está el código para eso (sigue el código anterior):

 disp(sprintf(' Magic_L = %08X, Magic_H = %08X, Length = %i', magic_l, magic_h, block_length)); correct_magic_l = hex2dec('4D445254'); correct_magic_h = hex2dec('43494741'); if(magic_l ~= correct_magic_l | magic_h ~= correct_magic_h) disp(['** Bad block start magic !']); ok = 0; return; end remaining_length = block_length - 3*4 - 3*4; % We read Block Header, and we expect a footer disp(sprintf(' Remaining Block bytes = %i', remaining_length)); 
  • ¿Qué está pasando con las %08X y hex2dec ?
  • Además, ¿por qué especificar 3*4 lugar de 12 ?

Sin embargo, realmente quiero saber cómo replicar [A, count] = fread(fid, 3, 'uint32'); en Python, como io.readline() solo está tirando de los primeros 3 caracteres del archivo. Disculpas si me falta el punto aquí. Es solo que el uso de io.readline(3) en el archivo parece devolver algo que no debería, y no entiendo cómo puede encajar el block_length en un solo byte cuando podría ser muy largo.

Gracias por leer este paseo. Espero que puedas entender algo de lo que quiero saber! (Cualquier apreciación en absoluto es apreciada.)

De la documentación de fread , es una función para leer datos binarios. El segundo argumento especifica el tamaño del vector de salida, el tercero el tamaño / tipo de los elementos leídos.

Para recrear esto en Python, puedes usar el módulo de array :

 f = open(...) import array a = array.array("L") # L is the typecode for uint32 a.fromfile(f, 3) 

Esto leerá leer tres valores uint32 del archivo f , que están disponibles en a posterior. De la documentación de fromfile :

Lea n elementos (como valores de máquina) del objeto de archivo f y agréguelos al final de la matriz. Si hay menos de n elementos disponibles, se genera EOFError, pero los elementos que estaban disponibles aún se insertan en la matriz. f debe ser un objeto de archivo incorporado real; algo más con un método de lectura () no servirá.

Las matrices implementan el protocolo de secuencia y, por lo tanto, admiten las mismas operaciones que las listas, pero también puede usar el método .tolist() para crear una lista normal a partir de la matriz.

Código de Python para leer una matriz de 1 dimensión

Al reemplazar Matlab con Python, quería leer datos binarios en un numpy.array , así que utilicé numpy.fromfile para leer los datos en una matriz de una dimensión:

 import numpy as np with open(inputfilename, 'rb') as fid: data_array = np.fromfile(fid, np.int16) 

Algunas ventajas de usar numpy.fromfile frente a otras soluciones de Python incluyen:

  • No tener que determinar manualmente el número de elementos a leer. Puede especificarlos usando el argumento count= , pero el valor predeterminado es -1 que indica la lectura de todo el archivo.
  • Poder especificar un objeto de archivo abierto (como lo hice anteriormente con fid ) o puede especificar un nombre de archivo. Prefiero usar un objeto de archivo abierto, pero si desea usar un nombre de archivo, puede reemplazar las dos líneas de arriba con:

     data_array = numpy.fromfile(inputfilename, numpy.int16) 

Código Matlab para una matriz de 2 dimensiones

El fread de Matlab tiene la capacidad de leer los datos en una matriz de forma [m, n] lugar de solo leerlos en un vector de columna. Por ejemplo, para leer datos en una matriz con 2 filas use:

 fid = fopen(inputfilename, 'r'); data_array = fread(fid, [2, inf], 'int16'); fclose(fid); 

Código de Python equivalente para una matriz bidimensional

Puedes manejar este escenario en Python usando la shape y la transpose Numpy.

 import numpy as np with open(inputfilename, 'rb') as fid: data_array = np.fromfile(fid, np.int16).reshape((-1, 2)).T 
  • El -1 le dice a numpy.reshape que numpy.reshape la longitud de la matriz para esa dimensión basándose en la otra dimensión, el equivalente de la representación infinita de Matlab.
  • La .T transpone la matriz de modo que sea una matriz bidimensional con la primera dimensión, el eje, que tiene una longitud de 2.

Sin embargo, realmente quiero saber cómo replicar [A, count] = fread(fid, 3, 'uint32');

En Matlab, una de las fread() de fread() es fread(fileID, sizeA, precision) . Esto lee en los primeros elementos de sizeA (no en bytes) de un archivo, cada uno de un tamaño suficiente para la precision . En este caso, ya que está leyendo en uint32 , cada elemento tiene un tamaño de 32 bits, o 4 bytes.

Entonces, en su lugar, intente io.readline(12) para obtener los primeros 3 elementos de 4 bytes del archivo.

La primera parte está cubierta por la respuesta de Torsten … necesitarás una array o una array numarray para hacer cualquier cosa con estos datos de todos modos.

En cuanto a% 08X y las cosas hex2dec,% 08X es solo el formato de impresión para esos números unit32 (8 dígitos hexadecimales, exactamente igual que Python), y hex2dec (‘4D445254’) es matlab para 0x4D445254.

Finalmente, ~ = en matlab es una comparación a nivel de bits; utilizar == en Python.