2017-10-20 6 views
3

Iは、データがそうように16ビットの整数ブロックに編成されたバイナリファイルを有する:読み出しバイナリデータ

  • ビット15:デジタルビットを1
  • ビット14:デジタルビット2
  • ビット13から0:14ビット符号付き整数

I 3つのアレイにファイルからデータを抽出する方法が見出さ唯一の方法である:

data = np.fromfile("test1.bin", dtype=np.uint16) 

digbit1 = data >= 2**15 

data = np.array([x - 2**15 if x >= 2**15 else x for x in data], dtype=np.uint16) 

digbit2 = data >= 2**14 

data = np.array([x-2**14 if x >= 2**14 else x for x in data]) 

data = np.array([x-2**14 if x >= 2**13 else x for x in data], dtype=np.int16) 

元のデータよりもforループで同じことをして3つの別々の配列に書き込むことができることは分かっていますが、これはまだ醜いでしょう。私が知りたいのはdtype=[('db', [('1', bit), ('2', bit)]), ('temp', 14bit-signed-int)])のスタイルでこれをより効率的に行う方法です。data['db']['1'] = array of ones and zerosのように簡単にアクセスできます。

+0

「pack」について聞いたことがあります。私はnumpyがバイナリファイルと関係があるかどうか実際には分かりません。 –

+0

もっと援助方法であなたのコメントを表現できますか?バイナリファイル自体とはあまり関係がないかもしれませんが、そこには本当に便利なコンテンツがあります。私の場合は少なくとも。 – TheoryX

答えて

2

Numpyはコンパイルされた速度でループを実行するので、コードよりも効率的です。これはPythonループよりもはるかに高速です。そして、私たちはそれらのifテストの代わりにビット単位の算術を使うことができます。

あなたはサンプルデータを提供していないので、いくつかの偽のデータを作成するためのPython 3のコードを書きました。私はそのデータを大きなファイル-形式で保存しますが、実際にデータがリトルエンディアンで保存されている場合は、変更するのは簡単です。そのデータを読むにはnumpy.fromfileを使用しません。それは、プレーンなPythonでファイルを読み込んでから、numpy.frombufferを使って読み込みバイトを変換するほうが速いからです。

厄介な部分は、これらの14ビット符号付き整数を扱うことだけです。私はあなたがtwo's complement表現を使用していると仮定します。

import numpy as np 

# Make some fake data 
bdata = [] 
bitlen = 14 
mask = (1 << bitlen) - 1 
for i in range(12): 
    # Two initial bits 
    a = i % 4 
    # A signed number 
    b = i - 6 
    # Combine initial bits with the signed number, 
    # using 14 bit two's complement. 
    n = (a << bitlen) | (b & mask) 
    # Convert to bytes, using 16 bit big-endian 
    nbytes = n.to_bytes(2, 'big') 
    bdata.append(nbytes) 
    print('{} {:2} {:016b} {} {:>5}'.format(a, b, n, nbytes.hex(), n)) 
print() 

# Save the data to a file 
fname = 'test1.bin' 
with open(fname, 'wb') as f: 
    f.write(b''.join(bdata)) 

# And read it back in 
with open(fname, 'rb') as f: 
    data = np.frombuffer(f.read(), dtype='>u2') 

print(data) 

# Get the leading bits 
digbit1 = data >> 15 
print(digbit1) 

# Get the second bits 
digbit2 = (data >> 14) & 1 
print(digbit2) 

# Get the 14 bit signed integers 
data = ((data & mask) << 2).astype(np.int16) >> 2 
print(data) 

出力

0 -6 0011111111111010 3ffa 16378 
1 -5 0111111111111011 7ffb 32763 
2 -4 1011111111111100 bffc 49148 
3 -3 1111111111111101 fffd 65533 
0 -2 0011111111111110 3ffe 16382 
1 -1 0111111111111111 7fff 32767 
2 0 1000000000000000 8000 32768 
3 1 1100000000000001 c001 49153 
0 2 0000000000000010 0002  2 
1 3 0100000000000011 4003 16387 
2 4 1000000000000100 8004 32772 
3 5 1100000000000101 c005 49157 

[16378 32763 49148 65533 16382 32767 32768 49153  2 16387 32772 49157] 
[0 0 1 1 0 0 1 1 0 0 1 1] 
[0 1 0 1 0 1 0 1 0 1 0 1] 
[-6 -5 -4 -3 -2 -1 0 1 2 3 4 5] 

あなただけnp.frombuffer呼び出しで'<u2'にDTYPEを変更、リトルエンディアンバイト順を使用する必要がある場合。それをテストするには、偽データ作成セクションのn.to_bytesコールで 'big'を 'little'に変更します。

+0

本当に素晴らしい答えをありがとう。それはまさに私が望んでいたものです。 numpyのドキュメントによると、 'fromfile'関数はdtypeをサポートしています。あなたのサンプルと私のデータはどちらも動作します。 「frombuffer」でtime-wiseの 'open'は' fromfile'より約25%高速です。 – TheoryX

+0

@ TheoryXいいえ心配しない。私は 'fromfile'文書の_Notes_セクションを誤解しました。私はすぐに私の答えを調整します。 –

関連する問題