pycontrails 0.54.2__cp310-cp310-win_amd64.whl → 0.54.4__cp310-cp310-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.cp310-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/models/accf.py
CHANGED
|
@@ -88,13 +88,16 @@ class ACCFParams(ModelParams):
|
|
|
88
88
|
h2o_scaling: float = 1.0
|
|
89
89
|
o3_scaling: float = 1.0
|
|
90
90
|
|
|
91
|
-
forecast_step: float =
|
|
91
|
+
forecast_step: float | None = None
|
|
92
92
|
|
|
93
93
|
sep_ri_rw: bool = False
|
|
94
94
|
|
|
95
95
|
climate_indicator: str = "ATR"
|
|
96
96
|
|
|
97
|
-
|
|
97
|
+
#: The horizontal resolution of the meteorological data in degrees.
|
|
98
|
+
#: If None, it will be inferred from the ``met`` dataset for :class:`MetDataset`
|
|
99
|
+
#: source, otherwise it will be set to 0.5.
|
|
100
|
+
horizontal_resolution: float | None = None
|
|
98
101
|
|
|
99
102
|
emission_scenario: str = "pulse"
|
|
100
103
|
|
|
@@ -116,6 +119,8 @@ class ACCFParams(ModelParams):
|
|
|
116
119
|
|
|
117
120
|
PMO: bool = False
|
|
118
121
|
|
|
122
|
+
unit_K_per_kg_fuel: bool = False
|
|
123
|
+
|
|
119
124
|
|
|
120
125
|
class ACCF(Model):
|
|
121
126
|
"""Compute Algorithmic Climate Change Functions (ACCF).
|
|
@@ -146,16 +151,13 @@ class ACCF(Model):
|
|
|
146
151
|
SpecificHumidity,
|
|
147
152
|
ecmwf.PotentialVorticity,
|
|
148
153
|
Geopotential,
|
|
149
|
-
RelativeHumidity,
|
|
154
|
+
(RelativeHumidity, ecmwf.RelativeHumidity),
|
|
150
155
|
NorthwardWind,
|
|
151
156
|
EastwardWind,
|
|
152
|
-
ecmwf.PotentialVorticity,
|
|
153
157
|
)
|
|
154
158
|
sur_variables = (ecmwf.SurfaceSolarDownwardRadiation, ecmwf.TopNetThermalRadiation)
|
|
155
159
|
default_params = ACCFParams
|
|
156
160
|
|
|
157
|
-
short_vars = frozenset(v.short_name for v in (*met_variables, *sur_variables))
|
|
158
|
-
|
|
159
161
|
# This variable won't get used since we are not writing the output
|
|
160
162
|
# anywhere, but the library will complain if it's not defined
|
|
161
163
|
path_lib = "./"
|
|
@@ -168,7 +170,13 @@ class ACCF(Model):
|
|
|
168
170
|
**params_kwargs: Any,
|
|
169
171
|
) -> None:
|
|
170
172
|
# Normalize ECMWF variables
|
|
171
|
-
|
|
173
|
+
variables = (v[0] if isinstance(v, tuple) else v for v in self.met_variables)
|
|
174
|
+
met = standardize_variables(met, variables)
|
|
175
|
+
|
|
176
|
+
# If relative humidity is in percentage, convert to a proportion
|
|
177
|
+
if met["relative_humidity"].attrs.get("units") == "%":
|
|
178
|
+
met.data["relative_humidity"] /= 100.0
|
|
179
|
+
met.data["relative_humidity"].attrs["units"] = "1"
|
|
172
180
|
|
|
173
181
|
# Ignore humidity scaling warning
|
|
174
182
|
with warnings.catch_warnings():
|
|
@@ -231,18 +239,21 @@ class ACCF(Model):
|
|
|
231
239
|
if hasattr(self, "surface"):
|
|
232
240
|
self.surface = self.source.downselect_met(self.surface)
|
|
233
241
|
|
|
234
|
-
if
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
hres = abs(longitude[1] - longitude[0])
|
|
239
|
-
self.params["horizontal_resolution"] = float(hres)
|
|
240
|
-
|
|
241
|
-
else:
|
|
242
|
+
if self.params["horizontal_resolution"] is None:
|
|
243
|
+
if isinstance(self.source, MetDataset):
|
|
244
|
+
# Overwrite horizontal resolution to match met
|
|
245
|
+
longitude = self.source.data["longitude"].values
|
|
242
246
|
latitude = self.source.data["latitude"].values
|
|
243
|
-
if
|
|
247
|
+
if longitude.size > 1:
|
|
248
|
+
hres = abs(longitude[1] - longitude[0])
|
|
249
|
+
self.params["horizontal_resolution"] = float(hres)
|
|
250
|
+
elif latitude.size > 1:
|
|
244
251
|
hres = abs(latitude[1] - latitude[0])
|
|
245
252
|
self.params["horizontal_resolution"] = float(hres)
|
|
253
|
+
else:
|
|
254
|
+
self.params["horizontal_resolution"] = 0.5
|
|
255
|
+
else:
|
|
256
|
+
self.params["horizontal_resolution"] = 0.5
|
|
246
257
|
|
|
247
258
|
p_settings = _get_accf_config(self.params)
|
|
248
259
|
|
|
@@ -267,10 +278,14 @@ class ACCF(Model):
|
|
|
267
278
|
aCCFs, _ = clim_imp.get_xarray()
|
|
268
279
|
|
|
269
280
|
# assign ACCF outputs to source
|
|
281
|
+
skip = {
|
|
282
|
+
v[0].short_name if isinstance(v, tuple) else v.short_name
|
|
283
|
+
for v in (*self.met_variables, *self.sur_variables)
|
|
284
|
+
}
|
|
270
285
|
maCCFs = MetDataset(aCCFs)
|
|
271
286
|
for key, arr in maCCFs.data.items():
|
|
272
287
|
# skip met variables
|
|
273
|
-
if key in
|
|
288
|
+
if key in skip:
|
|
274
289
|
continue
|
|
275
290
|
|
|
276
291
|
assert isinstance(key, str)
|
|
@@ -292,7 +307,12 @@ class ACCF(Model):
|
|
|
292
307
|
# It also needs variables to have the ECMWF short name
|
|
293
308
|
if isinstance(self.met, MetDataset):
|
|
294
309
|
ds_met = self.met.data.transpose("time", "level", "latitude", "longitude")
|
|
295
|
-
name_dict = {
|
|
310
|
+
name_dict = {
|
|
311
|
+
v[0].standard_name if isinstance(v, tuple) else v.standard_name: v[0].short_name
|
|
312
|
+
if isinstance(v, tuple)
|
|
313
|
+
else v.short_name
|
|
314
|
+
for v in self.met_variables
|
|
315
|
+
}
|
|
296
316
|
ds_met = ds_met.rename(name_dict)
|
|
297
317
|
else:
|
|
298
318
|
ds_met = None
|
|
@@ -340,7 +360,7 @@ def _get_accf_config(params: dict[str, Any]) -> dict[str, Any]:
|
|
|
340
360
|
"horizontal_resolution": params["horizontal_resolution"],
|
|
341
361
|
"forecast_step": params["forecast_step"],
|
|
342
362
|
"NOx_aCCF": True,
|
|
343
|
-
"
|
|
363
|
+
"NOx_EI&F_km": params["nox_ei"],
|
|
344
364
|
"output_format": "netCDF",
|
|
345
365
|
"mean": False,
|
|
346
366
|
"std": False,
|
|
@@ -361,6 +381,7 @@ def _get_accf_config(params: dict[str, Any]) -> dict[str, Any]:
|
|
|
361
381
|
"H2O": params["h2o_scaling"],
|
|
362
382
|
"O3": params["o3_scaling"],
|
|
363
383
|
},
|
|
384
|
+
"unit_K/kg(fuel)": params["unit_K_per_kg_fuel"],
|
|
364
385
|
"PCFA": params["pfca"],
|
|
365
386
|
"PCFA-ISSR": {
|
|
366
387
|
"rhi_threshold": params["issr_rhi_threshold"],
|
|
@@ -28,6 +28,7 @@ from pycontrails.core.met_var import (
|
|
|
28
28
|
SpecificHumidity,
|
|
29
29
|
VerticalVelocity,
|
|
30
30
|
)
|
|
31
|
+
from pycontrails.core.vector import GeoVectorDataset
|
|
31
32
|
from pycontrails.models.apcemm import utils
|
|
32
33
|
from pycontrails.models.apcemm.inputs import APCEMMInput
|
|
33
34
|
from pycontrails.models.dry_advection import DryAdvection
|
|
@@ -276,13 +277,13 @@ class APCEMM(models.Model):
|
|
|
276
277
|
"""
|
|
277
278
|
|
|
278
279
|
__slots__ = (
|
|
279
|
-
"
|
|
280
|
+
"_trajectory_downsampling",
|
|
280
281
|
"apcemm_input_params",
|
|
282
|
+
"apcemm_path",
|
|
281
283
|
"cachestore",
|
|
284
|
+
"contrail",
|
|
282
285
|
"trajectories",
|
|
283
286
|
"vortex",
|
|
284
|
-
"contrail",
|
|
285
|
-
"_trajectory_downsampling",
|
|
286
287
|
)
|
|
287
288
|
|
|
288
289
|
name = "apcemm"
|
|
@@ -314,7 +315,7 @@ class APCEMM(models.Model):
|
|
|
314
315
|
source: Flight
|
|
315
316
|
|
|
316
317
|
#: Output from trajectory calculation
|
|
317
|
-
trajectories:
|
|
318
|
+
trajectories: GeoVectorDataset | None
|
|
318
319
|
|
|
319
320
|
#: Time series output from the APCEMM early plume model
|
|
320
321
|
vortex: pd.DataFrame | None
|
|
@@ -15,9 +15,10 @@ from pycontrails.models.cocip.output_formats import (
|
|
|
15
15
|
|
|
16
16
|
__all__ = [
|
|
17
17
|
"Cocip",
|
|
18
|
+
"CocipFlightParams",
|
|
18
19
|
"CocipParams",
|
|
19
20
|
"CocipUncertaintyParams",
|
|
20
|
-
"
|
|
21
|
+
"compare_cocip_with_goes",
|
|
21
22
|
"contrail_flight_summary_statistics",
|
|
22
23
|
"contrails_to_hi_res_grid",
|
|
23
24
|
"flight_waypoint_summary_statistics",
|
|
@@ -25,5 +26,4 @@ __all__ = [
|
|
|
25
26
|
"longitude_latitude_grid",
|
|
26
27
|
"natural_cirrus_properties_to_hi_res_grid",
|
|
27
28
|
"time_slice_statistics",
|
|
28
|
-
"compare_cocip_with_goes",
|
|
29
29
|
]
|
|
@@ -195,14 +195,14 @@ class Cocip(Model):
|
|
|
195
195
|
"""
|
|
196
196
|
|
|
197
197
|
__slots__ = (
|
|
198
|
-
"
|
|
198
|
+
"_downwash_contrail",
|
|
199
|
+
"_downwash_flight",
|
|
200
|
+
"_sac_flight",
|
|
199
201
|
"contrail",
|
|
200
202
|
"contrail_dataset",
|
|
201
203
|
"contrail_list",
|
|
204
|
+
"rad",
|
|
202
205
|
"timesteps",
|
|
203
|
-
"_sac_flight",
|
|
204
|
-
"_downwash_flight",
|
|
205
|
-
"_downwash_contrail",
|
|
206
206
|
)
|
|
207
207
|
|
|
208
208
|
name = "cocip"
|
|
@@ -660,7 +660,7 @@ class Cocip(Model):
|
|
|
660
660
|
attrs = self.source.attrs
|
|
661
661
|
attrs.pop("fl_attrs", None)
|
|
662
662
|
attrs.pop("data_keys", None)
|
|
663
|
-
self.source = Fleet.from_seq(fls, broadcast_numeric=False,
|
|
663
|
+
self.source = Fleet.from_seq(fls, broadcast_numeric=False, attrs=attrs)
|
|
664
664
|
|
|
665
665
|
# Single flight
|
|
666
666
|
else:
|
|
@@ -2055,9 +2055,9 @@ def calc_radiative_properties(contrail: GeoVectorDataset, params: dict[str, Any]
|
|
|
2055
2055
|
|
|
2056
2056
|
def calc_contrail_properties(
|
|
2057
2057
|
contrail: GeoVectorDataset,
|
|
2058
|
-
effective_vertical_resolution: float | npt.NDArray[np.
|
|
2059
|
-
wind_shear_enhancement_exponent: float | npt.NDArray[np.
|
|
2060
|
-
sedimentation_impact_factor: float | npt.NDArray[np.
|
|
2058
|
+
effective_vertical_resolution: float | npt.NDArray[np.floating],
|
|
2059
|
+
wind_shear_enhancement_exponent: float | npt.NDArray[np.floating],
|
|
2060
|
+
sedimentation_impact_factor: float | npt.NDArray[np.floating],
|
|
2061
2061
|
radiative_heating_effects: bool,
|
|
2062
2062
|
) -> None:
|
|
2063
2063
|
"""Calculate geometric and ice-related properties of contrail.
|
|
@@ -2084,11 +2084,11 @@ def calc_contrail_properties(
|
|
|
2084
2084
|
----------
|
|
2085
2085
|
contrail : GeoVectorDataset
|
|
2086
2086
|
Grid points with many precomputed keys.
|
|
2087
|
-
effective_vertical_resolution : float | npt.NDArray[np.
|
|
2087
|
+
effective_vertical_resolution : float | npt.NDArray[np.floating]
|
|
2088
2088
|
Passed into :func:`wind_shear.wind_shear_enhancement_factor`.
|
|
2089
|
-
wind_shear_enhancement_exponent : float | npt.NDArray[np.
|
|
2089
|
+
wind_shear_enhancement_exponent : float | npt.NDArray[np.floating]
|
|
2090
2090
|
Passed into :func:`wind_shear.wind_shear_enhancement_factor`.
|
|
2091
|
-
sedimentation_impact_factor: float | npt.NDArray[np.
|
|
2091
|
+
sedimentation_impact_factor: float | npt.NDArray[np.floating]
|
|
2092
2092
|
Passed into `contrail_properties.vertical_diffusivity`.
|
|
2093
2093
|
radiative_heating_effects: bool
|
|
2094
2094
|
Include radiative heating effects on contrail cirrus properties.
|
|
@@ -2296,8 +2296,7 @@ def calc_timestep_contrail_evolution(
|
|
|
2296
2296
|
dt = time_2_array - time_1
|
|
2297
2297
|
|
|
2298
2298
|
# get new contrail location & segment properties after t_step
|
|
2299
|
-
longitude_2 = geo.
|
|
2300
|
-
latitude_2 = geo.advect_latitude(latitude_1, v_wind_1, dt)
|
|
2299
|
+
longitude_2, latitude_2 = geo.advect_horizontal(longitude_1, latitude_1, u_wind_1, v_wind_1, dt)
|
|
2301
2300
|
level_2 = geo.advect_level(level_1, vertical_velocity_1, rho_air_1, terminal_fall_speed_1, dt)
|
|
2302
2301
|
altitude_2 = units.pl_to_m(level_2)
|
|
2303
2302
|
|
|
@@ -2526,8 +2525,8 @@ def calc_timestep_contrail_evolution(
|
|
|
2526
2525
|
def _rad_accumulation_to_average_instantaneous(
|
|
2527
2526
|
rad: MetDataset,
|
|
2528
2527
|
name: str,
|
|
2529
|
-
arr: npt.NDArray[np.
|
|
2530
|
-
) -> npt.NDArray[np.
|
|
2528
|
+
arr: npt.NDArray[np.floating],
|
|
2529
|
+
) -> npt.NDArray[np.floating]:
|
|
2531
2530
|
"""Convert from radiation accumulation to average instantaneous values.
|
|
2532
2531
|
|
|
2533
2532
|
.. versionadded:: 0.48.0
|
|
@@ -2538,12 +2537,12 @@ def _rad_accumulation_to_average_instantaneous(
|
|
|
2538
2537
|
Radiation data
|
|
2539
2538
|
name : str
|
|
2540
2539
|
Variable name
|
|
2541
|
-
arr : npt.NDArray[np.
|
|
2540
|
+
arr : npt.NDArray[np.floating]
|
|
2542
2541
|
Array of values already interpolated from ``rad``
|
|
2543
2542
|
|
|
2544
2543
|
Returns
|
|
2545
2544
|
-------
|
|
2546
|
-
npt.NDArray[np.
|
|
2545
|
+
npt.NDArray[np.floating]
|
|
2547
2546
|
Array of values converted from accumulation to average instantaneous values
|
|
2548
2547
|
|
|
2549
2548
|
Raises
|
|
@@ -11,7 +11,7 @@ import numpy as np
|
|
|
11
11
|
import numpy.typing as npt
|
|
12
12
|
|
|
13
13
|
from pycontrails.core.aircraft_performance import AircraftPerformance
|
|
14
|
-
from pycontrails.core.models import
|
|
14
|
+
from pycontrails.core.models import AdvectionBuffers
|
|
15
15
|
from pycontrails.models.emissions.emissions import EmissionsParams
|
|
16
16
|
from pycontrails.models.humidity_scaling import HumidityScaling
|
|
17
17
|
|
|
@@ -50,7 +50,7 @@ def _habits() -> npt.NDArray[np.str_]:
|
|
|
50
50
|
|
|
51
51
|
|
|
52
52
|
@dataclasses.dataclass
|
|
53
|
-
class CocipParams(
|
|
53
|
+
class CocipParams(AdvectionBuffers):
|
|
54
54
|
"""Model parameters required by the CoCiP models."""
|
|
55
55
|
|
|
56
56
|
# -------------------------
|
|
@@ -116,15 +116,6 @@ class CocipParams(ModelParams):
|
|
|
116
116
|
#: evaluation after the met data is downselected.
|
|
117
117
|
compute_tau_cirrus_in_model_init: bool | str = "auto"
|
|
118
118
|
|
|
119
|
-
#: Met longitude [WGS84] buffer for Cocip evolution.
|
|
120
|
-
met_longitude_buffer: tuple[float, float] = (10.0, 10.0)
|
|
121
|
-
|
|
122
|
-
#: Met latitude buffer [WGS84] for Cocip evolution.
|
|
123
|
-
met_latitude_buffer: tuple[float, float] = (10.0, 10.0)
|
|
124
|
-
|
|
125
|
-
#: Met level buffer [:math:`hPa`] for Cocip initialization and evolution.
|
|
126
|
-
met_level_buffer: tuple[float, float] = (40.0, 40.0)
|
|
127
|
-
|
|
128
119
|
# ---------
|
|
129
120
|
# Filtering
|
|
130
121
|
# ---------
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
import dataclasses
|
|
5
6
|
import logging
|
|
6
|
-
from dataclasses import asdict, dataclass
|
|
7
7
|
from typing import Any, ClassVar
|
|
8
8
|
|
|
9
9
|
import numpy as np
|
|
@@ -70,7 +70,7 @@ class habit_dirichlet(rv_frozen):
|
|
|
70
70
|
return habit_weights
|
|
71
71
|
|
|
72
72
|
|
|
73
|
-
@dataclass
|
|
73
|
+
@dataclasses.dataclass
|
|
74
74
|
class CocipUncertaintyParams(CocipParams):
|
|
75
75
|
"""Model parameters for CoCiP epistemic uncertainty.
|
|
76
76
|
|
|
@@ -117,26 +117,30 @@ class CocipUncertaintyParams(CocipParams):
|
|
|
117
117
|
#: Schumann takes ``wind_shear_enhancement_exponent`` = 0.5 and discusses the case of 0 and 2/3
|
|
118
118
|
#: as possibilities.
|
|
119
119
|
#: With a value of 0, wind shear is not enhanced.
|
|
120
|
-
wind_shear_enhancement_exponent_uncertainty: rv_frozen | None =
|
|
121
|
-
|
|
120
|
+
wind_shear_enhancement_exponent_uncertainty: rv_frozen | None = dataclasses.field(
|
|
121
|
+
default_factory=lambda: stats.triang(
|
|
122
|
+
loc=0.0, c=CocipParams.wind_shear_enhancement_exponent, scale=1.0
|
|
123
|
+
)
|
|
122
124
|
)
|
|
123
125
|
|
|
124
126
|
#: Schumann takes ``initial_wake_vortex_depth`` = 0.5 and discusses some
|
|
125
127
|
#: uncertainty in this value. This parameter should be non-negative.
|
|
126
|
-
initial_wake_vortex_depth_uncertainty: rv_frozen | None =
|
|
127
|
-
|
|
128
|
+
initial_wake_vortex_depth_uncertainty: rv_frozen | None = dataclasses.field(
|
|
129
|
+
default_factory=lambda: stats.triang(
|
|
130
|
+
loc=0.3, c=CocipParams.initial_wake_vortex_depth, scale=0.4
|
|
131
|
+
)
|
|
128
132
|
)
|
|
129
133
|
|
|
130
134
|
#: Schumann takes a default value of 0.1 and describes it as an "important adjustable parameter"
|
|
131
135
|
#: Currently, `CocipParams` uses a default value of 0.5
|
|
132
|
-
sedimentation_impact_factor_uncertainty: rv_frozen | None =
|
|
133
|
-
loc=CocipParams.sedimentation_impact_factor, scale=0.1
|
|
136
|
+
sedimentation_impact_factor_uncertainty: rv_frozen | None = dataclasses.field(
|
|
137
|
+
default_factory=lambda: stats.norm(loc=CocipParams.sedimentation_impact_factor, scale=0.1)
|
|
134
138
|
)
|
|
135
139
|
|
|
136
140
|
#: Teoh 2022 (to appear) takes values between 70% decrease and 100% increase.
|
|
137
141
|
#: This coincides with the log normal distribution defined below.
|
|
138
|
-
nvpm_ei_n_enhancement_factor_uncertainty: rv_frozen | None =
|
|
139
|
-
s=0.15, scale=1 / stats.lognorm(s=0.15).mean()
|
|
142
|
+
nvpm_ei_n_enhancement_factor_uncertainty: rv_frozen | None = dataclasses.field(
|
|
143
|
+
default_factory=lambda: stats.lognorm(s=0.15, scale=1 / stats.lognorm(s=0.15).mean())
|
|
140
144
|
)
|
|
141
145
|
|
|
142
146
|
#: Scale shortwave radiative forcing.
|
|
@@ -145,8 +149,8 @@ class CocipUncertaintyParams(CocipParams):
|
|
|
145
149
|
#: by `libRadTran <http://www.libradtran.org/doku.php>`_.
|
|
146
150
|
#: We use the average RMS error across all habit types (pg 1397) as the standard deviation
|
|
147
151
|
#: of a normally distributed scaling factor for SW forcing
|
|
148
|
-
rf_sw_enhancement_factor_uncertainty: rv_frozen | None =
|
|
149
|
-
loc=CocipParams.rf_sw_enhancement_factor, scale=0.106
|
|
152
|
+
rf_sw_enhancement_factor_uncertainty: rv_frozen | None = dataclasses.field(
|
|
153
|
+
default_factory=lambda: stats.norm(loc=CocipParams.rf_sw_enhancement_factor, scale=0.106)
|
|
150
154
|
)
|
|
151
155
|
|
|
152
156
|
#: Scale longwave radiative forcing.
|
|
@@ -154,8 +158,8 @@ class CocipUncertaintyParams(CocipParams):
|
|
|
154
158
|
#: fit to the data generated by `libRadTran <http://www.libradtran.org/doku.php>`_.
|
|
155
159
|
#: We use the average RMS error across all habit types (pg 1397) as the standard deviation
|
|
156
160
|
#: of a normally distributed scaling factor for LW forcing.
|
|
157
|
-
rf_lw_enhancement_factor_uncertainty: rv_frozen | None =
|
|
158
|
-
loc=CocipParams.rf_lw_enhancement_factor, scale=0.071
|
|
161
|
+
rf_lw_enhancement_factor_uncertainty: rv_frozen | None = dataclasses.field(
|
|
162
|
+
default_factory=lambda: stats.norm(loc=CocipParams.rf_lw_enhancement_factor, scale=0.071)
|
|
159
163
|
)
|
|
160
164
|
|
|
161
165
|
#: Scale the habit distributions by a dirichlet distribution
|
|
@@ -163,7 +167,9 @@ class CocipUncertaintyParams(CocipParams):
|
|
|
163
167
|
#: where :math:`\text{G}_{i}` is the approximate habit weight distributions
|
|
164
168
|
#: defined in :attr:`CocipParams().habit_distributions`.
|
|
165
169
|
#: Higher values of :math:`\text{C}` correspond to higher confidence in initial estimates.
|
|
166
|
-
habit_distributions_uncertainty: rv_frozen | None =
|
|
170
|
+
habit_distributions_uncertainty: rv_frozen | None = dataclasses.field(
|
|
171
|
+
default_factory=habit_dirichlet
|
|
172
|
+
)
|
|
167
173
|
|
|
168
174
|
def __post_init__(self) -> None:
|
|
169
175
|
"""Override values of model parameters according to ranges."""
|
|
@@ -192,7 +198,7 @@ class CocipUncertaintyParams(CocipParams):
|
|
|
192
198
|
|
|
193
199
|
out = {}
|
|
194
200
|
|
|
195
|
-
param_dict = asdict(self)
|
|
201
|
+
param_dict = dataclasses.asdict(self)
|
|
196
202
|
for uncertainty_param, dist in param_dict.items():
|
|
197
203
|
if uncertainty_param.endswith("_uncertainty") and dist is not None:
|
|
198
204
|
param = uncertainty_param.split("_uncertainty")[0]
|
|
@@ -212,7 +218,7 @@ class CocipUncertaintyParams(CocipParams):
|
|
|
212
218
|
|
|
213
219
|
return out
|
|
214
220
|
|
|
215
|
-
def rvs(self, size: None | int = None) -> dict[str, np.float64 | npt.NDArray[np.
|
|
221
|
+
def rvs(self, size: None | int = None) -> dict[str, np.float64 | npt.NDArray[np.floating]]:
|
|
216
222
|
"""Call each distribution's `rvs` method to generate random parameters.
|
|
217
223
|
|
|
218
224
|
Seed calls to `rvs` with class variable `rng`.
|
|
@@ -224,7 +230,7 @@ class CocipUncertaintyParams(CocipParams):
|
|
|
224
230
|
|
|
225
231
|
Returns
|
|
226
232
|
-------
|
|
227
|
-
dict[str, float | npt.NDArray[np.
|
|
233
|
+
dict[str, float | npt.NDArray[np.floating]]
|
|
228
234
|
Dictionary of random parameters. Dictionary keys consists of names of parameters in
|
|
229
235
|
`CocipParams` to be overridden by random value.
|
|
230
236
|
|