hatmatrix
hatmatrix

Reputation: 44972

Converting 16-bit integer to 32-bit floating-point

I am trying to port a portion of a code written in a different language (an obscure one called Igor Pro by Wavemetrics for those of you have heard of it) to Python.

In this code, there is a conversion of a data type from a 16-bit integer (read in from a 16-bit, big endian binary file) to single-precision (32-bit) floating-point. In this program, the conversion is as follows:

Signed 16-bit integer:

print tmp
tmp[0]={-24160,18597,-24160,18597,-24160}

converted to 32-bit floating-point:

Redimension/S/E=1 tmp
print tmp
tmp[0]={339213,339213,5.79801e-41,0,0}

The /S flag/option indicates that the data type of tmp should be float32 instead of int16. However, I believe the important flag/option is /E=1, which is said to "Force reshape without converting or moving data."

In Python, the conversion is as follows:

>>> tmp[:5]
array([-24160,  18597, -24160,  18597, -24160], dtype=int16)

>>> tmp.astype('float32')
array([-24160.,  18597., -24160., ...,  18597., -24160.,  18597.], dtype=float32)

Which is what I expect, but I need to find a function/operation that emulates the /E=1 option in the original code above. Is there an obvious way in which -24160 and 18597 would both be converted to 339213? Does this have anything to do with byteswap or newbyteorder or something else?

Upvotes: 4

Views: 11903

Answers (3)

unutbu
unutbu

Reputation: 880717

Use view instead of astype:

In [9]: tmp=np.array([-24160,  18597, -24160,  18597, -24160, 18597], dtype=int16)

In [10]: tmp.view('float32')
Out[10]: array([ 339213.,  339213.,  339213.], dtype=float32)
  1. .astype creates a copy of the array cast to the new dtype
  2. .view returns a view of the array (with the same underlying data), with the data interpreted according to the new dtype.

Upvotes: 2

hmakholm left over Monica
hmakholm left over Monica

Reputation: 23342

Is there an obvious way in which -24160 and 18597 would both be converted to 339213?

No, but neither is there any obvious way in which -24160 would convert to 339213 and 5.79801e-41 and 0.

It looks more like the conversion takes two input numbers to create one output (probably by concatenating the raw 2×16 bits to 32 bits and calling the result a float). In that case the pair -24160,18597 consistently becomes 339213, and 5.79801e-41 probably results from -24160,0 where the 0 is invented because we run out of inputs. Since 5.79801e-41 looks like it might be a single-precision denormal, this implies that the two 16-bit blocks are probably concatenated in little-endian order.

It remains to see whether you need to byte-swap each of the 16-bit inputs, but you can check that for yourself.

Upvotes: 1

Winston Ewert
Winston Ewert

Reputation: 45059

import numpy
tmp=numpy.array([-24160,18597,-24160,18597,-24160, 0], numpy.int16)
tmp.dtype = numpy.float32
print tmp

Result:

[  3.39213000e+05   3.39213000e+05   5.79801253e-41]

I had to add a zero to the list of value because there are an odd number of values. It cannot interpret those as 32 bit floats since there 5 16 bit values.

Upvotes: 6

Related Questions