Rebuilding trajectories
The Rebuild class provides functionality for reconstructing aircraft trajectories from raw ADS-B and Mode S messages.
When to use the rebuild functionality
There are two main use cases for the Rebuild class:
Merge different data sources to rebuild a state vector table: Combine position, velocity, identification, and rollcall data that are stored in separate database tables into a single trajectory dataframe.
Redecode raw messages: Apply custom decoding logic to raw messages for more precise position calculations, BDS register extraction, or custom validation.
Rebuilding without custom decoding
If you only need to merge data from different sources and trust the database-decoded values, use the rebuild() method without specifying a decoder:
from pyopensky.trino import Trino
from pyopensky.rebuild import Rebuild
trino = Trino()
rebuild = Rebuild(trino)
# Fetch and merge position, velocity, identification data
df = rebuild.rebuild(
start="2023-01-03 16:00",
stop="2023-01-03 20:00",
icao24="400A0E"
)
This returns a dataframe with columns from all three sources merged on icao24 and mintime with a 5-second tolerance.
Rebuilding with custom decoding
When you need more control over position decoding or want to extract additional data from raw messages, specify a decoder:
from pyopensky.trino import Trino
from pyopensky.rebuild import Rebuild
trino = Trino()
rebuild = Rebuild(trino)
# Redecode position data with PyModesDecoder
df = rebuild.rebuild(
start="2023-01-03 16:00",
stop="2023-01-03 20:00",
icao24="400A0E",
decoder="pymodes" # Use string-based decoder selection
)
The decoder will process the raw messages and apply custom logic for CPR position decoding, validation, and filtering.
Available decoders
PyModes decoder
The PyModesDecoder uses the pyModeS library for decoding.
Features:
CPR position decoding with odd/even frame pairing
Reference position validation to filter outliers
BDS register decoding (BDS 4,0, BDS 5,0, BDS 6,0)
Pure Python implementation
Installation:
pip install 'pyopensky[pymodes]'
Usage:
from pyopensky.decoders import PyModesDecoder
from pyopensky.rebuild import Rebuild
from pyopensky.trino import Trino
trino = Trino()
rebuild = Rebuild(trino)
# Using string-based selection
df = rebuild.redecode_position(
start="2023-01-03 16:00",
stop="2023-01-03 20:00",
icao24="400A0E",
decoder="pymodes"
)
# Or instantiate the decoder directly
decoder = PyModesDecoder()
df = rebuild.redecode_position(
start="2023-01-03 16:00",
stop="2023-01-03 20:00",
icao24="400A0E",
decoder=decoder
)
Rs1090 decoder
The Rs1090Decoder uses the Rust-based rs1090 library for faster decoding.
Features:
High-performance Rust implementation
Same decoding logic as PyModesDecoder
Significantly faster for large datasets
Installation:
pip install 'pyopensky[rs1090]'
Usage:
from pyopensky.rebuild import Rebuild
from pyopensky.trino import Trino
trino = Trino()
rebuild = Rebuild(trino)
# Using string-based selection
df = rebuild.redecode_position(
start="2023-01-03 16:00",
stop="2023-01-03 20:00",
icao24="400A0E",
decoder="rs1090"
)
Custom decoder
You can implement your own decoder by subclassing Decoder:
from pyopensky.decoders import Decoder
import pandas as pd
class MyCustomDecoder(Decoder):
def decode_position(self, df: pd.DataFrame) -> pd.DataFrame:
# Custom position decoding logic
return df
def decode_velocity(self, df: pd.DataFrame) -> pd.DataFrame:
# Custom velocity decoding logic
return df
def decode_identification(self, df: pd.DataFrame) -> pd.DataFrame:
# Custom identification decoding logic
return df
def decode_rollcall(self, df: pd.DataFrame) -> pd.DataFrame:
# Custom rollcall decoding logic
return df
# Use your custom decoder
decoder = MyCustomDecoder()
df = rebuild.rebuild(
start="2023-01-03 16:00",
stop="2023-01-03 20:00",
icao24="400A0E",
decoder=decoder
)
Performance considerations
When to use PyModesDecoder vs Rs1090Decoder:
Use
PyModesDecoderfor small to medium datasets (< 1M messages) or when you need to inspect the decoding logicUse
Rs1090Decoderfor large datasets (> 1M messages) where performance is criticalBoth decoders produce equivalent results, Rs1090Decoder is simply faster
Database vs custom decoding:
Database-decoded positions are already validated and filtered by OpenSky
Custom decoding gives you full control over CPR frame pairing and outlier filtering
Use custom decoding when you need BDS register data or have specific validation requirements
Merge tolerance:
All merges use a 5-second tolerance by default. This means:
Position and velocity data must be within 5 seconds to be merged
Identification data must be within 5 seconds of position data
Rollcall data must be within 5 seconds of position data
This tolerance balances data completeness with temporal accuracy.
- class pyopensky.rebuild.Rebuild(trino)
Bases:
objectClass for rebuilding state vectors from raw ADS-B messages.
This class provides methods to download and decode raw ADS-B messages from different data tables and merge them into complete state vectors.
Example usage:
from pyopensky.trino import Trino from pyopensky.rebuild import Rebuild trino = Trino() rebuild = Rebuild(trino) # Without decoding data = rebuild.rebuild( start="2023-01-03 16:00", stop="2023-01-03 20:00", icao24="400A0E" ) # With pymodes or rs1090 decoding data = rebuild.rebuild( start="2023-01-03 16:00", stop="2023-01-03 20:00", icao24="400A0E", decoder="pymodes" # or "rs1090" )
- rebuild(start, stop, *, icao24=None, bounds=None, cached=True, compress=False, decoder=None, include_rollcall=False, **kwargs)
Rebuild state vectors by downloading and merging all data tables.
This method downloads data from position, velocity, identification, and optionally rollcall tables, then merges them using time-based joins to reconstruct complete state vectors.
- Parameters:
start (
Union[str,Real,datetime,Timestamp]) – start of time rangestop (
Union[str,Real,datetime,Timestamp]) – end of time rangeicao24 (
None|str|list[str]) – aircraft transponder code(s)bounds (
None|HasBounds|tuple[float,float,float,float]) – geographical footprintcached (
bool) – use cached datacompress (
bool) – compress cache filesdecoder (
Union[None,Decoder,Literal['pymodes','rs1090']]) – decoder for decoding raw messages (e.g. PyModesDecoder)include_rollcall (
bool) – include rollcall (squawk) data in merge
- Return type:
None|DataFrame- Returns:
DataFrame with merged state vectors
Example usage:
# Without decoding (use database decoded values) data = rebuild.rebuild( start="2023-01-03 16:00", stop="2023-01-03 20:00", icao24="400A0E" ) # With pymodes or rs1090 decoding data = rebuild.rebuild( start="2023-01-03 16:00", stop="2023-01-03 20:00", icao24="400A0E", decoder="pymodes" # or "rs1090" )
- redecode_identification(start, stop, *, icao24=None, cached=True, compress=False, decoder=None, **kwargs)
Download and optionally redecode identification (callsign) data.
- redecode_position(start, stop, *, icao24=None, bounds=None, cached=True, compress=False, decoder=None, **kwargs)
Download and optionally redecode position data from raw messages.
Downloads position data with raw ADS-B messages, pairs odd/even CPR frames, and optionally decodes them using a visitor pattern.
- Parameters:
start (
Union[str,Real,datetime,Timestamp]) – start of time rangestop (
Union[str,Real,datetime,Timestamp]) – end of time rangeicao24 (
None|str|list[str]) – aircraft transponder code(s)bounds (
None|HasBounds|tuple[float,float,float,float]) – geographical footprintcached (
bool) – use cached datacompress (
bool) – compress cache filesdecoder (
None|Decoder) – decoder object implementing decode_position(df) method that decodes raw messages. If None, returns raw data.
- Return type:
None|DataFrame- Returns:
DataFrame with position data (decoded if visitor provided)
Example usage:
# Create a pymodes decoder from pyopensky.decoders import PyModesDecoder decoder = PyModesDecoder() # Redecode positions pos = rebuild.redecode_position( start="2023-01-03 16:00", stop="2023-01-03 20:00", icao24="400A0E", decoder=decoder )
- redecode_rollcall(start, stop, *, icao24=None, cached=True, compress=False, decoder=None, **kwargs)
Download and optionally redecode rollcall (squawk) data.