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.
Files changed (50) hide show
  1. {pyopensky-2.14 → pyopensky-2.16}/.github/workflows/build-docs.yml +3 -3
  2. {pyopensky-2.14 → pyopensky-2.16}/.github/workflows/pypi_publish.yml +3 -3
  3. {pyopensky-2.14 → pyopensky-2.16}/.github/workflows/run_tests.yml +18 -5
  4. pyopensky-2.16/PKG-INFO +141 -0
  5. pyopensky-2.16/agents.md +21 -0
  6. {pyopensky-2.14 → pyopensky-2.16}/docs/source/credentials.rst +8 -24
  7. {pyopensky-2.14 → pyopensky-2.16}/docs/source/index.rst +4 -1
  8. pyopensky-2.16/docs/source/rebuild.rst +210 -0
  9. pyopensky-2.16/docs/source/trino_advanced.rst +342 -0
  10. {pyopensky-2.14 → pyopensky-2.16}/pyproject.toml +9 -10
  11. pyopensky-2.16/readme.md +113 -0
  12. {pyopensky-2.14 → pyopensky-2.16}/src/pyopensky/config.py +14 -6
  13. pyopensky-2.16/src/pyopensky/decoders/__init__.py +12 -0
  14. pyopensky-2.16/src/pyopensky/decoders/base.py +93 -0
  15. pyopensky-2.16/src/pyopensky/decoders/pymodes.py +244 -0
  16. pyopensky-2.16/src/pyopensky/decoders/rs1090.py +132 -0
  17. pyopensky-2.16/src/pyopensky/rebuild.py +538 -0
  18. {pyopensky-2.14 → pyopensky-2.16}/src/pyopensky/rest.py +63 -12
  19. {pyopensky-2.14 → pyopensky-2.16}/src/pyopensky/schema.py +18 -1
  20. {pyopensky-2.14 → pyopensky-2.16}/src/pyopensky/time.py +2 -2
  21. {pyopensky-2.14 → pyopensky-2.16}/src/pyopensky/trino.py +16 -2
  22. pyopensky-2.16/tests/test_rebuild.py +59 -0
  23. {pyopensky-2.14 → pyopensky-2.16}/tests/test_trino.py +0 -8
  24. pyopensky-2.16/uv.lock +4675 -0
  25. pyopensky-2.14/PKG-INFO +0 -87
  26. pyopensky-2.14/docs/source/api_reference.rst +0 -8
  27. pyopensky-2.14/readme.md +0 -61
  28. pyopensky-2.14/uv.lock +0 -3827
  29. {pyopensky-2.14 → pyopensky-2.16}/.github/dependabot.yml +0 -0
  30. {pyopensky-2.14 → pyopensky-2.16}/.github/renovate.json5 +0 -0
  31. {pyopensky-2.14 → pyopensky-2.16}/.gitignore +0 -0
  32. {pyopensky-2.14 → pyopensky-2.16}/docs/.gitignore +0 -0
  33. {pyopensky-2.14 → pyopensky-2.16}/docs/Makefile +0 -0
  34. {pyopensky-2.14 → pyopensky-2.16}/docs/make.bat +0 -0
  35. {pyopensky-2.14 → pyopensky-2.16}/docs/source/_static/main_stylesheet.css +0 -0
  36. {pyopensky-2.14 → pyopensky-2.16}/docs/source/conf.py +0 -0
  37. {pyopensky-2.14 → pyopensky-2.16}/docs/source/installation.rst +0 -0
  38. {pyopensky-2.14 → pyopensky-2.16}/docs/source/rest.rst +0 -0
  39. {pyopensky-2.14 → pyopensky-2.16}/docs/source/trino.rst +0 -0
  40. {pyopensky-2.14 → pyopensky-2.16}/license.txt +0 -0
  41. {pyopensky-2.14 → pyopensky-2.16}/scripts/decode_pymodes.py +0 -0
  42. {pyopensky-2.14 → pyopensky-2.16}/scripts/decode_rs1090.py +0 -0
  43. {pyopensky-2.14 → pyopensky-2.16}/src/pyopensky/__init__.py +0 -0
  44. {pyopensky-2.14 → pyopensky-2.16}/src/pyopensky/api.py +0 -0
  45. {pyopensky-2.14 → pyopensky-2.16}/src/pyopensky/py.typed +0 -0
  46. {pyopensky-2.14 → pyopensky-2.16}/src/pyopensky/s3.py +0 -0
  47. {pyopensky-2.14 → pyopensky-2.16}/src/pyopensky/tzdata.py +0 -0
  48. {pyopensky-2.14 → pyopensky-2.16}/tests/test_rest.py +0 -0
  49. {pyopensky-2.14 → pyopensky-2.16}/tests/test_s3.py +0 -0
  50. {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@v4
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@v5
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@v4
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@v4
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@v5
18
+ uses: actions/setup-python@v6
19
19
 
20
20
  - name: Cache folder for uv
21
- uses: actions/cache@v4
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@v4
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@v5
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@v4
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 --all-extras --dev --python ${{ matrix.python-version }}
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:
@@ -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.
@@ -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
- If you use the same login for the OpenSky website (therefore the REST API) and
25
- for Trino (it will be unified one day), just fill it here.
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).
@@ -26,5 +26,8 @@ use in your future studies. All functions return pandas :class:`~pandas.DataFram
26
26
 
27
27
  installation
28
28
  credentials
29
- api_reference
29
+ rest
30
+ trino
31
+ trino_advanced
32
+ rebuild
30
33
 
@@ -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: