Skip to main content

Introduction

CCSDSPy is a small, focused Python library for reading binary telemetry encoded in the Consultative Committee for Space Data Systems (CCSDS) Space Packet Protocol format. Spacecraft pack telemetry into tightly packed bits to minimize downlink bandwidth, which often produces fields that are not byte-aligned, are odd-length, or are otherwise awkward to decode with general-purpose tools. CCSDSPy lets you declare the layout of a packet once and then decode a file of those packets into NumPy arrays.

It is an I/O interface and set of utilities for CCSDS binary spacecraft data, and it is used in flight missions at NASA, NOAA, and SwRI.

note

CCSDS is a binary, bit-level format used by many NASA and ESA missions. Because fields can cross byte boundaries and have arbitrary bit lengths, you generally cannot decode a packet with a single struct.unpack call. CCSDSPy handles the bit-level unpacking for you.

What CCSDSPy does

  • Reads CCSDS telemetry / Space Packet Protocol packets from a binary file or stream.
  • Supports both fixed-length and variable-length packets.
  • Decodes each declared field, including fields that are not byte-aligned or have odd bit lengths, into a dictionary of NumPy arrays (one array per field, with one entry per packet).
  • Handles multi-dimensional fields such as sensor grids via array fields.

Missions using CCSDSPy

The project's documentation lists the following real missions among its users. This list is reproduced from the project README and may grow over time.

MissionAgency / Organization
GOES-RNASA
Europa ClipperNASA
MMS (Magnetospheric Multiscale)NASA
PACENASA
HERMESNASA
CSA missionCanadian Space Agency
PUNCHSwRI
SPHERExNASA / JPL
ELFINUCLA
PADREUC Berkeley
info

For Europa Clipper, NASA's open-source pyDownlinkParser parses science downlinks and relies heavily on CCSDSPy. Always check the CCSDSPy README for the current, authoritative mission list.

How it works

The decoding pipeline is straightforward: you start with a raw byte stream, hand it to a FixedLength or VariableLength packet definition, and receive back one NumPy array per declared field.

Packet types

CCSDSPy mirrors the two packet shapes defined by the CCSDS standard:

ClassUse it when
ccsdspy.FixedLengthEvery packet in the stream has the same byte length and field layout.
ccsdspy.VariableLengthPacket length varies between packets (for example, a field whose size is expanded to fill the remaining bytes, or an array sized by another field).

Fields are declared with two building blocks:

  • PacketField — a single scalar field, defined by name, data_type (such as 'uint', 'int', or 'fill'), and bit_length.
  • PacketArray — a multi-element field. In addition to name, data_type, and bit_length, it accepts array_shape (the dimensions) and array_order (the memory layout).

Installation

pip install ccsdspy

A first example

The snippet below is an illustrative example showing the typical shape of CCSDSPy code. Replace the field definitions and file name with the real layout for your mission.

import ccsdspy
from ccsdspy import PacketField, PacketArray

# Declare the packet layout once.
pkt = ccsdspy.FixedLength([
PacketField(name='SHCOARSE', data_type='uint', bit_length=32),
PacketField(name='VOLTAGE', data_type='int', bit_length=8),
PacketArray(
name='SENSOR_GRID',
data_type='uint',
bit_length=16,
array_shape=(32, 32),
),
])

# Decode every packet in the file.
result = pkt.load('MyCCSDS.tlm')

# `result` is a dict mapping field name -> numpy array (one entry per packet).
print(result['SHCOARSE']) # 1-D array of timestamps
print(result['SENSOR_GRID']) # array of 32x32 sensor grids

The .load() method returns a dictionary keyed by field name; each value is a NumPy array with one entry per packet decoded from the file.

tip

Start with a FixedLength definition whenever your packets share a single layout — it is simpler and faster. Reach for VariableLength only when a field's size genuinely changes from packet to packet.

Sources