Данные массива с плавающей запятой из двоичного файла, используя np.fromfile () - PullRequest
0 голосов
/ 06 февраля 2019

Язык: Python 3.6 / OS: Mac OS High Sierra / Среда: Xcode

У меня есть двоичный файл с различными типами данных.Я прочитал его, используя следующую команду:

fn=open(filePathname,mode='rb')

Я создаю тип данных, как показано ниже:

dt=np.dtype([('a','uint'),('b','uint'),('c','uint'),('d','uint'),('e','uint'),('f','uint'),('g',float),('h',np.float32)])

Я преобразовал из двоичного файла с помощью np.fromfile (), как показано:

numpy_data = np.fromfile(fn, dtype = dt)

Я ожидаю, что у меня будет массив, показывающий «фактические» значения в массиве, но я получаю набор байтов с соответствующими типами в массиве numpy_data.

Вывод

print(numpy_data['h'])

Результат

[ 5.8315540e-39  6.0152250e-39  6.0582729e-39 ... -4.2051079e-07

8.4560821e + 17 3.0060693e-10]

Проблема - Я знаю, что цифры неверны;Я думаю, что это показывает байтовые данные.Если да, то как правильно преобразовать их в «фактическую» стоимость?Я использую lumpy для скорости, и я не предпочитаю метод struct.unpack ().

1 Ответ

0 голосов
/ 07 февраля 2019

Вот пример использования вашего dtype с использованием строки байтов в памяти вместо файла:

In [279]: dt=np.dtype([('a','uint'),('b','uint'),('c','uint'),('d','uint'),('e','uint'),('f','
     ...: uint'),('g',float),('h',np.float32)])
In [280]: 
In [280]: x = np.ones((3,),dt)
In [281]: x
Out[281]: 
array([(1, 1, 1, 1, 1, 1, 1., 1.), (1, 1, 1, 1, 1, 1, 1., 1.),
       (1, 1, 1, 1, 1, 1, 1., 1.)],
      dtype=[('a', '<u8'), ('b', '<u8'), ('c', '<u8'), ('d', '<u8'), ('e', '<u8'), ('f', '<u8'), ('g', '<f8'), ('h', '<f4')])
In [282]: x.tostring()
Out[282]: b'\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0?\x00\x00\x80?\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0?\x00\x00\x80?\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0?\x00\x00\x80?'
In [283]: np.frombuffer(x.tostring(), dtype=dt)
Out[283]: 
array([(1, 1, 1, 1, 1, 1, 1., 1.), (1, 1, 1, 1, 1, 1, 1., 1.),
       (1, 1, 1, 1, 1, 1, 1., 1.)],
      dtype=[('a', '<u8'), ('b', '<u8'), ('c', '<u8'), ('d', '<u8'), ('e', '<u8'), ('f', '<u8'), ('g', '<f8'), ('h', '<f4')])

То, что uint действительно должно быть uint8 - 1-байтовое целое число без знака, а неполная 8-байтовая версия?

In [300]: dt1=np.dtype([('a','uint8'),('b','uint8'),('c','uint8'),('d','uint8'),('e','uint8'),
     ...: ('f','uint8'),('g',float),('h',np.float32)])
In [301]: y = np.ones((10,),dt1)

itemsize для двух массивов совершенно различна:

In [302]: x.itemsize
Out[302]: 60
In [303]: y.itemsize
Out[303]: 18

Но если бы общий размер был правильным, то любой из них мог бы быть прочитан другим (10 * 18 == 3 * 60):

In [304]: np.frombuffer(y.tostring(), dtype=dt1)
Out[304]: 
array([(1, 1, 1, 1, 1, 1, 1., 1.), (1, 1, 1, 1, 1, 1, 1., 1.),
       (1, 1, 1, 1, 1, 1, 1., 1.), (1, 1, 1, 1, 1, 1, 1., 1.),
       (1, 1, 1, 1, 1, 1, 1., 1.), (1, 1, 1, 1, 1, 1, 1., 1.),
       (1, 1, 1, 1, 1, 1, 1., 1.), (1, 1, 1, 1, 1, 1, 1., 1.),
       (1, 1, 1, 1, 1, 1, 1., 1.), (1, 1, 1, 1, 1, 1, 1., 1.)],
      dtype=[('a', 'u1'), ('b', 'u1'), ('c', 'u1'), ('d', 'u1'), ('e', 'u1'), ('f', 'u1'), ('g', '<f8'), ('h', '<f4')])

Несоответствие - это dtypes:

In [305]: np.frombuffer(y.tostring(), dtype=dt)
Out[305]: 
array([(      1103823438081,    70300024700928,   72340172838092672, 4607182418800017408, 72340173886586880,                 257, 7.8598509e-304, 2.3694278e-38),
       (4607182418800017408, 72340173886586880,                 257,   72408888003018736,          16843009, 4575657222481117184, 5.4536124e-312, 0.0000000e+00),
       (  72408888003018736,          16843009, 4575657222481117184,       1103823438081,    70300024700928,   72340172838092672, 1.0000000e+000, 1.0000000e+00)],
      dtype=[('a', '<u8'), ('b', '<u8'), ('c', '<u8'), ('d', '<u8'), ('e', '<u8'), ('f', '<u8'), ('g', '<f8'), ('h', '<f4')])

При несовпадении в dtypes мы можем получить ошибку:

ValueError: buffer size must be a multiple of element size

Все же случайное несоответствие в dtypes может объяснить чтение fromfile, которое запускается, но выдает неправильные значения, особенно те, которые выглядят не так.


На основании вашего комментария я написал:

In [347]: dt1=np.dtype([('a','u4'),('b','u4'),('c','u4'),('d','u4'),('e','u4'),('f','u4'),('g','f4')])

На данный момент я пропускаю h.

Теперь создайте массив с несколькими записями:

In [351]: x=np.ones((3,),dt1); x['g'][0]=10
In [352]: x
Out[352]: 
array([(1, 1, 1, 1, 1, 1, 10.), (1, 1, 1, 1, 1, 1,  1.),
       (1, 1, 1, 1, 1, 1,  1.)],
      dtype=[('a', '<u4'), ('b', '<u4'), ('c', '<u4'), ('d', '<u4'), ('e', '<u4'), ('f', '<u4'), ('g', '<f4')])

Напишите его, а затем загрузите только один счет:

In [353]: np.frombuffer(x.tostring(), count=1,dtype=dt1)
Out[353]: 
array([(1, 1, 1, 1, 1, 1, 10.)],
      dtype=[('a', '<u4'), ('b', '<u4'), ('c', '<u4'), ('d', '<u4'), ('e', '<u4'), ('f', '<u4'), ('g', '<f4')])

Я бы предложил использовать dt1 и использовать его для загрузки только одной записи.Посмотрите, выглядят ли значения разумными.

Я пропустил h, потому что вы описываете его как 'h' is a float array such that it is 4*g bytes long.Если «g» - это число с плавающей запятой, эта длина плохо определена;это должно быть int какого-то рода.

Если вы оставили fn открытым в этот момент, тогда np.fromfile(fn, '<f4', count=n) может работать для загрузки этого массива 'h'.Я бы начал с небольшого n, чтобы посмотреть, является ли это многообещающим, а позже попробуйте большее значение или открытый конец -1.

Другими словами, ваше описание звучит так, как будто файл содержит заголовокфиксированного размера, а затем блок плавающего размера.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...