4

Python でバイナリ ファイルを読み取る必要があります。これは、Fortran 90 プログラムによって次のように最初に記述されます。

open(unit=10,file=filename,form='unformatted')
write(10)table%n1,table%n2
write(10)table%nH
write(10)table%T2
write(10)table%cool
write(10)table%heat
write(10)table%cool_com
write(10)table%heat_com
write(10)table%metal
write(10)table%cool_prime
write(10)table%heat_prime
write(10)table%cool_com_prime
write(10)table%heat_com_prime
write(10)table%metal_prime
write(10)table%mu
if (if_species_abundances) write(10)table%n_spec
close(10)

このバイナリ ファイルは、次の IDL コードで簡単に読み取ることができます。

n1=161L
n2=101L
openr,1,file,/f77_unformatted
readu,1,n1,n2
print,n1,n2
spec=dblarr(n1,n2,6)
metal=dblarr(n1,n2)
cool=dblarr(n1,n2)
heat=dblarr(n1,n2)
metal_prime=dblarr(n1,n2)
cool_prime=dblarr(n1,n2)
heat_prime=dblarr(n1,n2)
mu  =dblarr(n1,n2)
n   =dblarr(n1)
T   =dblarr(n2)
Teq =dblarr(n1)
readu,1,n
readu,1,T
readu,1,Teq
readu,1,cool
readu,1,heat
readu,1,metal
readu,1,cool_prime
readu,1,heat_prime
readu,1,metal_prime
readu,1,mu
readu,1,spec
print,spec
close,1

私がやりたいことは、このバイナリ ファイルを Python で読み取ることです。しかし、いくつかの問題があります。まず、ファイルを読み取ろうとする試みは次のとおりです。

import numpy
from numpy import *
import struct

file='name_of_my_file'
with open(file,mode='rb') as lines:
    c=lines.read()

最初の 2 つの変数を読み取ろうとします。

dummy, n1, n2, dummy = struct.unpack('iiii',c[:16])

しかし、ご覧のとおり、ダミー変数を追加する必要がありました。これは、fortran プログラムがこれらの位置に整数 8 を追加するためです。

問題は、他のバイトを読み取ろうとするときです。IDL プログラムと同じ結果が得られません。

これが配列nを読み取ろうとする私の試みです

 double = 8
 end = 16+n1*double
 nH = struct.unpack('d'*n1,c[16:end])

ただし、この配列を印刷すると、意味のない値が得られます。つまり、上記の IDL コードでファイルを読み取ることができるので、何を期待すべきかがわかります。私の質問は次のとおりです。構造が正確にわからない場合、このファイルをどのように読むことができますか? IDL を使用すると、なぜ読み取りが簡単なのですか? このデータセットを Python で読み取る必要があります。

4

3 に答える 3

6

あなたが探しているのはstructモジュールです。

このモジュールを使用すると、文字列からデータをアンパックして、バイナリ データのように扱うことができます。

フォーマット文字列とファイル文字列を指定すると、バイナリ オブジェクトを返すデータが消費されます。

たとえば、変数を使用して:

import struct
content = f.read() #I'm not sure why in a binary file you were using "readlines",
                   #but if this is too much data, you can supply a size to read()
n, T, Teq, cool = struct.unpack("dddd",content[:32])

これにより、n、T、Teq、cool がバイナリ ファイルの最初の 4 つの double を保持します。もちろん、これは単なるデモンストレーションです。あなたの例は double のリストが必要なように見えます -struct.unpackタプルを便利に返します。渡された文字列全体を消費する必要があることに注意してください。struct.unpackそうしないと、struct.error. したがって、上記のコメントで述べたように、入力文字列をスライスするか、read使用する文字数のみをスライスします。

例えば、

n_content = f.read(8*number_of_ns) #8, because doubles are 8 bytes
n = struct.unpack("d"*number_of_ns,n_content)
于 2011-11-11T11:12:23.563 に答える
0

RAMSES によって生成されたCooling_0000x.outファイルを読み込もうとしているようです。

最初の 2 つの整数 (n1、n2) は、ファイルの本文に続く 2 つの次元テーブル (配列) の次元を提供することに注意してください。そのため、実際の量を知る前に、まずこれらの 2 つの整数を処理する必要があります*8。データはファイルの残りの部分にあります。

scipy が役立つはずです。これにより、任意の次元のバイナリ データを読み取ることができます。

http://wiki.scipy.org/Cookbook/InputOutput#head-e35c7736718209eea00ebf37a7e1dfb91df696e1

この python コードを既にお持ちの場合は、今日 (2014 年 9 月 17 日) 書くつもりだったのでお知らせください。

リック

于 2014-09-17T19:47:45.577 に答える
0

scipy.io.readsavを試してみましたか?

次のようにファイルを読み取るだけです。

mydict = scipy.io.readsav('name_of_file')
于 2012-01-04T10:37:09.877 に答える