def _serialize_array_as_le(file: BinaryIO, array: np.ndarray): native_is_le = sys.byteorder == "little" array_bo = array.dtype.byteorder array_is_le = array_bo in "<|" or (array_bo == "=" and native_is_le) if array_is_le: array.tofile(file) else: if array.ndim == 2: for row in array: row.byteswap(inplace=False).tofile(file) else: array.byteswap(inplace=False).tofile(file)
def sanitise_endianness(array: np.ndarray): """ If the data is big endian, swap the byte order to make it little endian. Special thanks to this link: https://stackoverflow.com/questions/60161759/valueerror-big-endian-buffer-not-supported-on-little-endian-compiler :return: A little-endian version of the input array. """ if array.dtype.byteorder == '>': array = array.byteswap().newbyteorder() return array
def byteorder(data: np.ndarray) -> np.ndarray: """ Swaps byteorder of numpy array into system format. :param data: np.ndarray to be converted """ sys_byteorder = ('>', '<')[sys.byteorder == 'little'] if data.dtype.byteorder not in ('=', sys_byteorder): return data.byteswap().newbyteorder(sys_byteorder).astype(np.float) return data
def _extract_field(bodies: np.ndarray, field: Field) -> np.ndarray: """ Args: bodies: A (non-empty) NumPy array containing CAN packet bodies belonging to the same identifier. The `np.ndarray` contains elements of type `np.uint64`. field: The field to extract. Returns: The extracted field values. The `np.ndarray` contains elements of type `np.uint64`. """ # With DBC's "sawtooth" byte ordering and bit indexing behaviour, "little endian" byte order means that # semantically adjacent bits are also using adjacent bit indizes. I.e. the bit that semantically follows # bit 7 (counting from 0) is bit 8. For "bit endian", the indizes do not logically follow the semantic # ordering. For example, the semantically next bit after bit 15 is bit 0 in case of big endian. With # little endian, bits sawtooth into the _next_ byte, while for big endian, they sawtooth into the # _previous_ byte. These jumps make it hard to extract a semantically coherent big endian field, if it # crosses byte borders. The following code solves this problem by swapping the bytes of the CAN packet # body and updating the index of the starting bit of the field to extract. By swapping the bytes, fields # that used to sawtooth into the next byte will now sawtooth into the previous byte and vice versa, thus # big endian fields are then accessible conveniently like little endian fields. if field.endianness is FieldEndianness.BIG: # Swap the bytes to achieve convenient little endian-style access bodies = bodies.byteswap() # Update the anchors accordingly lsb_anchor = (7 - (field.lsb_anchor // 8)) * 8 + field.lsb_anchor % 8 msb_anchor = (7 - (field.msb_anchor // 8)) * 8 + field.msb_anchor % 8 # Update the field, so that the following code for little endian fields can be reused. field = Field(lsb_anchor=lsb_anchor, msb_anchor=msb_anchor, size=field.size, endianness=FieldEndianness.LITTLE, type=field.type) mask = 0xFFFFFFFFFFFFFFFF if field.size == 64 else ((1 << field.size) - 1) return (bodies >> field.lsb_anchor) & mask
def write_wav(handle: IO[bytes], rate: int, data: np.ndarray) -> None: """Write a numpy array of samples as a single uncompressed WAV file. To write multiple-channels, use a 2-D array of shape (Nsamples, Nchannels). The bits-per-sample and PCM/float will be determined by the data-type. :param handle: handle to write the file to :param rate: the sample rate in samples/sec :param data: a 1D or 2D numpy array of either integer or float data-type """ dkind = data.dtype.kind if not (dkind == "i" or dkind == "f" or (dkind == "u" and data.dtype.itemsize == 1)): raise ValueError(f"unsupported data type {data.dtype!r}") header_data = b"RIFF" header_data += b"\x00\x00\x00\x00" header_data += b"WAVE" # fmt chunk header_data += b"fmt " if dkind == "f": format_tag = WAVE_FORMAT_IEEE_FLOAT else: format_tag = WAVE_FORMAT_PCM if data.ndim == 1: channels = 1 else: channels = data.shape[1] bit_depth = data.dtype.itemsize * 8 bytes_per_second = rate * (bit_depth // 8) * channels block_align = channels * (bit_depth // 8) fmt_chunk_data = struct.pack( "<HHIIHH", format_tag, channels, rate, bytes_per_second, block_align, bit_depth, ) if dkind not in "iu": # add cbSize field for non-PCM files fmt_chunk_data += b"\x00\x00" header_data += struct.pack("<I", len(fmt_chunk_data)) header_data += fmt_chunk_data # fact chunk (non-PCM files) if dkind not in "iu": header_data += b"fact" header_data += struct.pack("<II", 4, data.shape[0]) # check data size (needs to be immediately before the data chunk) if ((len(header_data) - 4 - 4) + (4 + 4 + data.nbytes)) > 0xFFFFFFFF: raise ValueError("data exceeds wave file size limit") handle.write(header_data) handle.write(b"data") handle.write(struct.pack("<I", data.nbytes)) if data.dtype.byteorder == ">" or (data.dtype.byteorder == "=" and sys.byteorder == "big"): data = data.byteswap() handle.write(data.ravel().view("b").data) # Determine file size and place it at start of the file. size = handle.tell() handle.seek(4) handle.write(struct.pack("<I", size - 8))
def ensure_native(data: np.ndarray) -> np.ndarray: if data.dtype.byteorder in ('=', sys.byteorder): return data return data.byteswap().newbyteorder()
def _H(self, hashvalues: np.ndarray): return bytes(hashvalues.byteswap().data)