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.

Files changed (62) hide show
  1. pycontrails/__init__.py +2 -2
  2. pycontrails/_version.py +2 -2
  3. pycontrails/core/__init__.py +1 -1
  4. pycontrails/core/aircraft_performance.py +58 -58
  5. pycontrails/core/cache.py +7 -7
  6. pycontrails/core/fleet.py +54 -29
  7. pycontrails/core/flight.py +218 -301
  8. pycontrails/core/interpolation.py +63 -60
  9. pycontrails/core/met.py +193 -125
  10. pycontrails/core/models.py +27 -13
  11. pycontrails/core/polygon.py +15 -15
  12. pycontrails/core/rgi_cython.cpython-313-darwin.so +0 -0
  13. pycontrails/core/vector.py +119 -96
  14. pycontrails/datalib/_met_utils/metsource.py +8 -5
  15. pycontrails/datalib/ecmwf/__init__.py +14 -14
  16. pycontrails/datalib/ecmwf/common.py +1 -1
  17. pycontrails/datalib/ecmwf/era5.py +7 -7
  18. pycontrails/datalib/ecmwf/hres.py +3 -3
  19. pycontrails/datalib/ecmwf/ifs.py +1 -1
  20. pycontrails/datalib/gfs/__init__.py +6 -6
  21. pycontrails/datalib/gfs/gfs.py +2 -2
  22. pycontrails/datalib/goes.py +5 -5
  23. pycontrails/ext/empirical_grid.py +1 -1
  24. pycontrails/models/apcemm/apcemm.py +5 -5
  25. pycontrails/models/apcemm/utils.py +1 -1
  26. pycontrails/models/cocip/__init__.py +2 -2
  27. pycontrails/models/cocip/cocip.py +23 -24
  28. pycontrails/models/cocip/cocip_params.py +2 -11
  29. pycontrails/models/cocip/cocip_uncertainty.py +24 -18
  30. pycontrails/models/cocip/contrail_properties.py +331 -316
  31. pycontrails/models/cocip/output_formats.py +53 -53
  32. pycontrails/models/cocip/radiative_forcing.py +135 -131
  33. pycontrails/models/cocip/radiative_heating.py +135 -135
  34. pycontrails/models/cocip/unterstrasser_wake_vortex.py +90 -87
  35. pycontrails/models/cocip/wake_vortex.py +92 -92
  36. pycontrails/models/cocip/wind_shear.py +8 -8
  37. pycontrails/models/cocipgrid/cocip_grid.py +37 -96
  38. pycontrails/models/dry_advection.py +60 -19
  39. pycontrails/models/emissions/__init__.py +2 -2
  40. pycontrails/models/emissions/black_carbon.py +108 -108
  41. pycontrails/models/emissions/emissions.py +87 -87
  42. pycontrails/models/emissions/ffm2.py +35 -35
  43. pycontrails/models/humidity_scaling/humidity_scaling.py +23 -23
  44. pycontrails/models/issr.py +2 -2
  45. pycontrails/models/ps_model/__init__.py +1 -1
  46. pycontrails/models/ps_model/ps_aircraft_params.py +8 -4
  47. pycontrails/models/ps_model/ps_grid.py +76 -66
  48. pycontrails/models/ps_model/ps_model.py +16 -16
  49. pycontrails/models/ps_model/ps_operational_limits.py +20 -18
  50. pycontrails/models/tau_cirrus.py +8 -1
  51. pycontrails/physics/geo.py +67 -67
  52. pycontrails/physics/jet.py +79 -79
  53. pycontrails/physics/units.py +14 -14
  54. pycontrails/utils/json.py +1 -2
  55. pycontrails/utils/types.py +12 -7
  56. {pycontrails-0.54.3.dist-info → pycontrails-0.54.5.dist-info}/METADATA +2 -2
  57. {pycontrails-0.54.3.dist-info → pycontrails-0.54.5.dist-info}/NOTICE +1 -1
  58. pycontrails-0.54.5.dist-info/RECORD +111 -0
  59. pycontrails-0.54.3.dist-info/RECORD +0 -111
  60. {pycontrails-0.54.3.dist-info → pycontrails-0.54.5.dist-info}/LICENSE +0 -0
  61. {pycontrails-0.54.3.dist-info → pycontrails-0.54.5.dist-info}/WHEEL +0 -0
  62. {pycontrails-0.54.3.dist-info → pycontrails-0.54.5.dist-info}/top_level.txt +0 -0
@@ -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.float64], segment_duration: npt.NDArray[np.float64]
35
- ) -> npt.NDArray[np.float64]:
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.float64]
40
+ true_airspeed : npt.NDArray[np.floating]
41
41
  True airspeed, [:math:`m \ s^{-1}`]
42
- segment_duration : npt.NDArray[np.float64]
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.float64]
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.float64], rocd: npt.NDArray[np.float64]
63
- ) -> npt.NDArray[np.float64]:
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.float64]
68
+ true_airspeed : npt.NDArray[np.floating]
69
69
  True airspeed, [:math:`m \ s^{-1}`]
70
- rocd : npt.NDArray[np.float64]
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.float64]
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.float64],
90
- air_temperature: npt.NDArray[np.float64],
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.float64], npt.NDArray[np.float64]]:
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.float64]
102
+ true_airspeed : npt.NDArray[np.floating]
103
103
  Array of true airspeed, [:math:`m \ s^{-1}`]
104
- air_temperature : npt.NDArray[np.float64]
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.float64]
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.float64]
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.float64],
141
- F_thrust: npt.NDArray[np.float64],
142
- fuel_flow: npt.NDArray[np.float64],
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.float64]:
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.float64]
155
+ true_airspeed: npt.NDArray[np.floating]
156
156
  True airspeed for each waypoint, [:math:`m s^{-1}`].
157
- F_thrust: npt.NDArray[np.float64]
157
+ F_thrust: npt.NDArray[np.floating]
158
158
  Thrust force provided by the engine, [:math:`N`].
159
- fuel_flow: npt.NDArray[np.float64]
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.float64] | None
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.float64]
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.float64], segment_duration: npt.NDArray[np.float64]
200
- ) -> npt.NDArray[np.float64]:
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.float64]
205
+ fuel_flow: npt.NDArray[np.floating]
206
206
  Fuel mass flow rate, [:math:`kg s^{-1}`]
207
- segment_duration: npt.NDArray[np.float64]
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.float64]
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.float64],
220
- theta_amb: npt.NDArray[np.float64],
221
- delta_amb: npt.NDArray[np.float64],
222
- mach_num: npt.NDArray[np.float64],
223
- ) -> npt.NDArray[np.float64]:
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.float64]
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.float64]
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.float64]
234
+ delta_amb : npt.NDArray[np.floating]
235
235
  Ratio of the pressure altitude to the surface pressure.
236
- mach_num : npt.NDArray[np.float64]
236
+ mach_num : npt.NDArray[np.floating]
237
237
  Mach number, [:math: `Ma`]
238
238
 
239
239
  Returns
240
240
  -------
241
- npt.NDArray[np.float64]
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.float64] | float,
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.float64]:
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.float64] | float
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.float64]
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.float64],
289
- altitude_ft: npt.NDArray[np.float64],
290
- fuel_flow: npt.NDArray[np.float64],
291
- fuel_burn: npt.NDArray[np.float64],
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.float64]
298
+ rocd: npt.NDArray[np.floating]
299
299
  Rate of climb and descent, [:math:`ft \ min^{-1}`]
300
- altitude_ft: npt.NDArray[np.float64]
300
+ altitude_ft: npt.NDArray[np.floating]
301
301
  Altitude, [:math:`ft`]
302
- fuel_flow: npt.NDArray[np.float64]
302
+ fuel_flow: npt.NDArray[np.floating]
303
303
  Fuel mass flow rate, [:math:`kg \ s^{-1}`].
304
- fuel_burn: npt.NDArray[np.float64]
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.float64]
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.float64],
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.float64]:
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.float64]
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.float64]
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.float64],
765
- true_airspeed: npt.NDArray[np.float64],
766
- segment_duration: npt.NDArray[np.float64],
767
- aircraft_mass: npt.NDArray[np.float64],
768
- F_drag: npt.NDArray[np.float64],
769
- ) -> npt.NDArray[np.float64]:
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.float64]
774
+ altitude : npt.NDArray[np.floating]
775
775
  Waypoint altitude, [:math:`m`]
776
- true_airspeed : npt.NDArray[np.float64]
776
+ true_airspeed : npt.NDArray[np.floating]
777
777
  True airspeed, [:math:`m \ s^{-1}`]
778
- segment_duration : npt.NDArray[np.float64]
778
+ segment_duration : npt.NDArray[np.floating]
779
779
  Time difference between waypoints, [:math:`s`]
780
- aircraft_mass : npt.NDArray[np.float64]
780
+ aircraft_mass : npt.NDArray[np.floating]
781
781
  Aircraft mass, [:math:`kg`]
782
- F_drag : npt.NDArray[np.float64]
782
+ F_drag : npt.NDArray[np.floating]
783
783
  Draft force, [:math:`N`]
784
784
 
785
785
  Returns
786
786
  -------
787
- npt.NDArray[np.float64]
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.float64]) -> npt.NDArray[np.float64]:
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.float64]
927
+ T : npt.NDArray[np.floating]
928
928
  Air temperature, [:math:`K`]
929
929
 
930
930
  Returns
931
931
  -------
932
- npt.NDArray[np.float64]
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.float64]) -> npt.NDArray[np.float64]:
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.float64]
943
+ p : npt.NDArray[np.floating]
944
944
  Air pressure, [:math:`Pa`]
945
945
 
946
946
  Returns
947
947
  -------
948
- npt.NDArray[np.float64]
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.float64]) -> npt.NDArray[np.float64]:
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.float64]
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.float64]
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
@@ -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.float64]) -> npt.NDArray[np.float64]:
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.float64]) -> npt.NDArray[np.float64]:
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.float64]) -> npt.NDArray[np.float64]:
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.float64]
129
+ h : npt.NDArray[np.floating]
130
130
  altitude, [:math:`m`]
131
131
 
132
132
  Returns
133
133
  -------
134
- npt.NDArray[np.float64]
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.float64]) -> npt.NDArray[np.float64]:
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.float64]) -> npt.NDArray[np.float64]:
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.float64]) -> npt.NDArray[np.float64]:
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.float64], T: float | npt.NDArray[np.float64]
414
- ) -> float | npt.NDArray[np.float64]:
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.float64]
419
+ mach_number : float | npt.NDArray[np.floating]
420
420
  Mach number, [:math: `Ma`]
421
- T : npt.NDArray[np.float64]
421
+ T : npt.NDArray[np.floating]
422
422
  Ambient temperature, [:math:`K`]
423
423
 
424
424
  Returns
425
425
  -------
426
- npt.NDArray[np.float64]
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.float64]:
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
@@ -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, np.float64, float)
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.ndarray], np.ndarray],
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 | np.float64):
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
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.6.2; extra == "dev"
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"
@@ -1,4 +1,4 @@
1
- Copyright (c) 2021-2023 Breakthrough Energy
1
+ Copyright (c) 2021-present Breakthrough Energy
2
2
 
3
3
 
4
4
  Attribution