Source code for pylab_ml.common.data

"""
This script contains functions for data manipulation and processing, such as converting between signed and unsigned data, calculating CRC checksums, and parsing strings to numeric values. 
These functions are commonly used in data processing tasks, especially when dealing with binary data or communication protocols.
"""
import time
import numpy as np
import datetime as dt


[docs] def unsigned_data(f): """ Convert to 16-bit unsigned_data. eg. unsigned_data(-1) -> 65535 unsigned_data(-33) -> 65503 unsigned_data(50) -> 50 Parameters ---------- f : 16-bit value Returns ------- int unsigned 16-bit value """ if f < 0.0: f += 65536.0 return int(f)
[docs] def signed_data(f, bitwidth=16): """ Convert to signed_data. eg. signed_data(65535) -> -1 signed_data(65503) -> -33 signed_data(50) -> 50 Parameters ---------- f : int default 16-bit value or define bitwidth bitwidth : int bit width Returns ------- int signed value """ if f > (1 << bitwidth-1)-1: f -= (1 << bitwidth) return int(f)
[docs] def byte2word(list8): """ Return a list with 16-bit data from a imput list with 8-bit data. eg. byte2word([0x01, 0x02, 0x03, 0x04]) -> [0x0201, 0x0403] Parameters ---------- list8 : list of 8-bit values Returns ------- list16 : list of 16-bit values """ list16 = [] for index in range(0, len(list8), 2): list16.append(list8[index] + (list8[index+1] << 8)) return list16
[docs] def byte2uint(list8): """ Return a list with 32-bit data from a imput list with 8-bit data. eg. byte2uint([0x01, 0x02, 0x03, 0x04]) -> [0x04030201] byte2uint([0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]) -> [0x04030201, 0x08070605] Parameters ---------- list8 : list of 8-bit values Returns ------- list32 : list of 32-bit values """ list32 = [] for index in range(0, len(list8), 4): list32.append(list8[index] + (list8[index+1] << 8) + (list8[index+2] << 16) + (list8[index+3] << 24)) return list32
[docs] def complement(value, bits): """ Binary complement from a positive value with number of bits. eg. complement(0, 8) -> 255 complement(1, 8) -> 254 complement(255, 8) -> 0 complement(1, 16) -> 65534 Parameters ---------- value : int Positive integer value to be complemented. bits : int Number of bits for the complement. Returns ------- int Complemented value. """ if value < 0: raise ValueError(f"complement value must be an positive integer, not {value}") formatstring = '{:0%ib}' % bits bvalue = formatstring.format(value) return int(''.join({'0': '1', '1': '0'}[x] for x in bvalue), 2)
[docs] def complement2(value, bits): """ 2's complement representation from a value with number of bits. eg. complement2(0, 8) -> 0 complement2(1, 8) -> 1 complement2(-1, 8) -> 255 complement2(33, 16) -> 223 Parameters ---------- value : int Integer value to be converted to 2's complement. bits : int Number of bits for the 2's complement representation. Returns ------- int 2's complement representation of the value. """ if value >= 2**(bits-1): raise ValueError(f"complement2 value must be < {2**(bits-1)}") result = value if value >=0 else complement(-value, bits)+1 return result & (2**bits -1)
[docs] def crc4(data): # width """ Calculate 4-bit crc from a data with width bits. polynomial = X4+X+1 eg. crc4(0b1011) -> 0b1110 crc4(0b1101) -> 0b0110 crc4(0b1111) -> 0b0000 Parameters ---------- data : int Input data for which the CRC is to be calculated. The data should be a non-negative integer. Returns ------- int The calculated 4-bit CRC value as an integer. """ data = f'{data:0b}' crcdat = 0 for bit in data: doinvert = int(bit) ^ ((crcdat & 8) >> 3) # DoInvert = ('1'==BitString[i]) ^ CRC[3]; crc = (crcdat << 1) & 0xc # CRC[3] = CRC[2]; CRC[2] = CRC[1]; crc |= ((crcdat & 1) ^ doinvert) << 1 # CRC[1] = CRC[0] ^ DoInvert; crc |= doinvert # CRC[0] = DoInvert; crcdat = crc return crc
[docs] def crc16(word_array): """ Calculate CRC-16 on array. eg. crc16([0x0201, 0x0403]) -> 0x29B1 crc16([0x1234, 0x5678]) -> 0xE5CC crc16([0xABCD, 0xEF01]) -> 0xD64E Parameters ---------- word_array : list of int Array of 16-bit words for which the CRC is to be calculated. Returns ------- crc : int 16-bit CRC value. """ crctable = [0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0] crc = 0xFFFF for currWord in word_array: for j in range(2): if j == 0: currByte = (np.uint8)(currWord & 0x00FF) else: currByte = (np.uint8)((currWord >> 8) & 0x00FF) crc = (np.uint16)((crc << 8) & 0xFFFF) ^ crctable[((crc >> 8) ^ currByte) & 0x00FF] crc_low = (np.uint8)(crc >> 8) crc_high = (np.uint8)(crc) crc_swap = crc_low | (np.uint16(crc_high) << 8) return crc_swap
[docs] def j1850_crc(buffer, length=None): """J1850 CRC-Calculation. eg. j1850_crc([0x01, 0x02, 0x03, 0x04]) -> 0x1D j1850_crc([0xAB, 0xCD, 0xEF]) -> 0x4B j1850_crc([0x00, 0xFF, 0x55]) -> 0xA2 Parameters ---------- buffer : list of int Input data for which the J1850 CRC is to be calculated. The data should be a list of integers representing bytes (0-255). length : int, optional Number of bytes to consider from the buffer for CRC calculation. If None, the entire buffer will be used. Default is None. Returns ------- int The calculated J1850 CRC value as an integer. """ length = len(buffer) if length is None else length crc_reg = 0xff for byte_count in range(0, length): bit_point = 0x80 for bit_count in range(0, 8): if bit_point & buffer[byte_count]: # case for new bit = 1 poly = 1 if crc_reg & 0x80 else 0x1c # define the polynomial crc_reg = ((crc_reg << 1) & 0xff | 1) ^ poly else: # case for new bit = 0 poly = 0x1d if crc_reg & 0x80 else 0 crc_reg = ((crc_reg << 1) & 0xff) ^ poly bit_point >>= 1 return complement(crc_reg, 8) # Return CRC
[docs] def Parity(data, even=True): """ Return the parity-bit from the data. eg. Parity(0b1011, even=True) -> 1 Parity(0b1011, even=False) -> 0 Parity(0b1101, even=True) -> 0 Parameters ---------- data : int Input data for which the parity bit is to be calculated. The data should be a non negative integer. even : bool, optional If True, calculate even parity; if False, calculate odd parity. Default is True. Returns ------- int Parity bit (0 or 1) based on the input data and parity type (even or odd). """ data = bin(data) parity = 1 if even else 0 for i in range(0, len(data)): parity += 1 if data[i] == '1' else 0 return parity % 2
[docs] def datetime(typ=None): """ Return the acual time as a string (year, month, day, _, hour, min, sec). eg. datetime() -> '20240615_123456' datetime(typ="str") -> '2024/06/15 12:34:56' Parameters ---------- typ : str, optional If None, return the datetime in the format 'YYYYMMDD_HHMMSS'. Returns ------- str The current date and time as a string in the specified format. """ if typ is None: date = time.localtime(time.time()) return f'{date.tm_year:04d}{date.tm_mon:02d}{date.tm_mday:02d}_{date.tm_hour:02d}{date.tm_min:02d}{date.tm_sec:02d}' elif typ == "str""": return dt.datetime.now().strftime("%Y/%m/%d %H:%M:%S")
[docs] def str2num(value, base=10, default=""): """ Translate str to numeric value. eg. str2num("0x1A") -> 26 str2num("0b1010") -> 10 str2num("") -> default value (empty string) str2num("3.14") -> 3.14 str2num("Hello") -> "Hello" Parameters ---------- value : str The string to be converted to a numeric value. The function will attempt to parse the string as an integer or a float, and will return the original string if it cannot be parsed as a number. base : int, optional The base to use for parsing integers. Default is 10. If the string starts with "0x" or "0b", the base will be automatically set to 16 or 2, respectively. default : any, optional The default value to return if the input string is empty or None. Default is an empty string. Returns ------- int, float, or str The parsed numeric value if the string can be converted to an integer or a float, or the original string if it cannot be parsed as a number. If the input string is empty or None, the specified default value will be returned. """ # if type(value) in [bool, int, float, np.int32, np.float64]: if type(value) is not str: return value value = value.strip() if value == "" or value is None: value = default return if value.find("0x") == 0: base = 16 elif value.find("0b") == 0: base = 2 try: return int(value, base) except ValueError: try: return float(value) except ValueError: return value