0

Numpy provides packbits function to convert from values to individual bits. With bitorder='little' I can read them in C as uint8_t values without issues. However, I would like to read them as uint32_t values. This means that I have to reverse the order of each 4 bytes. I tried to use

import numpy as np

array = np.array([1,0,1,1,0,1,0,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,1,1,0,0,1,0,1,0,1, 
   1,0,0,1,1,0,1,0,1,1,0,0,1,1,1,0,0,1])
array = np.packbits(array, bitorder='little')
array.dtype = np.uint32
array.byteswap(inplace=True)

print(array)

but have the following error:

Traceback (most recent call last):
  File "sample.py", line 5, in <module>
    array.dtype = np.uint32
ValueError: When changing to a larger dtype, its size must be a divisor of the total size in bytes of the last axis of the array.

I have 50 bits in the input. The first chunk of 32 bits written in the little-endian format (earliest input bit is the least significant bit) are 0b10101001101011001101001010101101 = 2846675629, the second is 0b100111001101011001 = 160601. So the expected output is

[2846675629 160601]
Gulzar
  • 23,452
  • 27
  • 113
  • 201
Curious
  • 507
  • 3
  • 16
  • Please, provide a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example), – Suthiro May 09 '21 at 10:43
  • 2
    @Curious In the future, please provide *full* error stack trace, not just the bottom line. It will help people help you much faster, and will greatly reduce the chance of your questions getting closed. Also include expected output. – Gulzar May 09 '21 at 10:54
  • What is the output you *expect*? – juanpa.arrivillaga May 09 '21 at 11:11
  • Also note that from the `packbits` doc: "Array of type uint8 whose elements represent bits corresponding to the logical (0 or nonzero) value of the input elements. The shape of packed has the same number of dimensions as the input (unless axis is None, in which case the output is 1-D)." - Returns a uint8. – Gulzar May 09 '21 at 11:13

2 Answers2

0

My first answer fixes the exception.

This answer, relies on this and this

  • Pad the array from the right to the nearest power of 2
  • Reshape to have some arrays, each array of size 32
  • Pack bits PER ARRAY and only then view as unit32.
import numpy as np
import math


# https://stackoverflow.com/questions/49791312/numpy-packbits-pack-to-uint16-array
# https://stackoverflow.com/questions/36534035/pad-0s-of-numpy-array-to-nearest-power-of-two/36534077


def next_power_of_2(number):
    # Returns next power of two following 'number'
    return 2**math.ceil(math.log(number, 2))


a = np.array([
    1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1,
    1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1
])

# a = np.array([
#     0 for _ in range(31)
# ] + [1])
padding_size = next_power_of_2(len(a)) - len(a)
b = np.concatenate([a, np.zeros(padding_size)])
c = b.reshape((-1, 32)).astype(np.uint8)
d = np.packbits(c, bitorder='little').view(np.uint32)

print(d)

output:

[2846675629 160601]

Gulzar
  • 23,452
  • 27
  • 113
  • 201
-1

You can't use array.dtype = np.uint32 as you did, because numpy arrays have to be consecutive in memory.

Instead, you can create a new array of the new type.

import numpy as np

array = np.array([1,0,1,1,0,1,0,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,1,1,0,0,1,0,1,0,1,1,0,0,1,1,0,1,0,1,1,0,0,1,1,1,0,0,1])
array = np.packbits(array, bitorder='little')
array = np.array(array, dtype=np.uint32)
array.byteswap(inplace=True)

print(array)
Gulzar
  • 23,452
  • 27
  • 113
  • 201
  • 1
    I expect the output array to contain only 2 values (64 bits total) since I have 50 input bits. However, your code produces 7 values: `[2902458368 3523215360 2885681152 2835349504 1493172224 1929379840 33554432]` – Curious May 09 '21 at 10:55
  • Please edit your question. It is not reproducible as it is now. – Gulzar May 09 '21 at 10:59
  • What exactly is not reproducible? I didn't get that. Do you mean the original question (I can run it with `python sample.py` with installed numpy) or my previous comment on your answer? – Curious May 09 '21 at 11:02
  • By [mre] I mean: 1. Exact expected output 2. full error trace 3. MINIMAL - can you reprocude this on something much simpler to understand than 50 bits? – Gulzar May 09 '21 at 11:06
  • I added expected output in the question – Curious May 09 '21 at 11:29