-
Notifications
You must be signed in to change notification settings - Fork 352
Description
On line 477 the original data is unpacked and shifted to the left 2 bits
data = data.astype(np.uint16) << 2
That's fine, as you're shifting everything to facilitate easier unpacking in the following lines
for byte in range(4):
data[:, byte::5] |= ((data[:, 4::5] >> (byte * 2)) & 3)
Which essentially says "every byte is made by the combination of the original byte shifted to the left 2 (from before), with the 5th byte's lowest 2 bits added on".
However, all the bytes were shifted by two, from above, so the 5th byte also contains shifted byte data. Taking for example byte = 0, so we're looking at the first byte, this essentially says "the 0th byte is the combination of itself shifted to the left, and the lowest two bits of the 4th (zero-indexed) byte, which is currently 0 because of the previous shift operation."
Should the code not instead be
for byte in range(4):
data[:, byte::5] |= ((data[:, 4::5] >> ((byte + 1) * 2)) & 3)
To make it even clearer, if we had this data representing the first byte and the 5th byte of some set
0000 0001 <- 1st byte
0000 0011 <- 5th byte
The shift by two results in 16 bit data looking like
0000 0000 0000 0100 <- 1st byte
0000 0000 0000 1100 <- 5th byte
On the first iteration of the loop, byte is 0, so the line reads
data[:, 0::5] |= ((data[:, 4::5] >> (0 * 2)) & 3)
Or simplified
data[:, 0::5] |= ((data[:, 4::5) & 3) <- no shift of the 5th byte.
The bitwise AND with 3 on the 5th byte looks like
0000 0000 0000 1100 <- 5th byte
0000 0000 0000 0011 <- 3
======
0000 0000 0000 0000 <- result
When it should look lke
0000 0000 0000 0011 <- 5th byte
0000 0000 0000 0011 <- 3
======
0000 0000 0000 0011 <- result
Hopefully that makes sense. Let me know if I missed something.
Followup:
Tested against the output looking at the lowest bits to confirm:
for byte in range(4):
print(byte, np.unique(data[byte::4, byte::4] & 3))
> 0 [0]
1 [0 1 2 3]
2 [0 1 2 3]
3 [0 1 2 3]
Every fourth byte ends in 00.