pycontrails 0.54.2__cp313-cp313-win_amd64.whl → 0.54.4__cp313-cp313-win_amd64.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 +75 -61
- pycontrails/core/cache.py +7 -7
- pycontrails/core/fleet.py +25 -21
- pycontrails/core/flight.py +215 -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.cp313-win_amd64.pyd +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/ecmwf/variables.py +1 -0
- pycontrails/datalib/gfs/__init__.py +6 -6
- pycontrails/datalib/gfs/gfs.py +2 -2
- pycontrails/datalib/goes.py +5 -5
- pycontrails/datalib/landsat.py +5 -8
- pycontrails/datalib/sentinel.py +7 -11
- pycontrails/ext/bada.py +3 -2
- pycontrails/ext/empirical_grid.py +1 -1
- pycontrails/ext/synthetic_flight.py +3 -2
- pycontrails/models/accf.py +40 -19
- pycontrails/models/apcemm/apcemm.py +5 -4
- pycontrails/models/cocip/__init__.py +2 -2
- pycontrails/models/cocip/cocip.py +16 -17
- 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 +118 -107
- pycontrails/models/dry_advection.py +59 -58
- 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 +3 -2
- pycontrails/models/ps_model/ps_aircraft_params.py +11 -6
- pycontrails/models/ps_model/ps_grid.py +256 -60
- pycontrails/models/ps_model/ps_model.py +18 -21
- pycontrails/models/ps_model/ps_operational_limits.py +58 -69
- pycontrails/models/tau_cirrus.py +8 -1
- pycontrails/physics/geo.py +216 -67
- pycontrails/physics/jet.py +220 -90
- pycontrails/physics/static/iata-cargo-load-factors-20241115.csv +71 -0
- pycontrails/physics/static/iata-passenger-load-factors-20241115.csv +71 -0
- pycontrails/physics/units.py +14 -14
- pycontrails/utils/json.py +1 -2
- pycontrails/utils/types.py +12 -7
- {pycontrails-0.54.2.dist-info → pycontrails-0.54.4.dist-info}/METADATA +10 -10
- {pycontrails-0.54.2.dist-info → pycontrails-0.54.4.dist-info}/NOTICE +1 -1
- pycontrails-0.54.4.dist-info/RECORD +111 -0
- {pycontrails-0.54.2.dist-info → pycontrails-0.54.4.dist-info}/WHEEL +1 -1
- pycontrails-0.54.2.dist-info/RECORD +0 -109
- {pycontrails-0.54.2.dist-info → pycontrails-0.54.4.dist-info}/LICENSE +0 -0
- {pycontrails-0.54.2.dist-info → pycontrails-0.54.4.dist-info}/top_level.txt +0 -0
pycontrails/__init__.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""
|
|
2
2
|
``pycontrails`` public API.
|
|
3
3
|
|
|
4
|
-
Copyright 2021-
|
|
4
|
+
Copyright 2021-present Breakthrough Energy
|
|
5
5
|
|
|
6
6
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
7
|
you may not use this file except in compliance with the License.
|
|
@@ -60,8 +60,8 @@ __all__ = [
|
|
|
60
60
|
"HydrogenFuel",
|
|
61
61
|
"JetA",
|
|
62
62
|
"MetDataArray",
|
|
63
|
-
"MetDataset",
|
|
64
63
|
"MetDataSource",
|
|
64
|
+
"MetDataset",
|
|
65
65
|
"MetVariable",
|
|
66
66
|
"Model",
|
|
67
67
|
"ModelParams",
|
pycontrails/_version.py
CHANGED
pycontrails/core/__init__.py
CHANGED
|
@@ -26,7 +26,9 @@ from pycontrails.physics import jet
|
|
|
26
26
|
from pycontrails.utils.types import ArrayOrFloat
|
|
27
27
|
|
|
28
28
|
#: Default load factor for aircraft performance models.
|
|
29
|
-
|
|
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
|
|
30
32
|
|
|
31
33
|
|
|
32
34
|
# --------------------------------------
|
|
@@ -35,7 +37,19 @@ DEFAULT_LOAD_FACTOR = 0.7
|
|
|
35
37
|
|
|
36
38
|
|
|
37
39
|
@dataclasses.dataclass
|
|
38
|
-
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):
|
|
39
53
|
"""Parameters for :class:`AircraftPerformance`."""
|
|
40
54
|
|
|
41
55
|
#: Whether to correct fuel flow to ensure it remains within
|
|
@@ -149,14 +163,14 @@ class AircraftPerformance(Model):
|
|
|
149
163
|
self,
|
|
150
164
|
*,
|
|
151
165
|
aircraft_type: str,
|
|
152
|
-
altitude_ft: npt.NDArray[np.
|
|
166
|
+
altitude_ft: npt.NDArray[np.floating],
|
|
153
167
|
time: npt.NDArray[np.datetime64],
|
|
154
|
-
true_airspeed: npt.NDArray[np.
|
|
155
|
-
air_temperature: npt.NDArray[np.
|
|
156
|
-
aircraft_mass: npt.NDArray[np.
|
|
157
|
-
thrust: npt.NDArray[np.
|
|
158
|
-
engine_efficiency: npt.NDArray[np.
|
|
159
|
-
fuel_flow: npt.NDArray[np.
|
|
168
|
+
true_airspeed: npt.NDArray[np.floating],
|
|
169
|
+
air_temperature: npt.NDArray[np.floating],
|
|
170
|
+
aircraft_mass: npt.NDArray[np.floating] | float | None,
|
|
171
|
+
thrust: npt.NDArray[np.floating] | float | None,
|
|
172
|
+
engine_efficiency: npt.NDArray[np.floating] | float | None,
|
|
173
|
+
fuel_flow: npt.NDArray[np.floating] | float | None,
|
|
160
174
|
q_fuel: float,
|
|
161
175
|
n_iter: int,
|
|
162
176
|
amass_oew: float,
|
|
@@ -178,21 +192,21 @@ class AircraftPerformance(Model):
|
|
|
178
192
|
----------
|
|
179
193
|
aircraft_type: str
|
|
180
194
|
Aircraft type designator used to query the underlying model database.
|
|
181
|
-
altitude_ft: npt.NDArray[np.
|
|
195
|
+
altitude_ft: npt.NDArray[np.floating]
|
|
182
196
|
Altitude at each waypoint, [:math:`ft`]
|
|
183
197
|
time: npt.NDArray[np.datetime64]
|
|
184
198
|
Waypoint time in ``np.datetime64`` format.
|
|
185
|
-
true_airspeed: npt.NDArray[np.
|
|
199
|
+
true_airspeed: npt.NDArray[np.floating]
|
|
186
200
|
True airspeed for each waypoint, [:math:`m s^{-1}`]
|
|
187
|
-
air_temperature : npt.NDArray[np.
|
|
201
|
+
air_temperature : npt.NDArray[np.floating]
|
|
188
202
|
Ambient temperature for each waypoint, [:math:`K`]
|
|
189
|
-
aircraft_mass : npt.NDArray[np.
|
|
203
|
+
aircraft_mass : npt.NDArray[np.floating] | float | None
|
|
190
204
|
Override the aircraft_mass at each waypoint, [:math:`kg`].
|
|
191
|
-
thrust : npt.NDArray[np.
|
|
205
|
+
thrust : npt.NDArray[np.floating] | float | None
|
|
192
206
|
Override the thrust setting at each waypoint, [:math: `N`].
|
|
193
|
-
engine_efficiency : npt.NDArray[np.
|
|
207
|
+
engine_efficiency : npt.NDArray[np.floating] | float | None
|
|
194
208
|
Override the engine efficiency at each waypoint.
|
|
195
|
-
fuel_flow : npt.NDArray[np.
|
|
209
|
+
fuel_flow : npt.NDArray[np.floating] | float | None
|
|
196
210
|
Override the fuel flow at each waypoint, [:math:`kg s^{-1}`].
|
|
197
211
|
q_fuel : float
|
|
198
212
|
Lower calorific value (LCV) of fuel, [:math:`J \ kg_{fuel}^{-1}`].
|
|
@@ -266,14 +280,14 @@ class AircraftPerformance(Model):
|
|
|
266
280
|
self,
|
|
267
281
|
*,
|
|
268
282
|
aircraft_type: str,
|
|
269
|
-
altitude_ft: npt.NDArray[np.
|
|
283
|
+
altitude_ft: npt.NDArray[np.floating],
|
|
270
284
|
time: npt.NDArray[np.datetime64],
|
|
271
|
-
true_airspeed: npt.NDArray[np.
|
|
272
|
-
air_temperature: npt.NDArray[np.
|
|
273
|
-
aircraft_mass: npt.NDArray[np.
|
|
274
|
-
thrust: npt.NDArray[np.
|
|
275
|
-
engine_efficiency: npt.NDArray[np.
|
|
276
|
-
fuel_flow: npt.NDArray[np.
|
|
285
|
+
true_airspeed: npt.NDArray[np.floating],
|
|
286
|
+
air_temperature: npt.NDArray[np.floating],
|
|
287
|
+
aircraft_mass: npt.NDArray[np.floating] | float,
|
|
288
|
+
thrust: npt.NDArray[np.floating] | float | None,
|
|
289
|
+
engine_efficiency: npt.NDArray[np.floating] | float | None,
|
|
290
|
+
fuel_flow: npt.NDArray[np.floating] | float | None,
|
|
277
291
|
q_fuel: float,
|
|
278
292
|
**kwargs: Any,
|
|
279
293
|
) -> AircraftPerformanceData:
|
|
@@ -318,13 +332,13 @@ class AircraftPerformance(Model):
|
|
|
318
332
|
self,
|
|
319
333
|
*,
|
|
320
334
|
aircraft_type: str,
|
|
321
|
-
altitude_ft: npt.NDArray[np.
|
|
335
|
+
altitude_ft: npt.NDArray[np.floating],
|
|
322
336
|
time: npt.NDArray[np.datetime64],
|
|
323
|
-
true_airspeed: npt.NDArray[np.
|
|
324
|
-
air_temperature: npt.NDArray[np.
|
|
325
|
-
thrust: npt.NDArray[np.
|
|
326
|
-
engine_efficiency: npt.NDArray[np.
|
|
327
|
-
fuel_flow: npt.NDArray[np.
|
|
337
|
+
true_airspeed: npt.NDArray[np.floating],
|
|
338
|
+
air_temperature: npt.NDArray[np.floating],
|
|
339
|
+
thrust: npt.NDArray[np.floating] | float | None,
|
|
340
|
+
engine_efficiency: npt.NDArray[np.floating] | float | None,
|
|
341
|
+
fuel_flow: npt.NDArray[np.floating] | float | None,
|
|
328
342
|
q_fuel: float,
|
|
329
343
|
n_iter: int,
|
|
330
344
|
amass_oew: float,
|
|
@@ -337,7 +351,7 @@ class AircraftPerformance(Model):
|
|
|
337
351
|
# Variable aircraft_mass will change dynamically after each iteration
|
|
338
352
|
# Set the initial aircraft mass depending on a possible load factor
|
|
339
353
|
|
|
340
|
-
aircraft_mass: npt.NDArray[np.
|
|
354
|
+
aircraft_mass: npt.NDArray[np.floating] | float
|
|
341
355
|
if takeoff_mass is not None:
|
|
342
356
|
aircraft_mass = takeoff_mass
|
|
343
357
|
else:
|
|
@@ -397,14 +411,14 @@ class AircraftPerformance(Model):
|
|
|
397
411
|
self,
|
|
398
412
|
*,
|
|
399
413
|
aircraft_type: str,
|
|
400
|
-
altitude_ft: npt.NDArray[np.
|
|
401
|
-
air_temperature: npt.NDArray[np.
|
|
414
|
+
altitude_ft: npt.NDArray[np.floating],
|
|
415
|
+
air_temperature: npt.NDArray[np.floating],
|
|
402
416
|
time: npt.NDArray[np.datetime64] | None,
|
|
403
|
-
true_airspeed: npt.NDArray[np.
|
|
404
|
-
aircraft_mass: npt.NDArray[np.
|
|
405
|
-
engine_efficiency: npt.NDArray[np.
|
|
406
|
-
fuel_flow: npt.NDArray[np.
|
|
407
|
-
thrust: npt.NDArray[np.
|
|
417
|
+
true_airspeed: npt.NDArray[np.floating] | float | None,
|
|
418
|
+
aircraft_mass: npt.NDArray[np.floating] | float,
|
|
419
|
+
engine_efficiency: npt.NDArray[np.floating] | float | None,
|
|
420
|
+
fuel_flow: npt.NDArray[np.floating] | float | None,
|
|
421
|
+
thrust: npt.NDArray[np.floating] | float | None,
|
|
408
422
|
q_fuel: float,
|
|
409
423
|
**kwargs: Any,
|
|
410
424
|
) -> AircraftPerformanceData:
|
|
@@ -427,24 +441,24 @@ class AircraftPerformance(Model):
|
|
|
427
441
|
----------
|
|
428
442
|
aircraft_type : str
|
|
429
443
|
Used to query the underlying model database for aircraft engine parameters.
|
|
430
|
-
altitude_ft : npt.NDArray[np.
|
|
444
|
+
altitude_ft : npt.NDArray[np.floating]
|
|
431
445
|
Altitude at each waypoint, [:math:`ft`]
|
|
432
|
-
air_temperature : npt.NDArray[np.
|
|
446
|
+
air_temperature : npt.NDArray[np.floating]
|
|
433
447
|
Ambient temperature for each waypoint, [:math:`K`]
|
|
434
448
|
time: npt.NDArray[np.datetime64] | None
|
|
435
449
|
Waypoint time in ``np.datetime64`` format. If None, only drag force
|
|
436
450
|
will is used in thrust calculations (ie, no vertical change and constant
|
|
437
451
|
horizontal change). In addition, aircraft is assumed to be in cruise.
|
|
438
|
-
true_airspeed : npt.NDArray[np.
|
|
452
|
+
true_airspeed : npt.NDArray[np.floating] | float | None
|
|
439
453
|
True airspeed for each waypoint, [:math:`m s^{-1}`].
|
|
440
454
|
If None, a nominal value is used.
|
|
441
|
-
aircraft_mass : npt.NDArray[np.
|
|
455
|
+
aircraft_mass : npt.NDArray[np.floating] | float
|
|
442
456
|
Aircraft mass for each waypoint, [:math:`kg`].
|
|
443
|
-
engine_efficiency : npt.NDArray[np.
|
|
457
|
+
engine_efficiency : npt.NDArray[np.floating] | float | None
|
|
444
458
|
Override the engine efficiency at each waypoint.
|
|
445
|
-
fuel_flow : npt.NDArray[np.
|
|
459
|
+
fuel_flow : npt.NDArray[np.floating] | float | None
|
|
446
460
|
Override the fuel flow at each waypoint, [:math:`kg s^{-1}`].
|
|
447
|
-
thrust : npt.NDArray[np.
|
|
461
|
+
thrust : npt.NDArray[np.floating] | float | None
|
|
448
462
|
Override the thrust setting at each waypoint, [:math: `N`].
|
|
449
463
|
q_fuel : float
|
|
450
464
|
Lower calorific value (LCV) of fuel, [:math:`J \ kg_{fuel}^{-1}`].
|
|
@@ -457,12 +471,12 @@ class AircraftPerformance(Model):
|
|
|
457
471
|
Derived performance metrics at each waypoint.
|
|
458
472
|
"""
|
|
459
473
|
|
|
460
|
-
def ensure_true_airspeed_on_source(self) -> npt.NDArray[np.
|
|
474
|
+
def ensure_true_airspeed_on_source(self) -> npt.NDArray[np.floating]:
|
|
461
475
|
"""Add ``true_airspeed`` field to :attr:`source` data if not already present.
|
|
462
476
|
|
|
463
477
|
Returns
|
|
464
478
|
-------
|
|
465
|
-
npt.NDArray[np.
|
|
479
|
+
npt.NDArray[np.floating]
|
|
466
480
|
True airspeed, [:math:`m s^{-1}`]. If ``true_airspeed`` is already present
|
|
467
481
|
on :attr:`source`, this is returned directly. Otherwise, it is calculated
|
|
468
482
|
using :meth:`Flight.segment_true_airspeed`.
|
|
@@ -515,30 +529,30 @@ class AircraftPerformanceData:
|
|
|
515
529
|
|
|
516
530
|
Parameters
|
|
517
531
|
----------
|
|
518
|
-
fuel_flow : npt.NDArray[np.
|
|
532
|
+
fuel_flow : npt.NDArray[np.floating]
|
|
519
533
|
Fuel mass flow rate for each waypoint, [:math:`kg s^{-1}`]
|
|
520
|
-
aircraft_mass : npt.NDArray[np.
|
|
534
|
+
aircraft_mass : npt.NDArray[np.floating]
|
|
521
535
|
Aircraft mass for each waypoint, [:math:`kg`]
|
|
522
|
-
true_airspeed : npt.NDArray[np.
|
|
536
|
+
true_airspeed : npt.NDArray[np.floating]
|
|
523
537
|
True airspeed at each waypoint, [:math: `m s^{-1}`]
|
|
524
|
-
fuel_burn: npt.NDArray[np.
|
|
538
|
+
fuel_burn: npt.NDArray[np.floating]
|
|
525
539
|
Fuel consumption for each waypoint, [:math:`kg`]. Set to an array of
|
|
526
540
|
all nan values if it cannot be computed (ie, working with gridpoints).
|
|
527
|
-
thrust: npt.NDArray[np.
|
|
541
|
+
thrust: npt.NDArray[np.floating]
|
|
528
542
|
Thrust force, [:math:`N`]
|
|
529
|
-
engine_efficiency: npt.NDArray[np.
|
|
543
|
+
engine_efficiency: npt.NDArray[np.floating]
|
|
530
544
|
Overall propulsion efficiency for each waypoint
|
|
531
|
-
rocd : npt.NDArray[np.
|
|
545
|
+
rocd : npt.NDArray[np.floating]
|
|
532
546
|
Rate of climb and descent, [:math:`ft min^{-1}`]
|
|
533
547
|
"""
|
|
534
548
|
|
|
535
|
-
fuel_flow: npt.NDArray[np.
|
|
536
|
-
aircraft_mass: npt.NDArray[np.
|
|
537
|
-
true_airspeed: npt.NDArray[np.
|
|
538
|
-
fuel_burn: npt.NDArray[np.
|
|
539
|
-
thrust: npt.NDArray[np.
|
|
540
|
-
engine_efficiency: npt.NDArray[np.
|
|
541
|
-
rocd: npt.NDArray[np.
|
|
549
|
+
fuel_flow: npt.NDArray[np.floating]
|
|
550
|
+
aircraft_mass: npt.NDArray[np.floating]
|
|
551
|
+
true_airspeed: npt.NDArray[np.floating]
|
|
552
|
+
fuel_burn: npt.NDArray[np.floating]
|
|
553
|
+
thrust: npt.NDArray[np.floating]
|
|
554
|
+
engine_efficiency: npt.NDArray[np.floating]
|
|
555
|
+
rocd: npt.NDArray[np.floating]
|
|
542
556
|
|
|
543
557
|
|
|
544
558
|
# --------------------------------
|
|
@@ -547,7 +561,7 @@ class AircraftPerformanceData:
|
|
|
547
561
|
|
|
548
562
|
|
|
549
563
|
@dataclasses.dataclass
|
|
550
|
-
class AircraftPerformanceGridParams(ModelParams):
|
|
564
|
+
class AircraftPerformanceGridParams(ModelParams, CommonAircraftPerformanceParams):
|
|
551
565
|
"""Parameters for :class:`AircraftPerformanceGrid`."""
|
|
552
566
|
|
|
553
567
|
#: Fuel type
|
pycontrails/core/cache.py
CHANGED
|
@@ -43,7 +43,7 @@ def _get_user_cache_dir() -> str:
|
|
|
43
43
|
class CacheStore(ABC):
|
|
44
44
|
"""Abstract cache storage class for storing staged and intermediate data."""
|
|
45
45
|
|
|
46
|
-
__slots__ = ("
|
|
46
|
+
__slots__ = ("allow_clear", "cache_dir")
|
|
47
47
|
cache_dir: str
|
|
48
48
|
allow_clear: bool
|
|
49
49
|
|
|
@@ -426,15 +426,15 @@ class GCPCacheStore(CacheStore):
|
|
|
426
426
|
"""
|
|
427
427
|
|
|
428
428
|
__slots__ = (
|
|
429
|
-
"
|
|
429
|
+
"_bucket",
|
|
430
|
+
"_client",
|
|
431
|
+
"_disk_cache",
|
|
430
432
|
"bucket",
|
|
433
|
+
"chunk_size",
|
|
434
|
+
"project",
|
|
431
435
|
"read_only",
|
|
432
|
-
"timeout",
|
|
433
436
|
"show_progress",
|
|
434
|
-
"
|
|
435
|
-
"_disk_cache",
|
|
436
|
-
"_client",
|
|
437
|
-
"_bucket",
|
|
437
|
+
"timeout",
|
|
438
438
|
)
|
|
439
439
|
project: str | None
|
|
440
440
|
bucket: str
|
pycontrails/core/fleet.py
CHANGED
|
@@ -32,7 +32,7 @@ class Fleet(Flight):
|
|
|
32
32
|
Flight waypoints are merged into a single :class:`Flight`-like object.
|
|
33
33
|
"""
|
|
34
34
|
|
|
35
|
-
__slots__ = ("
|
|
35
|
+
__slots__ = ("final_waypoints", "fl_attrs")
|
|
36
36
|
|
|
37
37
|
def __init__(
|
|
38
38
|
self,
|
|
@@ -132,13 +132,13 @@ class Fleet(Flight):
|
|
|
132
132
|
return final_waypoints, fl_attrs
|
|
133
133
|
|
|
134
134
|
@override
|
|
135
|
-
def copy(self, **kwargs: Any) ->
|
|
135
|
+
def copy(self, **kwargs: Any) -> Self:
|
|
136
136
|
kwargs.setdefault("fuel", self.fuel)
|
|
137
137
|
kwargs.setdefault("fl_attrs", self.fl_attrs)
|
|
138
138
|
return super().copy(**kwargs)
|
|
139
139
|
|
|
140
140
|
@override
|
|
141
|
-
def filter(self, mask: npt.NDArray[np.bool_], copy: bool = True, **kwargs: Any) ->
|
|
141
|
+
def filter(self, mask: npt.NDArray[np.bool_], copy: bool = True, **kwargs: Any) -> Self:
|
|
142
142
|
kwargs.setdefault("fuel", self.fuel)
|
|
143
143
|
|
|
144
144
|
flight_ids = set(np.unique(self["flight_id"][mask]))
|
|
@@ -162,7 +162,6 @@ class Fleet(Flight):
|
|
|
162
162
|
cls,
|
|
163
163
|
seq: Iterable[Flight],
|
|
164
164
|
broadcast_numeric: bool = True,
|
|
165
|
-
copy: bool = True,
|
|
166
165
|
attrs: dict[str, Any] | None = None,
|
|
167
166
|
) -> Self:
|
|
168
167
|
"""Instantiate a :class:`Fleet` instance from an iterable of :class:`Flight`.
|
|
@@ -177,8 +176,6 @@ class Fleet(Flight):
|
|
|
177
176
|
An iterable of :class:`Flight` instances.
|
|
178
177
|
broadcast_numeric : bool, optional
|
|
179
178
|
If True, broadcast numeric attributes to data variables.
|
|
180
|
-
copy : bool, optional
|
|
181
|
-
If True, make copy of each flight instance in ``seq``.
|
|
182
179
|
attrs : dict[str, Any] | None, optional
|
|
183
180
|
Global attribute to attach to instance.
|
|
184
181
|
|
|
@@ -190,15 +187,15 @@ class Fleet(Flight):
|
|
|
190
187
|
in ``seq``.
|
|
191
188
|
"""
|
|
192
189
|
|
|
193
|
-
def
|
|
194
|
-
return fl.
|
|
190
|
+
def _shallow_copy(fl: Flight) -> Flight:
|
|
191
|
+
return Flight(VectorDataDict(fl.data), attrs=fl.attrs, copy=False, fuel=fl.fuel)
|
|
195
192
|
|
|
196
193
|
def _maybe_warn(fl: Flight) -> Flight:
|
|
197
194
|
if not fl:
|
|
198
195
|
warnings.warn("Empty flight found in sequence. It will be filtered out.")
|
|
199
196
|
return fl
|
|
200
197
|
|
|
201
|
-
seq = tuple(
|
|
198
|
+
seq = tuple(_shallow_copy(fl) for fl in seq if _maybe_warn(fl))
|
|
202
199
|
|
|
203
200
|
if not seq:
|
|
204
201
|
msg = "Cannot create Fleet from empty sequence."
|
|
@@ -265,12 +262,12 @@ class Fleet(Flight):
|
|
|
265
262
|
|
|
266
263
|
def segment_true_airspeed(
|
|
267
264
|
self,
|
|
268
|
-
u_wind: npt.NDArray[np.
|
|
269
|
-
v_wind: npt.NDArray[np.
|
|
265
|
+
u_wind: npt.NDArray[np.floating] | float = 0.0,
|
|
266
|
+
v_wind: npt.NDArray[np.floating] | float = 0.0,
|
|
270
267
|
smooth: bool = True,
|
|
271
268
|
window_length: int = 7,
|
|
272
269
|
polyorder: int = 1,
|
|
273
|
-
) -> npt.NDArray[np.
|
|
270
|
+
) -> npt.NDArray[np.floating]:
|
|
274
271
|
"""Calculate the true airspeed [:math:`m / s`] from the ground speed and horizontal winds.
|
|
275
272
|
|
|
276
273
|
Because Flight.segment_true_airspeed uses a smoothing pattern, waypoints in :attr:`data`
|
|
@@ -302,7 +299,7 @@ class Fleet(Flight):
|
|
|
302
299
|
self[key] = v_wind
|
|
303
300
|
|
|
304
301
|
# Calculate TAS on each flight individually
|
|
305
|
-
def calc_tas(fl: Flight) -> npt.NDArray[np.
|
|
302
|
+
def calc_tas(fl: Flight) -> npt.NDArray[np.floating]:
|
|
306
303
|
u = fl.get("__u_wind", u_wind)
|
|
307
304
|
v = fl.get("__v_wind", v_wind)
|
|
308
305
|
|
|
@@ -325,19 +322,27 @@ class Fleet(Flight):
|
|
|
325
322
|
return np.concatenate(tas)
|
|
326
323
|
|
|
327
324
|
@override
|
|
328
|
-
def segment_groundspeed(self, *args: Any, **kwargs: Any) -> npt.NDArray[np.
|
|
325
|
+
def segment_groundspeed(self, *args: Any, **kwargs: Any) -> npt.NDArray[np.floating]:
|
|
329
326
|
fls = self.to_flight_list(copy=False)
|
|
330
327
|
gs = [fl.segment_groundspeed(*args, **kwargs) for fl in fls]
|
|
331
328
|
return np.concatenate(gs)
|
|
332
329
|
|
|
333
330
|
@override
|
|
334
|
-
def resample_and_fill(self, *args: Any, **kwargs: Any) ->
|
|
331
|
+
def resample_and_fill(self, *args: Any, **kwargs: Any) -> Self:
|
|
335
332
|
flights = self.to_flight_list(copy=False)
|
|
333
|
+
|
|
334
|
+
# We need to ensure that each flight has an flight_id attrs field
|
|
335
|
+
# When we call fl.resample_and_fill, any flight_id data field
|
|
336
|
+
# will be lost, so the call to Fleet.from_seq will fail.
|
|
337
|
+
for fl in flights:
|
|
338
|
+
if "flight_id" not in fl.attrs:
|
|
339
|
+
fl.attrs["flight_id"] = _extract_flight_id(fl)
|
|
340
|
+
|
|
336
341
|
flights = [fl.resample_and_fill(*args, **kwargs) for fl in flights]
|
|
337
|
-
return type(self).from_seq(flights,
|
|
342
|
+
return type(self).from_seq(flights, broadcast_numeric=False, attrs=self.attrs)
|
|
338
343
|
|
|
339
344
|
@override
|
|
340
|
-
def segment_length(self) -> npt.NDArray[np.
|
|
345
|
+
def segment_length(self) -> npt.NDArray[np.floating]:
|
|
341
346
|
return np.where(self.final_waypoints, np.nan, super().segment_length())
|
|
342
347
|
|
|
343
348
|
@property
|
|
@@ -346,11 +351,11 @@ class Fleet(Flight):
|
|
|
346
351
|
return np.nanmax(self.segment_length()).item()
|
|
347
352
|
|
|
348
353
|
@override
|
|
349
|
-
def segment_azimuth(self) -> npt.NDArray[np.
|
|
354
|
+
def segment_azimuth(self) -> npt.NDArray[np.floating]:
|
|
350
355
|
return np.where(self.final_waypoints, np.nan, super().segment_azimuth())
|
|
351
356
|
|
|
352
357
|
@override
|
|
353
|
-
def segment_angle(self) -> tuple[npt.NDArray[np.
|
|
358
|
+
def segment_angle(self) -> tuple[npt.NDArray[np.floating], npt.NDArray[np.floating]]:
|
|
354
359
|
sin_a, cos_a = super().segment_angle()
|
|
355
360
|
sin_a[self.final_waypoints] = np.nan
|
|
356
361
|
cos_a[self.final_waypoints] = np.nan
|
|
@@ -368,8 +373,7 @@ class Fleet(Flight):
|
|
|
368
373
|
force_filter: bool = False,
|
|
369
374
|
drop: bool = True,
|
|
370
375
|
keep_original_index: bool = False,
|
|
371
|
-
|
|
372
|
-
) -> Flight:
|
|
376
|
+
) -> NoReturn:
|
|
373
377
|
msg = "Only implemented for Flight instances"
|
|
374
378
|
raise NotImplementedError(msg)
|
|
375
379
|
|