.. _converters: ******************************** Post-Processing Transformations ******************************** Post-processing transformations are done through the Converters API, exposed through the `~ccsdspy.converters` module. Using Converters, one can create new fields transformed from another field. Examples including applying calibration curves, replacing enumerated values with strings, or converting your own time definition to a `datetime` instance. The following converters are built in, and you can write your own converter by extending the `~ccsdspy.converters.Converter` class (more on this below). When new fields are transformed from other fields, they are created as new entries in the returned dictionary. #. Polynomial Transformation (`~ccsdspy.converters.PolyConverter`) This applies a polynomial function to each value, using user-defined coefficients. #. Linear Transformation (`~ccsdspy.converters.LinearConverter`) This applies a linear transformation (`y = mx + b`) to each value, using a user-defined slope and intercept. #. Enumerated Values Transformation (`~ccsdspy.converters.EnumConverter`) This applies a dictionary replacement of integers to strings. For instance, you can use this to replace `0` with `"DISABLED"`, `1` with `"ENABLED"`, and `2` with `"STANDBY"`. #. Datetime Transformation (`~ccsdspy.converters.DatetimeConverter`) This converts fields to datetime instances, computed using offset(s) from a reference time. The offsets can span multiple fields (for example, one a coarse time, and another for a fine time). If the reference time has a timezone, the result will too. #. Stringify Bytes Transformation (`~ccsdspy.converters.StringifyBytesConverter`) This converts byte arrays or multi-byte numbers to strings in numeric representations such as binary, hexadecimal, or octal. .. contents:: :depth: 2 Using Built-In Transformations ================================ An example of using a built in transformation to parse time, apply a linear transformation to a first field, and apply a enumerated values transformation to a secondary field is below. .. code-block:: python from ccsdspy import FixedLength, converters pkt = FixedLength([ PacketField(name="CoarseTime", data_type="uint", bit_length=24) PacketField(name="FineTime", data_type="uint", bit_length=48) PacketField(name="FirstField", data_type="uint", bit_length=8), PacketField(name="SecondField", data_type="uint", bit_length=8), ]) pkt.add_converted_field( ("CoarseTime", "FineTime"), "Time_Converted", converters.DatetimeConverter( since=datetime(1970, 1, 1), units=("seconds", "nanoseconds"), ) ) pkt.add_converted_field( "FirstField", "FirstField_Converted", converters.LinearConverter(slope=1.2, intercept=0.4) ) pkt.add_converted_field( "SecondField", "SecondField_Converted", converters.EnumConverter({ 0: "DISABLED", 1: "ENABLED", 2: "STANDBY" }) ) result = pkt.load("MyCCSDS.bin") print(result["Time_Converted"]) print(result["FirstField_Converted"]) print(result["SecondField_Converted"]) Creating User-Defined Transformations ===================================== Users can create their own user-defined transformations by extending the `~ccsdspy.converters.Converter` class and overriding the `convert(*field_arrays)` function. This function accepts as many arguments argument as input fields were provided when the converter was added. Below is an example of creating a user-defined transformation to return False if the value is equal to zero, and True if the value is greater than zero. .. code-block:: python from ccsdspy import FixedLength, converters class CustomConverter(converters.Converter): def __init__(self): pass def convert(field_array): return (field_array > 0) pkt = FixedLength([ PacketField(name="MyField", data_type="uint", bit_length=8) ]) pkt.add_converted_field( "MyField", "MyField_Converted", CustomConverter() ) result = pkt.load("MyCCSDS.bin") print(result["MyField_Converted"])