Skip to main content

API reference

This page documents the public API of CCSDSPy, a Python library for reading tightly packed bits in the CCSDS Space Packet Protocol format used by spacecraft telemetry. It covers the two packet classes (FixedLength and VariableLength), the two field types you compose them from (PacketField and PacketArray), the load() decoding method, and the iter_packet_bytes() helper for working with raw packet bytes.

Signatures and parameter descriptions below are taken from the CCSDSPy source and User's Guide. See Sources for the upstream pages.

note

Everything here is part of the top-level ccsdspy namespace, except for the byte-level utilities (such as iter_packet_bytes), which live in ccsdspy.utils.

Packet classes

A "packet class" describes the layout of one packet type and knows how to decode a file containing a stream of those packets. You build one by passing an ordered list of PacketField and PacketArray objects.

FixedLength

Use FixedLength for packets that have the same length and layout every time — for example, housekeeping or status messages. It is the faster of the two classes.

class ccsdspy.FixedLength(fields, apid=None, name=None, description=None)
ParameterTypeDefaultDescription
fieldslist of PacketField or PacketArrayOrdered layout of the packet's fields. Must not contain variable-length fields.
apidint, optionalNoneApplication Process Identifier for this packet type. Used as metadata.
namestr, optionalNoneName of the packet. Used as metadata.
descriptionstr, optionalNoneDescription of the packet. Used as metadata.

Passing a field whose array_shape is a string (i.e. a variable-length field) raises ValueError; use VariableLength for those packets.

VariableLength

Use VariableLength when packets differ in length from one to the next. A variable-length field is a PacketArray whose array_shape is either "expand" (the field grows to fill the rest of the packet) or the name of an earlier field (which sets the element count).

class ccsdspy.VariableLength(fields, apid=None, name=None, description=None)

The constructor parameters are identical to FixedLength.

ParameterTypeDefaultDescription
fieldslist of PacketField or PacketArrayOrdered layout. Do not include the primary header fields and do not set explicit bit offsets.
apidint, optionalNoneApplication Process Identifier. Used as metadata.
namestr, optionalNoneName of the packet. Used as metadata.
descriptionstr, optionalNoneDescription of the packet. Used as metadata.

The constructor enforces several rules and raises ValueError if any are broken:

  • At most one field may use array_shape="expand".
  • A field sized by another field (array_shape="other_field") is only valid if other_field appears before it in the layout.
  • Explicit bit_offset values are not allowed; offsets are computed automatically.
tip

VariableLength can also parse fixed-length packets, but it is considerably slower. When every packet has the same layout, prefer FixedLength.

The load() method

Both packet classes expose the same load() method, which decodes a file (or file-like object) containing a sequence of these packets into NumPy arrays.

packet.load(file, include_primary_header=False, reset_file_obj=False)
ParameterTypeDefaultDescription
filestr or file-likePath to a file on disk, or an open file-like object.
include_primary_headerboolFalseIf True, include the CCSDS primary header fields in the output.
reset_file_objboolFalseIf True, restore the file object's stream position to where it was before load() was called. Ignored when file is a path string.

Returns — a dict mapping each field name (string) to a NumPy array. The key order matches the order of the fields in the packet definition. Each array has one entry per decoded packet (arrays add a leading packet axis).

When include_primary_header=True, seven extra keys are added for the CCSDS primary header:

Field nameMeaning
CCSDS_VERSION_NUMBERPacket version number
CCSDS_PACKET_TYPETelemetry (0) or telecommand (1)
CCSDS_SECONDARY_FLAGSecondary header presence flag
CCSDS_SEQUENCE_FLAGSequence (grouping) flag
CCSDS_APIDApplication Process Identifier
CCSDS_SEQUENCE_COUNTPacket sequence count
CCSDS_PACKET_LENGTHPacket data length field
info

load() issues a UserWarning (rather than raising) when it detects problems in the primary header — sequence counts out of order, missing sequence numbers, or more than one distinct APID in the file.

Field types

Packet layouts are built from two field classes. PacketArray is a subclass of PacketField, so it accepts all of PacketField's parameters plus two of its own.

PacketField

A single scalar field in a packet.

class ccsdspy.PacketField(name, data_type, bit_length, bit_offset=None,
byte_order="big", description=None)
ParameterTypeDefaultDescription
namestrIdentifier used as the key for this field in decoded output.
data_typestrOne of 'uint', 'int', 'float', 'str', 'fill'. See Data types.
bit_lengthintNumber of bits occupied by the field.
bit_offsetint, optionalNoneBit offset into the packet, including the 48-bit primary header. If omitted, it is calculated automatically from the field's position.
byte_orderstr"big""big", "little", or an ad-hoc ordering given as a digit string (see Byte order).
descriptionstr, optionalNoneFree-text description, used as metadata.

Invalid arguments raise TypeError (wrong type) or ValueError (unrecognized data_type or byte_order).

PacketArray

Represents multiple elements of the same size and type — for example, a sensor grid or an image row. It behaves like PacketField but decodes into a multi-dimensional array.

class ccsdspy.PacketArray(*args, array_shape=None, array_order="C", **kwargs)

In addition to the inherited PacketField parameters (name, data_type, bit_length, bit_offset, byte_order, description), PacketArray adds:

ParameterTypeDefaultDescription
array_shapeint, tuple of ints, str, or "expand"NoneShape of the array. A single int is treated as a 1-D shape. Pass another field's name to size the array from that field, or "expand" to grow to fill the packet.
array_orderstr"C"'C' for row-major (C-style) order or 'F' for column-major (Fortran-style) order.
note

String values of array_shape (a field name or "expand") are only valid inside a VariableLength packet, and such arrays must use data_type='uint' — CCSDSPy raises ValueError otherwise.

Data types

The data_type accepted by both field classes:

data_typeMeaning
uintUnsigned integer
intSigned integer
floatIEEE floating-point value
strString
fillPlaceholder/spacer bits, used to fill space between other fields

Byte order

byte_order applies to integer data types:

  • "big" — big endian (default); most significant byte at the lowest address.
  • "little" — little endian; least significant byte at the lowest address.
  • A digit string such as "4321" or "2341" — an ad-hoc byte ordering, useful for non-standard packing.

The iter_packet_bytes() helper

ccsdspy.utils.iter_packet_bytes() walks a file and yields the raw bytes of each packet, in file order. It works on mixed files that contain multiple APIDs and a mix of fixed- and variable-length packets, because it reads each packet's length from its primary header rather than from a packet definition.

ccsdspy.utils.iter_packet_bytes(file, include_primary_header=True)
ParameterTypeDefaultDescription
filestr or file-likePath to a file on disk, or an open file-like object.
include_primary_headerboolTrueIf False, the first six (primary header) bytes are excluded from each yielded object.

Yields — a bytes object for each packet. If the end of the last packet does not align with the end of the file, a UserWarning is issued for the likely truncation or trailing garbage.

tip

Related helpers in ccsdspy.utils build on the same byte-walking logic: split_packet_bytes() returns the same content as a list, count_packets() counts packets without decoding them, read_primary_headers() returns just the header fields, and split_by_apid() separates a mixed stream into one BytesIO per APID.

Putting it together

The following illustrative example defines a fixed-length packet with scalar fields and a 2-D array, then decodes a binary file.

import ccsdspy
from ccsdspy import PacketField, PacketArray

pkt = ccsdspy.FixedLength([
PacketField(name='SHCOARSE', data_type='uint', bit_length=32),
PacketField(name='SHFINE', data_type='uint', bit_length=20),
PacketField(name='OPMODE', data_type='uint', bit_length=3),
PacketField(name='SPACER', data_type='fill', bit_length=1),
PacketField(name='VOLTAGE', data_type='int', bit_length=8),
PacketArray(
name='SENSOR_GRID',
data_type='uint',
bit_length=16,
array_shape=(32, 32),
array_order='C',
),
])

result = pkt.load('mypackets.bin')
# result['SHCOARSE'] -> NumPy array, one value per packet
# result['SENSOR_GRID'] -> NumPy array of shape (num_packets, 32, 32)

A variable-length packet uses a PacketArray with array_shape="expand" (this illustrative snippet shows only the variable field):

import ccsdspy
from ccsdspy import PacketArray

pkt = ccsdspy.VariableLength([
PacketArray(name='DATA', data_type='uint', bit_length=8, array_shape='expand'),
])

result = pkt.load('variable_packets.bin')

Sources