pyopensky 2.14__tar.gz → 2.16__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pyopensky-2.14 → pyopensky-2.16}/.github/workflows/build-docs.yml +3 -3
- {pyopensky-2.14 → pyopensky-2.16}/.github/workflows/pypi_publish.yml +3 -3
- {pyopensky-2.14 → pyopensky-2.16}/.github/workflows/run_tests.yml +18 -5
- pyopensky-2.16/PKG-INFO +141 -0
- pyopensky-2.16/agents.md +21 -0
- {pyopensky-2.14 → pyopensky-2.16}/docs/source/credentials.rst +8 -24
- {pyopensky-2.14 → pyopensky-2.16}/docs/source/index.rst +4 -1
- pyopensky-2.16/docs/source/rebuild.rst +210 -0
- pyopensky-2.16/docs/source/trino_advanced.rst +342 -0
- {pyopensky-2.14 → pyopensky-2.16}/pyproject.toml +9 -10
- pyopensky-2.16/readme.md +113 -0
- {pyopensky-2.14 → pyopensky-2.16}/src/pyopensky/config.py +14 -6
- pyopensky-2.16/src/pyopensky/decoders/__init__.py +12 -0
- pyopensky-2.16/src/pyopensky/decoders/base.py +93 -0
- pyopensky-2.16/src/pyopensky/decoders/pymodes.py +244 -0
- pyopensky-2.16/src/pyopensky/decoders/rs1090.py +132 -0
- pyopensky-2.16/src/pyopensky/rebuild.py +538 -0
- {pyopensky-2.14 → pyopensky-2.16}/src/pyopensky/rest.py +63 -12
- {pyopensky-2.14 → pyopensky-2.16}/src/pyopensky/schema.py +18 -1
- {pyopensky-2.14 → pyopensky-2.16}/src/pyopensky/time.py +2 -2
- {pyopensky-2.14 → pyopensky-2.16}/src/pyopensky/trino.py +16 -2
- pyopensky-2.16/tests/test_rebuild.py +59 -0
- {pyopensky-2.14 → pyopensky-2.16}/tests/test_trino.py +0 -8
- pyopensky-2.16/uv.lock +4675 -0
- pyopensky-2.14/PKG-INFO +0 -87
- pyopensky-2.14/docs/source/api_reference.rst +0 -8
- pyopensky-2.14/readme.md +0 -61
- pyopensky-2.14/uv.lock +0 -3827
- {pyopensky-2.14 → pyopensky-2.16}/.github/dependabot.yml +0 -0
- {pyopensky-2.14 → pyopensky-2.16}/.github/renovate.json5 +0 -0
- {pyopensky-2.14 → pyopensky-2.16}/.gitignore +0 -0
- {pyopensky-2.14 → pyopensky-2.16}/docs/.gitignore +0 -0
- {pyopensky-2.14 → pyopensky-2.16}/docs/Makefile +0 -0
- {pyopensky-2.14 → pyopensky-2.16}/docs/make.bat +0 -0
- {pyopensky-2.14 → pyopensky-2.16}/docs/source/_static/main_stylesheet.css +0 -0
- {pyopensky-2.14 → pyopensky-2.16}/docs/source/conf.py +0 -0
- {pyopensky-2.14 → pyopensky-2.16}/docs/source/installation.rst +0 -0
- {pyopensky-2.14 → pyopensky-2.16}/docs/source/rest.rst +0 -0
- {pyopensky-2.14 → pyopensky-2.16}/docs/source/trino.rst +0 -0
- {pyopensky-2.14 → pyopensky-2.16}/license.txt +0 -0
- {pyopensky-2.14 → pyopensky-2.16}/scripts/decode_pymodes.py +0 -0
- {pyopensky-2.14 → pyopensky-2.16}/scripts/decode_rs1090.py +0 -0
- {pyopensky-2.14 → pyopensky-2.16}/src/pyopensky/__init__.py +0 -0
- {pyopensky-2.14 → pyopensky-2.16}/src/pyopensky/api.py +0 -0
- {pyopensky-2.14 → pyopensky-2.16}/src/pyopensky/py.typed +0 -0
- {pyopensky-2.14 → pyopensky-2.16}/src/pyopensky/s3.py +0 -0
- {pyopensky-2.14 → pyopensky-2.16}/src/pyopensky/tzdata.py +0 -0
- {pyopensky-2.14 → pyopensky-2.16}/tests/test_rest.py +0 -0
- {pyopensky-2.14 → pyopensky-2.16}/tests/test_s3.py +0 -0
- {pyopensky-2.14 → pyopensky-2.16}/tests/test_tzdata.py +0 -0
|
@@ -15,7 +15,7 @@ jobs:
|
|
|
15
15
|
UV_CACHE_DIR: /tmp/.uv-cache
|
|
16
16
|
|
|
17
17
|
steps:
|
|
18
|
-
- uses: actions/checkout@
|
|
18
|
+
- uses: actions/checkout@v6
|
|
19
19
|
with:
|
|
20
20
|
fetch-depth: 0
|
|
21
21
|
|
|
@@ -23,13 +23,13 @@ jobs:
|
|
|
23
23
|
run: curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
24
24
|
|
|
25
25
|
- name: Set up Python
|
|
26
|
-
uses: actions/setup-python@
|
|
26
|
+
uses: actions/setup-python@v6
|
|
27
27
|
with:
|
|
28
28
|
python-version: ${{ env.PYTHON_VERSION }}
|
|
29
29
|
|
|
30
30
|
|
|
31
31
|
- name: Cache folder for uv
|
|
32
|
-
uses: actions/cache@
|
|
32
|
+
uses: actions/cache@v5
|
|
33
33
|
with:
|
|
34
34
|
path: /tmp/.uv-cache
|
|
35
35
|
key: uv-${{ runner.os }}-${{ hashFiles('uv.lock') }}
|
|
@@ -9,16 +9,16 @@ jobs:
|
|
|
9
9
|
deploy:
|
|
10
10
|
runs-on: ubuntu-latest
|
|
11
11
|
steps:
|
|
12
|
-
- uses: actions/checkout@
|
|
12
|
+
- uses: actions/checkout@v6
|
|
13
13
|
|
|
14
14
|
- name: Set up uv
|
|
15
15
|
run: curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
16
16
|
|
|
17
17
|
- name: Set up Python
|
|
18
|
-
uses: actions/setup-python@
|
|
18
|
+
uses: actions/setup-python@v6
|
|
19
19
|
|
|
20
20
|
- name: Cache folder for uv
|
|
21
|
-
uses: actions/cache@
|
|
21
|
+
uses: actions/cache@v5
|
|
22
22
|
with:
|
|
23
23
|
path: /tmp/.uv-cache
|
|
24
24
|
key: uv-${{ runner.os }}-${{ hashFiles('uv.lock') }}
|
|
@@ -10,7 +10,6 @@ on:
|
|
|
10
10
|
jobs:
|
|
11
11
|
deploy:
|
|
12
12
|
name: python-${{ matrix.python-version }} on ${{ matrix.os }}
|
|
13
|
-
|
|
14
13
|
strategy:
|
|
15
14
|
matrix:
|
|
16
15
|
os:
|
|
@@ -23,6 +22,16 @@ jobs:
|
|
|
23
22
|
- "3.11"
|
|
24
23
|
- "3.12"
|
|
25
24
|
- "3.13"
|
|
25
|
+
- "3.14"
|
|
26
|
+
# `trino` (v0.336.0) depends on `orjson` (v3.11.5)
|
|
27
|
+
# which does not support Python 3.14t
|
|
28
|
+
# https://github.com/ijl/orjson/issues/591#issuecomment-3160351169
|
|
29
|
+
# - "3.14t"
|
|
30
|
+
exclude:
|
|
31
|
+
# greenlet v3.2.4 is not available for Python 3.14t on Windows
|
|
32
|
+
# and fails to compile there. Not much we can do about that right now.
|
|
33
|
+
- os: windows-latest
|
|
34
|
+
python-version: "3.14t"
|
|
26
35
|
|
|
27
36
|
fail-fast: false
|
|
28
37
|
|
|
@@ -32,17 +41,17 @@ jobs:
|
|
|
32
41
|
UV_CACHE_DIR: /tmp/.uv-cache
|
|
33
42
|
|
|
34
43
|
steps:
|
|
35
|
-
- uses: actions/checkout@
|
|
44
|
+
- uses: actions/checkout@v6
|
|
36
45
|
with:
|
|
37
46
|
fetch-depth: 0
|
|
38
47
|
|
|
39
48
|
- name: Install uv
|
|
40
|
-
uses: astral-sh/setup-uv@
|
|
49
|
+
uses: astral-sh/setup-uv@v7
|
|
41
50
|
with:
|
|
42
51
|
enable-cache: true
|
|
43
52
|
|
|
44
53
|
- name: Cache folder for data
|
|
45
|
-
uses: actions/cache@
|
|
54
|
+
uses: actions/cache@v5
|
|
46
55
|
id: cache-folder
|
|
47
56
|
with:
|
|
48
57
|
path: |
|
|
@@ -51,13 +60,17 @@ jobs:
|
|
|
51
60
|
key: opensky-${{ hashFiles('uv.lock') }}
|
|
52
61
|
|
|
53
62
|
- name: Install the project
|
|
54
|
-
run: uv sync --
|
|
63
|
+
run: uv sync --dev --python ${{ matrix.python-version }} --extra rs1090 --extra cartes
|
|
55
64
|
|
|
56
65
|
- name: Linting and formatting
|
|
57
66
|
run: |
|
|
58
67
|
uv run ruff check
|
|
59
68
|
uv run ruff format --check
|
|
60
69
|
|
|
70
|
+
- name: Type checking
|
|
71
|
+
if: ${{ matrix.python-version != '3.9' }}
|
|
72
|
+
run: uvx ty check src tests
|
|
73
|
+
|
|
61
74
|
- name: Run tests
|
|
62
75
|
if: ${{ (matrix.python-version == '3.12' && matrix.os == 'ubuntu-latest') || steps.cache-folder.outputs.cache-hit == 'true' }}
|
|
63
76
|
env:
|
pyopensky-2.16/PKG-INFO
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pyopensky
|
|
3
|
+
Version: 2.16
|
|
4
|
+
Summary: A Python interface for OpenSky database
|
|
5
|
+
Project-URL: Repository, https://github.com/open-aviation/pyopensky/
|
|
6
|
+
Author-email: Xavier Olive <git@xoolive.org>, Junzi Sun <j.sun-1@tudelft.nl>
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
Requires-Python: >=3.9
|
|
9
|
+
Requires-Dist: appdirs>=1.4.4
|
|
10
|
+
Requires-Dist: httpx>=0.27.2
|
|
11
|
+
Requires-Dist: minio>=7.2.8
|
|
12
|
+
Requires-Dist: numpy>=2.0.2
|
|
13
|
+
Requires-Dist: pandas>=2.2.2
|
|
14
|
+
Requires-Dist: pyarrow>=17.0.0
|
|
15
|
+
Requires-Dist: pyjwt>=2.9.0
|
|
16
|
+
Requires-Dist: python-dotenv>=1.0.1
|
|
17
|
+
Requires-Dist: tqdm>=4.66.5
|
|
18
|
+
Requires-Dist: trino[sqlalchemy]>=0.329.0
|
|
19
|
+
Requires-Dist: typing-extensions>=4.12.2
|
|
20
|
+
Requires-Dist: tzdata>=2024.2
|
|
21
|
+
Provides-Extra: cartes
|
|
22
|
+
Requires-Dist: cartes>=0.8.5; (python_version >= '3.10') and extra == 'cartes'
|
|
23
|
+
Provides-Extra: pymodes
|
|
24
|
+
Requires-Dist: pymodes>=2.18; extra == 'pymodes'
|
|
25
|
+
Provides-Extra: rs1090
|
|
26
|
+
Requires-Dist: rs1090>=0.3.8; extra == 'rs1090'
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
|
|
29
|
+
# pyopensky
|
|
30
|
+
|
|
31
|
+
The `pyopensky` Python library provides functions to download data from the OpenSky Network live API and historical databases. It aims at making ADS-B and Mode S data from OpenSky easily accessible in the Python programming environment.
|
|
32
|
+
|
|
33
|
+
**Key features:**
|
|
34
|
+
|
|
35
|
+
- Access to **live** aircraft state vectors and flight information via REST API
|
|
36
|
+
- Query **historical** ADS-B and Mode S data from the Trino database
|
|
37
|
+
- Decode and rebuild flight trajectories from raw messages
|
|
38
|
+
- Support for spatial and temporal filtering
|
|
39
|
+
- Built-in caching for efficient data retrieval
|
|
40
|
+
- Integration with pandas DataFrames for easy data analysis
|
|
41
|
+
|
|
42
|
+
Full documentation on <https://mode-s.org/pyopensky/>
|
|
43
|
+
|
|
44
|
+
## Installation
|
|
45
|
+
|
|
46
|
+
```sh
|
|
47
|
+
pip install pyopensky
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
or add it in your project with
|
|
51
|
+
|
|
52
|
+
```sh
|
|
53
|
+
uv add pyopensky
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
The library is also available on conda-forge, although this approach is no longer recommended:
|
|
57
|
+
|
|
58
|
+
```sh
|
|
59
|
+
conda install -c conda-forge pyopensky
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Credentials
|
|
63
|
+
|
|
64
|
+
Access to the OpenSky Network historical database requires authentication. See details in the [documentation](https://open-aviation.github.io/pyopensky/credentials.html) on how to:
|
|
65
|
+
|
|
66
|
+
- Apply an OpenSky Network account
|
|
67
|
+
- Configure your credentials for API access
|
|
68
|
+
- Set up authentication for the Trino database
|
|
69
|
+
|
|
70
|
+
## Usage
|
|
71
|
+
|
|
72
|
+
### 1. REST API
|
|
73
|
+
|
|
74
|
+
> [!IMPORTANT]
|
|
75
|
+
> Do NOT use REST API for historical data, use trino instead!
|
|
76
|
+
|
|
77
|
+
Access **live** and recent flight data.
|
|
78
|
+
|
|
79
|
+
#### Functions
|
|
80
|
+
|
|
81
|
+
```python
|
|
82
|
+
from pyopensky.rest import REST
|
|
83
|
+
|
|
84
|
+
rest = REST()
|
|
85
|
+
|
|
86
|
+
rest.states()
|
|
87
|
+
rest.tracks(icao24)
|
|
88
|
+
rest.routes(callsign)
|
|
89
|
+
rest.aircraft(icao24, begin, end)
|
|
90
|
+
rest.arrival(airport, begin, end)
|
|
91
|
+
rest.departure(airport, begin, end)
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
#### Examples
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
from pyopensky.rest import REST
|
|
98
|
+
|
|
99
|
+
rest = REST()
|
|
100
|
+
|
|
101
|
+
# Get current state vectors for all aircraft
|
|
102
|
+
rest.states()
|
|
103
|
+
|
|
104
|
+
# Get trajectory for a specific aircraft
|
|
105
|
+
rest.tracks(icao24="3c6444")
|
|
106
|
+
|
|
107
|
+
# Get route information for a callsign
|
|
108
|
+
rest.routes(callsign="AFR292")
|
|
109
|
+
|
|
110
|
+
# Get flights for a specific aircraft in a time range
|
|
111
|
+
# NOTE: do NOT use REST for historical data, use trino instead!!
|
|
112
|
+
rest.aircraft(icao24="3c6444", begin="2024-01-01", end="2024-01-02")
|
|
113
|
+
|
|
114
|
+
# Get arrivals at an airport
|
|
115
|
+
# NOTE: do NOT use REST for historical data, use trino instead!!
|
|
116
|
+
rest.arrival(airport="EHAM", begin="2024-01-01 12:00", end="2024-01-01 13:00")
|
|
117
|
+
|
|
118
|
+
# Get departures from an airport
|
|
119
|
+
# NOTE: do NOT use REST for historical data, use trino instead!!
|
|
120
|
+
rest.departure(airport="LFPG", begin="2024-01-01 12:00", end="2024-01-01 13:00")
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### 2. Trino Interface
|
|
124
|
+
|
|
125
|
+
Query **historical** ADS-B and Mode S data with advanced selection and processing.
|
|
126
|
+
|
|
127
|
+
Functions
|
|
128
|
+
|
|
129
|
+
```python
|
|
130
|
+
from pyopensky.trino import Trino
|
|
131
|
+
|
|
132
|
+
trino = Trino()
|
|
133
|
+
# full description of the whole set of parameters in the documentation
|
|
134
|
+
trino.flightlist(start, stop, *, airport, callsign, icao24)
|
|
135
|
+
trino.rawdata(start, stop, *, callsign, icao24, bounds)
|
|
136
|
+
trino.history(start, stop, *, callsign, icao24, bounds)
|
|
137
|
+
trino.rebuild(start, stop, *, icao24, bounds)
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
> [!IMPORTANT]
|
|
141
|
+
> Refer to the [documentation](https://mode-s.org/pyopensky) for advanced usage and parameter details.
|
pyopensky-2.16/agents.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Agent development guide
|
|
2
|
+
|
|
3
|
+
## Setup commands
|
|
4
|
+
|
|
5
|
+
- Run `uv sync --dev --extra rs1090 --extra cartes`
|
|
6
|
+
|
|
7
|
+
## Coding style
|
|
8
|
+
|
|
9
|
+
- Run `uv run ruff check` and `uv run ruff format` to check and format code
|
|
10
|
+
- Run `uvx ty check src/ tests/` to check types
|
|
11
|
+
|
|
12
|
+
## Documentation commands
|
|
13
|
+
|
|
14
|
+
- Build documentation: run `uv run make html` from the docs/ folder
|
|
15
|
+
- Only capitalize the first letter of the titles and headings, unless there are proper nouns
|
|
16
|
+
|
|
17
|
+
## Commit rules
|
|
18
|
+
|
|
19
|
+
- **NEVER COMMIT ANYTHING WITHOUT EXPLICIT APPROVAL**: encourage the developer to check the code before committing
|
|
20
|
+
- **DO NOT COMMIT DIRECTLY TO THE MAIN BRANCH**
|
|
21
|
+
- Create a feature branch from main for your changes
|
|
@@ -20,9 +20,13 @@ is created, including the following content:
|
|
|
20
20
|
[default]
|
|
21
21
|
username =
|
|
22
22
|
password =
|
|
23
|
+
client_id =
|
|
24
|
+
client_secret =
|
|
23
25
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
+
|
|
27
|
+
The username and password is used to access the Trino database, while the
|
|
28
|
+
client ID and client secret are used to access the OpenSky REST API.
|
|
29
|
+
Log in to your OpenSky account and visit the `Account <https://opensky-network.org/my-opensky/account>`_ page in order to create a new API client and retrieve your ``client_id`` and ``client_secret``.
|
|
26
30
|
|
|
27
31
|
You will identify the folder where the ``settings.conf`` file is located:
|
|
28
32
|
|
|
@@ -32,26 +36,6 @@ You will identify the folder where the ``settings.conf`` file is located:
|
|
|
32
36
|
|
|
33
37
|
print(opensky_config_dir)
|
|
34
38
|
|
|
35
|
-
|
|
36
|
-
Different credentials per service
|
|
37
|
-
---------------------------------
|
|
38
|
-
|
|
39
|
-
If you want to specify different credentials for the REST API and for the Trino
|
|
40
|
-
database, use the following sections in the configuration file.
|
|
41
|
-
|
|
42
|
-
.. code::
|
|
43
|
-
|
|
44
|
-
[opensky] # REST API
|
|
45
|
-
username =
|
|
46
|
-
password =
|
|
47
|
-
|
|
48
|
-
[trino] # Trino database
|
|
49
|
-
username =
|
|
50
|
-
password =
|
|
51
|
-
|
|
52
|
-
If these sections are commented, the library will use the credentials from the
|
|
53
|
-
[default] section.
|
|
54
|
-
|
|
55
39
|
Fallback configuration
|
|
56
40
|
----------------------
|
|
57
41
|
|
|
@@ -61,5 +45,5 @@ following steps are performed in order:
|
|
|
61
45
|
- try to get the credentials from the `traffic <https://traffic-viz.github.io>`_
|
|
62
46
|
configuration file;
|
|
63
47
|
- get the credentials from ``$OPENSKY_USERNAME`` and ``$OPENSKY_PASSWORD``
|
|
64
|
-
environment variables;
|
|
65
|
-
- open a browser and log in on a dedicated webpage.
|
|
48
|
+
environment variables (``$OPENSKY_CLIENT_ID`` and ``$OPENSKY_CLIENT_SECRET`` for the API client);
|
|
49
|
+
- open a browser and log in on a dedicated webpage (for Trino).
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
Rebuilding trajectories
|
|
2
|
+
=======================
|
|
3
|
+
|
|
4
|
+
The :class:`~pyopensky.rebuild.Rebuild` class provides functionality for reconstructing aircraft trajectories from raw ADS-B and Mode S messages.
|
|
5
|
+
|
|
6
|
+
When to use the rebuild functionality
|
|
7
|
+
--------------------------------------
|
|
8
|
+
|
|
9
|
+
There are two main use cases for the ``Rebuild`` class:
|
|
10
|
+
|
|
11
|
+
1. **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.
|
|
12
|
+
|
|
13
|
+
2. **Redecode raw messages**: Apply custom decoding logic to raw messages for more precise position calculations, BDS register extraction, or custom validation.
|
|
14
|
+
|
|
15
|
+
Rebuilding without custom decoding
|
|
16
|
+
-----------------------------------
|
|
17
|
+
|
|
18
|
+
If you only need to merge data from different sources and trust the database-decoded values, use the ``rebuild()`` method without specifying a decoder:
|
|
19
|
+
|
|
20
|
+
.. code-block:: python
|
|
21
|
+
|
|
22
|
+
from pyopensky.trino import Trino
|
|
23
|
+
from pyopensky.rebuild import Rebuild
|
|
24
|
+
|
|
25
|
+
trino = Trino()
|
|
26
|
+
rebuild = Rebuild(trino)
|
|
27
|
+
|
|
28
|
+
# Fetch and merge position, velocity, identification data
|
|
29
|
+
df = rebuild.rebuild(
|
|
30
|
+
start="2023-01-03 16:00",
|
|
31
|
+
stop="2023-01-03 20:00",
|
|
32
|
+
icao24="400A0E"
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
This returns a dataframe with columns from all three sources merged on ``icao24`` and ``mintime`` with a 5-second tolerance.
|
|
36
|
+
|
|
37
|
+
Rebuilding with custom decoding
|
|
38
|
+
--------------------------------
|
|
39
|
+
|
|
40
|
+
When you need more control over position decoding or want to extract additional data from raw messages, specify a decoder:
|
|
41
|
+
|
|
42
|
+
.. code-block:: python
|
|
43
|
+
|
|
44
|
+
from pyopensky.trino import Trino
|
|
45
|
+
from pyopensky.rebuild import Rebuild
|
|
46
|
+
|
|
47
|
+
trino = Trino()
|
|
48
|
+
rebuild = Rebuild(trino)
|
|
49
|
+
|
|
50
|
+
# Redecode position data with PyModesDecoder
|
|
51
|
+
df = rebuild.rebuild(
|
|
52
|
+
start="2023-01-03 16:00",
|
|
53
|
+
stop="2023-01-03 20:00",
|
|
54
|
+
icao24="400A0E",
|
|
55
|
+
decoder="pymodes" # Use string-based decoder selection
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
The decoder will process the raw messages and apply custom logic for CPR position decoding, validation, and filtering.
|
|
59
|
+
|
|
60
|
+
Available decoders
|
|
61
|
+
------------------
|
|
62
|
+
|
|
63
|
+
PyModes decoder
|
|
64
|
+
~~~~~~~~~~~~~~~
|
|
65
|
+
|
|
66
|
+
The :class:`~pyopensky.decoders.PyModesDecoder` uses the `pyModeS <https://github.com/junzis/pyModeS>`_ library for decoding.
|
|
67
|
+
|
|
68
|
+
**Features:**
|
|
69
|
+
|
|
70
|
+
- CPR position decoding with odd/even frame pairing
|
|
71
|
+
- Reference position validation to filter outliers
|
|
72
|
+
- BDS register decoding (BDS 4,0, BDS 5,0, BDS 6,0)
|
|
73
|
+
- Pure Python implementation
|
|
74
|
+
|
|
75
|
+
**Installation:**
|
|
76
|
+
|
|
77
|
+
.. code-block:: bash
|
|
78
|
+
|
|
79
|
+
pip install 'pyopensky[pymodes]'
|
|
80
|
+
|
|
81
|
+
**Usage:**
|
|
82
|
+
|
|
83
|
+
.. code-block:: python
|
|
84
|
+
|
|
85
|
+
from pyopensky.decoders import PyModesDecoder
|
|
86
|
+
from pyopensky.rebuild import Rebuild
|
|
87
|
+
from pyopensky.trino import Trino
|
|
88
|
+
|
|
89
|
+
trino = Trino()
|
|
90
|
+
rebuild = Rebuild(trino)
|
|
91
|
+
|
|
92
|
+
# Using string-based selection
|
|
93
|
+
df = rebuild.redecode_position(
|
|
94
|
+
start="2023-01-03 16:00",
|
|
95
|
+
stop="2023-01-03 20:00",
|
|
96
|
+
icao24="400A0E",
|
|
97
|
+
decoder="pymodes"
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
# Or instantiate the decoder directly
|
|
101
|
+
decoder = PyModesDecoder()
|
|
102
|
+
df = rebuild.redecode_position(
|
|
103
|
+
start="2023-01-03 16:00",
|
|
104
|
+
stop="2023-01-03 20:00",
|
|
105
|
+
icao24="400A0E",
|
|
106
|
+
decoder=decoder
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
Rs1090 decoder
|
|
110
|
+
~~~~~~~~~~~~~~
|
|
111
|
+
|
|
112
|
+
The :class:`~pyopensky.decoders.Rs1090Decoder` uses the Rust-based `rs1090 <https://github.com/xoolive/rs1090>`_ library for faster decoding.
|
|
113
|
+
|
|
114
|
+
**Features:**
|
|
115
|
+
|
|
116
|
+
- High-performance Rust implementation
|
|
117
|
+
- Same decoding logic as PyModesDecoder
|
|
118
|
+
- Significantly faster for large datasets
|
|
119
|
+
|
|
120
|
+
**Installation:**
|
|
121
|
+
|
|
122
|
+
.. code-block:: bash
|
|
123
|
+
|
|
124
|
+
pip install 'pyopensky[rs1090]'
|
|
125
|
+
|
|
126
|
+
**Usage:**
|
|
127
|
+
|
|
128
|
+
.. code-block:: python
|
|
129
|
+
|
|
130
|
+
from pyopensky.rebuild import Rebuild
|
|
131
|
+
from pyopensky.trino import Trino
|
|
132
|
+
|
|
133
|
+
trino = Trino()
|
|
134
|
+
rebuild = Rebuild(trino)
|
|
135
|
+
|
|
136
|
+
# Using string-based selection
|
|
137
|
+
df = rebuild.redecode_position(
|
|
138
|
+
start="2023-01-03 16:00",
|
|
139
|
+
stop="2023-01-03 20:00",
|
|
140
|
+
icao24="400A0E",
|
|
141
|
+
decoder="rs1090"
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
Custom decoder
|
|
145
|
+
~~~~~~~~~~~~~~
|
|
146
|
+
|
|
147
|
+
You can implement your own decoder by subclassing :class:`~pyopensky.decoders.Decoder`:
|
|
148
|
+
|
|
149
|
+
.. code-block:: python
|
|
150
|
+
|
|
151
|
+
from pyopensky.decoders import Decoder
|
|
152
|
+
import pandas as pd
|
|
153
|
+
|
|
154
|
+
class MyCustomDecoder(Decoder):
|
|
155
|
+
def decode_position(self, df: pd.DataFrame) -> pd.DataFrame:
|
|
156
|
+
# Custom position decoding logic
|
|
157
|
+
return df
|
|
158
|
+
|
|
159
|
+
def decode_velocity(self, df: pd.DataFrame) -> pd.DataFrame:
|
|
160
|
+
# Custom velocity decoding logic
|
|
161
|
+
return df
|
|
162
|
+
|
|
163
|
+
def decode_identification(self, df: pd.DataFrame) -> pd.DataFrame:
|
|
164
|
+
# Custom identification decoding logic
|
|
165
|
+
return df
|
|
166
|
+
|
|
167
|
+
def decode_rollcall(self, df: pd.DataFrame) -> pd.DataFrame:
|
|
168
|
+
# Custom rollcall decoding logic
|
|
169
|
+
return df
|
|
170
|
+
|
|
171
|
+
# Use your custom decoder
|
|
172
|
+
decoder = MyCustomDecoder()
|
|
173
|
+
df = rebuild.rebuild(
|
|
174
|
+
start="2023-01-03 16:00",
|
|
175
|
+
stop="2023-01-03 20:00",
|
|
176
|
+
icao24="400A0E",
|
|
177
|
+
decoder=decoder
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
Performance considerations
|
|
181
|
+
---------------------------
|
|
182
|
+
|
|
183
|
+
**When to use PyModesDecoder vs Rs1090Decoder:**
|
|
184
|
+
|
|
185
|
+
- Use ``PyModesDecoder`` for small to medium datasets (< 1M messages) or when you need to inspect the decoding logic
|
|
186
|
+
- Use ``Rs1090Decoder`` for large datasets (> 1M messages) where performance is critical
|
|
187
|
+
- Both decoders produce equivalent results, Rs1090Decoder is simply faster
|
|
188
|
+
|
|
189
|
+
**Database vs custom decoding:**
|
|
190
|
+
|
|
191
|
+
- Database-decoded positions are already validated and filtered by OpenSky
|
|
192
|
+
- Custom decoding gives you full control over CPR frame pairing and outlier filtering
|
|
193
|
+
- Use custom decoding when you need BDS register data or have specific validation requirements
|
|
194
|
+
|
|
195
|
+
**Merge tolerance:**
|
|
196
|
+
|
|
197
|
+
All merges use a 5-second tolerance by default. This means:
|
|
198
|
+
|
|
199
|
+
- Position and velocity data must be within 5 seconds to be merged
|
|
200
|
+
- Identification data must be within 5 seconds of position data
|
|
201
|
+
- Rollcall data must be within 5 seconds of position data
|
|
202
|
+
|
|
203
|
+
This tolerance balances data completeness with temporal accuracy.
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
.. autoclass:: pyopensky.rebuild.Rebuild
|
|
207
|
+
:members:
|
|
208
|
+
:inherited-members:
|
|
209
|
+
:no-undoc-members:
|
|
210
|
+
:show-inheritance:
|