pycontrails 0.42.0__cp39-cp39-win_amd64.whl → 0.42.2__cp39-cp39-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.

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.cp39-win_amd64.pyd +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
1
  pycontrails/__init__.py,sha256=n4f_-X3ryUqkFo1vI7G-fDyIs4iC83dvaIlUYlRHUEU,2014
2
- pycontrails/_version.py,sha256=IrhdRylAsWMYPGakwTCLXKBhaWFO7oG2sMLJynYZHBk,166
2
+ pycontrails/_version.py,sha256=DV5w0FxBOc0ieZdnbnOq2SN8N97gWalkx03aHRZYzwQ,166
3
3
  pycontrails/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  pycontrails/core/__init__.py,sha256=ERJZtX_MJyVgxHTQFAcZtkK6lzeJRlpnFr9ZZbGKpto,897
5
5
  pycontrails/core/airports.py,sha256=YFxXk8FFDdH_mjCqqYIrA0GOrTsOFm7LYD4N6S7Eprg,6994
6
- pycontrails/core/cache.py,sha256=ouuEjOlPZxvV0ghYPc4Q1kT1mgqW2HCa4oBiXwt8EWU,29412
6
+ pycontrails/core/cache.py,sha256=s4HHWDPmU0D9S5GNt3QDvYd4yTy7wQxdhKVC8WFDjkg,29304
7
7
  pycontrails/core/coordinates.py,sha256=TbttJt_UcntNI_SvjCTtGkXbqJeyGSFKtA6NM609lxU,5239
8
- pycontrails/core/datalib.py,sha256=5-fLs7vTOhF4I_omf6G8Ym7d4jE0LCZcFZWnf_FHmpo,22175
9
- pycontrails/core/fleet.py,sha256=uH3zlBbjrwsJPQ5AQWkCD33QYu3J4W9Hjhf3ZfQ-1nk,12795
10
- pycontrails/core/flight.py,sha256=717ZrznTmwuz6ZAuQu0cz-CF4biHoy8OQiGVIxeNuE0,58954
8
+ pycontrails/core/datalib.py,sha256=zPOuzye-qH9L03D9nT-0wgqWHNFR7m_caUvTh21yZqo,22274
9
+ pycontrails/core/fleet.py,sha256=Vt9uUARpykWcTkFJJbFNdStXYTx3SI_tkDf5RQSOJ0k,14813
10
+ pycontrails/core/flight.py,sha256=_dDm_OqNIMWw6OOlUb7_LOOkFzRLTsffhP8J4iE-ptY,63760
11
+ pycontrails/core/flightplan.py,sha256=hphWAKNAlCMHuC49vwObkVYiZTZ4gG3s6kON8nSwzDE,7874
11
12
  pycontrails/core/fuel.py,sha256=IgsubrJ0T242QKAFaWKt-G3s4pVXs9xrG38EiaxXIpI,4173
12
- pycontrails/core/interpolation.py,sha256=py0Q0yI7qA4qfBEv1JN5qHNMdX1kIp6Bs-H50yrFEOg,24713
13
- pycontrails/core/met.py,sha256=W2f-m3zdG6hzXeuNbsiLdwpG6hbsGANjS5QcyFk8gLc,89282
13
+ pycontrails/core/interpolation.py,sha256=snwuKoqxUyDLvtVuoli3UsKwtkO9Dl3znaV5R6INdHM,24390
14
+ pycontrails/core/met.py,sha256=H6rWYE3s-_YC7vL2Gi44YwRA3pY0MBiW4Ye4NsSkH58,89132
14
15
  pycontrails/core/met_var.py,sha256=Ent1Na3lWwMWGsthnQcQUTkHvlNXC4oCRyx1mcg-QvA,9498
15
- pycontrails/core/models.py,sha256=KIFx9pI2liPPLxWJORpO5xjJwfyrznnCFpBWXTYwyS0,27563
16
+ pycontrails/core/models.py,sha256=UThmsakcBdZOYTiyFv9o0xSPJMAXY9u55vKTl4Ucimo,27744
16
17
  pycontrails/core/polygon.py,sha256=bvipvjyoZtOPWW2f8_X2YcC0FaJMmhoCM3OH1fVucA4,17146
17
- pycontrails/core/rgi_cython.cp39-win_amd64.pyd,sha256=gSXzTHQwxhdgr85-90lxOWiJzAa-Cb-aulSKEilwtGw,198144
18
- pycontrails/core/vector.py,sha256=PbauZZkeEqzMDICsGofddAeUHuOv4AJ2l2_U2-sC6As,60135
18
+ pycontrails/core/rgi_cython.cp39-win_amd64.pyd,sha256=G0B_djVkvIje-6KA_ZNH6-wYC6bskXAX_1maCU2cw_M,198144
19
+ pycontrails/core/vector.py,sha256=Gkl-HI7RXhlfITpmhnJi8kubGKzJvHkWlxzIcPypeS4,60276
19
20
  pycontrails/datalib/__init__.py,sha256=WnXqgv20SrHZLjFZ9qpQEwRnf0QvfZU-YvMqh7PAUwg,246
20
21
  pycontrails/datalib/ecmwf/__init__.py,sha256=Qil0XaK3SpPFgTn-jZ2l4xsUwYhs1kp9fwNN1ctxh4A,1086
21
- pycontrails/datalib/ecmwf/common.py,sha256=1tQJIsnJ7xFQdEjxdx0RAG72jxRdq84LjCoJOkg4wFg,5022
22
+ pycontrails/datalib/ecmwf/common.py,sha256=_8mu73arA1MXPVoUJxetXzo_UllJSkRfZt2Nh4LuRGQ,4794
22
23
  pycontrails/datalib/ecmwf/era5.py,sha256=P28_RxbCDKxYDf76OReexBaItsi9LPGeZ0HnOnhicTU,20163
23
24
  pycontrails/datalib/ecmwf/hres.py,sha256=0KYaN1VHhl4PrxsGw3J81ah7sBBsPiMbf7djM8r31rI,31163
24
25
  pycontrails/datalib/ecmwf/ifs.py,sha256=0_kSrlbXrTpwm0M6xFF9gmSrYAIMN9zs7o-tqJ3PDlE,10725
@@ -28,25 +29,25 @@ pycontrails/datalib/gfs/gfs.py,sha256=bU80wKB5UQBrkOdHj79yXdKsLih7G8JQaCevjPjmiT
28
29
  pycontrails/datalib/gfs/variables.py,sha256=DHzhNaXEgcfZJCGUqfRyKcmnaJDMnMVKKC4KzbjrPKo,2959
29
30
  pycontrails/datalib/spire/__init__.py,sha256=YiS2SMSNU0bLHfbh41nQuKB8MnQNU8o3MldreM1nrM0,362
30
31
  pycontrails/datalib/spire/spire.py,sha256=cEIx8eC4JBC9J8RJng902bpiWA9CKrWFJxX28Wwqr4M,26090
31
- pycontrails/ext/bada/__init__.py,sha256=whbmKjOwJW0M6IhO8ztVpZ8c5l1ieOUkz4KZbmf98lE,1095
32
- pycontrails/ext/cirium/__init__.py,sha256=e5yUjoX5kK2_tuSaZLyZvI55PP3-rkTBzQEYbd8HJ_E,420
32
+ pycontrails/ext/bada/__init__.py,sha256=08M4NPJfi2N_tffJzflP-gFub-NAdLgRMk1TMaFzPyk,1100
33
+ pycontrails/ext/cirium/__init__.py,sha256=KJWOcMMgNJAkqYcxDU4NS4NoUYLJI6cOv5P4zzEv0yo,425
33
34
  pycontrails/models/__init__.py,sha256=TKhrXe1Pu1-mV1gctx8cUAMrVxCCAtBkbZi9olfWq8s,34
34
35
  pycontrails/models/accf.py,sha256=wdnWizzkaCu7C-qy_v511oSu8BOe6tGoXOW_A9oFbPE,12744
35
36
  pycontrails/models/aircraft_performance.py,sha256=OhLFdSu5f1Mh9-xcx0yDOPL4PSIRmmgwu7nm96VUDFU,1782
36
- pycontrails/models/humidity_scaling.py,sha256=FIDFBMtyaf6M3uuPVh7P7_qDEMdFche9Xv0knu8E-4g,20485
37
- pycontrails/models/issr.py,sha256=mBvk6abw7MpE9nm4ceU6YtS_n7o7J6nBJy1_qIomGXE,7792
37
+ pycontrails/models/humidity_scaling.py,sha256=mn7SwizdsCIdg_vlYch9S3Jh_hU1sqw9fwSHMZSb00s,30235
38
+ pycontrails/models/issr.py,sha256=EIxY5hgGx7_BWJ0sNKizhKSTRBlbnWVAdOyZRz7on4c,7762
38
39
  pycontrails/models/pcc.py,sha256=n5TmzpMVw4vbDspD5f1Q6oM0U5Vbj9kA7M0xXj4cbyo,11617
39
40
  pycontrails/models/pcr.py,sha256=NNnaXR4JeK8XIbhDCLJsCRDumSVdZVcgmaEN6q-wtfI,6067
40
- pycontrails/models/sac.py,sha256=1lvXssdqtCsRbsLAJ9FrlE9j2W8LPxfJ_DODgJJSVJM,16570
41
+ pycontrails/models/sac.py,sha256=_tkjX0Qf8pFOdlRERK1O5tXsNC8Gt0iuCrLlFMoHZAc,16617
41
42
  pycontrails/models/tau_cirrus.py,sha256=3zpjLXr68moOrjK3vSiCydINBxVkw-F5lF5pKWGcJpI,4642
42
43
  pycontrails/models/cocip/__init__.py,sha256=qkj5BtAqJky6hu1dNwkk_kn3kme2iDqRgGJnn5B6DvI,382
43
- pycontrails/models/cocip/cocip.py,sha256=CWk4iN_mzWCBR9ti3m-vBaNsfhukWEpSkrrWuWnIlyk,88824
44
- pycontrails/models/cocip/cocip_params.py,sha256=S3MLjqFzfOQ8aK5NKeN7bqEWlKzBV9qZSez5anL51yA,9332
45
- pycontrails/models/cocip/cocip_uncertainty.py,sha256=9y_oa4ZKS3pjnN_inKFopjtjGIQrCVn9UXboxamnbE0,12429
44
+ pycontrails/models/cocip/cocip.py,sha256=JFFbe_t4rbHuH8M2-A05nA46KBvrarEDR_ZjKO7ujew,88936
45
+ pycontrails/models/cocip/cocip_params.py,sha256=--vZbn-c62umyXZ1FWENbm6_Idkp_18iun1KuHn6Xhs,9454
46
+ pycontrails/models/cocip/cocip_uncertainty.py,sha256=ma4ZHZS5stCyJgVlCb1Vy-QjSbyaxG5PU4fr4ifr3Wg,12067
46
47
  pycontrails/models/cocip/contrail_properties.py,sha256=UqXPra10YMPY_P6eh23cVd30hxPriNK3oEBsqQYIeNQ,57135
47
- pycontrails/models/cocip/radiative_forcing.py,sha256=WX6gBX1zEeSInBHXBgoZiNIJ3nTJvxQM2sh-vTCb3XI,29690
48
+ pycontrails/models/cocip/radiative_forcing.py,sha256=FwE-1w8Q1IVQAoesZGljHXTI3iFXGhqSRKIcMJxSgbA,30919
48
49
  pycontrails/models/cocip/radiative_heating.py,sha256=k3HRZv2ik7SffG9FV7N8u2OIniudJKEmHQ95iQJKrxE,19295
49
- pycontrails/models/cocip/wake_vortex.py,sha256=dXeHr-OGt8UgPWecOpmanLSUQn4Fq9rxVCAXG5l7qVA,12016
50
+ pycontrails/models/cocip/wake_vortex.py,sha256=5t3xA4jiGcySPMLu8Z_MYQBQbYxpe1nYOyyNe58iSjU,13181
50
51
  pycontrails/models/cocip/wind_shear.py,sha256=ufZUJcxU-sPVS-egq1A0JefyxOH9-n1AUIjkh5z_naY,3846
51
52
  pycontrails/models/cocip/output/__init__.py,sha256=3TY2d0_fYj_Jh6umktdhdSkko2cP0r7blWa4Qq4rOCM,63
52
53
  pycontrails/models/cocip/output/flight_summary.py,sha256=e7oPCIp6Hk3zZsIzJNhzMbVRBCAKwxk76aoJ3JCinCw,9072
@@ -61,21 +62,23 @@ pycontrails/models/emissions/emissions.py,sha256=ngwoIiC0JPY3QVqSQQOmZuDdZ8xHt6U
61
62
  pycontrails/models/emissions/ffm2.py,sha256=JICuusRlHp--Limr-9NWGbHS4zQKGzaa4B5ll5CGp4I,12274
62
63
  pycontrails/models/emissions/static/edb-gaseous-v28c-engines.csv,sha256=UJjnqdyOwkokzz3Vd5bSXCpn8Sm-mSygOdC8CrGhhqo,119459
63
64
  pycontrails/models/emissions/static/edb-nvpm-v28c-engines.csv,sha256=JKYYEd42dQSeNujub6HgwbUoVZG84iHzBY9YO086lxA,63651
65
+ pycontrails/models/quantiles/era5_ensemble_quantiles.npy,sha256=78NME7RD7-HIy8xZgXc2cyDnfffbzm6eVN7Tau-amZA,64208
66
+ pycontrails/models/quantiles/iagos_quantiles.npy,sha256=mdpQBBsCVUnv8B66xbIOqcNff9bO66wqkNV7V92zD2E,6536
64
67
  pycontrails/physics/__init__.py,sha256=AScCMSMSZjKxfL6mssdSLwcja1ml7MzREThQp5PLr9U,45
65
68
  pycontrails/physics/constants.py,sha256=Qf_7943-wlWC6sBr64GNv4Z6eD0W8UZyFWnd6-YEenk,3064
66
- pycontrails/physics/geo.py,sha256=2bkuyWQ3u6S4iQN78o9X-bD2hpt0PujY0cjrfJ0Z__A,25975
69
+ pycontrails/physics/geo.py,sha256=WY2LJzb3fUzUYQVBTKQK0JTaQvRVRsGOpRK_oYP_8Ew,26008
67
70
  pycontrails/physics/jet.py,sha256=CStK4lLEzOu2MfXHo-AAtnMd6JowmGKRsxlvEXHq1XY,22802
68
71
  pycontrails/physics/thermo.py,sha256=_HkpS8EdzjRgdPNu7eLYC91-G4D25ZS-YfoEaYa9xlg,13266
69
72
  pycontrails/physics/units.py,sha256=SgMSqvoWu1MASDexkponfWKdlPCctvu3Qq6S-_WypfA,11795
70
73
  pycontrails/utils/__init__.py,sha256=VmklFC-5I5lGFQEzuomlPk_bM6CoM9XDljfjCovG3vw,33
71
74
  pycontrails/utils/iteration.py,sha256=jSII_Eb0kvDZz1uPiulTKVB4E0v3XJQurbSzpHqrFIQ,304
72
- pycontrails/utils/json.py,sha256=sOomUaRmAdOcFRjKTumXYCF7_DiQh8ePjgXTehpWav0,6183
75
+ pycontrails/utils/json.py,sha256=d2MJutSd4ZtVQFco70lURA2zuokFGryaTdKmjePd2qM,6180
73
76
  pycontrails/utils/synthetic_flight.py,sha256=FZF64zWX91UMdDLNlgpvPtIlIiO3COauo-wMe3W7PcQ,17020
74
77
  pycontrails/utils/temp.py,sha256=4S2BeY2mR5W_3gap3RyzQQmjwyuhJa7sOo68J1VrmWA,1150
75
78
  pycontrails/utils/types.py,sha256=ByKfuaQ6CSeQdOf_Wn_k93hkjDTNWf89bhCT9ErXQ5M,4685
76
- pycontrails-0.42.0.dist-info/LICENSE,sha256=HVr8JnZfTaA-12BfKUQZi5hdrB3awOwLWs5X_ga5QzA,10353
77
- pycontrails-0.42.0.dist-info/METADATA,sha256=1QwU6aPzmQkVqhtmmPD2u72jGq4N03JKa3umLgYwVsU,8516
78
- pycontrails-0.42.0.dist-info/NOTICE,sha256=qYeNEp8OjDK5jSW3hTlr9LQRjZeEhXQm0zDei5UFaYs,1969
79
- pycontrails-0.42.0.dist-info/WHEEL,sha256=eep6QWEFiQfg2wcclssb_WY-D33AnLYLnEKGA9Rn-VU,100
80
- pycontrails-0.42.0.dist-info/top_level.txt,sha256=dwaYXVcMhF92QWtAYcLvL0k02vyBqwhsv92lYs2V6zQ,23
81
- pycontrails-0.42.0.dist-info/RECORD,,
79
+ pycontrails-0.42.2.dist-info/LICENSE,sha256=HVr8JnZfTaA-12BfKUQZi5hdrB3awOwLWs5X_ga5QzA,10353
80
+ pycontrails-0.42.2.dist-info/METADATA,sha256=xyl17F0w-AYzi4XVhhnSIJEfIyVkfbDuAjPKm03voWg,8337
81
+ pycontrails-0.42.2.dist-info/NOTICE,sha256=qYeNEp8OjDK5jSW3hTlr9LQRjZeEhXQm0zDei5UFaYs,1969
82
+ pycontrails-0.42.2.dist-info/WHEEL,sha256=eep6QWEFiQfg2wcclssb_WY-D33AnLYLnEKGA9Rn-VU,100
83
+ pycontrails-0.42.2.dist-info/top_level.txt,sha256=dwaYXVcMhF92QWtAYcLvL0k02vyBqwhsv92lYs2V6zQ,23
84
+ pycontrails-0.42.2.dist-info/RECORD,,