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.
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)
| Parameter | Type | Default | Description |
|---|---|---|---|
fields | list of PacketField or PacketArray | — | Ordered layout of the packet's fields. Must not contain variable-length fields. |
apid | int, optional | None | Application Process Identifier for this packet type. Used as metadata. |
name | str, optional | None | Name of the packet. Used as metadata. |
description | str, optional | None | Description 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.
| Parameter | Type | Default | Description |
|---|---|---|---|
fields | list of PacketField or PacketArray | — | Ordered layout. Do not include the primary header fields and do not set explicit bit offsets. |
apid | int, optional | None | Application Process Identifier. Used as metadata. |
name | str, optional | None | Name of the packet. Used as metadata. |
description | str, optional | None | Description 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 ifother_fieldappears before it in the layout. - Explicit
bit_offsetvalues are not allowed; offsets are computed automatically.
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)
| Parameter | Type | Default | Description |
|---|---|---|---|
file | str or file-like | — | Path to a file on disk, or an open file-like object. |
include_primary_header | bool | False | If True, include the CCSDS primary header fields in the output. |
reset_file_obj | bool | False | If 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 name | Meaning |
|---|---|
CCSDS_VERSION_NUMBER | Packet version number |
CCSDS_PACKET_TYPE | Telemetry (0) or telecommand (1) |
CCSDS_SECONDARY_FLAG | Secondary header presence flag |
CCSDS_SEQUENCE_FLAG | Sequence (grouping) flag |
CCSDS_APID | Application Process Identifier |
CCSDS_SEQUENCE_COUNT | Packet sequence count |
CCSDS_PACKET_LENGTH | Packet data length field |
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)
| Parameter | Type | Default | Description |
|---|---|---|---|
name | str | — | Identifier used as the key for this field in decoded output. |
data_type | str | — | One of 'uint', 'int', 'float', 'str', 'fill'. See Data types. |
bit_length | int | — | Number of bits occupied by the field. |
bit_offset | int, optional | None | Bit offset into the packet, including the 48-bit primary header. If omitted, it is calculated automatically from the field's position. |
byte_order | str | "big" | "big", "little", or an ad-hoc ordering given as a digit string (see Byte order). |
description | str, optional | None | Free-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:
| Parameter | Type | Default | Description |
|---|---|---|---|
array_shape | int, tuple of ints, str, or "expand" | None | Shape 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_order | str | "C" | 'C' for row-major (C-style) order or 'F' for column-major (Fortran-style) order. |
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_type | Meaning |
|---|---|
uint | Unsigned integer |
int | Signed integer |
float | IEEE floating-point value |
str | String |
fill | Placeholder/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)
| Parameter | Type | Default | Description |
|---|---|---|---|
file | str or file-like | — | Path to a file on disk, or an open file-like object. |
include_primary_header | bool | True | If 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.
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')