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.

Files changed (122) hide show
  1. pycontrails/__init__.py +70 -0
  2. pycontrails/_version.py +34 -0
  3. pycontrails/core/__init__.py +30 -0
  4. pycontrails/core/aircraft_performance.py +679 -0
  5. pycontrails/core/airports.py +228 -0
  6. pycontrails/core/cache.py +889 -0
  7. pycontrails/core/coordinates.py +174 -0
  8. pycontrails/core/fleet.py +483 -0
  9. pycontrails/core/flight.py +2185 -0
  10. pycontrails/core/flightplan.py +228 -0
  11. pycontrails/core/fuel.py +140 -0
  12. pycontrails/core/interpolation.py +702 -0
  13. pycontrails/core/met.py +2931 -0
  14. pycontrails/core/met_var.py +387 -0
  15. pycontrails/core/models.py +1321 -0
  16. pycontrails/core/polygon.py +549 -0
  17. pycontrails/core/rgi_cython.cpython-314-darwin.so +0 -0
  18. pycontrails/core/vector.py +2249 -0
  19. pycontrails/datalib/__init__.py +12 -0
  20. pycontrails/datalib/_met_utils/metsource.py +746 -0
  21. pycontrails/datalib/ecmwf/__init__.py +73 -0
  22. pycontrails/datalib/ecmwf/arco_era5.py +345 -0
  23. pycontrails/datalib/ecmwf/common.py +114 -0
  24. pycontrails/datalib/ecmwf/era5.py +554 -0
  25. pycontrails/datalib/ecmwf/era5_model_level.py +490 -0
  26. pycontrails/datalib/ecmwf/hres.py +804 -0
  27. pycontrails/datalib/ecmwf/hres_model_level.py +466 -0
  28. pycontrails/datalib/ecmwf/ifs.py +287 -0
  29. pycontrails/datalib/ecmwf/model_levels.py +435 -0
  30. pycontrails/datalib/ecmwf/static/model_level_dataframe_v20240418.csv +139 -0
  31. pycontrails/datalib/ecmwf/variables.py +268 -0
  32. pycontrails/datalib/geo_utils.py +261 -0
  33. pycontrails/datalib/gfs/__init__.py +28 -0
  34. pycontrails/datalib/gfs/gfs.py +656 -0
  35. pycontrails/datalib/gfs/variables.py +104 -0
  36. pycontrails/datalib/goes.py +757 -0
  37. pycontrails/datalib/himawari/__init__.py +27 -0
  38. pycontrails/datalib/himawari/header_struct.py +266 -0
  39. pycontrails/datalib/himawari/himawari.py +667 -0
  40. pycontrails/datalib/landsat.py +589 -0
  41. pycontrails/datalib/leo_utils/__init__.py +5 -0
  42. pycontrails/datalib/leo_utils/correction.py +266 -0
  43. pycontrails/datalib/leo_utils/landsat_metadata.py +300 -0
  44. pycontrails/datalib/leo_utils/search.py +250 -0
  45. pycontrails/datalib/leo_utils/sentinel_metadata.py +748 -0
  46. pycontrails/datalib/leo_utils/static/bq_roi_query.sql +6 -0
  47. pycontrails/datalib/leo_utils/vis.py +59 -0
  48. pycontrails/datalib/sentinel.py +650 -0
  49. pycontrails/datalib/spire/__init__.py +5 -0
  50. pycontrails/datalib/spire/exceptions.py +62 -0
  51. pycontrails/datalib/spire/spire.py +604 -0
  52. pycontrails/ext/bada.py +42 -0
  53. pycontrails/ext/cirium.py +14 -0
  54. pycontrails/ext/empirical_grid.py +140 -0
  55. pycontrails/ext/synthetic_flight.py +431 -0
  56. pycontrails/models/__init__.py +1 -0
  57. pycontrails/models/accf.py +425 -0
  58. pycontrails/models/apcemm/__init__.py +8 -0
  59. pycontrails/models/apcemm/apcemm.py +983 -0
  60. pycontrails/models/apcemm/inputs.py +226 -0
  61. pycontrails/models/apcemm/static/apcemm_yaml_template.yaml +183 -0
  62. pycontrails/models/apcemm/utils.py +437 -0
  63. pycontrails/models/cocip/__init__.py +29 -0
  64. pycontrails/models/cocip/cocip.py +2742 -0
  65. pycontrails/models/cocip/cocip_params.py +305 -0
  66. pycontrails/models/cocip/cocip_uncertainty.py +291 -0
  67. pycontrails/models/cocip/contrail_properties.py +1530 -0
  68. pycontrails/models/cocip/output_formats.py +2270 -0
  69. pycontrails/models/cocip/radiative_forcing.py +1260 -0
  70. pycontrails/models/cocip/radiative_heating.py +520 -0
  71. pycontrails/models/cocip/unterstrasser_wake_vortex.py +508 -0
  72. pycontrails/models/cocip/wake_vortex.py +396 -0
  73. pycontrails/models/cocip/wind_shear.py +120 -0
  74. pycontrails/models/cocipgrid/__init__.py +9 -0
  75. pycontrails/models/cocipgrid/cocip_grid.py +2552 -0
  76. pycontrails/models/cocipgrid/cocip_grid_params.py +138 -0
  77. pycontrails/models/dry_advection.py +602 -0
  78. pycontrails/models/emissions/__init__.py +21 -0
  79. pycontrails/models/emissions/black_carbon.py +599 -0
  80. pycontrails/models/emissions/emissions.py +1353 -0
  81. pycontrails/models/emissions/ffm2.py +336 -0
  82. pycontrails/models/emissions/static/default-engine-uids.csv +239 -0
  83. pycontrails/models/emissions/static/edb-gaseous-v29b-engines.csv +596 -0
  84. pycontrails/models/emissions/static/edb-nvpm-v29b-engines.csv +215 -0
  85. pycontrails/models/extended_k15.py +1327 -0
  86. pycontrails/models/humidity_scaling/__init__.py +37 -0
  87. pycontrails/models/humidity_scaling/humidity_scaling.py +1075 -0
  88. pycontrails/models/humidity_scaling/quantiles/era5-model-level-quantiles.pq +0 -0
  89. pycontrails/models/humidity_scaling/quantiles/era5-pressure-level-quantiles.pq +0 -0
  90. pycontrails/models/issr.py +210 -0
  91. pycontrails/models/pcc.py +326 -0
  92. pycontrails/models/pcr.py +154 -0
  93. pycontrails/models/ps_model/__init__.py +18 -0
  94. pycontrails/models/ps_model/ps_aircraft_params.py +381 -0
  95. pycontrails/models/ps_model/ps_grid.py +701 -0
  96. pycontrails/models/ps_model/ps_model.py +1000 -0
  97. pycontrails/models/ps_model/ps_operational_limits.py +525 -0
  98. pycontrails/models/ps_model/static/ps-aircraft-params-20250328.csv +69 -0
  99. pycontrails/models/ps_model/static/ps-synonym-list-20250328.csv +104 -0
  100. pycontrails/models/sac.py +442 -0
  101. pycontrails/models/tau_cirrus.py +183 -0
  102. pycontrails/physics/__init__.py +1 -0
  103. pycontrails/physics/constants.py +117 -0
  104. pycontrails/physics/geo.py +1138 -0
  105. pycontrails/physics/jet.py +968 -0
  106. pycontrails/physics/static/iata-cargo-load-factors-20250221.csv +74 -0
  107. pycontrails/physics/static/iata-passenger-load-factors-20250221.csv +74 -0
  108. pycontrails/physics/thermo.py +551 -0
  109. pycontrails/physics/units.py +472 -0
  110. pycontrails/py.typed +0 -0
  111. pycontrails/utils/__init__.py +1 -0
  112. pycontrails/utils/dependencies.py +66 -0
  113. pycontrails/utils/iteration.py +13 -0
  114. pycontrails/utils/json.py +187 -0
  115. pycontrails/utils/temp.py +50 -0
  116. pycontrails/utils/types.py +163 -0
  117. pycontrails-0.58.0.dist-info/METADATA +180 -0
  118. pycontrails-0.58.0.dist-info/RECORD +122 -0
  119. pycontrails-0.58.0.dist-info/WHEEL +6 -0
  120. pycontrails-0.58.0.dist-info/licenses/LICENSE +178 -0
  121. pycontrails-0.58.0.dist-info/licenses/NOTICE +43 -0
  122. 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