pycontrails 0.58.0__cp314-cp314-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 (122) hide show
  1. pycontrails/__init__.py +70 -0
  2. pycontrails/_version.py +34 -0
  3. pycontrails/core/__init__.py +30 -0
  4. pycontrails/core/aircraft_performance.py +679 -0
  5. pycontrails/core/airports.py +228 -0
  6. pycontrails/core/cache.py +889 -0
  7. pycontrails/core/coordinates.py +174 -0
  8. pycontrails/core/fleet.py +483 -0
  9. pycontrails/core/flight.py +2185 -0
  10. pycontrails/core/flightplan.py +228 -0
  11. pycontrails/core/fuel.py +140 -0
  12. pycontrails/core/interpolation.py +702 -0
  13. pycontrails/core/met.py +2931 -0
  14. pycontrails/core/met_var.py +387 -0
  15. pycontrails/core/models.py +1321 -0
  16. pycontrails/core/polygon.py +549 -0
  17. pycontrails/core/rgi_cython.cp314-win_amd64.pyd +0 -0
  18. pycontrails/core/vector.py +2249 -0
  19. pycontrails/datalib/__init__.py +12 -0
  20. pycontrails/datalib/_met_utils/metsource.py +746 -0
  21. pycontrails/datalib/ecmwf/__init__.py +73 -0
  22. pycontrails/datalib/ecmwf/arco_era5.py +345 -0
  23. pycontrails/datalib/ecmwf/common.py +114 -0
  24. pycontrails/datalib/ecmwf/era5.py +554 -0
  25. pycontrails/datalib/ecmwf/era5_model_level.py +490 -0
  26. pycontrails/datalib/ecmwf/hres.py +804 -0
  27. pycontrails/datalib/ecmwf/hres_model_level.py +466 -0
  28. pycontrails/datalib/ecmwf/ifs.py +287 -0
  29. pycontrails/datalib/ecmwf/model_levels.py +435 -0
  30. pycontrails/datalib/ecmwf/static/model_level_dataframe_v20240418.csv +139 -0
  31. pycontrails/datalib/ecmwf/variables.py +268 -0
  32. pycontrails/datalib/geo_utils.py +261 -0
  33. pycontrails/datalib/gfs/__init__.py +28 -0
  34. pycontrails/datalib/gfs/gfs.py +656 -0
  35. pycontrails/datalib/gfs/variables.py +104 -0
  36. pycontrails/datalib/goes.py +757 -0
  37. pycontrails/datalib/himawari/__init__.py +27 -0
  38. pycontrails/datalib/himawari/header_struct.py +266 -0
  39. pycontrails/datalib/himawari/himawari.py +667 -0
  40. pycontrails/datalib/landsat.py +589 -0
  41. pycontrails/datalib/leo_utils/__init__.py +5 -0
  42. pycontrails/datalib/leo_utils/correction.py +266 -0
  43. pycontrails/datalib/leo_utils/landsat_metadata.py +300 -0
  44. pycontrails/datalib/leo_utils/search.py +250 -0
  45. pycontrails/datalib/leo_utils/sentinel_metadata.py +748 -0
  46. pycontrails/datalib/leo_utils/static/bq_roi_query.sql +6 -0
  47. pycontrails/datalib/leo_utils/vis.py +59 -0
  48. pycontrails/datalib/sentinel.py +650 -0
  49. pycontrails/datalib/spire/__init__.py +5 -0
  50. pycontrails/datalib/spire/exceptions.py +62 -0
  51. pycontrails/datalib/spire/spire.py +604 -0
  52. pycontrails/ext/bada.py +42 -0
  53. pycontrails/ext/cirium.py +14 -0
  54. pycontrails/ext/empirical_grid.py +140 -0
  55. pycontrails/ext/synthetic_flight.py +431 -0
  56. pycontrails/models/__init__.py +1 -0
  57. pycontrails/models/accf.py +425 -0
  58. pycontrails/models/apcemm/__init__.py +8 -0
  59. pycontrails/models/apcemm/apcemm.py +983 -0
  60. pycontrails/models/apcemm/inputs.py +226 -0
  61. pycontrails/models/apcemm/static/apcemm_yaml_template.yaml +183 -0
  62. pycontrails/models/apcemm/utils.py +437 -0
  63. pycontrails/models/cocip/__init__.py +29 -0
  64. pycontrails/models/cocip/cocip.py +2742 -0
  65. pycontrails/models/cocip/cocip_params.py +305 -0
  66. pycontrails/models/cocip/cocip_uncertainty.py +291 -0
  67. pycontrails/models/cocip/contrail_properties.py +1530 -0
  68. pycontrails/models/cocip/output_formats.py +2270 -0
  69. pycontrails/models/cocip/radiative_forcing.py +1260 -0
  70. pycontrails/models/cocip/radiative_heating.py +520 -0
  71. pycontrails/models/cocip/unterstrasser_wake_vortex.py +508 -0
  72. pycontrails/models/cocip/wake_vortex.py +396 -0
  73. pycontrails/models/cocip/wind_shear.py +120 -0
  74. pycontrails/models/cocipgrid/__init__.py +9 -0
  75. pycontrails/models/cocipgrid/cocip_grid.py +2552 -0
  76. pycontrails/models/cocipgrid/cocip_grid_params.py +138 -0
  77. pycontrails/models/dry_advection.py +602 -0
  78. pycontrails/models/emissions/__init__.py +21 -0
  79. pycontrails/models/emissions/black_carbon.py +599 -0
  80. pycontrails/models/emissions/emissions.py +1353 -0
  81. pycontrails/models/emissions/ffm2.py +336 -0
  82. pycontrails/models/emissions/static/default-engine-uids.csv +239 -0
  83. pycontrails/models/emissions/static/edb-gaseous-v29b-engines.csv +596 -0
  84. pycontrails/models/emissions/static/edb-nvpm-v29b-engines.csv +215 -0
  85. pycontrails/models/extended_k15.py +1327 -0
  86. pycontrails/models/humidity_scaling/__init__.py +37 -0
  87. pycontrails/models/humidity_scaling/humidity_scaling.py +1075 -0
  88. pycontrails/models/humidity_scaling/quantiles/era5-model-level-quantiles.pq +0 -0
  89. pycontrails/models/humidity_scaling/quantiles/era5-pressure-level-quantiles.pq +0 -0
  90. pycontrails/models/issr.py +210 -0
  91. pycontrails/models/pcc.py +326 -0
  92. pycontrails/models/pcr.py +154 -0
  93. pycontrails/models/ps_model/__init__.py +18 -0
  94. pycontrails/models/ps_model/ps_aircraft_params.py +381 -0
  95. pycontrails/models/ps_model/ps_grid.py +701 -0
  96. pycontrails/models/ps_model/ps_model.py +1000 -0
  97. pycontrails/models/ps_model/ps_operational_limits.py +525 -0
  98. pycontrails/models/ps_model/static/ps-aircraft-params-20250328.csv +69 -0
  99. pycontrails/models/ps_model/static/ps-synonym-list-20250328.csv +104 -0
  100. pycontrails/models/sac.py +442 -0
  101. pycontrails/models/tau_cirrus.py +183 -0
  102. pycontrails/physics/__init__.py +1 -0
  103. pycontrails/physics/constants.py +117 -0
  104. pycontrails/physics/geo.py +1138 -0
  105. pycontrails/physics/jet.py +968 -0
  106. pycontrails/physics/static/iata-cargo-load-factors-20250221.csv +74 -0
  107. pycontrails/physics/static/iata-passenger-load-factors-20250221.csv +74 -0
  108. pycontrails/physics/thermo.py +551 -0
  109. pycontrails/physics/units.py +472 -0
  110. pycontrails/py.typed +0 -0
  111. pycontrails/utils/__init__.py +1 -0
  112. pycontrails/utils/dependencies.py +66 -0
  113. pycontrails/utils/iteration.py +13 -0
  114. pycontrails/utils/json.py +187 -0
  115. pycontrails/utils/temp.py +50 -0
  116. pycontrails/utils/types.py +163 -0
  117. pycontrails-0.58.0.dist-info/METADATA +180 -0
  118. pycontrails-0.58.0.dist-info/RECORD +122 -0
  119. pycontrails-0.58.0.dist-info/WHEEL +5 -0
  120. pycontrails-0.58.0.dist-info/licenses/LICENSE +178 -0
  121. pycontrails-0.58.0.dist-info/licenses/NOTICE +43 -0
  122. pycontrails-0.58.0.dist-info/top_level.txt +3 -0
@@ -0,0 +1,183 @@
1
+ """Calculate tau cirrus on Met data."""
2
+
3
+ import dask.array
4
+ import xarray as xr
5
+
6
+ from pycontrails.core.met import MetDataset
7
+ from pycontrails.core.met_var import MetVariable
8
+ from pycontrails.physics import constants, thermo
9
+ from pycontrails.utils.types import ArrayLike
10
+
11
+ TauCirrus = MetVariable(
12
+ short_name="tau_cirrus",
13
+ standard_name="tau_cirrus",
14
+ long_name="Cirrus optical depth",
15
+ units="dimensionless",
16
+ )
17
+
18
+
19
+ def _geopotential_height(met: MetDataset) -> xr.DataArray:
20
+ """Extract geopotential height from MetDataset."""
21
+
22
+ # Attempt 1: Use geopotential height if available
23
+ try:
24
+ return met.data["geopotential_height"]
25
+ except KeyError:
26
+ pass
27
+
28
+ # Attempt 2: Use geopotential if available
29
+ try:
30
+ return met.data["geopotential"] / constants.g
31
+ except KeyError:
32
+ pass
33
+
34
+ # Attempt 3: Approximate geopotential height from altitude
35
+ # https://unidata.github.io/MetPy/latest/api/generated/metpy.calc.height_to_geopotential.html
36
+ altitude = met.data["altitude"]
37
+ return altitude * constants.radius_earth / (constants.radius_earth + altitude)
38
+
39
+
40
+ def tau_cirrus(met: MetDataset) -> xr.DataArray:
41
+ """Calculate the optical depth of NWP cirrus around each pressure level.
42
+
43
+ Parameters
44
+ ----------
45
+ met : MetDataset
46
+ A MetDataset with the following variables:
47
+
48
+ - "air_temperature"
49
+ - "mass_fraction_of_cloud_ice_in_air", "specific_cloud_ice_water_content",
50
+ or "ice_water_mixing_ratio"
51
+
52
+ Returns
53
+ -------
54
+ xr.DataArray
55
+ Array of tau cirrus values. Has the same dimensions as the input data.
56
+
57
+ Notes
58
+ -----
59
+ Implementation differs from original Fortran implementation in computing the
60
+ vertical derivative of geopotential height. In particular, the finite difference
61
+ at the top-most and bottom-most layers different from original calculation by a
62
+ factor of two. The implementation here is consistent with a numerical approximation
63
+ of the derivative.
64
+ """
65
+
66
+ geopotential_height = _geopotential_height(met)
67
+
68
+ # TODO: these are not *quite* the same, though we treat them the same for now
69
+ # The generic "mass_fraction_of_cloud_ice_in_air" and ECMWF "specific_cloud_ice_water_content"
70
+ # are mass ice per mass of *moist* air,
71
+ # whereas GFS "ice_water_mixing_ratio" is mass ice per mass of *dry* air
72
+ #
73
+ # The method `cirrus_effective_extinction_coef` uses input of mass ice per mass of *dry* air,
74
+ # so only the GFS data is exactly right.
75
+ if "mass_fraction_of_cloud_ice_in_air" in met.data:
76
+ ciwc = met.data["mass_fraction_of_cloud_ice_in_air"]
77
+ elif "specific_cloud_ice_water_content" in met.data:
78
+ ciwc = met.data["specific_cloud_ice_water_content"]
79
+ elif "ice_water_mixing_ratio" in met.data:
80
+ ciwc = met.data["ice_water_mixing_ratio"]
81
+ else:
82
+ msg = "Could not find cloud ice variable"
83
+ raise KeyError(msg)
84
+
85
+ beta_e = cirrus_effective_extinction_coef(
86
+ ciwc,
87
+ met.data["air_temperature"],
88
+ met.data["air_pressure"],
89
+ )
90
+
91
+ # dask.array.gradient expects at least 2 elements in each chunk
92
+ level_axis = geopotential_height.get_axis_num("level")
93
+ if geopotential_height.chunks:
94
+ level_chunks = geopotential_height.chunks[level_axis]
95
+ if any(chunk < 2 for chunk in level_chunks):
96
+ geopotential_height = geopotential_height.chunk(level=-1)
97
+
98
+ dz = -dask.array.gradient(geopotential_height, axis=level_axis)
99
+ dz = xr.DataArray(dz, dims=geopotential_height.dims)
100
+
101
+ da = beta_e * dz
102
+
103
+ da = da.cumsum(dim="level")
104
+
105
+ return _assign_attrs(da)
106
+
107
+
108
+ def cirrus_effective_extinction_coef(
109
+ ciwc: ArrayLike,
110
+ T: ArrayLike,
111
+ p: ArrayLike,
112
+ ) -> ArrayLike:
113
+ r"""Calculate the effective extinction coefficient for spectral range 0.2-0.69 um.
114
+
115
+ Parameters
116
+ ----------
117
+ ciwc : ArrayLike
118
+ Cloud ice water content, [:math:`kg_{ice} kg_{dry \ air}^{-1}`].
119
+ Note that ECMWF provides specific ice water content per mass *moist* air.
120
+ T : ArrayLike
121
+ Air temperature, [:math:`K`]
122
+ p : ArrayLike
123
+ Air pressure, [:math:`Pa`]
124
+
125
+ Returns
126
+ -------
127
+ ArrayLike
128
+ Effective extinction coefficient for spectral range 0.2-0.69 um, [:math:`m^{-1}`]
129
+
130
+ References
131
+ ----------
132
+ - :cite:`schumannContrailCirrusPrediction2012`
133
+ - :cite:`sunParametrizationEffectiveSizes1999`
134
+
135
+ Notes
136
+ -----
137
+ References as noted in :cite:`schumannContrailCirrusPrediction2012`:
138
+
139
+ - Sun and Rikus QJRMS (1999), 125, 3037-3055
140
+ - Sun QJRMS (2001), 127, 267-271
141
+ - McFarquhar QJRMS (2001), 127, 261-265
142
+ """
143
+ # ciwc has some negative values
144
+ # these become NaN when we raise them to powers down below
145
+ # explicitly clipping at 0
146
+ ciwc = ciwc.clip(min=0.0)
147
+
148
+ # Coefficients to calculate beta_e
149
+ a_0_beta = -1.30817e-4
150
+ a_1_beta = 2.52883e0
151
+
152
+ rho_air = thermo.rho_d(T, p)
153
+ riwc = ciwc * rho_air * 1000.0
154
+
155
+ # calculates the ice particle effective diameter in the NWP cirrus (in um)
156
+ # Computing these exponentials is expensive. If this is a bottleneck, numexpr
157
+ # should be used.
158
+ tiwc = T + constants.absolute_zero + 190.0
159
+ d_eff = 45.8966 * riwc**0.2214 + 0.7957 * tiwc * riwc**0.2535
160
+
161
+ # explicitly clipping at 10
162
+ d_eff = d_eff.clip(min=10.0)
163
+
164
+ return riwc * (a_0_beta + a_1_beta / d_eff)
165
+
166
+
167
+ def _assign_attrs(da: xr.DataArray) -> xr.DataArray:
168
+ """Assign name and attrs to xr.DataArray.
169
+
170
+ Parameters
171
+ ----------
172
+ da : xr.DataArray
173
+ DataArray to assign attributes to
174
+
175
+ Returns
176
+ -------
177
+ xr.DataArray
178
+ DataArray with assigned attributes
179
+ """
180
+ da.name = TauCirrus.standard_name
181
+ da.attrs = TauCirrus.attrs
182
+
183
+ return da
@@ -0,0 +1 @@
1
+ """Physical and thermodynamic relations."""
@@ -0,0 +1,117 @@
1
+ """Meteorological, thermophysical, and aircraft constants."""
2
+
3
+ from __future__ import annotations
4
+
5
+ # -------
6
+ # General
7
+ # -------
8
+
9
+ # NOTE: Use a decimal point for each float-valued constant. This is important for
10
+ # converting to numpy arrays.
11
+
12
+ #: Absolute zero value :math:`[C]`
13
+ absolute_zero: float = -273.15
14
+
15
+ #: Gravitational acceleration :math:`[m \ s^{-2}]`
16
+ g: float = 9.80665
17
+
18
+ #: Radius of Earth :math:`[m]`
19
+ radius_earth: float = 6371229.0
20
+
21
+ #: Surface area of Earth :math:`[m^2]`
22
+ surface_area_earth: float = 5.10072e14
23
+
24
+ #: ISA height of the tropopause :math:`[m]`
25
+ #: :cite:`wikipediacontributorsInternationalStandardAtmosphere2023`
26
+ h_tropopause: float = 11000.0
27
+
28
+ #: Seconds in a Julian year :math:`[s]`
29
+ seconds_per_year: float = 3.15576e7
30
+
31
+ # -------------
32
+ # Thermodynamic
33
+ # -------------
34
+
35
+ #: Surface pressure, international standard atmosphere :math:`[Pa]`
36
+ #: :cite:`wikipediacontributorsInternationalStandardAtmosphere2023`
37
+ p_surface: float = 101325.0
38
+
39
+ #: Isobaric heat capacity of dry air :math:`[J \ kg^{-1} \ K^{-1}]`
40
+ c_pd: float = 1004.0 # 1005.7?
41
+
42
+ #: Isobaric heat capacity of water vapor :math:`[J \ kg^{-1} \ K^{-1}]`
43
+ c_pv: float = 1870.0
44
+
45
+ #: Molar mass of dry air :math:`[kg \ mol^{-1}]`
46
+ M_d: float = 28.9647e-3
47
+
48
+ #: Molar mass of water :math:`[kg \ mol^{-1}]`
49
+ M_v: float = 18.0153e-3
50
+
51
+ #: Ratio of heat capacities, TODO: which heat capacities?
52
+ gamma: float = 1.4
53
+
54
+ #: Molar gas constant :math:`[J \ mol^{-1} \ K^{-1}]`
55
+ R: float = 8.314462618
56
+
57
+ #: Gas constant of dry air :math:`[J \ kg^{-1} \ K^{-1}]`
58
+ R_d: float = 287.05
59
+
60
+ #: Gas constant of water vapour :math:`[J \ kg^{-1} \ K^{-1}]`
61
+ R_v: float = 461.51
62
+
63
+ #: Ratio of gas constant for dry air / gas constant for water vapor
64
+ epsilon: float = R_d / R_v
65
+
66
+ #: Density of ice :math:`[kg \ m^{-3}]`
67
+ rho_ice: float = 917.0
68
+
69
+ #: Adiabatic index air
70
+ kappa: float = 1.4
71
+
72
+ #: Standard atmospheric density at mean sea level (MSL) :math:`[kg \ m^{-3}]`
73
+ rho_msl: float = 1.225
74
+
75
+ #: Standard atmospheric temperature at mean sea level (MSL) :math:`[K]`
76
+ T_msl: float = 288.15
77
+
78
+ #: Speed of sound at mean sea level (MSL) in standard atmosphere :math:`[m \ s^{-1}]`
79
+ c_msl: float = 340.294
80
+
81
+ #: The rate at which the ISA ambient temperature falls with altitude :math:`[K \ m^{-1}]`
82
+ #: :cite:`wikipediacontributorsInternationalStandardAtmosphere2023`
83
+ T_lapse_rate: float = -0.0065
84
+
85
+ #: Average incident solar radiation, :math:`[W \ m^{-2}]`
86
+ #: This value can range +/- 3% as the earth orbits the sun.
87
+ #: From :cite:`uosolarradiationmonitoringlaboratoryUOSRMLSolar2022` citing
88
+ #: :cite:`paltridgeRadiativeProcessesMeteorology1976`
89
+ solar_constant: float = 1361.0
90
+
91
+ # ----
92
+ # Fuel
93
+ # ----
94
+
95
+ #: Isobaric heat capacity of combustion products :math:`[J \ kg^{-1} \ K^{-1}]`
96
+ c_p_combustion: float = 1250.0
97
+
98
+ # ------------------
99
+ # Optical Properties
100
+ # ------------------
101
+
102
+ #: Real refractive index of ice
103
+ mu_ice: float = 1.31
104
+
105
+ #: Wavelength of visible light (550 nm)
106
+ lambda_light: float = 550e-9
107
+
108
+ #: Ratio between the volume mean radius and the effective radius (Uncertainty +- 0.3)
109
+ c_r: float = 0.9
110
+
111
+ # ------
112
+ # Flight
113
+ # ------
114
+
115
+ #: Nominal rate of climb/descent of aircraft [:math:`m \ s^{-1}`].
116
+ #: Note [:math:`12.7 m \ s^{-1} = 2500 ft \ min^{-1}`].
117
+ nominal_rocd: float = 12.7