pycontrails 0.54.3__cp313-cp313-macosx_11_0_arm64.whl → 0.54.5__cp313-cp313-macosx_11_0_arm64.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 +2 -2
- pycontrails/_version.py +2 -2
- pycontrails/core/__init__.py +1 -1
- pycontrails/core/aircraft_performance.py +58 -58
- pycontrails/core/cache.py +7 -7
- pycontrails/core/fleet.py +54 -29
- pycontrails/core/flight.py +218 -301
- pycontrails/core/interpolation.py +63 -60
- pycontrails/core/met.py +193 -125
- pycontrails/core/models.py +27 -13
- pycontrails/core/polygon.py +15 -15
- pycontrails/core/rgi_cython.cpython-313-darwin.so +0 -0
- pycontrails/core/vector.py +119 -96
- pycontrails/datalib/_met_utils/metsource.py +8 -5
- pycontrails/datalib/ecmwf/__init__.py +14 -14
- pycontrails/datalib/ecmwf/common.py +1 -1
- pycontrails/datalib/ecmwf/era5.py +7 -7
- pycontrails/datalib/ecmwf/hres.py +3 -3
- pycontrails/datalib/ecmwf/ifs.py +1 -1
- pycontrails/datalib/gfs/__init__.py +6 -6
- pycontrails/datalib/gfs/gfs.py +2 -2
- pycontrails/datalib/goes.py +5 -5
- pycontrails/ext/empirical_grid.py +1 -1
- pycontrails/models/apcemm/apcemm.py +5 -5
- pycontrails/models/apcemm/utils.py +1 -1
- pycontrails/models/cocip/__init__.py +2 -2
- pycontrails/models/cocip/cocip.py +23 -24
- pycontrails/models/cocip/cocip_params.py +2 -11
- pycontrails/models/cocip/cocip_uncertainty.py +24 -18
- pycontrails/models/cocip/contrail_properties.py +331 -316
- pycontrails/models/cocip/output_formats.py +53 -53
- pycontrails/models/cocip/radiative_forcing.py +135 -131
- pycontrails/models/cocip/radiative_heating.py +135 -135
- pycontrails/models/cocip/unterstrasser_wake_vortex.py +90 -87
- pycontrails/models/cocip/wake_vortex.py +92 -92
- pycontrails/models/cocip/wind_shear.py +8 -8
- pycontrails/models/cocipgrid/cocip_grid.py +37 -96
- pycontrails/models/dry_advection.py +60 -19
- pycontrails/models/emissions/__init__.py +2 -2
- pycontrails/models/emissions/black_carbon.py +108 -108
- pycontrails/models/emissions/emissions.py +87 -87
- pycontrails/models/emissions/ffm2.py +35 -35
- pycontrails/models/humidity_scaling/humidity_scaling.py +23 -23
- pycontrails/models/issr.py +2 -2
- pycontrails/models/ps_model/__init__.py +1 -1
- pycontrails/models/ps_model/ps_aircraft_params.py +8 -4
- pycontrails/models/ps_model/ps_grid.py +76 -66
- pycontrails/models/ps_model/ps_model.py +16 -16
- pycontrails/models/ps_model/ps_operational_limits.py +20 -18
- pycontrails/models/tau_cirrus.py +8 -1
- pycontrails/physics/geo.py +67 -67
- pycontrails/physics/jet.py +79 -79
- pycontrails/physics/units.py +14 -14
- pycontrails/utils/json.py +1 -2
- pycontrails/utils/types.py +12 -7
- {pycontrails-0.54.3.dist-info → pycontrails-0.54.5.dist-info}/METADATA +2 -2
- {pycontrails-0.54.3.dist-info → pycontrails-0.54.5.dist-info}/NOTICE +1 -1
- pycontrails-0.54.5.dist-info/RECORD +111 -0
- pycontrails-0.54.3.dist-info/RECORD +0 -111
- {pycontrails-0.54.3.dist-info → pycontrails-0.54.5.dist-info}/LICENSE +0 -0
- {pycontrails-0.54.3.dist-info → pycontrails-0.54.5.dist-info}/WHEEL +0 -0
- {pycontrails-0.54.3.dist-info → pycontrails-0.54.5.dist-info}/top_level.txt +0 -0
pycontrails/physics/jet.py
CHANGED
|
@@ -31,20 +31,20 @@ CLF_PATH = _path_to_static / "iata-cargo-load-factors-20241115.csv"
|
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
def acceleration(
|
|
34
|
-
true_airspeed: npt.NDArray[np.
|
|
35
|
-
) -> npt.NDArray[np.
|
|
34
|
+
true_airspeed: npt.NDArray[np.floating], segment_duration: npt.NDArray[np.floating]
|
|
35
|
+
) -> npt.NDArray[np.floating]:
|
|
36
36
|
r"""Calculate the acceleration/deceleration at each waypoint.
|
|
37
37
|
|
|
38
38
|
Parameters
|
|
39
39
|
----------
|
|
40
|
-
true_airspeed : npt.NDArray[np.
|
|
40
|
+
true_airspeed : npt.NDArray[np.floating]
|
|
41
41
|
True airspeed, [:math:`m \ s^{-1}`]
|
|
42
|
-
segment_duration : npt.NDArray[np.
|
|
42
|
+
segment_duration : npt.NDArray[np.floating]
|
|
43
43
|
Time difference between waypoints, [:math:`s`]
|
|
44
44
|
|
|
45
45
|
Returns
|
|
46
46
|
-------
|
|
47
|
-
npt.NDArray[np.
|
|
47
|
+
npt.NDArray[np.floating]
|
|
48
48
|
Acceleration/deceleration, [:math:`m \ s^{-2}`]
|
|
49
49
|
|
|
50
50
|
See Also
|
|
@@ -59,20 +59,20 @@ def acceleration(
|
|
|
59
59
|
|
|
60
60
|
|
|
61
61
|
def climb_descent_angle(
|
|
62
|
-
true_airspeed: npt.NDArray[np.
|
|
63
|
-
) -> npt.NDArray[np.
|
|
62
|
+
true_airspeed: npt.NDArray[np.floating], rocd: npt.NDArray[np.floating]
|
|
63
|
+
) -> npt.NDArray[np.floating]:
|
|
64
64
|
r"""Calculate angle between the horizontal plane and the actual flight path.
|
|
65
65
|
|
|
66
66
|
Parameters
|
|
67
67
|
----------
|
|
68
|
-
true_airspeed : npt.NDArray[np.
|
|
68
|
+
true_airspeed : npt.NDArray[np.floating]
|
|
69
69
|
True airspeed, [:math:`m \ s^{-1}`]
|
|
70
|
-
rocd : npt.NDArray[np.
|
|
70
|
+
rocd : npt.NDArray[np.floating]
|
|
71
71
|
Rate of climb/descent, [:math:`ft min^{-1}`]
|
|
72
72
|
|
|
73
73
|
Returns
|
|
74
74
|
-------
|
|
75
|
-
npt.NDArray[np.
|
|
75
|
+
npt.NDArray[np.floating]
|
|
76
76
|
Climb (positive value) or descent (negative value) angle, [:math:`\deg`]
|
|
77
77
|
|
|
78
78
|
See Also
|
|
@@ -86,10 +86,10 @@ def climb_descent_angle(
|
|
|
86
86
|
|
|
87
87
|
|
|
88
88
|
def clip_mach_number(
|
|
89
|
-
true_airspeed: npt.NDArray[np.
|
|
90
|
-
air_temperature: npt.NDArray[np.
|
|
89
|
+
true_airspeed: npt.NDArray[np.floating],
|
|
90
|
+
air_temperature: npt.NDArray[np.floating],
|
|
91
91
|
max_mach_number: ArrayOrFloat,
|
|
92
|
-
) -> tuple[npt.NDArray[np.
|
|
92
|
+
) -> tuple[npt.NDArray[np.floating], npt.NDArray[np.floating]]:
|
|
93
93
|
r"""Compute the Mach number from the true airspeed and ambient temperature.
|
|
94
94
|
|
|
95
95
|
This method clips the computed Mach number to the value of ``max_mach_number``.
|
|
@@ -99,9 +99,9 @@ def clip_mach_number(
|
|
|
99
99
|
|
|
100
100
|
Parameters
|
|
101
101
|
----------
|
|
102
|
-
true_airspeed : npt.NDArray[np.
|
|
102
|
+
true_airspeed : npt.NDArray[np.floating]
|
|
103
103
|
Array of true airspeed, [:math:`m \ s^{-1}`]
|
|
104
|
-
air_temperature : npt.NDArray[np.
|
|
104
|
+
air_temperature : npt.NDArray[np.floating]
|
|
105
105
|
Array of ambient temperature, [:math: `K`]
|
|
106
106
|
max_mach_number : ArrayOrFloat
|
|
107
107
|
Maximum mach number associated to aircraft. If no clipping
|
|
@@ -109,10 +109,10 @@ def clip_mach_number(
|
|
|
109
109
|
|
|
110
110
|
Returns
|
|
111
111
|
-------
|
|
112
|
-
true_airspeed : npt.NDArray[np.
|
|
112
|
+
true_airspeed : npt.NDArray[np.floating]
|
|
113
113
|
Array of true airspeed, [:math:`m \ s^{-1}`]. All values are clipped at
|
|
114
114
|
``max_mach_number``.
|
|
115
|
-
mach_num : npt.NDArray[np.
|
|
115
|
+
mach_num : npt.NDArray[np.floating]
|
|
116
116
|
Array of Mach numbers, [:math:`Ma`]. All values are clipped at
|
|
117
117
|
``max_mach_number``.
|
|
118
118
|
"""
|
|
@@ -137,13 +137,13 @@ def clip_mach_number(
|
|
|
137
137
|
|
|
138
138
|
|
|
139
139
|
def overall_propulsion_efficiency(
|
|
140
|
-
true_airspeed: npt.NDArray[np.
|
|
141
|
-
F_thrust: npt.NDArray[np.
|
|
142
|
-
fuel_flow: npt.NDArray[np.
|
|
140
|
+
true_airspeed: npt.NDArray[np.floating],
|
|
141
|
+
F_thrust: npt.NDArray[np.floating],
|
|
142
|
+
fuel_flow: npt.NDArray[np.floating],
|
|
143
143
|
q_fuel: float,
|
|
144
144
|
is_descent: npt.NDArray[np.bool_] | bool | None,
|
|
145
145
|
threshold: float = 0.5,
|
|
146
|
-
) -> npt.NDArray[np.
|
|
146
|
+
) -> npt.NDArray[np.floating]:
|
|
147
147
|
r"""Calculate the overall propulsion efficiency (OPE).
|
|
148
148
|
|
|
149
149
|
Negative OPE values can occur during the descent phase and is clipped to a
|
|
@@ -152,22 +152,22 @@ def overall_propulsion_efficiency(
|
|
|
152
152
|
|
|
153
153
|
Parameters
|
|
154
154
|
----------
|
|
155
|
-
true_airspeed: npt.NDArray[np.
|
|
155
|
+
true_airspeed: npt.NDArray[np.floating]
|
|
156
156
|
True airspeed for each waypoint, [:math:`m s^{-1}`].
|
|
157
|
-
F_thrust: npt.NDArray[np.
|
|
157
|
+
F_thrust: npt.NDArray[np.floating]
|
|
158
158
|
Thrust force provided by the engine, [:math:`N`].
|
|
159
|
-
fuel_flow: npt.NDArray[np.
|
|
159
|
+
fuel_flow: npt.NDArray[np.floating]
|
|
160
160
|
Fuel mass flow rate, [:math:`kg s^{-1}`].
|
|
161
161
|
q_fuel : float
|
|
162
162
|
Lower calorific value (LCV) of fuel, [:math:`J \ kg_{fuel}^{-1}`].
|
|
163
|
-
is_descent : npt.NDArray[np.
|
|
163
|
+
is_descent : npt.NDArray[np.floating] | None
|
|
164
164
|
Boolean array that indicates if a waypoint is in a descent phase.
|
|
165
165
|
threshold : float
|
|
166
166
|
Upper bound for realistic engine efficiency.
|
|
167
167
|
|
|
168
168
|
Returns
|
|
169
169
|
-------
|
|
170
|
-
npt.NDArray[np.
|
|
170
|
+
npt.NDArray[np.floating]
|
|
171
171
|
Overall propulsion efficiency (OPE)
|
|
172
172
|
|
|
173
173
|
References
|
|
@@ -196,49 +196,49 @@ def overall_propulsion_efficiency(
|
|
|
196
196
|
|
|
197
197
|
|
|
198
198
|
def fuel_burn(
|
|
199
|
-
fuel_flow: npt.NDArray[np.
|
|
200
|
-
) -> npt.NDArray[np.
|
|
199
|
+
fuel_flow: npt.NDArray[np.floating], segment_duration: npt.NDArray[np.floating]
|
|
200
|
+
) -> npt.NDArray[np.floating]:
|
|
201
201
|
"""Calculate the fuel consumption at each waypoint.
|
|
202
202
|
|
|
203
203
|
Parameters
|
|
204
204
|
----------
|
|
205
|
-
fuel_flow: npt.NDArray[np.
|
|
205
|
+
fuel_flow: npt.NDArray[np.floating]
|
|
206
206
|
Fuel mass flow rate, [:math:`kg s^{-1}`]
|
|
207
|
-
segment_duration: npt.NDArray[np.
|
|
207
|
+
segment_duration: npt.NDArray[np.floating]
|
|
208
208
|
Time difference between waypoints, [:math:`s`]
|
|
209
209
|
|
|
210
210
|
Returns
|
|
211
211
|
-------
|
|
212
|
-
npt.NDArray[np.
|
|
212
|
+
npt.NDArray[np.floating]
|
|
213
213
|
Fuel consumption at each waypoint, [:math:`kg`]
|
|
214
214
|
"""
|
|
215
215
|
return fuel_flow * segment_duration
|
|
216
216
|
|
|
217
217
|
|
|
218
218
|
def equivalent_fuel_flow_rate_at_sea_level(
|
|
219
|
-
fuel_flow_cruise: npt.NDArray[np.
|
|
220
|
-
theta_amb: npt.NDArray[np.
|
|
221
|
-
delta_amb: npt.NDArray[np.
|
|
222
|
-
mach_num: npt.NDArray[np.
|
|
223
|
-
) -> npt.NDArray[np.
|
|
219
|
+
fuel_flow_cruise: npt.NDArray[np.floating],
|
|
220
|
+
theta_amb: npt.NDArray[np.floating],
|
|
221
|
+
delta_amb: npt.NDArray[np.floating],
|
|
222
|
+
mach_num: npt.NDArray[np.floating],
|
|
223
|
+
) -> npt.NDArray[np.floating]:
|
|
224
224
|
r"""Convert fuel mass flow rate at cruise conditions to equivalent flow rate at sea level.
|
|
225
225
|
|
|
226
226
|
Refer to Eq. (40) in :cite:`duboisFuelFlowMethod22006`.
|
|
227
227
|
|
|
228
228
|
Parameters
|
|
229
229
|
----------
|
|
230
|
-
fuel_flow_cruise : npt.NDArray[np.
|
|
230
|
+
fuel_flow_cruise : npt.NDArray[np.floating]
|
|
231
231
|
Fuel mass flow rate per engine, [:math:`kg s^{-1}`]
|
|
232
|
-
theta_amb : npt.NDArray[np.
|
|
232
|
+
theta_amb : npt.NDArray[np.floating]
|
|
233
233
|
Ratio of the ambient temperature to the temperature at mean sea-level.
|
|
234
|
-
delta_amb : npt.NDArray[np.
|
|
234
|
+
delta_amb : npt.NDArray[np.floating]
|
|
235
235
|
Ratio of the pressure altitude to the surface pressure.
|
|
236
|
-
mach_num : npt.NDArray[np.
|
|
236
|
+
mach_num : npt.NDArray[np.floating]
|
|
237
237
|
Mach number, [:math: `Ma`]
|
|
238
238
|
|
|
239
239
|
Returns
|
|
240
240
|
-------
|
|
241
|
-
npt.NDArray[np.
|
|
241
|
+
npt.NDArray[np.floating]
|
|
242
242
|
Estimate of fuel flow per engine at sea level, [:math:`kg \ s^{-1}`].
|
|
243
243
|
|
|
244
244
|
References
|
|
@@ -249,18 +249,18 @@ def equivalent_fuel_flow_rate_at_sea_level(
|
|
|
249
249
|
|
|
250
250
|
|
|
251
251
|
def equivalent_fuel_flow_rate_at_cruise(
|
|
252
|
-
fuel_flow_sls: npt.NDArray[np.
|
|
252
|
+
fuel_flow_sls: npt.NDArray[np.floating] | float,
|
|
253
253
|
theta_amb: ArrayOrFloat,
|
|
254
254
|
delta_amb: ArrayOrFloat,
|
|
255
255
|
mach_num: ArrayOrFloat,
|
|
256
|
-
) -> npt.NDArray[np.
|
|
256
|
+
) -> npt.NDArray[np.floating]:
|
|
257
257
|
r"""Convert fuel mass flow rate at sea level to equivalent fuel flow rate at cruise conditions.
|
|
258
258
|
|
|
259
259
|
Refer to Eq. (40) in :cite:`duboisFuelFlowMethod22006`.
|
|
260
260
|
|
|
261
261
|
Parameters
|
|
262
262
|
----------
|
|
263
|
-
fuel_flow_sls : npt.NDArray[np.
|
|
263
|
+
fuel_flow_sls : npt.NDArray[np.floating] | float
|
|
264
264
|
Fuel mass flow rate, [:math:`kg s^{-1}`]
|
|
265
265
|
theta_amb : ArrayOrFloat
|
|
266
266
|
Ratio of the ambient temperature to the temperature at mean sea-level.
|
|
@@ -271,7 +271,7 @@ def equivalent_fuel_flow_rate_at_cruise(
|
|
|
271
271
|
|
|
272
272
|
Returns
|
|
273
273
|
-------
|
|
274
|
-
npt.NDArray[np.
|
|
274
|
+
npt.NDArray[np.floating]
|
|
275
275
|
Estimate of fuel mass flow rate at sea level, [:math:`kg \ s^{-1}`]
|
|
276
276
|
|
|
277
277
|
References
|
|
@@ -285,28 +285,28 @@ def equivalent_fuel_flow_rate_at_cruise(
|
|
|
285
285
|
|
|
286
286
|
|
|
287
287
|
def reserve_fuel_requirements(
|
|
288
|
-
rocd: npt.NDArray[np.
|
|
289
|
-
altitude_ft: npt.NDArray[np.
|
|
290
|
-
fuel_flow: npt.NDArray[np.
|
|
291
|
-
fuel_burn: npt.NDArray[np.
|
|
288
|
+
rocd: npt.NDArray[np.floating],
|
|
289
|
+
altitude_ft: npt.NDArray[np.floating],
|
|
290
|
+
fuel_flow: npt.NDArray[np.floating],
|
|
291
|
+
fuel_burn: npt.NDArray[np.floating],
|
|
292
292
|
) -> float:
|
|
293
293
|
r"""
|
|
294
294
|
Estimate reserve fuel requirements.
|
|
295
295
|
|
|
296
296
|
Parameters
|
|
297
297
|
----------
|
|
298
|
-
rocd: npt.NDArray[np.
|
|
298
|
+
rocd: npt.NDArray[np.floating]
|
|
299
299
|
Rate of climb and descent, [:math:`ft \ min^{-1}`]
|
|
300
|
-
altitude_ft: npt.NDArray[np.
|
|
300
|
+
altitude_ft: npt.NDArray[np.floating]
|
|
301
301
|
Altitude, [:math:`ft`]
|
|
302
|
-
fuel_flow: npt.NDArray[np.
|
|
302
|
+
fuel_flow: npt.NDArray[np.floating]
|
|
303
303
|
Fuel mass flow rate, [:math:`kg \ s^{-1}`].
|
|
304
|
-
fuel_burn: npt.NDArray[np.
|
|
304
|
+
fuel_burn: npt.NDArray[np.floating]
|
|
305
305
|
Fuel consumption for each waypoint, [:math:`kg`]
|
|
306
306
|
|
|
307
307
|
Returns
|
|
308
308
|
-------
|
|
309
|
-
npt.NDArray[np.
|
|
309
|
+
npt.NDArray[np.floating]
|
|
310
310
|
Reserve fuel requirements, [:math:`kg`]
|
|
311
311
|
|
|
312
312
|
References
|
|
@@ -553,11 +553,11 @@ def update_aircraft_mass(
|
|
|
553
553
|
operating_empty_weight: float,
|
|
554
554
|
max_takeoff_weight: float,
|
|
555
555
|
max_payload: float,
|
|
556
|
-
fuel_burn: npt.NDArray[np.
|
|
556
|
+
fuel_burn: npt.NDArray[np.floating],
|
|
557
557
|
total_reserve_fuel: float,
|
|
558
558
|
load_factor: float,
|
|
559
559
|
takeoff_mass: float | None,
|
|
560
|
-
) -> npt.NDArray[np.
|
|
560
|
+
) -> npt.NDArray[np.floating]:
|
|
561
561
|
"""Update aircraft mass based on the simulated total fuel consumption.
|
|
562
562
|
|
|
563
563
|
Used internally for finding aircraft mass iteratively.
|
|
@@ -573,7 +573,7 @@ def update_aircraft_mass(
|
|
|
573
573
|
Aircraft maximum take-off weight, [:math:`kg`].
|
|
574
574
|
max_payload: float
|
|
575
575
|
Aircraft maximum payload, [:math:`kg`]
|
|
576
|
-
fuel_burn: npt.NDArray[np.
|
|
576
|
+
fuel_burn: npt.NDArray[np.floating]
|
|
577
577
|
Fuel consumption for each waypoint, [:math:`kg`]
|
|
578
578
|
total_reserve_fuel: float
|
|
579
579
|
Total reserve fuel requirements, [:math:`kg`]
|
|
@@ -587,7 +587,7 @@ def update_aircraft_mass(
|
|
|
587
587
|
|
|
588
588
|
Returns
|
|
589
589
|
-------
|
|
590
|
-
npt.NDArray[np.
|
|
590
|
+
npt.NDArray[np.floating]
|
|
591
591
|
Updated aircraft mass, [:math:`kg`]
|
|
592
592
|
|
|
593
593
|
See Also
|
|
@@ -761,30 +761,30 @@ def turbine_inlet_temperature(
|
|
|
761
761
|
|
|
762
762
|
|
|
763
763
|
def thrust_force(
|
|
764
|
-
altitude: npt.NDArray[np.
|
|
765
|
-
true_airspeed: npt.NDArray[np.
|
|
766
|
-
segment_duration: npt.NDArray[np.
|
|
767
|
-
aircraft_mass: npt.NDArray[np.
|
|
768
|
-
F_drag: npt.NDArray[np.
|
|
769
|
-
) -> npt.NDArray[np.
|
|
764
|
+
altitude: npt.NDArray[np.floating],
|
|
765
|
+
true_airspeed: npt.NDArray[np.floating],
|
|
766
|
+
segment_duration: npt.NDArray[np.floating],
|
|
767
|
+
aircraft_mass: npt.NDArray[np.floating],
|
|
768
|
+
F_drag: npt.NDArray[np.floating],
|
|
769
|
+
) -> npt.NDArray[np.floating]:
|
|
770
770
|
r"""Calculate the thrust force at each waypoint.
|
|
771
771
|
|
|
772
772
|
Parameters
|
|
773
773
|
----------
|
|
774
|
-
altitude : npt.NDArray[np.
|
|
774
|
+
altitude : npt.NDArray[np.floating]
|
|
775
775
|
Waypoint altitude, [:math:`m`]
|
|
776
|
-
true_airspeed : npt.NDArray[np.
|
|
776
|
+
true_airspeed : npt.NDArray[np.floating]
|
|
777
777
|
True airspeed, [:math:`m \ s^{-1}`]
|
|
778
|
-
segment_duration : npt.NDArray[np.
|
|
778
|
+
segment_duration : npt.NDArray[np.floating]
|
|
779
779
|
Time difference between waypoints, [:math:`s`]
|
|
780
|
-
aircraft_mass : npt.NDArray[np.
|
|
780
|
+
aircraft_mass : npt.NDArray[np.floating]
|
|
781
781
|
Aircraft mass, [:math:`kg`]
|
|
782
|
-
F_drag : npt.NDArray[np.
|
|
782
|
+
F_drag : npt.NDArray[np.floating]
|
|
783
783
|
Draft force, [:math:`N`]
|
|
784
784
|
|
|
785
785
|
Returns
|
|
786
786
|
-------
|
|
787
|
-
npt.NDArray[np.
|
|
787
|
+
npt.NDArray[np.floating]
|
|
788
788
|
Thrust force, [:math:`N`]
|
|
789
789
|
|
|
790
790
|
References
|
|
@@ -919,49 +919,49 @@ def air_to_fuel_ratio(
|
|
|
919
919
|
# -------------------
|
|
920
920
|
|
|
921
921
|
|
|
922
|
-
def temperature_ratio(T: npt.NDArray[np.
|
|
922
|
+
def temperature_ratio(T: npt.NDArray[np.floating]) -> npt.NDArray[np.floating]:
|
|
923
923
|
"""Calculate the ratio of ambient temperature relative to the temperature at mean sea level.
|
|
924
924
|
|
|
925
925
|
Parameters
|
|
926
926
|
----------
|
|
927
|
-
T : npt.NDArray[np.
|
|
927
|
+
T : npt.NDArray[np.floating]
|
|
928
928
|
Air temperature, [:math:`K`]
|
|
929
929
|
|
|
930
930
|
Returns
|
|
931
931
|
-------
|
|
932
|
-
npt.NDArray[np.
|
|
932
|
+
npt.NDArray[np.floating]
|
|
933
933
|
Ratio of the temperature to the temperature at mean sea-level (MSL).
|
|
934
934
|
"""
|
|
935
935
|
return T / constants.T_msl
|
|
936
936
|
|
|
937
937
|
|
|
938
|
-
def pressure_ratio(p: npt.NDArray[np.
|
|
938
|
+
def pressure_ratio(p: npt.NDArray[np.floating]) -> npt.NDArray[np.floating]:
|
|
939
939
|
"""Calculate the ratio of ambient pressure relative to the surface pressure.
|
|
940
940
|
|
|
941
941
|
Parameters
|
|
942
942
|
----------
|
|
943
|
-
p : npt.NDArray[np.
|
|
943
|
+
p : npt.NDArray[np.floating]
|
|
944
944
|
Air pressure, [:math:`Pa`]
|
|
945
945
|
|
|
946
946
|
Returns
|
|
947
947
|
-------
|
|
948
|
-
npt.NDArray[np.
|
|
948
|
+
npt.NDArray[np.floating]
|
|
949
949
|
Ratio of the pressure altitude to the surface pressure.
|
|
950
950
|
"""
|
|
951
951
|
return p / constants.p_surface
|
|
952
952
|
|
|
953
953
|
|
|
954
|
-
def density_ratio(rho: npt.NDArray[np.
|
|
954
|
+
def density_ratio(rho: npt.NDArray[np.floating]) -> npt.NDArray[np.floating]:
|
|
955
955
|
r"""Calculate the ratio of air density relative to the air density at mean-sea-level.
|
|
956
956
|
|
|
957
957
|
Parameters
|
|
958
958
|
----------
|
|
959
|
-
rho : npt.NDArray[np.
|
|
959
|
+
rho : npt.NDArray[np.floating]
|
|
960
960
|
Air density, [:math:`kg \ m^{3}`]
|
|
961
961
|
|
|
962
962
|
Returns
|
|
963
963
|
-------
|
|
964
|
-
npt.NDArray[np.
|
|
964
|
+
npt.NDArray[np.floating]
|
|
965
965
|
Ratio of the density to the air density at mean sea-level (MSL).
|
|
966
966
|
"""
|
|
967
967
|
return rho / constants.rho_msl
|
pycontrails/physics/units.py
CHANGED
|
@@ -106,13 +106,13 @@ def m_to_T_isa(h: ArrayScalarLike) -> ArrayScalarLike:
|
|
|
106
106
|
return constants.T_msl + h_min * constants.T_lapse_rate # type: ignore[return-value]
|
|
107
107
|
|
|
108
108
|
|
|
109
|
-
def _low_altitude_m_to_pl(h: npt.NDArray[np.
|
|
109
|
+
def _low_altitude_m_to_pl(h: npt.NDArray[np.floating]) -> npt.NDArray[np.floating]:
|
|
110
110
|
T_isa: np.ndarray = m_to_T_isa(h)
|
|
111
111
|
power_term = -constants.g / (constants.T_lapse_rate * constants.R_d)
|
|
112
112
|
return (constants.p_surface * (T_isa / constants.T_msl) ** power_term) / 100.0
|
|
113
113
|
|
|
114
114
|
|
|
115
|
-
def _high_altitude_m_to_pl(h: npt.NDArray[np.
|
|
115
|
+
def _high_altitude_m_to_pl(h: npt.NDArray[np.floating]) -> npt.NDArray[np.floating]:
|
|
116
116
|
T_tropopause_isa = m_to_T_isa(np.asarray(constants.h_tropopause))
|
|
117
117
|
power_term = -constants.g / (constants.T_lapse_rate * constants.R_d)
|
|
118
118
|
p_tropopause_isa = constants.p_surface * (T_tropopause_isa / constants.T_msl) ** power_term
|
|
@@ -121,17 +121,17 @@ def _high_altitude_m_to_pl(h: npt.NDArray[np.float64]) -> npt.NDArray[np.float64
|
|
|
121
121
|
|
|
122
122
|
|
|
123
123
|
@support_arraylike
|
|
124
|
-
def m_to_pl(h: npt.NDArray[np.
|
|
124
|
+
def m_to_pl(h: npt.NDArray[np.floating]) -> npt.NDArray[np.floating]:
|
|
125
125
|
r"""Convert from altitude (m) to pressure level (hPa).
|
|
126
126
|
|
|
127
127
|
Parameters
|
|
128
128
|
----------
|
|
129
|
-
h : npt.NDArray[np.
|
|
129
|
+
h : npt.NDArray[np.floating]
|
|
130
130
|
altitude, [:math:`m`]
|
|
131
131
|
|
|
132
132
|
Returns
|
|
133
133
|
-------
|
|
134
|
-
npt.NDArray[np.
|
|
134
|
+
npt.NDArray[np.floating]
|
|
135
135
|
pressure level, [:math:`hPa`], [:math:`mbar`]
|
|
136
136
|
|
|
137
137
|
References
|
|
@@ -152,14 +152,14 @@ def m_to_pl(h: npt.NDArray[np.float64]) -> npt.NDArray[np.float64]:
|
|
|
152
152
|
return np.piecewise(h, condlist, funclist)
|
|
153
153
|
|
|
154
154
|
|
|
155
|
-
def _low_altitude_pl_to_m(pl: npt.NDArray[np.
|
|
155
|
+
def _low_altitude_pl_to_m(pl: npt.NDArray[np.floating]) -> npt.NDArray[np.floating]:
|
|
156
156
|
base = 100.0 * pl / constants.p_surface
|
|
157
157
|
exponent = -constants.T_lapse_rate * constants.R_d / constants.g
|
|
158
158
|
T_isa = constants.T_msl * base**exponent
|
|
159
159
|
return (T_isa - constants.T_msl) / constants.T_lapse_rate
|
|
160
160
|
|
|
161
161
|
|
|
162
|
-
def _high_altitude_pl_to_m(pl: npt.NDArray[np.
|
|
162
|
+
def _high_altitude_pl_to_m(pl: npt.NDArray[np.floating]) -> npt.NDArray[np.floating]:
|
|
163
163
|
T_tropopause_isa = m_to_T_isa(np.asarray(constants.h_tropopause))
|
|
164
164
|
power_term = -constants.g / (constants.T_lapse_rate * constants.R_d)
|
|
165
165
|
p_tropopause_isa = constants.p_surface * (T_tropopause_isa / constants.T_msl) ** power_term
|
|
@@ -168,7 +168,7 @@ def _high_altitude_pl_to_m(pl: npt.NDArray[np.float64]) -> npt.NDArray[np.float6
|
|
|
168
168
|
|
|
169
169
|
|
|
170
170
|
@support_arraylike
|
|
171
|
-
def pl_to_m(pl: npt.NDArray[np.
|
|
171
|
+
def pl_to_m(pl: npt.NDArray[np.floating]) -> npt.NDArray[np.floating]:
|
|
172
172
|
r"""Convert from pressure level (hPa) to altitude (m).
|
|
173
173
|
|
|
174
174
|
Function is slightly different from the classical formula:
|
|
@@ -410,20 +410,20 @@ def tas_to_mach_number(true_airspeed: ArrayScalarLike, T: ArrayScalarLike) -> Ar
|
|
|
410
410
|
|
|
411
411
|
|
|
412
412
|
def mach_number_to_tas(
|
|
413
|
-
mach_number: float | npt.NDArray[np.
|
|
414
|
-
) -> float | npt.NDArray[np.
|
|
413
|
+
mach_number: float | npt.NDArray[np.floating], T: float | npt.NDArray[np.floating]
|
|
414
|
+
) -> float | npt.NDArray[np.floating]:
|
|
415
415
|
r"""Calculate true airspeed from the Mach number at a specified ambient temperature.
|
|
416
416
|
|
|
417
417
|
Parameters
|
|
418
418
|
----------
|
|
419
|
-
mach_number : float | npt.NDArray[np.
|
|
419
|
+
mach_number : float | npt.NDArray[np.floating]
|
|
420
420
|
Mach number, [:math: `Ma`]
|
|
421
|
-
T : npt.NDArray[np.
|
|
421
|
+
T : npt.NDArray[np.floating]
|
|
422
422
|
Ambient temperature, [:math:`K`]
|
|
423
423
|
|
|
424
424
|
Returns
|
|
425
425
|
-------
|
|
426
|
-
npt.NDArray[np.
|
|
426
|
+
npt.NDArray[np.floating]
|
|
427
427
|
True airspeed, [:math:`m \ s^{-1}`]
|
|
428
428
|
|
|
429
429
|
References
|
|
@@ -452,7 +452,7 @@ def lbs_to_kg(lbs: ArrayScalarLike) -> ArrayScalarLike:
|
|
|
452
452
|
def dt_to_seconds(
|
|
453
453
|
dt: npt.NDArray[np.timedelta64] | np.timedelta64,
|
|
454
454
|
dtype: npt.DTypeLike = np.float64,
|
|
455
|
-
) -> npt.NDArray[np.
|
|
455
|
+
) -> npt.NDArray[np.floating]:
|
|
456
456
|
"""Convert a time delta to seconds as a float with specified ``dtype`` precision.
|
|
457
457
|
|
|
458
458
|
Parameters
|
pycontrails/utils/json.py
CHANGED
|
@@ -172,8 +172,7 @@ def dataframe_to_geojson_points(
|
|
|
172
172
|
k: (
|
|
173
173
|
row[k]
|
|
174
174
|
if not isinstance(row[k], float)
|
|
175
|
-
or isinstance(row[k], float)
|
|
176
|
-
and not np.isnan(row[k])
|
|
175
|
+
or (isinstance(row[k], float) and not np.isnan(row[k]))
|
|
177
176
|
else None
|
|
178
177
|
)
|
|
179
178
|
for k in unused_keys
|
pycontrails/utils/types.py
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import functools
|
|
6
|
+
import sys
|
|
6
7
|
from collections.abc import Callable
|
|
7
8
|
from datetime import datetime
|
|
8
9
|
from typing import Any, TypeVar
|
|
@@ -16,16 +17,13 @@ import xarray as xr
|
|
|
16
17
|
ArrayLike = TypeVar("ArrayLike", np.ndarray, xr.DataArray, xr.DataArray | np.ndarray)
|
|
17
18
|
|
|
18
19
|
#: Array or Float (np.ndarray, float)
|
|
19
|
-
ArrayOrFloat = TypeVar(
|
|
20
|
-
"ArrayOrFloat", npt.NDArray[np.float64], float, float | npt.NDArray[np.float64]
|
|
21
|
-
)
|
|
20
|
+
ArrayOrFloat = TypeVar("ArrayOrFloat", npt.NDArray[np.floating], float)
|
|
22
21
|
|
|
23
|
-
#: Array like input (np.ndarray, xr.DataArray,
|
|
22
|
+
#: Array like input (np.ndarray, xr.DataArray, float)
|
|
24
23
|
ArrayScalarLike = TypeVar(
|
|
25
24
|
"ArrayScalarLike",
|
|
26
25
|
np.ndarray,
|
|
27
26
|
xr.DataArray,
|
|
28
|
-
np.float64,
|
|
29
27
|
float,
|
|
30
28
|
np.ndarray | float,
|
|
31
29
|
xr.DataArray | np.ndarray,
|
|
@@ -34,9 +32,16 @@ ArrayScalarLike = TypeVar(
|
|
|
34
32
|
#: Datetime like input (datetime, pd.Timestamp, np.datetime64)
|
|
35
33
|
DatetimeLike = TypeVar("DatetimeLike", datetime, pd.Timestamp, np.datetime64, str)
|
|
36
34
|
|
|
35
|
+
# Crude fix for autodoc issue calling TypeVar.__dict__ on Python 3.13
|
|
36
|
+
if "sphinx" in sys.modules and sys.version_info >= (3, 13):
|
|
37
|
+
ArrayLike.__dict__ = {}
|
|
38
|
+
ArrayOrFloat.__dict__ = {}
|
|
39
|
+
ArrayScalarLike.__dict__ = {}
|
|
40
|
+
DatetimeLike.__dict__ = {}
|
|
41
|
+
|
|
37
42
|
|
|
38
43
|
def support_arraylike(
|
|
39
|
-
func: Callable[[np.
|
|
44
|
+
func: Callable[[npt.NDArray[np.floating]], npt.NDArray[np.floating]],
|
|
40
45
|
) -> Callable[[ArrayScalarLike], ArrayScalarLike]:
|
|
41
46
|
"""Extend a numpy universal function operating on arrays of floats.
|
|
42
47
|
|
|
@@ -72,7 +77,7 @@ def support_arraylike(
|
|
|
72
77
|
return ret
|
|
73
78
|
|
|
74
79
|
# Keep python native numeric types native
|
|
75
|
-
if isinstance(arr, float | int
|
|
80
|
+
if isinstance(arr, float | int):
|
|
76
81
|
return ret.item()
|
|
77
82
|
|
|
78
83
|
# Recreate pd.Series
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pycontrails
|
|
3
|
-
Version: 0.54.
|
|
3
|
+
Version: 0.54.5
|
|
4
4
|
Summary: Python library for modeling aviation climate impacts
|
|
5
5
|
Author-email: Breakthrough Energy <py@contrails.org>
|
|
6
6
|
License: Apache-2.0
|
|
@@ -49,7 +49,7 @@ Requires-Dist: pyarrow>=5.0; extra == "dev"
|
|
|
49
49
|
Requires-Dist: pytest>=8.2; extra == "dev"
|
|
50
50
|
Requires-Dist: pytest-cov>=2.11; extra == "dev"
|
|
51
51
|
Requires-Dist: requests>=2.25; extra == "dev"
|
|
52
|
-
Requires-Dist: ruff==0.
|
|
52
|
+
Requires-Dist: ruff==0.8.0; extra == "dev"
|
|
53
53
|
Requires-Dist: setuptools; extra == "dev"
|
|
54
54
|
Provides-Extra: docs
|
|
55
55
|
Requires-Dist: doc8>=1.1; extra == "docs"
|