pycontrails 0.58.0__cp314-cp314-macosx_10_13_x86_64.whl
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.
Potentially problematic release.
This version of pycontrails might be problematic. Click here for more details.
- pycontrails/__init__.py +70 -0
- pycontrails/_version.py +34 -0
- pycontrails/core/__init__.py +30 -0
- pycontrails/core/aircraft_performance.py +679 -0
- pycontrails/core/airports.py +228 -0
- pycontrails/core/cache.py +889 -0
- pycontrails/core/coordinates.py +174 -0
- pycontrails/core/fleet.py +483 -0
- pycontrails/core/flight.py +2185 -0
- pycontrails/core/flightplan.py +228 -0
- pycontrails/core/fuel.py +140 -0
- pycontrails/core/interpolation.py +702 -0
- pycontrails/core/met.py +2931 -0
- pycontrails/core/met_var.py +387 -0
- pycontrails/core/models.py +1321 -0
- pycontrails/core/polygon.py +549 -0
- pycontrails/core/rgi_cython.cpython-314-darwin.so +0 -0
- pycontrails/core/vector.py +2249 -0
- pycontrails/datalib/__init__.py +12 -0
- pycontrails/datalib/_met_utils/metsource.py +746 -0
- pycontrails/datalib/ecmwf/__init__.py +73 -0
- pycontrails/datalib/ecmwf/arco_era5.py +345 -0
- pycontrails/datalib/ecmwf/common.py +114 -0
- pycontrails/datalib/ecmwf/era5.py +554 -0
- pycontrails/datalib/ecmwf/era5_model_level.py +490 -0
- pycontrails/datalib/ecmwf/hres.py +804 -0
- pycontrails/datalib/ecmwf/hres_model_level.py +466 -0
- pycontrails/datalib/ecmwf/ifs.py +287 -0
- pycontrails/datalib/ecmwf/model_levels.py +435 -0
- pycontrails/datalib/ecmwf/static/model_level_dataframe_v20240418.csv +139 -0
- pycontrails/datalib/ecmwf/variables.py +268 -0
- pycontrails/datalib/geo_utils.py +261 -0
- pycontrails/datalib/gfs/__init__.py +28 -0
- pycontrails/datalib/gfs/gfs.py +656 -0
- pycontrails/datalib/gfs/variables.py +104 -0
- pycontrails/datalib/goes.py +757 -0
- pycontrails/datalib/himawari/__init__.py +27 -0
- pycontrails/datalib/himawari/header_struct.py +266 -0
- pycontrails/datalib/himawari/himawari.py +667 -0
- pycontrails/datalib/landsat.py +589 -0
- pycontrails/datalib/leo_utils/__init__.py +5 -0
- pycontrails/datalib/leo_utils/correction.py +266 -0
- pycontrails/datalib/leo_utils/landsat_metadata.py +300 -0
- pycontrails/datalib/leo_utils/search.py +250 -0
- pycontrails/datalib/leo_utils/sentinel_metadata.py +748 -0
- pycontrails/datalib/leo_utils/static/bq_roi_query.sql +6 -0
- pycontrails/datalib/leo_utils/vis.py +59 -0
- pycontrails/datalib/sentinel.py +650 -0
- pycontrails/datalib/spire/__init__.py +5 -0
- pycontrails/datalib/spire/exceptions.py +62 -0
- pycontrails/datalib/spire/spire.py +604 -0
- pycontrails/ext/bada.py +42 -0
- pycontrails/ext/cirium.py +14 -0
- pycontrails/ext/empirical_grid.py +140 -0
- pycontrails/ext/synthetic_flight.py +431 -0
- pycontrails/models/__init__.py +1 -0
- pycontrails/models/accf.py +425 -0
- pycontrails/models/apcemm/__init__.py +8 -0
- pycontrails/models/apcemm/apcemm.py +983 -0
- pycontrails/models/apcemm/inputs.py +226 -0
- pycontrails/models/apcemm/static/apcemm_yaml_template.yaml +183 -0
- pycontrails/models/apcemm/utils.py +437 -0
- pycontrails/models/cocip/__init__.py +29 -0
- pycontrails/models/cocip/cocip.py +2742 -0
- pycontrails/models/cocip/cocip_params.py +305 -0
- pycontrails/models/cocip/cocip_uncertainty.py +291 -0
- pycontrails/models/cocip/contrail_properties.py +1530 -0
- pycontrails/models/cocip/output_formats.py +2270 -0
- pycontrails/models/cocip/radiative_forcing.py +1260 -0
- pycontrails/models/cocip/radiative_heating.py +520 -0
- pycontrails/models/cocip/unterstrasser_wake_vortex.py +508 -0
- pycontrails/models/cocip/wake_vortex.py +396 -0
- pycontrails/models/cocip/wind_shear.py +120 -0
- pycontrails/models/cocipgrid/__init__.py +9 -0
- pycontrails/models/cocipgrid/cocip_grid.py +2552 -0
- pycontrails/models/cocipgrid/cocip_grid_params.py +138 -0
- pycontrails/models/dry_advection.py +602 -0
- pycontrails/models/emissions/__init__.py +21 -0
- pycontrails/models/emissions/black_carbon.py +599 -0
- pycontrails/models/emissions/emissions.py +1353 -0
- pycontrails/models/emissions/ffm2.py +336 -0
- pycontrails/models/emissions/static/default-engine-uids.csv +239 -0
- pycontrails/models/emissions/static/edb-gaseous-v29b-engines.csv +596 -0
- pycontrails/models/emissions/static/edb-nvpm-v29b-engines.csv +215 -0
- pycontrails/models/extended_k15.py +1327 -0
- pycontrails/models/humidity_scaling/__init__.py +37 -0
- pycontrails/models/humidity_scaling/humidity_scaling.py +1075 -0
- pycontrails/models/humidity_scaling/quantiles/era5-model-level-quantiles.pq +0 -0
- pycontrails/models/humidity_scaling/quantiles/era5-pressure-level-quantiles.pq +0 -0
- pycontrails/models/issr.py +210 -0
- pycontrails/models/pcc.py +326 -0
- pycontrails/models/pcr.py +154 -0
- pycontrails/models/ps_model/__init__.py +18 -0
- pycontrails/models/ps_model/ps_aircraft_params.py +381 -0
- pycontrails/models/ps_model/ps_grid.py +701 -0
- pycontrails/models/ps_model/ps_model.py +1000 -0
- pycontrails/models/ps_model/ps_operational_limits.py +525 -0
- pycontrails/models/ps_model/static/ps-aircraft-params-20250328.csv +69 -0
- pycontrails/models/ps_model/static/ps-synonym-list-20250328.csv +104 -0
- pycontrails/models/sac.py +442 -0
- pycontrails/models/tau_cirrus.py +183 -0
- pycontrails/physics/__init__.py +1 -0
- pycontrails/physics/constants.py +117 -0
- pycontrails/physics/geo.py +1138 -0
- pycontrails/physics/jet.py +968 -0
- pycontrails/physics/static/iata-cargo-load-factors-20250221.csv +74 -0
- pycontrails/physics/static/iata-passenger-load-factors-20250221.csv +74 -0
- pycontrails/physics/thermo.py +551 -0
- pycontrails/physics/units.py +472 -0
- pycontrails/py.typed +0 -0
- pycontrails/utils/__init__.py +1 -0
- pycontrails/utils/dependencies.py +66 -0
- pycontrails/utils/iteration.py +13 -0
- pycontrails/utils/json.py +187 -0
- pycontrails/utils/temp.py +50 -0
- pycontrails/utils/types.py +163 -0
- pycontrails-0.58.0.dist-info/METADATA +180 -0
- pycontrails-0.58.0.dist-info/RECORD +122 -0
- pycontrails-0.58.0.dist-info/WHEEL +6 -0
- pycontrails-0.58.0.dist-info/licenses/LICENSE +178 -0
- pycontrails-0.58.0.dist-info/licenses/NOTICE +43 -0
- pycontrails-0.58.0.dist-info/top_level.txt +3 -0
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
"""Airport data support."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import functools
|
|
6
|
+
|
|
7
|
+
import numpy as np
|
|
8
|
+
import pandas as pd
|
|
9
|
+
|
|
10
|
+
from pycontrails.core import cache
|
|
11
|
+
from pycontrails.physics import geo, units
|
|
12
|
+
|
|
13
|
+
#: URL for `Our Airports <https://ourairports.com/>`_ database.
|
|
14
|
+
#: Fork of the `ourairports-data repository <https://github.com/davidmegginson/ourairports-data>`_.
|
|
15
|
+
OURAIRPORTS_DATABASE_URL: str = (
|
|
16
|
+
"https://github.com/contrailcirrus/ourairports-data/raw/main/airports.csv"
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _download_ourairports_csv() -> pd.DataFrame:
|
|
21
|
+
"""Download CSV file from fork of ourairports-data github."""
|
|
22
|
+
return pd.read_csv(
|
|
23
|
+
OURAIRPORTS_DATABASE_URL,
|
|
24
|
+
usecols=[
|
|
25
|
+
"type",
|
|
26
|
+
"name",
|
|
27
|
+
"latitude_deg",
|
|
28
|
+
"longitude_deg",
|
|
29
|
+
"elevation_ft",
|
|
30
|
+
"iso_country",
|
|
31
|
+
"iso_region",
|
|
32
|
+
"municipality",
|
|
33
|
+
"scheduled_service",
|
|
34
|
+
"gps_code",
|
|
35
|
+
"iata_code",
|
|
36
|
+
],
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@functools.cache
|
|
41
|
+
def global_airport_database(
|
|
42
|
+
cachestore: cache.CacheStore | None = None, update_cache: bool = False
|
|
43
|
+
) -> pd.DataFrame:
|
|
44
|
+
"""
|
|
45
|
+
Load and process global airport database from `Our Airports <https://ourairports.com/>`_.
|
|
46
|
+
|
|
47
|
+
The database includes coordinates and metadata for 74867 unique airports.
|
|
48
|
+
|
|
49
|
+
Parameters
|
|
50
|
+
----------
|
|
51
|
+
cachestore : cache.CacheStore | None, optional
|
|
52
|
+
Cache store for airport database.
|
|
53
|
+
Defaults to :class:`cache.DiskCacheStore`.
|
|
54
|
+
update_cache : bool, optional
|
|
55
|
+
Force update to cached airports database.
|
|
56
|
+
|
|
57
|
+
Returns
|
|
58
|
+
-------
|
|
59
|
+
pd.DataFrame
|
|
60
|
+
Processed global airport database.
|
|
61
|
+
|
|
62
|
+
Global airport database.
|
|
63
|
+
|
|
64
|
+
Notes
|
|
65
|
+
-----
|
|
66
|
+
As of 2023 March 30, the global airport database contains:
|
|
67
|
+
|
|
68
|
+
.. csv-table::
|
|
69
|
+
:header: "Airport Type", "Number"
|
|
70
|
+
:widths: 70, 30
|
|
71
|
+
|
|
72
|
+
"small_airport", 39327
|
|
73
|
+
"heliport", 19039
|
|
74
|
+
"closed", 10107
|
|
75
|
+
"medium_airport", 4753
|
|
76
|
+
"seaplane_base", 1133
|
|
77
|
+
"large_airport", 463
|
|
78
|
+
"balloonport", 45
|
|
79
|
+
|
|
80
|
+
References
|
|
81
|
+
----------
|
|
82
|
+
- :cite:`megginsonOpendataDownloadsOurAirports2023`
|
|
83
|
+
"""
|
|
84
|
+
cachestore = cachestore or cache.DiskCacheStore()
|
|
85
|
+
|
|
86
|
+
cache_key = "ourairports-data_airports.csv"
|
|
87
|
+
if cachestore.exists(cache_key) and not update_cache:
|
|
88
|
+
airports = pd.read_csv(cachestore.path(cache_key))
|
|
89
|
+
else:
|
|
90
|
+
airports = _download_ourairports_csv()
|
|
91
|
+
airports.to_csv(cachestore.path(cache_key), index=False)
|
|
92
|
+
|
|
93
|
+
#: Format dataset by renaming columns & filling nan values
|
|
94
|
+
airports = airports.rename(
|
|
95
|
+
columns={"latitude_deg": "latitude", "longitude_deg": "longitude", "gps_code": "icao_code"},
|
|
96
|
+
)
|
|
97
|
+
airports.fillna({"elevation_ft": 0.0}, inplace=True)
|
|
98
|
+
|
|
99
|
+
# Keep specific airport types used by commercial aviation
|
|
100
|
+
subset = ("large_airport", "medium_airport", "small_airport", "heliport")
|
|
101
|
+
select_airport_types = airports["type"].isin(subset)
|
|
102
|
+
|
|
103
|
+
# Keep airports with valid ICAO codes
|
|
104
|
+
select_icao_codes = (airports["icao_code"].str.len() == 4) & (
|
|
105
|
+
airports["icao_code"].str.isalpha()
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
# filter airports
|
|
109
|
+
airports = airports.loc[select_airport_types & select_icao_codes]
|
|
110
|
+
|
|
111
|
+
# Format dataset
|
|
112
|
+
airports["elevation_m"] = units.ft_to_m(airports["elevation_ft"].to_numpy())
|
|
113
|
+
airports = airports.sort_values(by="icao_code", ascending=True)
|
|
114
|
+
|
|
115
|
+
return airports.reset_index(drop=True)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def find_nearest_airport(
|
|
119
|
+
airports: pd.DataFrame,
|
|
120
|
+
longitude: float,
|
|
121
|
+
latitude: float,
|
|
122
|
+
altitude: float,
|
|
123
|
+
*,
|
|
124
|
+
bbox: float = 2.0,
|
|
125
|
+
) -> str | None:
|
|
126
|
+
r"""
|
|
127
|
+
Find airport nearest to the waypoints.
|
|
128
|
+
|
|
129
|
+
Parameters
|
|
130
|
+
----------
|
|
131
|
+
airports: pd.DataFrame
|
|
132
|
+
Airport database in the format returned from :func:`global_airport_database`.
|
|
133
|
+
longitude: float
|
|
134
|
+
Waypoint longitude, [:math:`\deg`]
|
|
135
|
+
latitude: float
|
|
136
|
+
Waypoint latitude, [:math:`\deg`]
|
|
137
|
+
altitude: float
|
|
138
|
+
Waypoint altitude, [:math:`m`]
|
|
139
|
+
bbox: float
|
|
140
|
+
Search airports within spatial bounding box of ± `bbox` from the waypoint, [:math:`\deg`]
|
|
141
|
+
Defaults to :math:`2\deg`
|
|
142
|
+
|
|
143
|
+
Returns
|
|
144
|
+
-------
|
|
145
|
+
str | None
|
|
146
|
+
ICAO code of nearest airport.
|
|
147
|
+
Returns None if no airport is found within ``bbox``.
|
|
148
|
+
|
|
149
|
+
Notes
|
|
150
|
+
-----
|
|
151
|
+
Function will first search for large airports around the waypoint vicinity.
|
|
152
|
+
If none is found, it will search for medium and small airports
|
|
153
|
+
around the waypoint vicinity.
|
|
154
|
+
|
|
155
|
+
The waypoint must be below 10,000 feet to increase the
|
|
156
|
+
probability of identifying the correct airport.
|
|
157
|
+
"""
|
|
158
|
+
if altitude > 3000:
|
|
159
|
+
raise ValueError(
|
|
160
|
+
f"Altitude ({altitude} m) is too high (> 3000 m) to identify nearest airport."
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
is_near_waypoint = airports["longitude"].between(
|
|
164
|
+
(longitude - bbox), (longitude + bbox)
|
|
165
|
+
) & airports["latitude"].between((latitude - bbox), (latitude + bbox))
|
|
166
|
+
|
|
167
|
+
# Find the nearest airport from largest to smallest airport type
|
|
168
|
+
search_priority = ("large_airport", "medium_airport", "small_airport")
|
|
169
|
+
|
|
170
|
+
for airport_type in search_priority:
|
|
171
|
+
is_airport_type = airports["type"] == airport_type
|
|
172
|
+
nearest_airports = airports.loc[is_near_waypoint & is_airport_type]
|
|
173
|
+
|
|
174
|
+
if len(nearest_airports) == 1:
|
|
175
|
+
return nearest_airports["icao_code"].values[0]
|
|
176
|
+
|
|
177
|
+
if len(nearest_airports) > 1:
|
|
178
|
+
distance = distance_to_airports(
|
|
179
|
+
nearest_airports,
|
|
180
|
+
longitude,
|
|
181
|
+
latitude,
|
|
182
|
+
altitude,
|
|
183
|
+
)
|
|
184
|
+
i_nearest = np.argmin(distance)
|
|
185
|
+
return nearest_airports["icao_code"].values[i_nearest]
|
|
186
|
+
|
|
187
|
+
continue
|
|
188
|
+
|
|
189
|
+
return None
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def distance_to_airports(
|
|
193
|
+
airports: pd.DataFrame,
|
|
194
|
+
longitude: float,
|
|
195
|
+
latitude: float,
|
|
196
|
+
altitude: float,
|
|
197
|
+
) -> np.ndarray:
|
|
198
|
+
r"""
|
|
199
|
+
Calculate the 3D distance from the waypoint to the provided airports.
|
|
200
|
+
|
|
201
|
+
Parameters
|
|
202
|
+
----------
|
|
203
|
+
airports : pd.DataFrame
|
|
204
|
+
Airport database in the format returned from :func:`global_airport_database`.
|
|
205
|
+
longitude : float
|
|
206
|
+
Waypoint longitude, [:math:`\deg`]
|
|
207
|
+
latitude : float
|
|
208
|
+
Waypoint latitude, [:math:`\deg`]
|
|
209
|
+
altitude : float
|
|
210
|
+
Waypoint altitude, [:math:`m`]
|
|
211
|
+
|
|
212
|
+
Returns
|
|
213
|
+
-------
|
|
214
|
+
np.ndarray
|
|
215
|
+
3D distance from waypoint to airports, [:math:`m`]
|
|
216
|
+
|
|
217
|
+
See Also
|
|
218
|
+
--------
|
|
219
|
+
:func:`geo.haversine`
|
|
220
|
+
"""
|
|
221
|
+
dist_horizontal = geo.haversine(
|
|
222
|
+
np.full(airports["longitude"].shape, longitude),
|
|
223
|
+
np.full(airports["latitude"].shape, latitude),
|
|
224
|
+
airports["longitude"].to_numpy(),
|
|
225
|
+
airports["latitude"].to_numpy(),
|
|
226
|
+
)
|
|
227
|
+
dist_vertical = altitude - airports["elevation_m"].to_numpy()
|
|
228
|
+
return (dist_horizontal**2 + dist_vertical**2) ** 0.5
|