pycontrails 0.54.3__cp312-cp312-macosx_11_0_arm64.whl → 0.54.4__cp312-cp312-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 +25 -21
- pycontrails/core/flight.py +213 -301
- pycontrails/core/interpolation.py +56 -56
- pycontrails/core/met.py +48 -39
- pycontrails/core/models.py +25 -11
- pycontrails/core/polygon.py +15 -15
- pycontrails/core/rgi_cython.cpython-312-darwin.so +0 -0
- pycontrails/core/vector.py +22 -22
- 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 +3 -3
- pycontrails/models/cocip/__init__.py +2 -2
- pycontrails/models/cocip/cocip.py +15 -15
- 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 +93 -87
- pycontrails/models/dry_advection.py +10 -5
- pycontrails/models/emissions/__init__.py +2 -2
- pycontrails/models/emissions/black_carbon.py +108 -108
- pycontrails/models/emissions/emissions.py +85 -85
- pycontrails/models/emissions/ffm2.py +35 -35
- pycontrails/models/humidity_scaling/humidity_scaling.py +23 -23
- 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 +74 -64
- pycontrails/models/ps_model/ps_model.py +14 -14
- 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.4.dist-info}/METADATA +2 -2
- {pycontrails-0.54.3.dist-info → pycontrails-0.54.4.dist-info}/NOTICE +1 -1
- pycontrails-0.54.4.dist-info/RECORD +111 -0
- pycontrails-0.54.3.dist-info/RECORD +0 -111
- {pycontrails-0.54.3.dist-info → pycontrails-0.54.4.dist-info}/LICENSE +0 -0
- {pycontrails-0.54.3.dist-info → pycontrails-0.54.4.dist-info}/WHEEL +0 -0
- {pycontrails-0.54.3.dist-info → pycontrails-0.54.4.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.
|
|
46
|
+
points : tuple[npt.NDArray[np.floating], ...]
|
|
47
47
|
Coordinates of the grid points.
|
|
48
|
-
values : npt.NDArray[np.
|
|
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.
|
|
63
|
-
values: npt.NDArray[np.
|
|
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.
|
|
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.
|
|
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.
|
|
110
|
-
) -> npt.NDArray[np.
|
|
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.
|
|
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.
|
|
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.
|
|
140
|
+
out: npt.NDArray[np.floating],
|
|
141
141
|
out_of_bounds: npt.NDArray[np.bool_],
|
|
142
|
-
) -> npt.NDArray[np.
|
|
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.
|
|
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.
|
|
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.
|
|
166
|
-
) -> npt.NDArray[np.
|
|
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.
|
|
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.
|
|
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
|
"""
|
|
@@ -254,14 +254,14 @@ def _pick_method(scipy_version: str, method: str) -> str:
|
|
|
254
254
|
raise ValueError(msg) from exc
|
|
255
255
|
|
|
256
256
|
reimplemented_methods = ["slinear", "cubic", "quintic"]
|
|
257
|
-
if major > 1 or (major == 1 and minor >= 13) and method in reimplemented_methods:
|
|
257
|
+
if major > 1 or ((major == 1 and minor >= 13) and method in reimplemented_methods):
|
|
258
258
|
return method + "_legacy"
|
|
259
259
|
return method
|
|
260
260
|
|
|
261
261
|
|
|
262
262
|
def _floatize_time(
|
|
263
263
|
time: npt.NDArray[np.datetime64], offset: np.datetime64
|
|
264
|
-
) -> npt.NDArray[np.
|
|
264
|
+
) -> npt.NDArray[np.floating]:
|
|
265
265
|
"""Convert an array of ``np.datetime64`` to an array of ``np.float64``.
|
|
266
266
|
|
|
267
267
|
In calls to :class:`scipy.interpolate.RegularGridInterpolator`, it's critical
|
|
@@ -296,7 +296,7 @@ def _floatize_time(
|
|
|
296
296
|
|
|
297
297
|
Returns
|
|
298
298
|
-------
|
|
299
|
-
npt.NDArray[np.
|
|
299
|
+
npt.NDArray[np.floating]
|
|
300
300
|
The number of milliseconds since ``offset``.
|
|
301
301
|
"""
|
|
302
302
|
delta = time - offset
|
|
@@ -354,9 +354,9 @@ def _localize(da: xr.DataArray, coords: dict[str, np.ndarray]) -> xr.DataArray:
|
|
|
354
354
|
|
|
355
355
|
@overload
|
|
356
356
|
def interp(
|
|
357
|
-
longitude: npt.NDArray[np.
|
|
358
|
-
latitude: npt.NDArray[np.
|
|
359
|
-
level: npt.NDArray[np.
|
|
357
|
+
longitude: npt.NDArray[np.floating],
|
|
358
|
+
latitude: npt.NDArray[np.floating],
|
|
359
|
+
level: npt.NDArray[np.floating],
|
|
360
360
|
time: npt.NDArray[np.datetime64],
|
|
361
361
|
da: xr.DataArray,
|
|
362
362
|
method: str,
|
|
@@ -366,14 +366,14 @@ def interp(
|
|
|
366
366
|
*,
|
|
367
367
|
indices: RGIArtifacts | None = ...,
|
|
368
368
|
return_indices: Literal[False] = ...,
|
|
369
|
-
) -> npt.NDArray[np.
|
|
369
|
+
) -> npt.NDArray[np.floating]: ...
|
|
370
370
|
|
|
371
371
|
|
|
372
372
|
@overload
|
|
373
373
|
def interp(
|
|
374
|
-
longitude: npt.NDArray[np.
|
|
375
|
-
latitude: npt.NDArray[np.
|
|
376
|
-
level: npt.NDArray[np.
|
|
374
|
+
longitude: npt.NDArray[np.floating],
|
|
375
|
+
latitude: npt.NDArray[np.floating],
|
|
376
|
+
level: npt.NDArray[np.floating],
|
|
377
377
|
time: npt.NDArray[np.datetime64],
|
|
378
378
|
da: xr.DataArray,
|
|
379
379
|
method: str,
|
|
@@ -383,14 +383,14 @@ def interp(
|
|
|
383
383
|
*,
|
|
384
384
|
indices: RGIArtifacts | None = ...,
|
|
385
385
|
return_indices: Literal[True],
|
|
386
|
-
) -> tuple[npt.NDArray[np.
|
|
386
|
+
) -> tuple[npt.NDArray[np.floating], RGIArtifacts]: ...
|
|
387
387
|
|
|
388
388
|
|
|
389
389
|
@overload
|
|
390
390
|
def interp(
|
|
391
|
-
longitude: npt.NDArray[np.
|
|
392
|
-
latitude: npt.NDArray[np.
|
|
393
|
-
level: npt.NDArray[np.
|
|
391
|
+
longitude: npt.NDArray[np.floating],
|
|
392
|
+
latitude: npt.NDArray[np.floating],
|
|
393
|
+
level: npt.NDArray[np.floating],
|
|
394
394
|
time: npt.NDArray[np.datetime64],
|
|
395
395
|
da: xr.DataArray,
|
|
396
396
|
method: str,
|
|
@@ -400,13 +400,13 @@ def interp(
|
|
|
400
400
|
*,
|
|
401
401
|
indices: RGIArtifacts | None = ...,
|
|
402
402
|
return_indices: bool = ...,
|
|
403
|
-
) -> npt.NDArray[np.
|
|
403
|
+
) -> npt.NDArray[np.floating] | tuple[npt.NDArray[np.floating], RGIArtifacts]: ...
|
|
404
404
|
|
|
405
405
|
|
|
406
406
|
def interp(
|
|
407
|
-
longitude: npt.NDArray[np.
|
|
408
|
-
latitude: npt.NDArray[np.
|
|
409
|
-
level: npt.NDArray[np.
|
|
407
|
+
longitude: npt.NDArray[np.floating],
|
|
408
|
+
latitude: npt.NDArray[np.floating],
|
|
409
|
+
level: npt.NDArray[np.floating],
|
|
410
410
|
time: npt.NDArray[np.datetime64],
|
|
411
411
|
da: xr.DataArray,
|
|
412
412
|
method: str,
|
|
@@ -416,7 +416,7 @@ def interp(
|
|
|
416
416
|
*,
|
|
417
417
|
indices: RGIArtifacts | None = None,
|
|
418
418
|
return_indices: bool = False,
|
|
419
|
-
) -> npt.NDArray[np.
|
|
419
|
+
) -> npt.NDArray[np.floating] | tuple[npt.NDArray[np.floating], RGIArtifacts]:
|
|
420
420
|
"""Interpolate over a grid with ``localize`` option.
|
|
421
421
|
|
|
422
422
|
.. versionchanged:: 0.25.6
|
|
@@ -471,7 +471,7 @@ def interp(
|
|
|
471
471
|
|
|
472
472
|
Returns
|
|
473
473
|
-------
|
|
474
|
-
npt.NDArray[np.
|
|
474
|
+
npt.NDArray[np.floating] | tuple[npt.NDArray[np.floating], RGIArtifacts]
|
|
475
475
|
Interpolated values with same size as ``longitude``. If ``return_indices``
|
|
476
476
|
is True, return intermediate indices artifacts as well.
|
|
477
477
|
|
|
@@ -499,7 +499,7 @@ def interp(
|
|
|
499
499
|
t = _floatize_time(t, offset)
|
|
500
500
|
|
|
501
501
|
single_level = z.size == 1 and z.item() == -1.0
|
|
502
|
-
points: tuple[npt.NDArray[np.
|
|
502
|
+
points: tuple[npt.NDArray[np.floating], ...]
|
|
503
503
|
if single_level:
|
|
504
504
|
values = da.values.squeeze(axis=2)
|
|
505
505
|
points = x, y, t
|
|
@@ -529,13 +529,13 @@ def interp(
|
|
|
529
529
|
|
|
530
530
|
|
|
531
531
|
def _buildxi(
|
|
532
|
-
longitude: npt.NDArray[np.
|
|
533
|
-
latitude: npt.NDArray[np.
|
|
534
|
-
level: npt.NDArray[np.
|
|
532
|
+
longitude: npt.NDArray[np.floating],
|
|
533
|
+
latitude: npt.NDArray[np.floating],
|
|
534
|
+
level: npt.NDArray[np.floating],
|
|
535
535
|
time: npt.NDArray[np.datetime64],
|
|
536
536
|
offset: np.datetime64,
|
|
537
537
|
single_level: bool,
|
|
538
|
-
) -> npt.NDArray[np.
|
|
538
|
+
) -> npt.NDArray[np.floating]:
|
|
539
539
|
"""Build the input array for interpolation.
|
|
540
540
|
|
|
541
541
|
The implementation below achieves the same result as the following::
|
|
@@ -562,10 +562,10 @@ def _buildxi(
|
|
|
562
562
|
|
|
563
563
|
def _linear_interp_with_indices(
|
|
564
564
|
interp: PycontrailsRegularGridInterpolator,
|
|
565
|
-
xi: npt.NDArray[np.
|
|
565
|
+
xi: npt.NDArray[np.floating] | None,
|
|
566
566
|
localize: bool,
|
|
567
567
|
indices: RGIArtifacts | None,
|
|
568
|
-
) -> tuple[npt.NDArray[np.
|
|
568
|
+
) -> tuple[npt.NDArray[np.floating], RGIArtifacts]:
|
|
569
569
|
if interp.method != "linear":
|
|
570
570
|
msg = "Parameter 'indices' is only supported for 'method=linear'"
|
|
571
571
|
raise ValueError(msg)
|
|
@@ -589,7 +589,7 @@ class RGIArtifacts:
|
|
|
589
589
|
"""An interface to intermediate RGI interpolation artifacts."""
|
|
590
590
|
|
|
591
591
|
xi_indices: npt.NDArray[np.int64]
|
|
592
|
-
norm_distances: npt.NDArray[np.
|
|
592
|
+
norm_distances: npt.NDArray[np.floating]
|
|
593
593
|
out_of_bounds: npt.NDArray[np.bool_]
|
|
594
594
|
|
|
595
595
|
|
|
@@ -608,10 +608,10 @@ class EmissionsProfileInterpolator:
|
|
|
608
608
|
|
|
609
609
|
Parameters
|
|
610
610
|
----------
|
|
611
|
-
xp : npt.
|
|
611
|
+
xp : npt.NDArray[np.floating]
|
|
612
612
|
Array of x-values. These must be strictly increasing and free from
|
|
613
613
|
any nan values. Passed to :func:`numpy.interp`.
|
|
614
|
-
fp : npt.
|
|
614
|
+
fp : npt.NDArray[np.floating]
|
|
615
615
|
Array of y-values. Passed to :func:`numpy.interp`.
|
|
616
616
|
drop_duplicates : bool, optional
|
|
617
617
|
Whether to drop duplicate values in ``xp``. Defaults to ``True``.
|
|
@@ -648,8 +648,8 @@ class EmissionsProfileInterpolator:
|
|
|
648
648
|
|
|
649
649
|
def __init__(
|
|
650
650
|
self,
|
|
651
|
-
xp: npt.NDArray[np.
|
|
652
|
-
fp: npt.NDArray[np.
|
|
651
|
+
xp: npt.NDArray[np.floating],
|
|
652
|
+
fp: npt.NDArray[np.floating],
|
|
653
653
|
drop_duplicates: bool = True,
|
|
654
654
|
) -> None:
|
|
655
655
|
if drop_duplicates:
|
|
@@ -680,17 +680,17 @@ class EmissionsProfileInterpolator:
|
|
|
680
680
|
msg = "xp must not contain nan values"
|
|
681
681
|
raise ValueError(msg)
|
|
682
682
|
|
|
683
|
-
def interp(self, x: npt.NDArray[np.
|
|
683
|
+
def interp(self, x: npt.NDArray[np.floating]) -> npt.NDArray[np.floating]:
|
|
684
684
|
"""Interpolate x against xp and fp.
|
|
685
685
|
|
|
686
686
|
Parameters
|
|
687
687
|
----------
|
|
688
|
-
x : npt.NDArray[np.
|
|
688
|
+
x : npt.NDArray[np.floating]
|
|
689
689
|
Array of x-values to interpolate.
|
|
690
690
|
|
|
691
691
|
Returns
|
|
692
692
|
-------
|
|
693
|
-
npt.NDArray[np.
|
|
693
|
+
npt.NDArray[np.floating]
|
|
694
694
|
Array of interpolated y-values arising from the x-values. The ``dtype`` of
|
|
695
695
|
the output array is the same as the ``dtype`` of ``x``.
|
|
696
696
|
"""
|
|
@@ -700,7 +700,7 @@ class EmissionsProfileInterpolator:
|
|
|
700
700
|
dtype = np.result_type(x, np.float32)
|
|
701
701
|
return np.interp(x, self.xp, self.fp).astype(dtype)
|
|
702
702
|
|
|
703
|
-
def log_interp(self, x: npt.NDArray[np.
|
|
703
|
+
def log_interp(self, x: npt.NDArray[np.floating]) -> npt.NDArray[np.floating]:
|
|
704
704
|
"""Interpolate x against xp and fp on a logarithmic scale.
|
|
705
705
|
|
|
706
706
|
This method composes the following three functions.
|
|
@@ -710,12 +710,12 @@ class EmissionsProfileInterpolator:
|
|
|
710
710
|
|
|
711
711
|
Parameters
|
|
712
712
|
----------
|
|
713
|
-
x : npt.NDArray[np.
|
|
713
|
+
x : npt.NDArray[np.floating]
|
|
714
714
|
Array of x-values to interpolate.
|
|
715
715
|
|
|
716
716
|
Returns
|
|
717
717
|
-------
|
|
718
|
-
npt.NDArray[np.
|
|
718
|
+
npt.NDArray[np.floating]
|
|
719
719
|
Array of interpolated y-values arising from the x-values.
|
|
720
720
|
"""
|
|
721
721
|
return np.exp(self.interp(np.log(x)))
|
pycontrails/core/met.py
CHANGED
|
@@ -1495,9 +1495,9 @@ class MetDataArray(MetBase):
|
|
|
1495
1495
|
@overload
|
|
1496
1496
|
def interpolate(
|
|
1497
1497
|
self,
|
|
1498
|
-
longitude: float | npt.NDArray[np.
|
|
1499
|
-
latitude: float | npt.NDArray[np.
|
|
1500
|
-
level: float | npt.NDArray[np.
|
|
1498
|
+
longitude: float | npt.NDArray[np.floating],
|
|
1499
|
+
latitude: float | npt.NDArray[np.floating],
|
|
1500
|
+
level: float | npt.NDArray[np.floating],
|
|
1501
1501
|
time: np.datetime64 | npt.NDArray[np.datetime64],
|
|
1502
1502
|
*,
|
|
1503
1503
|
method: str = ...,
|
|
@@ -1507,14 +1507,14 @@ class MetDataArray(MetBase):
|
|
|
1507
1507
|
lowmem: bool = ...,
|
|
1508
1508
|
indices: interpolation.RGIArtifacts | None = ...,
|
|
1509
1509
|
return_indices: Literal[False] = ...,
|
|
1510
|
-
) -> npt.NDArray[np.
|
|
1510
|
+
) -> npt.NDArray[np.floating]: ...
|
|
1511
1511
|
|
|
1512
1512
|
@overload
|
|
1513
1513
|
def interpolate(
|
|
1514
1514
|
self,
|
|
1515
|
-
longitude: float | npt.NDArray[np.
|
|
1516
|
-
latitude: float | npt.NDArray[np.
|
|
1517
|
-
level: float | npt.NDArray[np.
|
|
1515
|
+
longitude: float | npt.NDArray[np.floating],
|
|
1516
|
+
latitude: float | npt.NDArray[np.floating],
|
|
1517
|
+
level: float | npt.NDArray[np.floating],
|
|
1518
1518
|
time: np.datetime64 | npt.NDArray[np.datetime64],
|
|
1519
1519
|
*,
|
|
1520
1520
|
method: str = ...,
|
|
@@ -1524,13 +1524,13 @@ class MetDataArray(MetBase):
|
|
|
1524
1524
|
lowmem: bool = ...,
|
|
1525
1525
|
indices: interpolation.RGIArtifacts | None = ...,
|
|
1526
1526
|
return_indices: Literal[True],
|
|
1527
|
-
) -> tuple[npt.NDArray[np.
|
|
1527
|
+
) -> tuple[npt.NDArray[np.floating], interpolation.RGIArtifacts]: ...
|
|
1528
1528
|
|
|
1529
1529
|
def interpolate(
|
|
1530
1530
|
self,
|
|
1531
|
-
longitude: float | npt.NDArray[np.
|
|
1532
|
-
latitude: float | npt.NDArray[np.
|
|
1533
|
-
level: float | npt.NDArray[np.
|
|
1531
|
+
longitude: float | npt.NDArray[np.floating],
|
|
1532
|
+
latitude: float | npt.NDArray[np.floating],
|
|
1533
|
+
level: float | npt.NDArray[np.floating],
|
|
1534
1534
|
time: np.datetime64 | npt.NDArray[np.datetime64],
|
|
1535
1535
|
*,
|
|
1536
1536
|
method: str = "linear",
|
|
@@ -1540,7 +1540,7 @@ class MetDataArray(MetBase):
|
|
|
1540
1540
|
lowmem: bool = False,
|
|
1541
1541
|
indices: interpolation.RGIArtifacts | None = None,
|
|
1542
1542
|
return_indices: bool = False,
|
|
1543
|
-
) -> npt.NDArray[np.
|
|
1543
|
+
) -> npt.NDArray[np.floating] | tuple[npt.NDArray[np.floating], interpolation.RGIArtifacts]:
|
|
1544
1544
|
"""Interpolate values over underlying DataArray.
|
|
1545
1545
|
|
|
1546
1546
|
Zero dimensional coordinates are reshaped to 1D arrays.
|
|
@@ -1569,11 +1569,11 @@ class MetDataArray(MetBase):
|
|
|
1569
1569
|
|
|
1570
1570
|
Parameters
|
|
1571
1571
|
----------
|
|
1572
|
-
longitude : float | npt.NDArray[np.
|
|
1572
|
+
longitude : float | npt.NDArray[np.floating]
|
|
1573
1573
|
Longitude values to interpolate. Assumed to be 0 or 1 dimensional.
|
|
1574
|
-
latitude : float | npt.NDArray[np.
|
|
1574
|
+
latitude : float | npt.NDArray[np.floating]
|
|
1575
1575
|
Latitude values to interpolate. Assumed to be 0 or 1 dimensional.
|
|
1576
|
-
level : float | npt.NDArray[np.
|
|
1576
|
+
level : float | npt.NDArray[np.floating]
|
|
1577
1577
|
Level values to interpolate. Assumed to be 0 or 1 dimensional.
|
|
1578
1578
|
time : np.datetime64 | npt.NDArray[np.datetime64]
|
|
1579
1579
|
Time values to interpolate. Assumed to be 0 or 1 dimensional.
|
|
@@ -1696,18 +1696,17 @@ class MetDataArray(MetBase):
|
|
|
1696
1696
|
|
|
1697
1697
|
def _interp_lowmem(
|
|
1698
1698
|
self,
|
|
1699
|
-
longitude: float | npt.NDArray[np.
|
|
1700
|
-
latitude: float | npt.NDArray[np.
|
|
1701
|
-
level: float | npt.NDArray[np.
|
|
1699
|
+
longitude: float | npt.NDArray[np.floating],
|
|
1700
|
+
latitude: float | npt.NDArray[np.floating],
|
|
1701
|
+
level: float | npt.NDArray[np.floating],
|
|
1702
1702
|
time: np.datetime64 | npt.NDArray[np.datetime64],
|
|
1703
1703
|
*,
|
|
1704
1704
|
method: str = "linear",
|
|
1705
1705
|
bounds_error: bool = False,
|
|
1706
1706
|
fill_value: float | np.float64 | None = np.nan,
|
|
1707
|
-
minimize_memory: bool = False,
|
|
1708
1707
|
indices: interpolation.RGIArtifacts | None = None,
|
|
1709
1708
|
return_indices: bool = False,
|
|
1710
|
-
) -> npt.NDArray[np.
|
|
1709
|
+
) -> npt.NDArray[np.floating] | tuple[npt.NDArray[np.floating], interpolation.RGIArtifacts]:
|
|
1711
1710
|
"""Interpolate values against underlying DataArray.
|
|
1712
1711
|
|
|
1713
1712
|
This method is used by :meth:`interpolate` when ``lowmem=True``.
|
|
@@ -1762,27 +1761,37 @@ class MetDataArray(MetBase):
|
|
|
1762
1761
|
)
|
|
1763
1762
|
da.load()
|
|
1764
1763
|
|
|
1765
|
-
tmp = interpolation.interp(
|
|
1766
|
-
longitude=lon_sl,
|
|
1767
|
-
latitude=lat_sl,
|
|
1768
|
-
level=lev_sl,
|
|
1769
|
-
time=t_sl,
|
|
1770
|
-
da=da,
|
|
1771
|
-
method=method,
|
|
1772
|
-
bounds_error=bounds_error,
|
|
1773
|
-
fill_value=fill_value,
|
|
1774
|
-
localize=False, # would be no-op; da is localized already
|
|
1775
|
-
indices=indices_sl,
|
|
1776
|
-
return_indices=return_indices,
|
|
1777
|
-
)
|
|
1778
|
-
|
|
1779
1764
|
if return_indices:
|
|
1780
|
-
out[mask], rgi_sl =
|
|
1765
|
+
out[mask], rgi_sl = interpolation.interp(
|
|
1766
|
+
longitude=lon_sl,
|
|
1767
|
+
latitude=lat_sl,
|
|
1768
|
+
level=lev_sl,
|
|
1769
|
+
time=t_sl,
|
|
1770
|
+
da=da,
|
|
1771
|
+
method=method,
|
|
1772
|
+
bounds_error=bounds_error,
|
|
1773
|
+
fill_value=fill_value,
|
|
1774
|
+
localize=False, # would be no-op; da is localized already
|
|
1775
|
+
indices=indices_sl,
|
|
1776
|
+
return_indices=return_indices,
|
|
1777
|
+
)
|
|
1781
1778
|
rgi_artifacts.xi_indices[:, mask] = rgi_sl.xi_indices
|
|
1782
1779
|
rgi_artifacts.norm_distances[:, mask] = rgi_sl.norm_distances
|
|
1783
1780
|
rgi_artifacts.out_of_bounds[mask] = rgi_sl.out_of_bounds
|
|
1784
1781
|
else:
|
|
1785
|
-
out[mask] =
|
|
1782
|
+
out[mask] = interpolation.interp(
|
|
1783
|
+
longitude=lon_sl,
|
|
1784
|
+
latitude=lat_sl,
|
|
1785
|
+
level=lev_sl,
|
|
1786
|
+
time=t_sl,
|
|
1787
|
+
da=da,
|
|
1788
|
+
method=method,
|
|
1789
|
+
bounds_error=bounds_error,
|
|
1790
|
+
fill_value=fill_value,
|
|
1791
|
+
localize=False, # would be no-op; da is localized already
|
|
1792
|
+
indices=indices_sl,
|
|
1793
|
+
return_indices=return_indices,
|
|
1794
|
+
)
|
|
1786
1795
|
|
|
1787
1796
|
if return_indices:
|
|
1788
1797
|
return out, rgi_artifacts
|
|
@@ -1878,7 +1887,7 @@ class MetDataArray(MetBase):
|
|
|
1878
1887
|
if not self.binary:
|
|
1879
1888
|
raise NotImplementedError("proportion method is only implemented for binary fields")
|
|
1880
1889
|
|
|
1881
|
-
return self.data.sum().values.item() / self.data.count().values.item()
|
|
1890
|
+
return self.data.sum().values.item() / self.data.count().values.item() # type: ignore[operator]
|
|
1882
1891
|
|
|
1883
1892
|
def find_edges(self) -> MetDataArray:
|
|
1884
1893
|
"""Find edges of regions.
|
|
@@ -2592,9 +2601,9 @@ def _extract_2d_arr_and_altitude(
|
|
|
2592
2601
|
except KeyError:
|
|
2593
2602
|
altitude = None
|
|
2594
2603
|
else:
|
|
2595
|
-
altitude = round(altitude)
|
|
2604
|
+
altitude = round(altitude) # type: ignore[call-overload]
|
|
2596
2605
|
|
|
2597
|
-
return arr, altitude
|
|
2606
|
+
return arr, altitude # type: ignore[return-value]
|
|
2598
2607
|
|
|
2599
2608
|
|
|
2600
2609
|
def downselect(data: XArrayType, bbox: tuple[float, ...]) -> XArrayType:
|
pycontrails/core/models.py
CHANGED
|
@@ -135,6 +135,20 @@ class ModelParams:
|
|
|
135
135
|
return {(name := field.name): getattr(self, name) for field in fields(self)}
|
|
136
136
|
|
|
137
137
|
|
|
138
|
+
@dataclass
|
|
139
|
+
class AdvectionBuffers(ModelParams):
|
|
140
|
+
"""Override buffers in :class:`ModelParams` for advection models."""
|
|
141
|
+
|
|
142
|
+
#: Met longitude [WGS84] buffer for evolution by advection.
|
|
143
|
+
met_longitude_buffer: tuple[float, float] = (10.0, 10.0)
|
|
144
|
+
|
|
145
|
+
#: Met latitude buffer [WGS84] for evolution by advection.
|
|
146
|
+
met_latitude_buffer: tuple[float, float] = (10.0, 10.0)
|
|
147
|
+
|
|
148
|
+
#: Met level buffer [:math:`hPa`] for evolution by advection.
|
|
149
|
+
met_level_buffer: tuple[float, float] = (40.0, 40.0)
|
|
150
|
+
|
|
151
|
+
|
|
138
152
|
# ------
|
|
139
153
|
# Models
|
|
140
154
|
# ------
|
|
@@ -146,7 +160,7 @@ class Model(ABC):
|
|
|
146
160
|
Implementing classes must implement the :meth:`eval` method
|
|
147
161
|
"""
|
|
148
162
|
|
|
149
|
-
__slots__ = ("
|
|
163
|
+
__slots__ = ("met", "params", "source")
|
|
150
164
|
|
|
151
165
|
#: Default model parameter dataclass
|
|
152
166
|
default_params: type[ModelParams] = ModelParams
|
|
@@ -825,7 +839,7 @@ def interpolate_met(
|
|
|
825
839
|
*,
|
|
826
840
|
q_method: str | None = None,
|
|
827
841
|
**interp_kwargs: Any,
|
|
828
|
-
) -> npt.NDArray[np.
|
|
842
|
+
) -> npt.NDArray[np.floating]:
|
|
829
843
|
"""Interpolate ``vector`` against ``met`` gridded data.
|
|
830
844
|
|
|
831
845
|
If ``vector_key`` (=``met_key`` by default) already exists,
|
|
@@ -854,7 +868,7 @@ def interpolate_met(
|
|
|
854
868
|
|
|
855
869
|
Returns
|
|
856
870
|
-------
|
|
857
|
-
npt.NDArray[np.
|
|
871
|
+
npt.NDArray[np.floating]
|
|
858
872
|
Interpolated values.
|
|
859
873
|
|
|
860
874
|
Raises
|
|
@@ -933,15 +947,15 @@ def _extract_q(met: MetDataset, met_key: str, q_method: str) -> tuple[MetDataArr
|
|
|
933
947
|
|
|
934
948
|
|
|
935
949
|
def _prepare_q(
|
|
936
|
-
mda: MetDataArray, level: npt.NDArray[np.
|
|
937
|
-
) -> tuple[MetDataArray, npt.NDArray[np.
|
|
950
|
+
mda: MetDataArray, level: npt.NDArray[np.floating], q_method: str, log_applied: bool
|
|
951
|
+
) -> tuple[MetDataArray, npt.NDArray[np.floating]]:
|
|
938
952
|
"""Prepare specific humidity for interpolation with experimental ``q_method``.
|
|
939
953
|
|
|
940
954
|
Parameters
|
|
941
955
|
----------
|
|
942
956
|
mda : MetDataArray
|
|
943
957
|
MetDataArray of specific humidity.
|
|
944
|
-
level : npt.NDArray[np.
|
|
958
|
+
level : npt.NDArray[np.floating]
|
|
945
959
|
Levels to interpolate to, [:math:`hPa`].
|
|
946
960
|
q_method : str
|
|
947
961
|
One of ``"log-q-log-p"`` or ``"cubic-spline"``.
|
|
@@ -952,7 +966,7 @@ def _prepare_q(
|
|
|
952
966
|
-------
|
|
953
967
|
mda : MetDataArray
|
|
954
968
|
MetDataArray of specific humidity transformed for interpolation.
|
|
955
|
-
level : npt.NDArray[np.
|
|
969
|
+
level : npt.NDArray[np.floating]
|
|
956
970
|
Transformed levels for interpolation.
|
|
957
971
|
"""
|
|
958
972
|
da = mda.data
|
|
@@ -975,8 +989,8 @@ def _prepare_q(
|
|
|
975
989
|
|
|
976
990
|
|
|
977
991
|
def _prepare_q_log_q_log_p(
|
|
978
|
-
da: xr.DataArray, level: npt.NDArray[np.
|
|
979
|
-
) -> tuple[MetDataArray, npt.NDArray[np.
|
|
992
|
+
da: xr.DataArray, level: npt.NDArray[np.floating], log_applied: bool
|
|
993
|
+
) -> tuple[MetDataArray, npt.NDArray[np.floating]]:
|
|
980
994
|
da = da.assign_coords(level=np.log(da["level"]))
|
|
981
995
|
|
|
982
996
|
if not log_applied:
|
|
@@ -994,8 +1008,8 @@ def _prepare_q_log_q_log_p(
|
|
|
994
1008
|
|
|
995
1009
|
|
|
996
1010
|
def _prepare_q_cubic_spline(
|
|
997
|
-
da: xr.DataArray, level: npt.NDArray[np.
|
|
998
|
-
) -> tuple[MetDataArray, npt.NDArray[np.
|
|
1011
|
+
da: xr.DataArray, level: npt.NDArray[np.floating]
|
|
1012
|
+
) -> tuple[MetDataArray, npt.NDArray[np.floating]]:
|
|
999
1013
|
if da["level"][0] < 50.0 or da["level"][-1] > 1000.0:
|
|
1000
1014
|
msg = "Cubic spline interpolation requires data to span 50-1000 hPa."
|
|
1001
1015
|
raise ValueError(msg)
|