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
@@ -43,9 +43,9 @@ class PycontrailsRegularGridInterpolator(scipy.interpolate.RegularGridInterpolat
43
43
 
44
44
  Parameters
45
45
  ----------
46
- points : tuple[npt.NDArray[np.float64], ...]
46
+ points : tuple[npt.NDArray[np.floating], ...]
47
47
  Coordinates of the grid points.
48
- values : npt.NDArray[np.float64]
48
+ values : npt.NDArray[np.floating]
49
49
  Grid values. The shape of this array must be compatible with the
50
50
  coordinates. An error is raised if the dtype is not ``np.float32``
51
51
  or ``np.float64``.
@@ -59,8 +59,8 @@ class PycontrailsRegularGridInterpolator(scipy.interpolate.RegularGridInterpolat
59
59
 
60
60
  def __init__(
61
61
  self,
62
- points: tuple[npt.NDArray[np.float64], ...],
63
- values: npt.NDArray[np.float64],
62
+ points: tuple[npt.NDArray[np.floating], ...],
63
+ values: npt.NDArray[np.floating],
64
64
  method: str,
65
65
  bounds_error: bool,
66
66
  fill_value: float | np.float64 | None,
@@ -78,12 +78,12 @@ class PycontrailsRegularGridInterpolator(scipy.interpolate.RegularGridInterpolat
78
78
  self.fill_value = fill_value
79
79
  self._spline = None
80
80
 
81
- def _prepare_xi_simple(self, xi: npt.NDArray[np.float64]) -> npt.NDArray[np.bool_]:
81
+ def _prepare_xi_simple(self, xi: npt.NDArray[np.floating]) -> npt.NDArray[np.bool_]:
82
82
  """Run looser version of :meth:`_prepare_xi`.
83
83
 
84
84
  Parameters
85
85
  ----------
86
- xi : npt.NDArray[np.float64]
86
+ xi : npt.NDArray[np.floating]
87
87
  Points at which to interpolate.
88
88
 
89
89
  Returns
@@ -106,13 +106,13 @@ class PycontrailsRegularGridInterpolator(scipy.interpolate.RegularGridInterpolat
106
106
  return self._find_out_of_bounds(xi.T)
107
107
 
108
108
  def __call__(
109
- self, xi: npt.NDArray[np.float64], method: str | None = None
110
- ) -> npt.NDArray[np.float64]:
109
+ self, xi: npt.NDArray[np.floating], method: str | None = None
110
+ ) -> npt.NDArray[np.floating]:
111
111
  """Evaluate the interpolator at the given points.
112
112
 
113
113
  Parameters
114
114
  ----------
115
- xi : npt.NDArray[np.float64]
115
+ xi : npt.NDArray[np.floating]
116
116
  Points at which to interpolate. Must have shape ``(n, ndim)``, where
117
117
  ``ndim`` is the number of dimensions of the interpolator.
118
118
  method : str | None
@@ -120,7 +120,7 @@ class PycontrailsRegularGridInterpolator(scipy.interpolate.RegularGridInterpolat
120
120
 
121
121
  Returns
122
122
  -------
123
- npt.NDArray[np.float64]
123
+ npt.NDArray[np.floating]
124
124
  Interpolated values. Has shape ``(n,)``. When computing linear interpolation,
125
125
  the dtype is the same as the :attr:`values` array.
126
126
  """
@@ -137,21 +137,21 @@ class PycontrailsRegularGridInterpolator(scipy.interpolate.RegularGridInterpolat
137
137
 
138
138
  def _set_out_of_bounds(
139
139
  self,
140
- out: npt.NDArray[np.float64],
140
+ out: npt.NDArray[np.floating],
141
141
  out_of_bounds: npt.NDArray[np.bool_],
142
- ) -> npt.NDArray[np.float64]:
142
+ ) -> npt.NDArray[np.floating]:
143
143
  """Set out-of-bounds values to the fill value.
144
144
 
145
145
  Parameters
146
146
  ----------
147
- out : npt.NDArray[np.float64]
147
+ out : npt.NDArray[np.floating]
148
148
  Values from interpolation. This is modified in-place.
149
149
  out_of_bounds : npt.NDArray[np.bool_]
150
150
  A 1-dimensional Boolean array indicating which points are out of bounds.
151
151
 
152
152
  Returns
153
153
  -------
154
- out : npt.NDArray[np.float64]
154
+ out : npt.NDArray[np.floating]
155
155
  A reference to the ``out`` array.
156
156
  """
157
157
  if self.fill_value is not None and np.any(out_of_bounds):
@@ -162,8 +162,8 @@ class PycontrailsRegularGridInterpolator(scipy.interpolate.RegularGridInterpolat
162
162
  def _evaluate_linear(
163
163
  self,
164
164
  indices: npt.NDArray[np.int64],
165
- norm_distances: npt.NDArray[np.float64],
166
- ) -> npt.NDArray[np.float64]:
165
+ norm_distances: npt.NDArray[np.floating],
166
+ ) -> npt.NDArray[np.floating]:
167
167
  """Evaluate the interpolator using linear interpolation.
168
168
 
169
169
  This is a faster alternative to
@@ -181,13 +181,13 @@ class PycontrailsRegularGridInterpolator(scipy.interpolate.RegularGridInterpolat
181
181
  indices : npt.NDArray[np.int64]
182
182
  Indices of the grid points to the left of the interpolation points.
183
183
  Has shape ``(ndim, n_points)``.
184
- norm_distances : npt.NDArray[np.float64]
184
+ norm_distances : npt.NDArray[np.floating]
185
185
  Normalized distances between the interpolation points and the grid
186
186
  points to the left. Has shape ``(ndim, n_points)``.
187
187
 
188
188
  Returns
189
189
  -------
190
- npt.NDArray[np.float64]
190
+ npt.NDArray[np.floating]
191
191
  Interpolated values with shape ``(n_points,)`` and the same dtype as
192
192
  the :attr:`values` array.
193
193
  """
@@ -245,6 +245,9 @@ def _pick_method(scipy_version: str, method: str) -> str:
245
245
  str
246
246
  Interpolation method adjusted for compatibility with this class.
247
247
  """
248
+ if method == "linear":
249
+ return method
250
+
248
251
  try:
249
252
  version = scipy_version.split(".")
250
253
  major = int(version[0])
@@ -254,14 +257,14 @@ def _pick_method(scipy_version: str, method: str) -> str:
254
257
  raise ValueError(msg) from exc
255
258
 
256
259
  reimplemented_methods = ["slinear", "cubic", "quintic"]
257
- if major > 1 or (major == 1 and minor >= 13) and method in reimplemented_methods:
260
+ if major > 1 or ((major == 1 and minor >= 13) and method in reimplemented_methods):
258
261
  return method + "_legacy"
259
262
  return method
260
263
 
261
264
 
262
265
  def _floatize_time(
263
266
  time: npt.NDArray[np.datetime64], offset: np.datetime64
264
- ) -> npt.NDArray[np.float64]:
267
+ ) -> npt.NDArray[np.floating]:
265
268
  """Convert an array of ``np.datetime64`` to an array of ``np.float64``.
266
269
 
267
270
  In calls to :class:`scipy.interpolate.RegularGridInterpolator`, it's critical
@@ -296,7 +299,7 @@ def _floatize_time(
296
299
 
297
300
  Returns
298
301
  -------
299
- npt.NDArray[np.float64]
302
+ npt.NDArray[np.floating]
300
303
  The number of milliseconds since ``offset``.
301
304
  """
302
305
  delta = time - offset
@@ -354,9 +357,9 @@ def _localize(da: xr.DataArray, coords: dict[str, np.ndarray]) -> xr.DataArray:
354
357
 
355
358
  @overload
356
359
  def interp(
357
- longitude: npt.NDArray[np.float64],
358
- latitude: npt.NDArray[np.float64],
359
- level: npt.NDArray[np.float64],
360
+ longitude: npt.NDArray[np.floating],
361
+ latitude: npt.NDArray[np.floating],
362
+ level: npt.NDArray[np.floating],
360
363
  time: npt.NDArray[np.datetime64],
361
364
  da: xr.DataArray,
362
365
  method: str,
@@ -366,14 +369,14 @@ def interp(
366
369
  *,
367
370
  indices: RGIArtifacts | None = ...,
368
371
  return_indices: Literal[False] = ...,
369
- ) -> npt.NDArray[np.float64]: ...
372
+ ) -> npt.NDArray[np.floating]: ...
370
373
 
371
374
 
372
375
  @overload
373
376
  def interp(
374
- longitude: npt.NDArray[np.float64],
375
- latitude: npt.NDArray[np.float64],
376
- level: npt.NDArray[np.float64],
377
+ longitude: npt.NDArray[np.floating],
378
+ latitude: npt.NDArray[np.floating],
379
+ level: npt.NDArray[np.floating],
377
380
  time: npt.NDArray[np.datetime64],
378
381
  da: xr.DataArray,
379
382
  method: str,
@@ -383,14 +386,14 @@ def interp(
383
386
  *,
384
387
  indices: RGIArtifacts | None = ...,
385
388
  return_indices: Literal[True],
386
- ) -> tuple[npt.NDArray[np.float64], RGIArtifacts]: ...
389
+ ) -> tuple[npt.NDArray[np.floating], RGIArtifacts]: ...
387
390
 
388
391
 
389
392
  @overload
390
393
  def interp(
391
- longitude: npt.NDArray[np.float64],
392
- latitude: npt.NDArray[np.float64],
393
- level: npt.NDArray[np.float64],
394
+ longitude: npt.NDArray[np.floating],
395
+ latitude: npt.NDArray[np.floating],
396
+ level: npt.NDArray[np.floating],
394
397
  time: npt.NDArray[np.datetime64],
395
398
  da: xr.DataArray,
396
399
  method: str,
@@ -400,13 +403,13 @@ def interp(
400
403
  *,
401
404
  indices: RGIArtifacts | None = ...,
402
405
  return_indices: bool = ...,
403
- ) -> npt.NDArray[np.float64] | tuple[npt.NDArray[np.float64], RGIArtifacts]: ...
406
+ ) -> npt.NDArray[np.floating] | tuple[npt.NDArray[np.floating], RGIArtifacts]: ...
404
407
 
405
408
 
406
409
  def interp(
407
- longitude: npt.NDArray[np.float64],
408
- latitude: npt.NDArray[np.float64],
409
- level: npt.NDArray[np.float64],
410
+ longitude: npt.NDArray[np.floating],
411
+ latitude: npt.NDArray[np.floating],
412
+ level: npt.NDArray[np.floating],
410
413
  time: npt.NDArray[np.datetime64],
411
414
  da: xr.DataArray,
412
415
  method: str,
@@ -416,7 +419,7 @@ def interp(
416
419
  *,
417
420
  indices: RGIArtifacts | None = None,
418
421
  return_indices: bool = False,
419
- ) -> npt.NDArray[np.float64] | tuple[npt.NDArray[np.float64], RGIArtifacts]:
422
+ ) -> npt.NDArray[np.floating] | tuple[npt.NDArray[np.floating], RGIArtifacts]:
420
423
  """Interpolate over a grid with ``localize`` option.
421
424
 
422
425
  .. versionchanged:: 0.25.6
@@ -471,7 +474,7 @@ def interp(
471
474
 
472
475
  Returns
473
476
  -------
474
- npt.NDArray[np.float64] | tuple[npt.NDArray[np.float64], RGIArtifacts]
477
+ npt.NDArray[np.floating] | tuple[npt.NDArray[np.floating], RGIArtifacts]
475
478
  Interpolated values with same size as ``longitude``. If ``return_indices``
476
479
  is True, return intermediate indices artifacts as well.
477
480
 
@@ -486,20 +489,20 @@ def interp(
486
489
  da = _localize(da, coords)
487
490
 
488
491
  indexes = da._indexes
489
- x = indexes["longitude"].index.to_numpy() # type: ignore[attr-defined]
490
- y = indexes["latitude"].index.to_numpy() # type: ignore[attr-defined]
491
- z = indexes["level"].index.to_numpy() # type: ignore[attr-defined]
492
+ x = indexes["longitude"].index.values # type: ignore[attr-defined]
493
+ y = indexes["latitude"].index.values # type: ignore[attr-defined]
494
+ z = indexes["level"].index.values # type: ignore[attr-defined]
492
495
  if any(v.dtype != np.float64 for v in (x, y, z)):
493
496
  msg = "da must have float64 dtype for longitude, latitude, and level coordinates"
494
497
  raise ValueError(msg)
495
498
 
496
499
  # Convert t and time to float64
497
- t = indexes["time"].index.to_numpy() # type: ignore[attr-defined]
500
+ t = indexes["time"].index.values # type: ignore[attr-defined]
498
501
  offset = t[0]
499
502
  t = _floatize_time(t, offset)
500
503
 
501
504
  single_level = z.size == 1 and z.item() == -1.0
502
- points: tuple[npt.NDArray[np.float64], ...]
505
+ points: tuple[npt.NDArray[np.floating], ...]
503
506
  if single_level:
504
507
  values = da.values.squeeze(axis=2)
505
508
  points = x, y, t
@@ -529,13 +532,13 @@ def interp(
529
532
 
530
533
 
531
534
  def _buildxi(
532
- longitude: npt.NDArray[np.float64],
533
- latitude: npt.NDArray[np.float64],
534
- level: npt.NDArray[np.float64],
535
+ longitude: npt.NDArray[np.floating],
536
+ latitude: npt.NDArray[np.floating],
537
+ level: npt.NDArray[np.floating],
535
538
  time: npt.NDArray[np.datetime64],
536
539
  offset: np.datetime64,
537
540
  single_level: bool,
538
- ) -> npt.NDArray[np.float64]:
541
+ ) -> npt.NDArray[np.floating]:
539
542
  """Build the input array for interpolation.
540
543
 
541
544
  The implementation below achieves the same result as the following::
@@ -562,10 +565,10 @@ def _buildxi(
562
565
 
563
566
  def _linear_interp_with_indices(
564
567
  interp: PycontrailsRegularGridInterpolator,
565
- xi: npt.NDArray[np.float64] | None,
568
+ xi: npt.NDArray[np.floating] | None,
566
569
  localize: bool,
567
570
  indices: RGIArtifacts | None,
568
- ) -> tuple[npt.NDArray[np.float64], RGIArtifacts]:
571
+ ) -> tuple[npt.NDArray[np.floating], RGIArtifacts]:
569
572
  if interp.method != "linear":
570
573
  msg = "Parameter 'indices' is only supported for 'method=linear'"
571
574
  raise ValueError(msg)
@@ -589,7 +592,7 @@ class RGIArtifacts:
589
592
  """An interface to intermediate RGI interpolation artifacts."""
590
593
 
591
594
  xi_indices: npt.NDArray[np.int64]
592
- norm_distances: npt.NDArray[np.float64]
595
+ norm_distances: npt.NDArray[np.floating]
593
596
  out_of_bounds: npt.NDArray[np.bool_]
594
597
 
595
598
 
@@ -608,10 +611,10 @@ class EmissionsProfileInterpolator:
608
611
 
609
612
  Parameters
610
613
  ----------
611
- xp : npt.NDarray[np.float64]
614
+ xp : npt.NDArray[np.floating]
612
615
  Array of x-values. These must be strictly increasing and free from
613
616
  any nan values. Passed to :func:`numpy.interp`.
614
- fp : npt.NDarray[np.float64]
617
+ fp : npt.NDArray[np.floating]
615
618
  Array of y-values. Passed to :func:`numpy.interp`.
616
619
  drop_duplicates : bool, optional
617
620
  Whether to drop duplicate values in ``xp``. Defaults to ``True``.
@@ -648,8 +651,8 @@ class EmissionsProfileInterpolator:
648
651
 
649
652
  def __init__(
650
653
  self,
651
- xp: npt.NDArray[np.float64],
652
- fp: npt.NDArray[np.float64],
654
+ xp: npt.NDArray[np.floating],
655
+ fp: npt.NDArray[np.floating],
653
656
  drop_duplicates: bool = True,
654
657
  ) -> None:
655
658
  if drop_duplicates:
@@ -680,17 +683,17 @@ class EmissionsProfileInterpolator:
680
683
  msg = "xp must not contain nan values"
681
684
  raise ValueError(msg)
682
685
 
683
- def interp(self, x: npt.NDArray[np.float64]) -> npt.NDArray[np.float64]:
686
+ def interp(self, x: npt.NDArray[np.floating]) -> npt.NDArray[np.floating]:
684
687
  """Interpolate x against xp and fp.
685
688
 
686
689
  Parameters
687
690
  ----------
688
- x : npt.NDArray[np.float64]
691
+ x : npt.NDArray[np.floating]
689
692
  Array of x-values to interpolate.
690
693
 
691
694
  Returns
692
695
  -------
693
- npt.NDArray[np.float64]
696
+ npt.NDArray[np.floating]
694
697
  Array of interpolated y-values arising from the x-values. The ``dtype`` of
695
698
  the output array is the same as the ``dtype`` of ``x``.
696
699
  """
@@ -700,7 +703,7 @@ class EmissionsProfileInterpolator:
700
703
  dtype = np.result_type(x, np.float32)
701
704
  return np.interp(x, self.xp, self.fp).astype(dtype)
702
705
 
703
- def log_interp(self, x: npt.NDArray[np.float64]) -> npt.NDArray[np.float64]:
706
+ def log_interp(self, x: npt.NDArray[np.floating]) -> npt.NDArray[np.floating]:
704
707
  """Interpolate x against xp and fp on a logarithmic scale.
705
708
 
706
709
  This method composes the following three functions.
@@ -710,12 +713,12 @@ class EmissionsProfileInterpolator:
710
713
 
711
714
  Parameters
712
715
  ----------
713
- x : npt.NDArray[np.float64]
716
+ x : npt.NDArray[np.floating]
714
717
  Array of x-values to interpolate.
715
718
 
716
719
  Returns
717
720
  -------
718
- npt.NDArray[np.float64]
721
+ npt.NDArray[np.floating]
719
722
  Array of interpolated y-values arising from the x-values.
720
723
  """
721
724
  return np.exp(self.interp(np.log(x)))