pycontrails 0.42.0__cp311-cp311-macosx_11_0_arm64.whl → 0.42.2__cp311-cp311-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 (32) hide show
  1. pycontrails/_version.py +2 -2
  2. pycontrails/core/cache.py +4 -6
  3. pycontrails/core/datalib.py +5 -2
  4. pycontrails/core/fleet.py +59 -7
  5. pycontrails/core/flight.py +175 -49
  6. pycontrails/core/flightplan.py +238 -0
  7. pycontrails/core/interpolation.py +11 -15
  8. pycontrails/core/met.py +5 -5
  9. pycontrails/core/models.py +4 -0
  10. pycontrails/core/rgi_cython.cpython-311-darwin.so +0 -0
  11. pycontrails/core/vector.py +17 -12
  12. pycontrails/datalib/ecmwf/common.py +14 -19
  13. pycontrails/ext/bada/__init__.py +6 -6
  14. pycontrails/ext/cirium/__init__.py +2 -2
  15. pycontrails/models/cocip/cocip.py +37 -39
  16. pycontrails/models/cocip/cocip_params.py +37 -30
  17. pycontrails/models/cocip/cocip_uncertainty.py +47 -58
  18. pycontrails/models/cocip/radiative_forcing.py +220 -193
  19. pycontrails/models/cocip/wake_vortex.py +96 -91
  20. pycontrails/models/humidity_scaling.py +265 -8
  21. pycontrails/models/issr.py +1 -1
  22. pycontrails/models/quantiles/era5_ensemble_quantiles.npy +0 -0
  23. pycontrails/models/quantiles/iagos_quantiles.npy +0 -0
  24. pycontrails/models/sac.py +2 -0
  25. pycontrails/physics/geo.py +2 -1
  26. pycontrails/utils/json.py +3 -3
  27. {pycontrails-0.42.0.dist-info → pycontrails-0.42.2.dist-info}/METADATA +4 -7
  28. {pycontrails-0.42.0.dist-info → pycontrails-0.42.2.dist-info}/RECORD +32 -29
  29. {pycontrails-0.42.0.dist-info → pycontrails-0.42.2.dist-info}/LICENSE +0 -0
  30. {pycontrails-0.42.0.dist-info → pycontrails-0.42.2.dist-info}/NOTICE +0 -0
  31. {pycontrails-0.42.0.dist-info → pycontrails-0.42.2.dist-info}/WHEEL +0 -0
  32. {pycontrails-0.42.0.dist-info → pycontrails-0.42.2.dist-info}/top_level.txt +0 -0
@@ -1,17 +1,20 @@
1
- """Support for humidity scaling methodologies on ERA5 data."""
1
+ """Support for humidity scaling methodologies."""
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
5
  import abc
6
6
  import dataclasses
7
+ import functools
8
+ import pathlib
7
9
  import warnings
8
10
  from typing import Any, NoReturn, overload
9
11
 
10
12
  import numpy as np
13
+ import numpy.typing as npt
11
14
  import xarray as xr
12
15
  from overrides import overrides
13
16
 
14
- from pycontrails.core.met import MetDataset
17
+ from pycontrails.core.met import MetDataArray, MetDataset
15
18
  from pycontrails.core.models import Model, ModelParams
16
19
  from pycontrails.core.vector import GeoVectorDataset
17
20
  from pycontrails.physics import constants, thermo, units
@@ -19,7 +22,7 @@ from pycontrails.utils.types import ArrayLike
19
22
 
20
23
 
21
24
  def _rhi_over_q(air_temperature: ArrayLike, air_pressure: ArrayLike) -> ArrayLike:
22
- """Compute the quotient RHi / q."""
25
+ """Compute the quotient ``RHi / q``."""
23
26
  return air_pressure * (constants.R_v / constants.R_d) / thermo.e_sat_ice(air_temperature)
24
27
 
25
28
 
@@ -140,12 +143,14 @@ class HumidityScaling(Model):
140
143
  "being applied more than once."
141
144
  )
142
145
 
146
+ p: np.ndarray | xr.DataArray
143
147
  if isinstance(self.source, GeoVectorDataset):
144
- self.source.setdefault("air_pressure", self.source.air_pressure)
148
+ p = self.source.setdefault("air_pressure", self.source.air_pressure)
149
+ else:
150
+ p = self.source.data["air_pressure"]
145
151
 
146
152
  q = self.source.data["specific_humidity"]
147
153
  T = self.source.data["air_temperature"]
148
- p = self.source.data["air_pressure"]
149
154
  kwargs = {k: self.get_source_param(k) for k in self.scaler_specific_keys}
150
155
 
151
156
  q, rhi = self.scale(q, T, p, **kwargs)
@@ -264,7 +269,7 @@ class ExponentialBoostHumidityScaling(HumidityScaling):
264
269
  rhi /= rhi_adj
265
270
 
266
271
  # Find ISSRs
267
- is_issr = rhi >= 1
272
+ is_issr = rhi >= 1.0
268
273
 
269
274
  # Apply boosting to ISSRs
270
275
  if isinstance(rhi, xr.DataArray):
@@ -440,7 +445,7 @@ def _calc_rhi_max(air_temperature: ArrayLike) -> ArrayLike:
440
445
  p_ice = thermo.e_sat_ice(air_temperature)
441
446
  p_liq = thermo.e_sat_liquid(air_temperature)
442
447
  return xr.where(
443
- air_temperature < 235,
448
+ air_temperature < 235.0,
444
449
  1.67 + (1.45 - 1.67) * (air_temperature - 190.0) / (235.0 - 190.0),
445
450
  p_liq / p_ice,
446
451
  )
@@ -553,10 +558,262 @@ class HumidityScalingByLevel(HumidityScaling):
553
558
  "attribute 'mid_troposphere_threshold'."
554
559
  )
555
560
 
556
- level = air_pressure / 100
561
+ level = air_pressure / 100.0
557
562
  fp = [rhi_adj_stratosphere, rhi_adj_mid_troposphere]
558
563
  rhi_adj = np.interp(level, xp=xp, fp=fp)
559
564
 
560
565
  q = specific_humidity / rhi_adj
561
566
  rhi = thermo.rhi(q, air_temperature, air_pressure)
562
567
  return q, rhi
568
+
569
+
570
+ @functools.cache
571
+ def _load_iagos_quantiles() -> npt.NDArray[np.float64]:
572
+ path = pathlib.Path(__file__).parent / "quantiles" / "iagos_quantiles.npy"
573
+ # FIXME: Recompute to avoid the divide by 100.0 here
574
+ return np.load(path, allow_pickle=False) / 100.0
575
+
576
+
577
+ @functools.cache
578
+ def _load_era5_ensemble_quantiles() -> npt.NDArray[np.float64]:
579
+ path = pathlib.Path(__file__).parent / "quantiles" / "era5_ensemble_quantiles.npy"
580
+ # FIXME: Recompute to avoid the divide by 100.0 here
581
+ return np.load(path, allow_pickle=False) / 100.0
582
+
583
+
584
+ def quantile_rhi_map(era5_rhi: npt.NDArray[np.float_], member: int) -> npt.NDArray[np.float64]:
585
+ """Map ERA5-derived RHi to it's corresponding IAGOS quantile via histogram matching.
586
+
587
+ This matching is performed on a **single** ERA5 ensemble member.
588
+
589
+ Parameters
590
+ ----------
591
+ era5_rhi : npt.NDArray[np.float_]
592
+ ERA5-derived RHi values for the given ensemble member.
593
+ member : int
594
+ The ERA5 ensemble member to use. Must be in the range ``[0, 10)``.
595
+
596
+ Returns
597
+ -------
598
+ npt.NDArray[np.float64]
599
+ The IAGOS quantiles corresponding to the ERA5-derived RHi values.
600
+ """
601
+
602
+ era5_quantiles = _load_era5_ensemble_quantiles() # shape (801, 10)
603
+ era5_quantiles = era5_quantiles[:, member] # shape (801,)
604
+ iagos_quantiles = _load_iagos_quantiles() # shape (801,)
605
+
606
+ return np.interp(era5_rhi, era5_quantiles, iagos_quantiles)
607
+
608
+
609
+ def recalibrate_rhi(
610
+ era5_rhi_all_members: npt.NDArray[np.float_], member: int
611
+ ) -> npt.NDArray[np.float_]:
612
+ """Recalibrate ERA5-derived RHi values to IAGOS quantiles.
613
+
614
+ This recalibration requires values for **all** ERA5 ensemble members.
615
+
616
+ Parameters
617
+ ----------
618
+ era5_rhi_all_members : npt.NDArray[np.float_]
619
+ ERA5-derived RHi values for all ensemble members. This array should have shape ``(n, 10)``.
620
+ member : int
621
+ The ERA5 ensemble member to use. Must be in the range ``[0, 10)``.
622
+
623
+ Returns
624
+ -------
625
+ npt.NDArray[np.float_]
626
+ The recalibrated RHi values. This is an array of shape ``(n,)``.
627
+
628
+ References
629
+ ----------
630
+ :cite:`eckelCalibratedProbabilisticQuantitative1998`
631
+ """
632
+
633
+ n_members = 10
634
+ assert era5_rhi_all_members.shape[1] == n_members
635
+
636
+ # Perform histogram matching on the given ensemble member
637
+ recalibrated_rhi = quantile_rhi_map(era5_rhi_all_members[:, member], member)
638
+
639
+ # Perform histogram matching on all other ensemble members
640
+ # Add up the results into a single 'ensemble_mean_rhi' array
641
+ ensemble_mean_rhi: npt.NDArray[np.float_] = 0.0 # type: ignore[assignment]
642
+ for r in range(n_members):
643
+ if r == member:
644
+ ensemble_mean_rhi += recalibrated_rhi
645
+ else:
646
+ ensemble_mean_rhi += quantile_rhi_map(era5_rhi_all_members[:, r], r)
647
+
648
+ # Divide by the number of ensemble members to get the mean
649
+ ensemble_mean_rhi /= n_members
650
+
651
+ eckel_a = -0.005213832567192828
652
+ eckel_c = 2.7859172756970354
653
+
654
+ out = (ensemble_mean_rhi - eckel_a) + eckel_c * (recalibrated_rhi - ensemble_mean_rhi)
655
+ return out.astype(era5_rhi_all_members.dtype)
656
+
657
+
658
+ @dataclasses.dataclass
659
+ class HistogramMatchingWithEckelParams(ModelParams):
660
+ """Parameters for :class:`HistogramMatchingWithEckel`.
661
+
662
+ .. warning::
663
+ Experimental. This may change or be removed in a future release.
664
+ """
665
+
666
+ #: A length-10 list of ERA5 ensemble members.
667
+ #: Each element is a :class:`MetDataArray` holding specific humidity
668
+ #: values for a single ensemble member. If None, a ValueError will be
669
+ #: raised at model instantiation time. The order of the list must be
670
+ #: consistent with the order of the ERA5 ensemble members.
671
+ ensemble_specific_humidity: list[MetDataArray] | None = None
672
+
673
+ #: The specific member used. Must be in the range [0, 10). If None,
674
+ #: a ValueError will be raised at model instantiation time.
675
+ member: int | None = None
676
+
677
+
678
+ class HistogramMatchingWithEckel(HumidityScaling):
679
+ """Scale humidity by histogram matching to IAGOS RHi quantiles.
680
+
681
+ This method also applies the Eckel scaling to the recalibrated RHi values.
682
+
683
+ Unlike other specific humidity scaling methods, this method requires met data
684
+ and performs interpolation at evaluation time.
685
+
686
+ .. warning::
687
+ Experimental. This may change or be removed in a future release.
688
+
689
+ References
690
+ ----------
691
+ :cite:`eckelCalibratedProbabilisticQuantitative1998`
692
+ """
693
+
694
+ name = "histogram_matching_with_eckel"
695
+ long_name = "IAGOS RHi histogram matching with Eckel scaling"
696
+ formula = "era5_quantiles -> iagos_quantiles -> recalibrated_rhi"
697
+ default_params = HistogramMatchingWithEckelParams
698
+
699
+ n_members = 10 # hard-coded elsewhere
700
+
701
+ def __init__(
702
+ self,
703
+ met: MetDataset | None = None,
704
+ params: dict[str, Any] | None = None,
705
+ **params_kwargs: Any,
706
+ ) -> None:
707
+ super().__init__(met, params, **params_kwargs)
708
+
709
+ # Some very crude validation
710
+ member = self.params["member"]
711
+ assert member in range(self.n_members)
712
+ self.member: int = member
713
+
714
+ ensemble_specific_humidity = self.params["ensemble_specific_humidity"]
715
+ assert len(ensemble_specific_humidity) == self.n_members
716
+ for member, mda in enumerate(ensemble_specific_humidity):
717
+ try:
718
+ assert mda.data["number"] == member
719
+ except KeyError:
720
+ pass
721
+
722
+ self.ensemble_specific_humidity: list[MetDataArray] = ensemble_specific_humidity
723
+
724
+ @overload
725
+ def eval(self, source: GeoVectorDataset, **params: Any) -> GeoVectorDataset:
726
+ ...
727
+
728
+ @overload
729
+ def eval(self, source: MetDataset, **params: Any) -> NoReturn:
730
+ ...
731
+
732
+ @overload
733
+ def eval(self, source: None = ..., **params: Any) -> NoReturn:
734
+ ...
735
+
736
+ def eval(
737
+ self, source: GeoVectorDataset | MetDataset | None = None, **params: Any
738
+ ) -> GeoVectorDataset | MetDataset:
739
+ """Scale specific humidity by histogram matching to IAGOS RHi quantiles.
740
+
741
+ This method assumes ``source`` is equipped with the following variables:
742
+
743
+ - air_temperature
744
+ - specific_humidity: Humidity values for the :attr:`member` ERA5 ensemble member.
745
+ """
746
+
747
+ self.update_params(params)
748
+ self.set_source(source)
749
+ self.source = self.require_source_type(GeoVectorDataset)
750
+
751
+ if "rhi" in self.source:
752
+ warnings.warn(
753
+ "Variable 'rhi' already found on source to be scaled. This "
754
+ "is unexpected and may be the result of humidity scaling "
755
+ "being applied more than once."
756
+ )
757
+
758
+ # Create a 2D array of specific humidity values for all ensemble members
759
+ # The specific humidity values for the current member are taken from the source
760
+ # This matches patterns used in other humidity scaling methods
761
+ # The remaining values are interpolated from the ERA5 ensemble members
762
+ q = self.source.data["specific_humidity"]
763
+ q2d = np.empty((len(self.source), self.n_members), dtype=q.dtype)
764
+
765
+ for member, mda in enumerate(self.ensemble_specific_humidity):
766
+ if member == self.member:
767
+ q2d[:, member] = q
768
+ else:
769
+ q2d[:, member] = self.source.intersect_met(mda, **self.interp_kwargs)
770
+
771
+ p = self.source.setdefault("air_pressure", self.source.air_pressure)
772
+ T = self.source.data["air_temperature"]
773
+
774
+ q, rhi = self.scale(q2d, T, p)
775
+ self.source.update(specific_humidity=q, rhi=rhi)
776
+
777
+ return self.source
778
+
779
+ @overrides
780
+ def scale( # type: ignore[override]
781
+ self,
782
+ specific_humidity: npt.NDArray[np.float_],
783
+ air_temperature: npt.NDArray[np.float_],
784
+ air_pressure: npt.NDArray[np.float_],
785
+ **kwargs: Any,
786
+ ) -> tuple[npt.NDArray[np.float_], npt.NDArray[np.float_]]:
787
+ """Scale specific humidity values via histogram matching and Eckel scaling.
788
+
789
+ Unlike the method on the base class, the method assumes each of the input
790
+ arrays are :class:`np.ndarray` and not :class:`xr.DataArray` objects.
791
+
792
+ Parameters
793
+ ----------
794
+ specific_humidity : npt.NDArray[np.float_]
795
+ A 2D array of specific humidity values for all ERA5 ensemble members.
796
+ The shape of this array must be ``(n, 10)``, where ``n`` is the number
797
+ of observations and ``10`` is the number of ERA5 ensemble members.
798
+ air_temperature : npt.NDArray[np.float_]
799
+ A 1D array of air temperature values with shape ``(n,)``.
800
+ air_pressure : npt.NDArray[np.float_]
801
+ A 1D array of air pressure values with shape ``(n,)``.
802
+ kwargs: Any
803
+ Unused, kept for compatibility with the base class.
804
+
805
+ Returns
806
+ -------
807
+ specific_humidity : npt.NDArray[np.float_]
808
+ The recalibrated specific humidity values. A 1D array with shape ``(n,)``.
809
+ rhi : npt.NDArray[np.float_]
810
+ The recalibrated RHi values. A 1D array with shape ``(n,)``.
811
+ """
812
+
813
+ rhi_over_q = _rhi_over_q(air_temperature, air_pressure)
814
+ rhi = rhi_over_q[:, np.newaxis] * specific_humidity
815
+
816
+ recalibrated_rhi = recalibrate_rhi(rhi, self.member)
817
+ recalibrated_q = recalibrated_rhi / rhi_over_q
818
+
819
+ return recalibrated_q, recalibrated_rhi
@@ -51,7 +51,7 @@ class ISSR(Model):
51
51
  >>> variables = ["air_temperature", "specific_humidity"]
52
52
  >>> pressure_levels = [200, 250, 300]
53
53
  >>> era5 = ERA5(time, variables, pressure_levels)
54
- >>> met = era5.open_metdataset(xr_kwargs=dict(parallel=False))
54
+ >>> met = era5.open_metdataset()
55
55
 
56
56
  >>> # Instantiate and run model
57
57
  >>> scaling = ConstantHumidityScaling(rhi_adj=0.98)
pycontrails/models/sac.py CHANGED
@@ -438,6 +438,8 @@ def T_critical_sac(
438
438
  # We only apply Newton's method at points with rh bounded below 1 (scipy will
439
439
  # raise an error if Newton's method is not converging well).
440
440
  filt = relative_humidity < 0.999
441
+ if not np.any(filt):
442
+ return T_LM
441
443
 
442
444
  U_filt = relative_humidity[filt]
443
445
  T_LM_filt = T_LM[filt]
@@ -3,6 +3,7 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import numpy as np
6
+ import numpy.typing as npt
6
7
  import xarray as xr
7
8
 
8
9
  from pycontrails.physics import constants, units
@@ -834,7 +835,7 @@ def advect_level(
834
835
  return (level * 100.0 + (dt_s * velocity)) / 100.0
835
836
 
836
837
 
837
- def _dt_to_float_seconds(dt: np.ndarray | np.timedelta64, dtype: np.dtype) -> np.ndarray:
838
+ def _dt_to_float_seconds(dt: np.ndarray | np.timedelta64, dtype: npt.DTypeLike) -> np.ndarray:
838
839
  """Convert a time delta to seconds as a float with specified ``dtype`` precision.
839
840
 
840
841
  Parameters
pycontrails/utils/json.py CHANGED
@@ -161,9 +161,9 @@ def dataframe_to_geojson_points(
161
161
 
162
162
  def row_to_feature(row: pd.Series) -> dict[str, str | dict[str, Any]]:
163
163
  point = [
164
- np.around(row.longitude, decimals=4) if not np.isnan(row.longitude) else None,
165
- np.around(row.latitude, decimals=4) if not np.isnan(row.latitude) else None,
166
- np.around(row.altitude, decimals=4) if not np.isnan(row.altitude) else None,
164
+ np.round(row.longitude, decimals=4) if not np.isnan(row.longitude) else None,
165
+ np.round(row.latitude, decimals=4) if not np.isnan(row.latitude) else None,
166
+ np.round(row.altitude, decimals=4) if not np.isnan(row.altitude) else None,
167
167
  ]
168
168
  # converting to int to allow JSON serialization
169
169
  properties = {"time": int(row.time.timestamp())}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pycontrails
3
- Version: 0.42.0
3
+ Version: 0.42.2
4
4
  Summary: Python library for modeling aviation climate impacts
5
5
  Author-email: Breakthrough Energy <py@contrails.org>
6
6
  License: Apache-2.0
@@ -34,12 +34,7 @@ Requires-Dist: pyproj (>=3.5)
34
34
  Requires-Dist: scipy (>=1.10)
35
35
  Requires-Dist: xarray (>=2022.3)
36
36
  Provides-Extra: complete
37
- Requires-Dist: pycontrails[ecmwf] ; extra == 'complete'
38
- Requires-Dist: pycontrails[gcp] ; extra == 'complete'
39
- Requires-Dist: pycontrails[gfs] ; extra == 'complete'
40
- Requires-Dist: pycontrails[jupyter] ; extra == 'complete'
41
- Requires-Dist: pycontrails[vis] ; extra == 'complete'
42
- Requires-Dist: pycontrails[zarr] ; extra == 'complete'
37
+ Requires-Dist: pycontrails[ecmwf,gcp,gfs,jupyter,pwlf,vis,zarr] ; extra == 'complete'
43
38
  Provides-Extra: dev
44
39
  Requires-Dist: black (>=22) ; extra == 'dev'
45
40
  Requires-Dist: black[jupyter] ; extra == 'dev'
@@ -96,6 +91,8 @@ Requires-Dist: ipywidgets (>=7.6) ; extra == 'jupyter'
96
91
  Requires-Dist: jupyterlab (>=2.2) ; extra == 'jupyter'
97
92
  Provides-Extra: open3d
98
93
  Requires-Dist: open3d (>=0.14) ; extra == 'open3d'
94
+ Provides-Extra: pwlf
95
+ Requires-Dist: pwlf (>=2.2.1) ; extra == 'pwlf'
99
96
  Provides-Extra: vis
100
97
  Requires-Dist: matplotlib (>=3.3) ; extra == 'vis'
101
98
  Requires-Dist: opencv-python-headless (>=4.5) ; extra == 'vis'
@@ -1,24 +1,25 @@
1
- pycontrails-0.42.0.dist-info/RECORD,,
2
- pycontrails-0.42.0.dist-info/LICENSE,sha256=gJ-h7SFFD1mCfR6a7HILvEtodDT6Iig8bLXdgqR6ucA,10175
3
- pycontrails-0.42.0.dist-info/WHEEL,sha256=GYWT1Q_60SI2bAUaGrkLwkEA5yYDmphib6XcY6K30ZQ,110
4
- pycontrails-0.42.0.dist-info/NOTICE,sha256=gKI8DcN1WhiXB2SFRKDogcjONldGubTvBxiOYdC4CXU,1926
5
- pycontrails-0.42.0.dist-info/top_level.txt,sha256=Z8J1R_AiBAyCVjNw6jYLdrA68PrQqTg0t3_Yek_IZ0Q,29
6
- pycontrails-0.42.0.dist-info/METADATA,sha256=xQ9tt3JbcEkYt0cretDHsuaUW0Aorvo93bIC2Ue6CaM,8354
7
- pycontrails/_version.py,sha256=CprMv6GTEx4IrrUdo6yTukVOLmxjWTO3U6cWecLEjMA,162
1
+ pycontrails-0.42.2.dist-info/RECORD,,
2
+ pycontrails-0.42.2.dist-info/LICENSE,sha256=gJ-h7SFFD1mCfR6a7HILvEtodDT6Iig8bLXdgqR6ucA,10175
3
+ pycontrails-0.42.2.dist-info/WHEEL,sha256=GYWT1Q_60SI2bAUaGrkLwkEA5yYDmphib6XcY6K30ZQ,110
4
+ pycontrails-0.42.2.dist-info/NOTICE,sha256=gKI8DcN1WhiXB2SFRKDogcjONldGubTvBxiOYdC4CXU,1926
5
+ pycontrails-0.42.2.dist-info/top_level.txt,sha256=Z8J1R_AiBAyCVjNw6jYLdrA68PrQqTg0t3_Yek_IZ0Q,29
6
+ pycontrails-0.42.2.dist-info/METADATA,sha256=Eyt-RbhPHpnumnU-YHOXVzYv6GFaHe5NXkzbjdo9hd4,8178
7
+ pycontrails/_version.py,sha256=JQ-ensPiphsIDBK4lnzSeMWxygjAp19P9cOtQQsBrjI,162
8
8
  pycontrails/__init__.py,sha256=sf7Xhr91V2jAvcQkla9oPqNCaXSKQp2M_dcxkiVkl6w,1943
9
9
  pycontrails/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
- pycontrails/core/rgi_cython.cpython-311-darwin.so,sha256=xys8mlfel4-CeSskueU16xo1YzO0CU36gpRKPHjAjaw,261341
11
- pycontrails/core/vector.py,sha256=qxxYQK1YJF5rC5d3wIeOumlDh0QPATiAUTFYipQhEtQ,58368
12
- pycontrails/core/models.py,sha256=eapTP-JlMgfXVvvLn3WcbushGpCRgbUp3u25sgwi9IU,26792
13
- pycontrails/core/interpolation.py,sha256=3SK7xE0ChmCc7Ev4uM1saUF3LhS7h0mqNMk4qR3XxwY,24032
14
- pycontrails/core/fleet.py,sha256=L-tQPLjflT_ofc5z0mt49O2o4_gzXxoQTpCZLA_VkpE,12453
15
- pycontrails/core/flight.py,sha256=qd0lZQ_0xIUVMbDByOVlYl_8gdm85r0tPtK5SIlptcM,57318
10
+ pycontrails/core/rgi_cython.cpython-311-darwin.so,sha256=uWNsaY22_-09tZ4fCijYCyAAfbcwYFp7cY_KfvcCm6g,261341
11
+ pycontrails/core/vector.py,sha256=JF-K_6ieGh5TG0TrqF-jexH5diusfluYW1lzzzSapV8,58504
12
+ pycontrails/core/models.py,sha256=-_W0nbAlfeYQfiHnzAIyHB-Wi8957B_s4T8q-gmGmwQ,26969
13
+ pycontrails/core/interpolation.py,sha256=J-drgXpacQG_z7pOOpIIfWBW3TSkK09pEUL7HV8qfOk,23713
14
+ pycontrails/core/fleet.py,sha256=dkDHEvzqB0T1_zxGUQhkdZaER4SR8H1wnTryWRkc42Q,14419
15
+ pycontrails/core/flight.py,sha256=VIIvRtdPPqJxP170ZGcBnHngvBwhphdnvyRP3DXAx7g,61998
16
16
  pycontrails/core/fuel.py,sha256=lEMUgLeFBoazDsiKN07s9udQ12xghOos5v3H9bjveBs,4044
17
17
  pycontrails/core/polygon.py,sha256=FlFHJvonnxajq6iY12cuqW-MP8wGGeb3aiNJh-hks3g,16636
18
- pycontrails/core/datalib.py,sha256=BT-iFvD2nACKqh82j0wxBRcRgH2WL8VtN3FdSmNFMiQ,21517
19
- pycontrails/core/cache.py,sha256=uMzN45MUgIni1uhlypLVjc0NhFDvn6m-uK78p9sDdE8,28536
18
+ pycontrails/core/datalib.py,sha256=bI1PRTYdYYEQAp0d6MEm7HXq0n7Xgpwa_MESsbux2RY,21613
19
+ pycontrails/core/cache.py,sha256=0JyO0N5gddWoeo3UeOVUHtCkXoPVhIJ-RBLk_eFgYqs,28430
20
20
  pycontrails/core/__init__.py,sha256=C6bOLNBKeQaLCHCRza1oPrQTUazutPST7hX4C6O2MG0,866
21
- pycontrails/core/met.py,sha256=jID-joG-1Mm-SSHVAWijOZL6yLwGd7GJAs2v7dybR2E,86826
21
+ pycontrails/core/flightplan.py,sha256=Vq__4eDPo6hTwXMgiCj7boV4P9gTjNtst5n0sy6j4UI,7636
22
+ pycontrails/core/met.py,sha256=zW9HFpaaS3pXUFZxWboTo_cV6RPPMrz_j5DLiPcnkzs,86676
22
23
  pycontrails/core/airports.py,sha256=5D0VF9DxleQlVOmMW-P8_fVVkob-aB3doO1Co2XNFss,6766
23
24
  pycontrails/core/met_var.py,sha256=-gaodcmxx507ryMVKvFclqKkf1c8OHVVtXeG9s2eOOs,9191
24
25
  pycontrails/core/coordinates.py,sha256=b7D2lknnnwh8rBSla9M3ojqRYiASAOrVv0OAFD8xpDw,5078
@@ -27,27 +28,27 @@ pycontrails/datalib/ecmwf/era5.py,sha256=ulII_wQDSLmaqpMdZpAlOCmCCxhpzfSdBBgb8NW
27
28
  pycontrails/datalib/ecmwf/hres.py,sha256=wnGSZ67fnJ7NOw4hZXk3UCNcfFvShK1pWMm4nx0fz6c,30333
28
29
  pycontrails/datalib/ecmwf/variables.py,sha256=akqjUS3WKnSzV1Y0KkHLylH7QByvitc3wo8NBFeSNew,8714
29
30
  pycontrails/datalib/ecmwf/__init__.py,sha256=9rrlhfePtMrkofmFMg7t9fJ3teVufRJ0uM3Y-2PdzQ4,1045
30
- pycontrails/datalib/ecmwf/common.py,sha256=MCIFgGPnjb9tzjia4QzyPxIOAZBBqmpb4ucmua-B62Q,4890
31
+ pycontrails/datalib/ecmwf/common.py,sha256=tqoKnYOH3B4OzdEe6ZzoyjFO03GaT9QVJqe3sBPYyWQ,4667
31
32
  pycontrails/datalib/ecmwf/ifs.py,sha256=2Atnpc4q6Yy9LjEyE4tYzmnlC0bnnbzUiZvj7XUh0Bs,10448
32
33
  pycontrails/datalib/gfs/gfs.py,sha256=-3_Qd1fKRU2LYCBK8mDvc9FycL2lYTEzJfXeAXpP73M,23084
33
34
  pycontrails/datalib/gfs/variables.py,sha256=s6rKyFdDA8E0Jz8X4twM7mgq5zhRGlk5qTedItyqoY8,2860
34
35
  pycontrails/datalib/gfs/__init__.py,sha256=tWxgqmlW8Uo07J-3fBTXPrteatzTka9mSXomhWy3NVA,684
35
36
  pycontrails/datalib/spire/spire.py,sha256=l52ID6LdYWpWcxxVbupCBono06MvPfwIBOGI9AcxpHQ,25351
36
37
  pycontrails/datalib/spire/__init__.py,sha256=4EZPJUmNnF8v2n6QhBvSi_3rYXRBX2zGcPE-WEA-dP8,343
37
- pycontrails/ext/cirium/__init__.py,sha256=dkNoMUbMfNQJCK69OMgspJGBBI5T6rXzp2MqjDtfkTw,406
38
- pycontrails/ext/bada/__init__.py,sha256=LYRF_nDHDocSJ603XSJKEEFIX0kfUpFBMXercEndQd8,1054
38
+ pycontrails/ext/cirium/__init__.py,sha256=erApEeJGry3Nbk5yh6YDvwDXmwgtr-Mmav2BuvC9dDU,411
39
+ pycontrails/ext/bada/__init__.py,sha256=n7BZKOxtAew9CaGOICDfO4mzhP_ndURtoGK_WyTbpfg,1059
39
40
  pycontrails/utils/iteration.py,sha256=UjMn2FRDyC0A7q_MqKNpqqeNZm-lA23Ws-KV7zFzAl4,292
40
41
  pycontrails/utils/synthetic_flight.py,sha256=y05WJE4Z_SuDlU3q5wodiLImyub_dd4MxYqGZb9XOno,16596
41
42
  pycontrails/utils/__init__.py,sha256=Gt_57sBgfliFSxx9sDpuchykFDxmM11Wg9xAeSqPcnI,32
42
43
  pycontrails/utils/types.py,sha256=0uH2eVmQJZiL76N0v_UtHDyv3FJHeRd7BxEZ_occ0n4,4525
43
44
  pycontrails/utils/temp.py,sha256=6BlJ5NaQpACyL-n3FuqfscFb9Mfbgvs72BwWfSzBfmU,1100
44
- pycontrails/utils/json.py,sha256=lcZtaeJQNx_U5rgR322spbI8zs1XcQ-5So1bb26ow9E,5993
45
- pycontrails/models/humidity_scaling.py,sha256=pmKDGFT9wRkz7u_qHjeE1uZSi_lOADM2BVg0VlpZof4,19923
45
+ pycontrails/utils/json.py,sha256=zB_23_mqE39G231sQ_XXmxpQQ9pGjIGQCPJ2JaknRrY,5990
46
+ pycontrails/models/humidity_scaling.py,sha256=AkJGD_hNRxsu9na_PPAhgy6ShUE-FlYQvmMKOuFSdPo,29416
46
47
  pycontrails/models/pcc.py,sha256=yWi0TochaCWCgrb68dUad9xPMqysIRa2hr6VT8PvxL4,11286
47
48
  pycontrails/models/tau_cirrus.py,sha256=jYilgsGQw7aFLjIJaG8zvbu8ITNGlXZvbl18C8vHbE4,4491
48
49
  pycontrails/models/__init__.py,sha256=dQTOLQb7RdUdUwslt5se__5y_ymbInBexQmNrmAeOdE,33
49
- pycontrails/models/issr.py,sha256=VIafGHMXLrTnU52WKvpujsKwUIPu4cVwFjGbB1-9ncs,7577
50
- pycontrails/models/sac.py,sha256=6kwCAC3kFfgXiEJfyEzdPdH9OhlguPaaVBiESSPSFBs,16105
50
+ pycontrails/models/issr.py,sha256=a1mT_dGPliGHIDYxOtTHw3svb8KW19pHFP1wRuyiYS8,7547
51
+ pycontrails/models/sac.py,sha256=FNM8_LmHl7NPHFHw1R6_r3Mr-dcwELppt969OOvjth4,16150
51
52
  pycontrails/models/accf.py,sha256=WRFGNrkt2hLgO-mIsgk3JXk9_R7Hbw0jCPUC6iGpcCg,12368
52
53
  pycontrails/models/aircraft_performance.py,sha256=r-SdOw6Aor9JXIz4mVKe7HTrG4lKCXpAraUY2KTZhiE,1722
53
54
  pycontrails/models/pcr.py,sha256=m9cLtZr2DK4omtljgWdIVzDpQAeb3hDEDVVfr6zMDtM,5900
@@ -57,23 +58,25 @@ pycontrails/models/emissions/emissions.py,sha256=VW7ZPWmeWfmIsEgcQ88-A08YlmdBTpK
57
58
  pycontrails/models/emissions/black_carbon.py,sha256=EDU5yMTuPeWQIeUE3YDkZ6HHFii8ngfi67Svt3AOVH4,20122
58
59
  pycontrails/models/emissions/static/edb-gaseous-v28c-engines.csv,sha256=9mok7P9NQSNJnej_gna29pTbgBuZsfI9N5OOoj1S4WI,118901
59
60
  pycontrails/models/emissions/static/edb-nvpm-v28c-engines.csv,sha256=otZ3PWXcbu7ZuEgZ3v3bLB0CGjGRAacd69CGFUXAdSU,63472
60
- pycontrails/models/cocip/radiative_forcing.py,sha256=ReLufq2BWw_Vot18MIBkTkaOqNXrbGyGcoZnAwO0NOg,28853
61
+ pycontrails/models/cocip/radiative_forcing.py,sha256=WfsPtCfUhK7MNTG734dDpDbsOL-BVVNKzeZ4UoUNxyQ,30055
61
62
  pycontrails/models/cocip/wind_shear.py,sha256=p4QVwqcpqCP4Pf8rAHPhU_rPM6LlmuWy_fSpOwdIi5w,3727
62
- pycontrails/models/cocip/cocip.py,sha256=PDnMfZZ7FXqd5r-WWtQCZurD_FyLIvcY2qBELw0YXZE,86552
63
+ pycontrails/models/cocip/cocip.py,sha256=yqVVvqFCeRQoBM2nZlikowEmwebrLiF3qrqu6EPW7S8,86666
63
64
  pycontrails/models/cocip/__init__.py,sha256=vBicDVNyw-M3bglx1iVplxm6CQRPRk5SS-3_VgL7WQM,370
64
- pycontrails/models/cocip/cocip_params.py,sha256=0624P6cVc2vBeD8-2S3lMnfZtKkdOaycGhscgyp_nYo,9098
65
- pycontrails/models/cocip/wake_vortex.py,sha256=mH8qbuWvZlFzmjBokHp6TAIgii6wVXvaV_xmHzb34MI,11654
66
- pycontrails/models/cocip/cocip_uncertainty.py,sha256=qZjMi9xZkSFftCrY1kQvoJpdys9ve-fkYu98o3O7V-k,12133
65
+ pycontrails/models/cocip/cocip_params.py,sha256=MQr3I_On4m1MVB_lJbm7FREaOUGRyMNqIog4qKKZcB8,9213
66
+ pycontrails/models/cocip/wake_vortex.py,sha256=DV9Qvjp-nlZjBJK6TFkls8nd7aALlXQZeMpxolUSaHQ,12814
67
+ pycontrails/models/cocip/cocip_uncertainty.py,sha256=wJ43NJr3YZX92GiMhY6LUVni9qbsqKg0duCRSS_r_mw,11782
67
68
  pycontrails/models/cocip/radiative_heating.py,sha256=HTvAXv4kU_HIasLUFCF15K-sRzJVK8UAulj2W_gNjKE,18770
68
69
  pycontrails/models/cocip/contrail_properties.py,sha256=aoFg19_L2Fd7-Uv3SSMJ5i2rV3xl17XMSZMOekt2tkA,55613
69
70
  pycontrails/models/cocip/output/flight_summary.py,sha256=vjm6UwKJT0PoIBj0zLj1_1Q8ZokAZT-GO4T3tB3Jw1I,8838
70
71
  pycontrails/models/cocip/output/__init__.py,sha256=-PzsG-acxd6jXOdBjK4kxuYiQ_9Llf5C6JqgZ8mse6U,62
71
72
  pycontrails/models/cocip/output/grid_cirrus.py,sha256=_2MdTTahsOK3M14ONOZAN58XS2j90xtt1MAaclLbEhc,25194
73
+ pycontrails/models/quantiles/iagos_quantiles.npy,sha256=mdpQBBsCVUnv8B66xbIOqcNff9bO66wqkNV7V92zD2E,6536
74
+ pycontrails/models/quantiles/era5_ensemble_quantiles.npy,sha256=78NME7RD7-HIy8xZgXc2cyDnfffbzm6eVN7Tau-amZA,64208
72
75
  pycontrails/models/cocipgrid/cocip_grid_params.py,sha256=fe7w2bw-wQ-PG8ua5K7nBb19lSMfAoVuaHCVKUsKQCk,5323
73
76
  pycontrails/models/cocipgrid/__init__.py,sha256=ar6bF_8Pusbb-myujz_q5ntFylQTNH8yiM8fxP7Zk30,262
74
77
  pycontrails/models/cocipgrid/cocip_time_handling.py,sha256=kXO8ePbmjlqZgdV6FMxqA7IAWXUQtVQDRU8RJ12ClWU,13826
75
78
  pycontrails/models/cocipgrid/cocip_grid.py,sha256=RCtYk1I49qNgALzLaNlI6EoJaAX4JMmXr_pDYUYJhy4,84548
76
- pycontrails/physics/geo.py,sha256=-PoXkcdRJ-KR_a7YdZN15q-b5DnGuSuYboG8ATzqFOM,25121
79
+ pycontrails/physics/geo.py,sha256=qQMu4R63I_lyK3p6uztuzCViPK_ja0wHzxAU-3VHdZk,25153
77
80
  pycontrails/physics/units.py,sha256=MV2C3qDV7Qf9Bk-ri_crqNSY-qSZj8MPdelNNu--crM,11349
78
81
  pycontrails/physics/constants.py,sha256=GJ_M9W7N78osXopNIfRDcHuqcaINLLAhOpOHQBsaI3I,2955
79
82
  pycontrails/physics/__init__.py,sha256=_1eWbEy6evEWdfJCEkwDiSdpiDNzNWEPVqaPekHyhwU,44