pycontrails 0.54.1__cp313-cp313-macosx_11_0_arm64.whl → 0.54.3__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/_version.py +2 -2
- pycontrails/core/aircraft_performance.py +24 -5
- pycontrails/core/cache.py +14 -10
- pycontrails/core/fleet.py +22 -12
- pycontrails/core/flight.py +25 -15
- pycontrails/core/met.py +34 -22
- pycontrails/core/rgi_cython.cpython-313-darwin.so +0 -0
- pycontrails/core/vector.py +38 -38
- pycontrails/datalib/ecmwf/arco_era5.py +10 -5
- pycontrails/datalib/ecmwf/common.py +7 -2
- pycontrails/datalib/ecmwf/era5.py +9 -4
- pycontrails/datalib/ecmwf/era5_model_level.py +9 -5
- pycontrails/datalib/ecmwf/hres.py +12 -7
- pycontrails/datalib/ecmwf/hres_model_level.py +10 -5
- pycontrails/datalib/ecmwf/ifs.py +11 -6
- pycontrails/datalib/ecmwf/variables.py +1 -0
- pycontrails/datalib/gfs/gfs.py +52 -34
- pycontrails/datalib/gfs/variables.py +6 -2
- pycontrails/datalib/landsat.py +5 -8
- pycontrails/datalib/sentinel.py +7 -11
- pycontrails/ext/bada.py +3 -2
- pycontrails/ext/synthetic_flight.py +3 -2
- pycontrails/models/accf.py +40 -19
- pycontrails/models/apcemm/apcemm.py +2 -1
- pycontrails/models/cocip/cocip.py +8 -4
- pycontrails/models/cocipgrid/cocip_grid.py +25 -20
- pycontrails/models/dry_advection.py +50 -54
- pycontrails/models/humidity_scaling/humidity_scaling.py +12 -7
- pycontrails/models/ps_model/__init__.py +2 -1
- pycontrails/models/ps_model/ps_aircraft_params.py +3 -2
- pycontrails/models/ps_model/ps_grid.py +187 -1
- pycontrails/models/ps_model/ps_model.py +12 -10
- pycontrails/models/ps_model/ps_operational_limits.py +39 -52
- pycontrails/physics/geo.py +149 -0
- pycontrails/physics/jet.py +141 -11
- pycontrails/physics/static/iata-cargo-load-factors-20241115.csv +71 -0
- pycontrails/physics/static/iata-passenger-load-factors-20241115.csv +71 -0
- {pycontrails-0.54.1.dist-info → pycontrails-0.54.3.dist-info}/METADATA +12 -11
- {pycontrails-0.54.1.dist-info → pycontrails-0.54.3.dist-info}/RECORD +43 -41
- {pycontrails-0.54.1.dist-info → pycontrails-0.54.3.dist-info}/WHEEL +1 -1
- {pycontrails-0.54.1.dist-info → pycontrails-0.54.3.dist-info}/LICENSE +0 -0
- {pycontrails-0.54.1.dist-info → pycontrails-0.54.3.dist-info}/NOTICE +0 -0
- {pycontrails-0.54.1.dist-info → pycontrails-0.54.3.dist-info}/top_level.txt +0 -0
pycontrails/_version.py
CHANGED
|
@@ -4,12 +4,17 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import abc
|
|
6
6
|
import dataclasses
|
|
7
|
+
import sys
|
|
7
8
|
import warnings
|
|
8
9
|
from typing import Any, Generic, NoReturn, overload
|
|
9
10
|
|
|
11
|
+
if sys.version_info >= (3, 12):
|
|
12
|
+
from typing import override
|
|
13
|
+
else:
|
|
14
|
+
from typing_extensions import override
|
|
15
|
+
|
|
10
16
|
import numpy as np
|
|
11
17
|
import numpy.typing as npt
|
|
12
|
-
from overrides import overrides
|
|
13
18
|
|
|
14
19
|
from pycontrails.core import flight, fuel
|
|
15
20
|
from pycontrails.core.fleet import Fleet
|
|
@@ -21,7 +26,9 @@ from pycontrails.physics import jet
|
|
|
21
26
|
from pycontrails.utils.types import ArrayOrFloat
|
|
22
27
|
|
|
23
28
|
#: Default load factor for aircraft performance models.
|
|
24
|
-
|
|
29
|
+
#: See :func:`pycontrails.physics.jet.aircraft_load_factor`
|
|
30
|
+
#: for a higher precision approach to estimating the load factor.
|
|
31
|
+
DEFAULT_LOAD_FACTOR = 0.83
|
|
25
32
|
|
|
26
33
|
|
|
27
34
|
# --------------------------------------
|
|
@@ -30,7 +37,19 @@ DEFAULT_LOAD_FACTOR = 0.7
|
|
|
30
37
|
|
|
31
38
|
|
|
32
39
|
@dataclasses.dataclass
|
|
33
|
-
class
|
|
40
|
+
class CommonAircraftPerformanceParams:
|
|
41
|
+
"""Params for :class:`AircraftPerformanceParams` and :class:`AircraftPerformanceGridParams`."""
|
|
42
|
+
|
|
43
|
+
#: Account for "in-service" engine deterioration between maintenance cycles.
|
|
44
|
+
#: Default value is set to +2.5% increase in fuel consumption.
|
|
45
|
+
#: Reference:
|
|
46
|
+
#: Gurrola Arrieta, M.D.J., Botez, R.M. and Lasne, A., 2024. An Engine Deterioration Model for
|
|
47
|
+
#: Predicting Fuel Consumption Impact in a Regional Aircraft. Aerospace, 11(6), p.426.
|
|
48
|
+
engine_deterioration_factor: float = 0.025
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@dataclasses.dataclass
|
|
52
|
+
class AircraftPerformanceParams(ModelParams, CommonAircraftPerformanceParams):
|
|
34
53
|
"""Parameters for :class:`AircraftPerformance`."""
|
|
35
54
|
|
|
36
55
|
#: Whether to correct fuel flow to ensure it remains within
|
|
@@ -123,7 +142,7 @@ class AircraftPerformance(Model):
|
|
|
123
142
|
Flight trajectory with aircraft performance data.
|
|
124
143
|
"""
|
|
125
144
|
|
|
126
|
-
@
|
|
145
|
+
@override
|
|
127
146
|
def set_source_met(self, *args: Any, **kwargs: Any) -> None:
|
|
128
147
|
fill_with_isa = self.params["fill_low_altitude_with_isa_temperature"]
|
|
129
148
|
if fill_with_isa and (self.met is None or "air_temperature" not in self.met):
|
|
@@ -542,7 +561,7 @@ class AircraftPerformanceData:
|
|
|
542
561
|
|
|
543
562
|
|
|
544
563
|
@dataclasses.dataclass
|
|
545
|
-
class AircraftPerformanceGridParams(ModelParams):
|
|
564
|
+
class AircraftPerformanceGridParams(ModelParams, CommonAircraftPerformanceParams):
|
|
546
565
|
"""Parameters for :class:`AircraftPerformanceGrid`."""
|
|
547
566
|
|
|
548
567
|
#: Fuel type
|
pycontrails/core/cache.py
CHANGED
|
@@ -7,14 +7,18 @@ import logging
|
|
|
7
7
|
import os
|
|
8
8
|
import pathlib
|
|
9
9
|
import shutil
|
|
10
|
+
import sys
|
|
10
11
|
import warnings
|
|
11
12
|
from abc import ABC, abstractmethod
|
|
12
13
|
from collections.abc import Sequence
|
|
13
14
|
from typing import TYPE_CHECKING, Any
|
|
14
15
|
|
|
15
|
-
|
|
16
|
+
if sys.version_info >= (3, 12):
|
|
17
|
+
from typing import override
|
|
18
|
+
else:
|
|
19
|
+
from typing_extensions import override
|
|
16
20
|
|
|
17
|
-
|
|
21
|
+
logger = logging.getLogger(__name__)
|
|
18
22
|
|
|
19
23
|
from pycontrails.utils import dependencies
|
|
20
24
|
|
|
@@ -203,20 +207,20 @@ class DiskCacheStore(CacheStore):
|
|
|
203
207
|
return f"DiskCacheStore: {self.cache_dir}"
|
|
204
208
|
|
|
205
209
|
@property
|
|
206
|
-
@
|
|
210
|
+
@override
|
|
207
211
|
def size(self) -> float:
|
|
208
212
|
disk_path = pathlib.Path(self.cache_dir)
|
|
209
213
|
size = sum(f.stat().st_size for f in disk_path.rglob("*") if f.is_file())
|
|
210
214
|
logger.debug("Disk cache size %s bytes", size)
|
|
211
215
|
return size / 1e6
|
|
212
216
|
|
|
213
|
-
@
|
|
217
|
+
@override
|
|
214
218
|
def listdir(self, path: str = "") -> list[str]:
|
|
215
219
|
path = self.path(path)
|
|
216
220
|
iter_ = pathlib.Path(path).iterdir()
|
|
217
221
|
return sorted(str(f.relative_to(path)) for f in iter_)
|
|
218
222
|
|
|
219
|
-
@
|
|
223
|
+
@override
|
|
220
224
|
def path(self, cache_path: str) -> str:
|
|
221
225
|
if cache_path.startswith(self.cache_dir):
|
|
222
226
|
disk_path = pathlib.Path(cache_path)
|
|
@@ -228,7 +232,7 @@ class DiskCacheStore(CacheStore):
|
|
|
228
232
|
|
|
229
233
|
return str(disk_path)
|
|
230
234
|
|
|
231
|
-
@
|
|
235
|
+
@override
|
|
232
236
|
def exists(self, cache_path: str) -> bool:
|
|
233
237
|
disk_path = pathlib.Path(self.path(cache_path))
|
|
234
238
|
return disk_path.exists()
|
|
@@ -551,7 +555,7 @@ class GCPCacheStore(CacheStore):
|
|
|
551
555
|
return self._client
|
|
552
556
|
|
|
553
557
|
@property
|
|
554
|
-
@
|
|
558
|
+
@override
|
|
555
559
|
def size(self) -> float:
|
|
556
560
|
# get list of blobs below this path
|
|
557
561
|
blobs = self._bucket.list_blobs(prefix=self.cache_dir)
|
|
@@ -559,7 +563,7 @@ class GCPCacheStore(CacheStore):
|
|
|
559
563
|
logger.debug("GCP cache size %s bytes", size)
|
|
560
564
|
return size / 1e6
|
|
561
565
|
|
|
562
|
-
@
|
|
566
|
+
@override
|
|
563
567
|
def listdir(self, path: str = "") -> list[str]:
|
|
564
568
|
# I don't necessarily think we want to implement this .... it might be
|
|
565
569
|
# very slow if the bucket is large. BUT, it won't be slower than the size
|
|
@@ -572,7 +576,7 @@ class GCPCacheStore(CacheStore):
|
|
|
572
576
|
"list files in the local disk cache."
|
|
573
577
|
)
|
|
574
578
|
|
|
575
|
-
@
|
|
579
|
+
@override
|
|
576
580
|
def path(self, cache_path: str) -> str:
|
|
577
581
|
if cache_path.startswith(self.cache_dir):
|
|
578
582
|
return cache_path
|
|
@@ -604,7 +608,7 @@ class GCPCacheStore(CacheStore):
|
|
|
604
608
|
bucket_path = self.path(cache_path)
|
|
605
609
|
return f"gs://{self.bucket}/{bucket_path}"
|
|
606
610
|
|
|
607
|
-
@
|
|
611
|
+
@override
|
|
608
612
|
def exists(self, cache_path: str) -> bool:
|
|
609
613
|
# see if file is in the mirror disk cache
|
|
610
614
|
if self._disk_cache.exists(cache_path):
|
pycontrails/core/fleet.py
CHANGED
|
@@ -2,14 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
import sys
|
|
5
6
|
import warnings
|
|
6
7
|
from collections.abc import Iterable
|
|
7
8
|
from typing import Any, NoReturn
|
|
8
9
|
|
|
10
|
+
if sys.version_info >= (3, 11):
|
|
11
|
+
from typing import Self
|
|
12
|
+
else:
|
|
13
|
+
from typing_extensions import Self
|
|
14
|
+
|
|
15
|
+
if sys.version_info >= (3, 12):
|
|
16
|
+
from typing import override
|
|
17
|
+
else:
|
|
18
|
+
from typing_extensions import override
|
|
19
|
+
|
|
9
20
|
import numpy as np
|
|
10
21
|
import numpy.typing as npt
|
|
11
22
|
import pandas as pd
|
|
12
|
-
from overrides import overrides
|
|
13
23
|
|
|
14
24
|
from pycontrails.core.flight import Flight
|
|
15
25
|
from pycontrails.core.fuel import Fuel, JetA
|
|
@@ -121,13 +131,13 @@ class Fleet(Flight):
|
|
|
121
131
|
|
|
122
132
|
return final_waypoints, fl_attrs
|
|
123
133
|
|
|
124
|
-
@
|
|
134
|
+
@override
|
|
125
135
|
def copy(self, **kwargs: Any) -> Fleet:
|
|
126
136
|
kwargs.setdefault("fuel", self.fuel)
|
|
127
137
|
kwargs.setdefault("fl_attrs", self.fl_attrs)
|
|
128
138
|
return super().copy(**kwargs)
|
|
129
139
|
|
|
130
|
-
@
|
|
140
|
+
@override
|
|
131
141
|
def filter(self, mask: npt.NDArray[np.bool_], copy: bool = True, **kwargs: Any) -> Fleet:
|
|
132
142
|
kwargs.setdefault("fuel", self.fuel)
|
|
133
143
|
|
|
@@ -137,7 +147,7 @@ class Fleet(Flight):
|
|
|
137
147
|
|
|
138
148
|
return super().filter(mask, copy=copy, **kwargs)
|
|
139
149
|
|
|
140
|
-
@
|
|
150
|
+
@override
|
|
141
151
|
def sort(self, by: str | list[str]) -> NoReturn:
|
|
142
152
|
msg = (
|
|
143
153
|
"Fleet.sort is not implemented. A Fleet instance must be sorted "
|
|
@@ -154,7 +164,7 @@ class Fleet(Flight):
|
|
|
154
164
|
broadcast_numeric: bool = True,
|
|
155
165
|
copy: bool = True,
|
|
156
166
|
attrs: dict[str, Any] | None = None,
|
|
157
|
-
) ->
|
|
167
|
+
) -> Self:
|
|
158
168
|
"""Instantiate a :class:`Fleet` instance from an iterable of :class:`Flight`.
|
|
159
169
|
|
|
160
170
|
.. versionchanged:: 0.49.3
|
|
@@ -314,39 +324,39 @@ class Fleet(Flight):
|
|
|
314
324
|
# use case isn't seen.
|
|
315
325
|
return np.concatenate(tas)
|
|
316
326
|
|
|
317
|
-
@
|
|
327
|
+
@override
|
|
318
328
|
def segment_groundspeed(self, *args: Any, **kwargs: Any) -> npt.NDArray[np.float64]:
|
|
319
329
|
fls = self.to_flight_list(copy=False)
|
|
320
330
|
gs = [fl.segment_groundspeed(*args, **kwargs) for fl in fls]
|
|
321
331
|
return np.concatenate(gs)
|
|
322
332
|
|
|
323
|
-
@
|
|
333
|
+
@override
|
|
324
334
|
def resample_and_fill(self, *args: Any, **kwargs: Any) -> Fleet:
|
|
325
335
|
flights = self.to_flight_list(copy=False)
|
|
326
336
|
flights = [fl.resample_and_fill(*args, **kwargs) for fl in flights]
|
|
327
337
|
return type(self).from_seq(flights, copy=False, broadcast_numeric=False, attrs=self.attrs)
|
|
328
338
|
|
|
329
|
-
@
|
|
339
|
+
@override
|
|
330
340
|
def segment_length(self) -> npt.NDArray[np.float64]:
|
|
331
341
|
return np.where(self.final_waypoints, np.nan, super().segment_length())
|
|
332
342
|
|
|
333
343
|
@property
|
|
334
|
-
@
|
|
344
|
+
@override
|
|
335
345
|
def max_distance_gap(self) -> float:
|
|
336
346
|
return np.nanmax(self.segment_length()).item()
|
|
337
347
|
|
|
338
|
-
@
|
|
348
|
+
@override
|
|
339
349
|
def segment_azimuth(self) -> npt.NDArray[np.float64]:
|
|
340
350
|
return np.where(self.final_waypoints, np.nan, super().segment_azimuth())
|
|
341
351
|
|
|
342
|
-
@
|
|
352
|
+
@override
|
|
343
353
|
def segment_angle(self) -> tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]:
|
|
344
354
|
sin_a, cos_a = super().segment_angle()
|
|
345
355
|
sin_a[self.final_waypoints] = np.nan
|
|
346
356
|
cos_a[self.final_waypoints] = np.nan
|
|
347
357
|
return sin_a, cos_a
|
|
348
358
|
|
|
349
|
-
@
|
|
359
|
+
@override
|
|
350
360
|
def clean_and_resample(
|
|
351
361
|
self,
|
|
352
362
|
freq: str = "1min",
|
pycontrails/core/flight.py
CHANGED
|
@@ -4,14 +4,20 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import enum
|
|
6
6
|
import logging
|
|
7
|
+
import sys
|
|
7
8
|
import warnings
|
|
8
9
|
from typing import TYPE_CHECKING, Any, NoReturn, TypeVar
|
|
9
10
|
|
|
11
|
+
if sys.version_info >= (3, 12):
|
|
12
|
+
from typing import override
|
|
13
|
+
else:
|
|
14
|
+
from typing_extensions import override
|
|
15
|
+
|
|
16
|
+
|
|
10
17
|
import numpy as np
|
|
11
18
|
import numpy.typing as npt
|
|
12
19
|
import pandas as pd
|
|
13
20
|
import scipy.signal
|
|
14
|
-
from overrides import overrides
|
|
15
21
|
|
|
16
22
|
from pycontrails.core.fuel import Fuel, JetA
|
|
17
23
|
from pycontrails.core.vector import AttrDict, GeoVectorDataset, VectorDataDict, VectorDataset
|
|
@@ -115,6 +121,8 @@ class Flight(GeoVectorDataset):
|
|
|
115
121
|
calculations with the ICAO Aircraft Emissions Databank (EDB).
|
|
116
122
|
- ``max_mach_number``: Maximum Mach number at cruise altitude. Used by
|
|
117
123
|
some aircraft performance models to clip true airspeed.
|
|
124
|
+
- ``load_factor``: The load factor used in determining the aircraft's
|
|
125
|
+
take-off weight. Used by some aircraft performance models.
|
|
118
126
|
|
|
119
127
|
Numeric quantities that are constant over the entire flight trajectory
|
|
120
128
|
should be included as attributes.
|
|
@@ -276,19 +284,19 @@ class Flight(GeoVectorDataset):
|
|
|
276
284
|
"'drop_duplicated_times=True' or call the 'resample_and_fill' method."
|
|
277
285
|
)
|
|
278
286
|
|
|
279
|
-
@
|
|
287
|
+
@override
|
|
280
288
|
def copy(self: FlightType, **kwargs: Any) -> FlightType:
|
|
281
289
|
kwargs.setdefault("fuel", self.fuel)
|
|
282
290
|
return super().copy(**kwargs)
|
|
283
291
|
|
|
284
|
-
@
|
|
292
|
+
@override
|
|
285
293
|
def filter(
|
|
286
294
|
self: FlightType, mask: npt.NDArray[np.bool_], copy: bool = True, **kwargs: Any
|
|
287
295
|
) -> FlightType:
|
|
288
296
|
kwargs.setdefault("fuel", self.fuel)
|
|
289
297
|
return super().filter(mask, copy=copy, **kwargs)
|
|
290
298
|
|
|
291
|
-
@
|
|
299
|
+
@override
|
|
292
300
|
def sort(self, by: str | list[str]) -> NoReturn:
|
|
293
301
|
msg = (
|
|
294
302
|
"Flight.sort is not implemented. A Flight instance is automatically sorted "
|
|
@@ -955,7 +963,7 @@ class Flight(GeoVectorDataset):
|
|
|
955
963
|
msg = f"{msg} Pass 'keep_original_index=True' to keep the original index."
|
|
956
964
|
warnings.warn(msg)
|
|
957
965
|
|
|
958
|
-
return Flight(data=df, attrs=self.attrs)
|
|
966
|
+
return Flight(data=df, attrs=self.attrs, fuel=self.fuel)
|
|
959
967
|
|
|
960
968
|
def clean_and_resample(
|
|
961
969
|
self,
|
|
@@ -1091,7 +1099,7 @@ class Flight(GeoVectorDataset):
|
|
|
1091
1099
|
|
|
1092
1100
|
Notes
|
|
1093
1101
|
-----
|
|
1094
|
-
Algorithm is derived from :meth:`traffic.core.
|
|
1102
|
+
Algorithm is derived from :meth:`traffic.core.Flight.filter`.
|
|
1095
1103
|
|
|
1096
1104
|
The `traffic
|
|
1097
1105
|
<https://traffic-viz.github.io/api_reference/traffic.core.flight.html#traffic.core.Flight.filter>`_
|
|
@@ -1419,19 +1427,21 @@ class Flight(GeoVectorDataset):
|
|
|
1419
1427
|
return {"type": "FeatureCollection", "features": features}
|
|
1420
1428
|
|
|
1421
1429
|
def to_traffic(self) -> traffic.core.Flight:
|
|
1422
|
-
"""Convert
|
|
1423
|
-
|
|
1424
|
-
See https://traffic-viz.github.io/traffic.core.flight.html#traffic.core.Flight
|
|
1430
|
+
"""Convert to :class:`traffic.core.Flight`instance.
|
|
1425
1431
|
|
|
1426
1432
|
Returns
|
|
1427
1433
|
-------
|
|
1428
|
-
|
|
1429
|
-
|
|
1434
|
+
traffic.core.Flight
|
|
1435
|
+
traffic flight instance
|
|
1430
1436
|
|
|
1431
1437
|
Raises
|
|
1432
1438
|
------
|
|
1433
1439
|
ModuleNotFoundError
|
|
1434
1440
|
`traffic` package not installed
|
|
1441
|
+
|
|
1442
|
+
See Also
|
|
1443
|
+
--------
|
|
1444
|
+
:class:`traffic.core.Flight`
|
|
1435
1445
|
"""
|
|
1436
1446
|
try:
|
|
1437
1447
|
import traffic.core
|
|
@@ -1977,18 +1987,18 @@ def filter_altitude(
|
|
|
1977
1987
|
|
|
1978
1988
|
Notes
|
|
1979
1989
|
-----
|
|
1980
|
-
Algorithm is derived from :meth:`traffic.core.
|
|
1990
|
+
Algorithm is derived from :meth:`traffic.core.Flight.filter`.
|
|
1981
1991
|
|
|
1982
|
-
The `traffic
|
|
1992
|
+
The `traffic filter algorithm
|
|
1983
1993
|
<https://traffic-viz.github.io/api_reference/traffic.core.flight.html#traffic.core.Flight.filter>`_
|
|
1984
|
-
|
|
1994
|
+
also computes thresholds on sliding windows
|
|
1985
1995
|
and replaces unacceptable values with NaNs.
|
|
1986
1996
|
|
|
1987
1997
|
Errors may raised if the ``kernel_size`` is too large.
|
|
1988
1998
|
|
|
1989
1999
|
See Also
|
|
1990
2000
|
--------
|
|
1991
|
-
:meth:`traffic.core.
|
|
2001
|
+
:meth:`traffic.core.Flight.filter`
|
|
1992
2002
|
:func:`scipy.signal.medfilt`
|
|
1993
2003
|
"""
|
|
1994
2004
|
if not len(altitude_ft):
|
pycontrails/core/met.py
CHANGED
|
@@ -6,6 +6,7 @@ import hashlib
|
|
|
6
6
|
import json
|
|
7
7
|
import logging
|
|
8
8
|
import pathlib
|
|
9
|
+
import sys
|
|
9
10
|
import typing
|
|
10
11
|
import warnings
|
|
11
12
|
from abc import ABC, abstractmethod
|
|
@@ -29,11 +30,20 @@ from typing import (
|
|
|
29
30
|
overload,
|
|
30
31
|
)
|
|
31
32
|
|
|
33
|
+
if sys.version_info >= (3, 11):
|
|
34
|
+
from typing import Self
|
|
35
|
+
else:
|
|
36
|
+
from typing_extensions import Self
|
|
37
|
+
|
|
38
|
+
if sys.version_info >= (3, 12):
|
|
39
|
+
from typing import override
|
|
40
|
+
else:
|
|
41
|
+
from typing_extensions import override
|
|
42
|
+
|
|
32
43
|
import numpy as np
|
|
33
44
|
import numpy.typing as npt
|
|
34
45
|
import pandas as pd
|
|
35
46
|
import xarray as xr
|
|
36
|
-
from overrides import overrides
|
|
37
47
|
|
|
38
48
|
from pycontrails.core import interpolation
|
|
39
49
|
from pycontrails.core import vector as vector_module
|
|
@@ -863,13 +873,13 @@ class MetDataset(MetBase):
|
|
|
863
873
|
return key in self.data
|
|
864
874
|
|
|
865
875
|
@property
|
|
866
|
-
@
|
|
876
|
+
@override
|
|
867
877
|
def shape(self) -> tuple[int, int, int, int]:
|
|
868
878
|
sizes = self.data.sizes
|
|
869
879
|
return sizes["longitude"], sizes["latitude"], sizes["level"], sizes["time"]
|
|
870
880
|
|
|
871
881
|
@property
|
|
872
|
-
@
|
|
882
|
+
@override
|
|
873
883
|
def size(self) -> int:
|
|
874
884
|
return np.prod(self.shape).item()
|
|
875
885
|
|
|
@@ -978,7 +988,7 @@ class MetDataset(MetBase):
|
|
|
978
988
|
hash: str,
|
|
979
989
|
cachestore: CacheStore | None = None,
|
|
980
990
|
chunks: dict[str, int] | None = None,
|
|
981
|
-
) ->
|
|
991
|
+
) -> Self:
|
|
982
992
|
"""Load saved intermediate from :attr:`cachestore`.
|
|
983
993
|
|
|
984
994
|
Parameters
|
|
@@ -993,7 +1003,7 @@ class MetDataset(MetBase):
|
|
|
993
1003
|
|
|
994
1004
|
Returns
|
|
995
1005
|
-------
|
|
996
|
-
|
|
1006
|
+
Self
|
|
997
1007
|
New MetDataArray with loaded data.
|
|
998
1008
|
"""
|
|
999
1009
|
cachestore = cachestore or DiskCacheStore()
|
|
@@ -1015,14 +1025,14 @@ class MetDataset(MetBase):
|
|
|
1015
1025
|
cachestore=self.cachestore,
|
|
1016
1026
|
)
|
|
1017
1027
|
|
|
1018
|
-
@
|
|
1028
|
+
@override
|
|
1019
1029
|
def broadcast_coords(self, name: str) -> xr.DataArray:
|
|
1020
1030
|
da = xr.ones_like(self.data[next(iter(self.data.keys()))]) * self.data[name]
|
|
1021
1031
|
da.name = name
|
|
1022
1032
|
|
|
1023
1033
|
return da
|
|
1024
1034
|
|
|
1025
|
-
@
|
|
1035
|
+
@override
|
|
1026
1036
|
def downselect(self, bbox: tuple[float, ...]) -> MetDataset:
|
|
1027
1037
|
data = downselect(self.data, bbox)
|
|
1028
1038
|
return MetDataset(data, cachestore=self.cachestore, copy=False)
|
|
@@ -1179,7 +1189,7 @@ class MetDataset(MetBase):
|
|
|
1179
1189
|
latitude: npt.ArrayLike | float,
|
|
1180
1190
|
level: npt.ArrayLike | float,
|
|
1181
1191
|
time: npt.ArrayLike | np.datetime64,
|
|
1182
|
-
) ->
|
|
1192
|
+
) -> Self:
|
|
1183
1193
|
r"""Create a :class:`MetDataset` containing a coordinate skeleton from coordinate arrays.
|
|
1184
1194
|
|
|
1185
1195
|
Parameters
|
|
@@ -1193,7 +1203,7 @@ class MetDataset(MetBase):
|
|
|
1193
1203
|
|
|
1194
1204
|
Returns
|
|
1195
1205
|
-------
|
|
1196
|
-
|
|
1206
|
+
Self
|
|
1197
1207
|
MetDataset with no variables.
|
|
1198
1208
|
|
|
1199
1209
|
Examples
|
|
@@ -1279,7 +1289,7 @@ class MetDataset(MetBase):
|
|
|
1279
1289
|
return cls(xr.Dataset({}, coords=coords))
|
|
1280
1290
|
|
|
1281
1291
|
@classmethod
|
|
1282
|
-
def from_zarr(cls, store: Any, **kwargs: Any) ->
|
|
1292
|
+
def from_zarr(cls, store: Any, **kwargs: Any) -> Self:
|
|
1283
1293
|
"""Create a :class:`MetDataset` from a path to a Zarr store.
|
|
1284
1294
|
|
|
1285
1295
|
Parameters
|
|
@@ -1291,7 +1301,7 @@ class MetDataset(MetBase):
|
|
|
1291
1301
|
|
|
1292
1302
|
Returns
|
|
1293
1303
|
-------
|
|
1294
|
-
|
|
1304
|
+
Self
|
|
1295
1305
|
MetDataset with data from Zarr store.
|
|
1296
1306
|
"""
|
|
1297
1307
|
kwargs.setdefault("storage_options", {"read_only": True})
|
|
@@ -1400,8 +1410,9 @@ class MetDataArray(MetBase):
|
|
|
1400
1410
|
|
|
1401
1411
|
See Also
|
|
1402
1412
|
--------
|
|
1403
|
-
|
|
1404
|
-
|
|
1413
|
+
:meth:`xarray.Dataset.load`
|
|
1414
|
+
:meth:`xarray.DataArray.load`
|
|
1415
|
+
|
|
1405
1416
|
"""
|
|
1406
1417
|
if not self.in_memory:
|
|
1407
1418
|
self._check_memory("Extracting numpy array from")
|
|
@@ -1432,12 +1443,12 @@ class MetDataArray(MetBase):
|
|
|
1432
1443
|
return np.array_equal(self.data, self.data.astype(bool))
|
|
1433
1444
|
|
|
1434
1445
|
@property
|
|
1435
|
-
@
|
|
1446
|
+
@override
|
|
1436
1447
|
def size(self) -> int:
|
|
1437
1448
|
return self.data.size
|
|
1438
1449
|
|
|
1439
1450
|
@property
|
|
1440
|
-
@
|
|
1451
|
+
@override
|
|
1441
1452
|
def shape(self) -> tuple[int, int, int, int]:
|
|
1442
1453
|
# https://github.com/python/mypy/issues/1178
|
|
1443
1454
|
return typing.cast(tuple[int, int, int, int], self.data.shape)
|
|
@@ -1827,7 +1838,7 @@ class MetDataArray(MetBase):
|
|
|
1827
1838
|
hash: str,
|
|
1828
1839
|
cachestore: CacheStore | None = None,
|
|
1829
1840
|
chunks: dict[str, int] | None = None,
|
|
1830
|
-
) ->
|
|
1841
|
+
) -> Self:
|
|
1831
1842
|
"""Load saved intermediate from :attr:`cachestore`.
|
|
1832
1843
|
|
|
1833
1844
|
Parameters
|
|
@@ -2016,7 +2027,7 @@ class MetDataArray(MetBase):
|
|
|
2016
2027
|
See Also
|
|
2017
2028
|
--------
|
|
2018
2029
|
:meth:`to_polyhedra`
|
|
2019
|
-
:func:`
|
|
2030
|
+
:func:`polygons.find_multipolygons`
|
|
2020
2031
|
|
|
2021
2032
|
Examples
|
|
2022
2033
|
--------
|
|
@@ -2220,7 +2231,7 @@ class MetDataArray(MetBase):
|
|
|
2220
2231
|
|
|
2221
2232
|
Returns
|
|
2222
2233
|
-------
|
|
2223
|
-
dict |
|
|
2234
|
+
dict | open3d.geometry.TriangleMesh
|
|
2224
2235
|
Python representation of geojson object or `Open3D Triangle Mesh
|
|
2225
2236
|
<http://www.open3d.org/docs/release/tutorial/geometry/mesh.html>`_ depending on the
|
|
2226
2237
|
`return_type` parameter.
|
|
@@ -2234,8 +2245,9 @@ class MetDataArray(MetBase):
|
|
|
2234
2245
|
|
|
2235
2246
|
See Also
|
|
2236
2247
|
--------
|
|
2237
|
-
:meth:`
|
|
2238
|
-
|
|
2248
|
+
:meth:`to_polygon_feature`
|
|
2249
|
+
:func:`skimage.measure.marching_cubes`
|
|
2250
|
+
:class:`open3d.geometry.TriangleMesh`
|
|
2239
2251
|
|
|
2240
2252
|
Notes
|
|
2241
2253
|
-----
|
|
@@ -2380,14 +2392,14 @@ class MetDataArray(MetBase):
|
|
|
2380
2392
|
)
|
|
2381
2393
|
return mesh
|
|
2382
2394
|
|
|
2383
|
-
@
|
|
2395
|
+
@override
|
|
2384
2396
|
def broadcast_coords(self, name: str) -> xr.DataArray:
|
|
2385
2397
|
da = xr.ones_like(self.data) * self.data[name]
|
|
2386
2398
|
da.name = name
|
|
2387
2399
|
|
|
2388
2400
|
return da
|
|
2389
2401
|
|
|
2390
|
-
@
|
|
2402
|
+
@override
|
|
2391
2403
|
def downselect(self, bbox: tuple[float, ...]) -> MetDataArray:
|
|
2392
2404
|
data = downselect(self.data, bbox)
|
|
2393
2405
|
return MetDataArray(data, cachestore=self.cachestore)
|
|
Binary file
|