pycontrails 0.54.6__tar.gz → 0.54.7__tar.gz
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-0.54.6 → pycontrails-0.54.7}/CHANGELOG.md +25 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/NOTICE +1 -1
- {pycontrails-0.54.6/pycontrails.egg-info → pycontrails-0.54.7}/PKG-INFO +3 -3
- {pycontrails-0.54.6 → pycontrails-0.54.7}/RELEASE.md +1 -1
- {pycontrails-0.54.6 → pycontrails-0.54.7}/docs/conf.py +4 -2
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/__init__.py +1 -1
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/_version.py +2 -2
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/core/aircraft_performance.py +12 -30
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/core/airports.py +4 -1
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/core/flight.py +4 -4
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/core/met.py +41 -33
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/core/met_var.py +18 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/core/models.py +79 -3
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/core/rgi_cython.c +195 -195
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/core/vector.py +66 -0
- pycontrails-0.54.7/pycontrails/datalib/spire/__init__.py +5 -0
- pycontrails-0.54.7/pycontrails/datalib/spire/exceptions.py +62 -0
- pycontrails-0.54.7/pycontrails/datalib/spire/spire.py +606 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/models/accf.py +4 -4
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/models/cocip/cocip.py +38 -1
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/models/cocip/cocip_params.py +10 -1
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/models/cocip/unterstrasser_wake_vortex.py +132 -30
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/models/cocipgrid/cocip_grid.py +3 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/models/emissions/black_carbon.py +19 -14
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/models/emissions/emissions.py +8 -8
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/models/ps_model/ps_model.py +1 -1
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/physics/constants.py +2 -1
- {pycontrails-0.54.6 → pycontrails-0.54.7/pycontrails.egg-info}/PKG-INFO +3 -3
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails.egg-info/SOURCES.txt +3 -1
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails.egg-info/requires.txt +1 -1
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pyproject.toml +3 -3
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/test_apcemm.py +1 -2
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/test_cocip.py +62 -2
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/test_cocip_grid.py +19 -1
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/test_cocip_grid_parity.py +1 -1
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/test_geo.py +1 -2
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/test_met.py +1 -1
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/test_models.py +22 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/test_ps_model.py +1 -2
- pycontrails-0.54.7/tests/unit/test_spire.py +200 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/test_unterstrasser_wake_vortex.py +42 -26
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/test_vector.py +1 -2
- pycontrails-0.54.6/pycontrails/datalib/spire.py +0 -739
- pycontrails-0.54.6/tests/unit/test_spire.py +0 -93
- {pycontrails-0.54.6 → pycontrails-0.54.7}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/.github/dependabot.yaml +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/.github/pull_request_template.md +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/.github/workflows/docs.yaml +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/.github/workflows/doctest.yaml +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/.github/workflows/release.yaml +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/.github/workflows/scorecard.yaml +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/.github/workflows/test.yaml +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/.gitignore +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/.pre-commit-config.yaml +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/.zenodo.json +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/CONTRIBUTING.md +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/LICENSE +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/Makefile +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/README.md +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/docs/_static/css/style.css +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/docs/_static/img/colab.png +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/docs/_static/img/favicon.png +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/docs/_static/img/logo-dark.png +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/docs/_static/img/logo.png +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/docs/_static/pycontrails.bib +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/docs/api.rst +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/docs/changelog.rst +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/docs/contributing.rst +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/docs/develop.rst +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/docs/flight.rst +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/docs/index.rst +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/docs/install.rst +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/docs/integrations/ACCF.ipynb +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/docs/integrations/APCEMM.ipynb +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/docs/literature.rst +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/docs/meteorology.rst +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/docs/models.rst +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/docs/notebooks/ARCO-ERA5.ipynb +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/docs/notebooks/AircraftPerformance.ipynb +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/docs/notebooks/Cache.ipynb +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/docs/notebooks/CoCiP.ipynb +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/docs/notebooks/CoCiPGrid.ipynb +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/docs/notebooks/ECMWF.ipynb +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/docs/notebooks/Flight.ipynb +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/docs/notebooks/GFS.ipynb +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/docs/notebooks/GOES.ipynb +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/docs/notebooks/ISSR.ipynb +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/docs/notebooks/Landsat.ipynb +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/docs/notebooks/Meteorology.ipynb +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/docs/notebooks/SAC.ipynb +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/docs/notebooks/Sentinel.ipynb +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/docs/notebooks/advection.ipynb +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/docs/notebooks/airports.ipynb +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/docs/notebooks/data/.gitignore +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/docs/notebooks/data/flight-ap.csv +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/docs/notebooks/data/flight-cocip.csv +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/docs/notebooks/data/flight-fdr.csv +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/docs/notebooks/data/flight-noisy.csv +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/docs/notebooks/data/flight.csv +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/docs/notebooks/data/iagos-flight-landsat.csv +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/docs/notebooks/data/iagos-flight-sentinel.csv +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/docs/notebooks/flightplan.ipynb +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/docs/notebooks/model-levels.ipynb +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/docs/notebooks/run-cocip-on-flight.ipynb +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/docs/notebooks/run-cocip-with-fdr.ipynb +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/docs/notebooks/specific-humidity-interpolation.ipynb +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/docs/notebooks.rst +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/docs/observations.rst +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/docs/tutorials.rst +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/docs/utilities.rst +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/core/__init__.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/core/cache.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/core/coordinates.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/core/fleet.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/core/flightplan.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/core/fuel.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/core/interpolation.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/core/polygon.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/core/rgi_cython.pyx +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/datalib/__init__.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/datalib/_leo_utils/search.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/datalib/_leo_utils/static/bq_roi_query.sql +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/datalib/_leo_utils/vis.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/datalib/_met_utils/metsource.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/datalib/ecmwf/__init__.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/datalib/ecmwf/arco_era5.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/datalib/ecmwf/common.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/datalib/ecmwf/era5.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/datalib/ecmwf/era5_model_level.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/datalib/ecmwf/hres.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/datalib/ecmwf/hres_model_level.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/datalib/ecmwf/ifs.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/datalib/ecmwf/model_levels.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/datalib/ecmwf/static/model_level_dataframe_v20240418.csv +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/datalib/ecmwf/variables.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/datalib/gfs/__init__.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/datalib/gfs/gfs.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/datalib/gfs/variables.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/datalib/goes.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/datalib/landsat.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/datalib/sentinel.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/ext/bada.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/ext/cirium.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/ext/empirical_grid.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/ext/synthetic_flight.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/models/__init__.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/models/apcemm/__init__.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/models/apcemm/apcemm.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/models/apcemm/inputs.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/models/apcemm/static/apcemm_yaml_template.yaml +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/models/apcemm/utils.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/models/cocip/__init__.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/models/cocip/cocip_uncertainty.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/models/cocip/contrail_properties.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/models/cocip/output_formats.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/models/cocip/radiative_forcing.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/models/cocip/radiative_heating.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/models/cocip/wake_vortex.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/models/cocip/wind_shear.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/models/cocipgrid/__init__.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/models/cocipgrid/cocip_grid_params.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/models/dry_advection.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/models/emissions/__init__.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/models/emissions/ffm2.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/models/emissions/static/default-engine-uids.csv +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/models/emissions/static/edb-gaseous-v29b-engines.csv +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/models/emissions/static/edb-nvpm-v29b-engines.csv +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/models/humidity_scaling/__init__.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/models/humidity_scaling/humidity_scaling.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/models/humidity_scaling/quantiles/era5-model-level-quantiles.pq +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/models/humidity_scaling/quantiles/era5-pressure-level-quantiles.pq +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/models/issr.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/models/pcc.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/models/pcr.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/models/ps_model/__init__.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/models/ps_model/ps_aircraft_params.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/models/ps_model/ps_grid.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/models/ps_model/ps_operational_limits.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/models/ps_model/static/ps-aircraft-params-20240524.csv +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/models/ps_model/static/ps-synonym-list-20240524.csv +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/models/sac.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/models/tau_cirrus.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/physics/__init__.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/physics/geo.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/physics/jet.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/physics/static/iata-cargo-load-factors-20241115.csv +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/physics/static/iata-passenger-load-factors-20241115.csv +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/physics/thermo.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/physics/units.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/py.typed +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/utils/__init__.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/utils/dependencies.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/utils/iteration.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/utils/json.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/utils/temp.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails/utils/types.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails.egg-info/dependency_links.txt +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/pycontrails.egg-info/top_level.txt +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/setup.cfg +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/setup.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/__init__.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/_deprecated.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/benchmark/cocip/Makefile +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/benchmark/cocip/README.md +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/benchmark/cocip/benchmark.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/benchmark/cocip/compare.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/benchmark/cocip/data.md +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/benchmark/cocip/output.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/benchmark/cocip/review.ipynb +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/benchmark/cocip-fortran/README.md +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/benchmark/north-atlantic-study/.gcloudignore +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/benchmark/north-atlantic-study/README.md +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/benchmark/north-atlantic-study/support.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/benchmark/north-atlantic-study/validate.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/fixtures/cocip-met.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/fixtures/cocip-met2.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/fixtures/ecmwf-met.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/fixtures/gfs-met.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/__init__.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/conftest.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/static/NOAA_Solar_Calculations_day.csv +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/static/cocip-contrail-output.json +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/static/cocip-contrail-output2.json +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/static/cocip-flight-output.json +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/static/cocip-flight-output2.json +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/static/cocip-output-contrail-edges.json +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/static/cocip-output-flts-20190101-eu.pq +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/static/flight-cocip2.csv +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/static/flight-meridian.csv +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/static/flight-metadata.json +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/static/flight-spire-data-cleaning.pq +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/static/flight.csv +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/static/flt-wypts-20190101-eu.pq +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/static/met-20190101-eu.nc +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/static/met-accf-pl.nc +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/static/met-accf-sl.nc +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/static/met-ecmwf-lnsp.nc +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/static/met-ecmwf-ml.nc +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/static/met-ecmwf-pl.nc +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/static/met-ecmwf-sl.nc +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/static/met-era5-cocip1.nc +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/static/met-era5-cocip2.nc +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/static/met-gfs.nc +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/static/polygon-bug.nc +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/static/rad-20190101-eu.nc +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/static/rad-era5-cocip1.nc +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/static/rad-era5-cocip2.nc +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/static/rad-gfs.nc +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/test_accf.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/test_airports.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/test_cache.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/test_cocip_radiative_forcing.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/test_cocip_uncertainty.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/test_coordinates.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/test_datalib_metsource.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/test_dry_advection.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/test_dtypes.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/test_ecmwf.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/test_emissions.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/test_fleet.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/test_flight.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/test_flightplan.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/test_fuel.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/test_gfs.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/test_goes.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/test_grid_to_netcdf.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/test_humidity_scaling.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/test_init.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/test_interpolation.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/test_leo.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/test_met_cache.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/test_pcc.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/test_polygons.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/test_sac_issr.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/test_tau_cirrus.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/test_thermo_sac.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/test_units.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/test_utils.py +0 -0
- {pycontrails-0.54.6 → pycontrails-0.54.7}/tests/unit/test_zarr.py +0 -0
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## v0.54.7
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
- Add helper `classmethods` to `Model`, `Cocip`, and `CocipGrid` for generating lists of required variables from specific data sources.
|
|
8
|
+
- Add a `ValidateTrajectoryHandler` to the `spire` module to validate spire ADS-B data. This work is experimental and will be improved in future releases.
|
|
9
|
+
- Update Unterstrasser (2016)'s parameterised model of the contrail ice crystal survival fraction to the latest version (Lottermoser & Unterstrasser, 2025). This update:
|
|
10
|
+
- improves the goodness of fit between the parameterised model and LES, and
|
|
11
|
+
- expands the parameter space for application to very low and very high nvPM inputs, different fuel types (where the EI H2Os are different), and higher ambient temperatures (up to 235 K) to accommodate for contrails formed by liquid hydrogen aircraft.
|
|
12
|
+
|
|
13
|
+
### Breaking changes
|
|
14
|
+
|
|
15
|
+
- The `MetDataset.standardize_variables` method now returns a new `MetDataset` rather than modifying the existing dataset in place. To retain the previous behavior, use `MetDataset.standardize_variables(..., inplace=True)`.
|
|
16
|
+
|
|
17
|
+
### Fixes
|
|
18
|
+
|
|
19
|
+
- Change naming convention for eastward and northward wind fields in `AircraftPerformance` models for consistency with the `Cocip` and `DryAdvection` models. Fields on the `source` are now named `u_wind` and `v_wind` instead of `eastward_wind` and `northward_wind`. Under some paths of computation, this avoids a redundant interpolation.
|
|
20
|
+
- Fix the `AircraftPerformance.ensure_true_airspeed_on_source` method in the case when the `met` attr is None and the `fill_with_groundspeed` parameter is enabled.
|
|
21
|
+
|
|
22
|
+
### Internals
|
|
23
|
+
|
|
24
|
+
- Make `pycontrails` compatible with `pandas 2.0` and `pandas 2.1`.
|
|
25
|
+
- Avoid auto-promotion of float32 to float64 within the `Emissions` model run-time.
|
|
26
|
+
- Add convenience `VectorDataset.get_constant` method.
|
|
27
|
+
|
|
3
28
|
## v0.54.6
|
|
4
29
|
|
|
5
30
|
### Features
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: pycontrails
|
|
3
|
-
Version: 0.54.
|
|
3
|
+
Version: 0.54.7
|
|
4
4
|
Summary: Python library for modeling aviation climate impacts
|
|
5
|
-
Author-email:
|
|
5
|
+
Author-email: "Contrails.org" <py@contrails.org>
|
|
6
6
|
License: Apache-2.0
|
|
7
7
|
Project-URL: Changelog, https://py.contrails.org/changelog.html
|
|
8
8
|
Project-URL: Documentation, https://py.contrails.org
|
|
@@ -29,7 +29,7 @@ License-File: LICENSE
|
|
|
29
29
|
License-File: NOTICE
|
|
30
30
|
Requires-Dist: dask>=2022.3
|
|
31
31
|
Requires-Dist: numpy>=1.22
|
|
32
|
-
Requires-Dist: pandas>=2.
|
|
32
|
+
Requires-Dist: pandas>=2.0
|
|
33
33
|
Requires-Dist: scipy>=1.10
|
|
34
34
|
Requires-Dist: typing-extensions>=4.5; python_version < "3.12"
|
|
35
35
|
Requires-Dist: xarray>=2022.3
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
Double check that the release tag is consistent and consecutive with
|
|
12
12
|
the previous release tag following [PEP 440](https://peps.python.org/pep-0440/#version-scheme).
|
|
13
13
|
This often but not always agrees with [Semantic Versioning](https://semver.org/).
|
|
14
|
-
1. Copy the CHANGELOG content for the release into the *Description*.
|
|
14
|
+
1. Copy the [CHANGELOG](https://raw.githubusercontent.com/contrailcirrus/pycontrails/refs/heads/main/CHANGELOG.md) content for the release into the *Description*.
|
|
15
15
|
1. Publish the new release.
|
|
16
16
|
This will create a tag on `main` and trigger the [Release Action](https://github.com/contrailcirrus/pycontrails/actions/workflows/release.yaml).
|
|
17
17
|
1. Confirm that the release is successfully deployed to [PyPI](https://pypi.org/project/pycontrails/).
|
|
@@ -15,9 +15,11 @@ import pycontrails
|
|
|
15
15
|
# -- Project information -----------------------------------------------------
|
|
16
16
|
|
|
17
17
|
project = "pycontrails"
|
|
18
|
-
copyright =
|
|
18
|
+
copyright = (
|
|
19
|
+
f"2021-{datetime.datetime.now().year}, Contrails.org and the Breakthrough Energy Foundation"
|
|
20
|
+
)
|
|
19
21
|
|
|
20
|
-
author = "
|
|
22
|
+
author = "Contrails.org"
|
|
21
23
|
version = pycontrails.__version__
|
|
22
24
|
release = pycontrails.__version__
|
|
23
25
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""
|
|
2
2
|
``pycontrails`` public API.
|
|
3
3
|
|
|
4
|
-
Copyright 2021-present Breakthrough Energy
|
|
4
|
+
Copyright 2021-present Contrails.org and the Breakthrough Energy Foundation
|
|
5
5
|
|
|
6
6
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
7
|
you may not use this file except in compliance with the License.
|
|
@@ -71,6 +71,8 @@ class AircraftPerformanceParams(ModelParams, CommonAircraftPerformanceParams):
|
|
|
71
71
|
#: level with zero wind when computing true airspeed. In other words,
|
|
72
72
|
#: approximate low-altitude true airspeed with the ground speed. Enabling
|
|
73
73
|
#: this does NOT remove any NaN values in the ``met`` data itself.
|
|
74
|
+
#: In the case that ``met`` is not provided, any missing values are
|
|
75
|
+
#: filled with zero wind.
|
|
74
76
|
fill_low_altitude_with_zero_wind: bool = False
|
|
75
77
|
|
|
76
78
|
|
|
@@ -509,7 +511,8 @@ class AircraftPerformance(Model):
|
|
|
509
511
|
tas[cond] = self.source.segment_groundspeed()[cond]
|
|
510
512
|
return tas
|
|
511
513
|
|
|
512
|
-
|
|
514
|
+
# Use current cocip convention: eastward_wind on met, u_wind on source
|
|
515
|
+
wind_available = ("u_wind" in self.source and "v_wind" in self.source) or (
|
|
513
516
|
self.met is not None and "eastward_wind" in self.met and "northward_wind" in self.met
|
|
514
517
|
)
|
|
515
518
|
|
|
@@ -526,12 +529,16 @@ class AircraftPerformance(Model):
|
|
|
526
529
|
)
|
|
527
530
|
raise ValueError(msg)
|
|
528
531
|
|
|
529
|
-
u = interpolate_met(self.met, self.source, "eastward_wind", **self.interp_kwargs)
|
|
530
|
-
v = interpolate_met(self.met, self.source, "northward_wind", **self.interp_kwargs)
|
|
532
|
+
u = interpolate_met(self.met, self.source, "eastward_wind", "u_wind", **self.interp_kwargs)
|
|
533
|
+
v = interpolate_met(self.met, self.source, "northward_wind", "v_wind", **self.interp_kwargs)
|
|
531
534
|
|
|
532
535
|
if fill_with_groundspeed:
|
|
533
|
-
|
|
534
|
-
|
|
536
|
+
if self.met is None:
|
|
537
|
+
cond = np.isnan(u) & np.isnan(v)
|
|
538
|
+
else:
|
|
539
|
+
met_level_max = self.met.data["level"][-1].item() # type: ignore[union-attr]
|
|
540
|
+
cond = self.source.level > met_level_max
|
|
541
|
+
|
|
535
542
|
# We DON'T overwrite the original u and v arrays already attached to the source
|
|
536
543
|
u = np.where(cond, 0.0, u)
|
|
537
544
|
v = np.where(cond, 0.0, v)
|
|
@@ -657,28 +664,3 @@ def _fill_low_altitude_with_isa_temperature(vector: GeoVectorDataset, met_level_
|
|
|
657
664
|
|
|
658
665
|
t_isa = vector.T_isa()
|
|
659
666
|
air_temperature[cond] = t_isa[cond]
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
def _fill_low_altitude_tas_with_true_groundspeed(fl: Flight, met_level_max: float) -> None:
|
|
663
|
-
"""Fill low-altitude NaN values in ``true_airspeed`` with ground speed.
|
|
664
|
-
|
|
665
|
-
The ``true_airspeed`` param is assumed to have been computed by
|
|
666
|
-
interpolating against a gridded wind field that did not necessarily
|
|
667
|
-
extend to the surface. This function fills points below the lowest
|
|
668
|
-
altitude in the gridded data with ground speed values.
|
|
669
|
-
|
|
670
|
-
This function operates in-place and modifies the ``true_airspeed`` field.
|
|
671
|
-
|
|
672
|
-
Parameters
|
|
673
|
-
----------
|
|
674
|
-
fl : Flight
|
|
675
|
-
Flight instance associated with the ``true_airspeed`` data.
|
|
676
|
-
met_level_max : float
|
|
677
|
-
The maximum level in the met data, [:math:`hPa`].
|
|
678
|
-
"""
|
|
679
|
-
tas = fl["true_airspeed"]
|
|
680
|
-
is_nan = np.isnan(tas)
|
|
681
|
-
low_alt = fl.level > met_level_max
|
|
682
|
-
cond = is_nan & low_alt
|
|
683
|
-
|
|
684
|
-
tas[cond] = fl.segment_groundspeed()[cond]
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
import functools
|
|
6
|
+
|
|
5
7
|
import numpy as np
|
|
6
8
|
import pandas as pd
|
|
7
9
|
|
|
@@ -35,6 +37,7 @@ def _download_ourairports_csv() -> pd.DataFrame:
|
|
|
35
37
|
)
|
|
36
38
|
|
|
37
39
|
|
|
40
|
+
@functools.cache
|
|
38
41
|
def global_airport_database(
|
|
39
42
|
cachestore: cache.CacheStore | None = None, update_cache: bool = False
|
|
40
43
|
) -> pd.DataFrame:
|
|
@@ -91,7 +94,7 @@ def global_airport_database(
|
|
|
91
94
|
airports = airports.rename(
|
|
92
95
|
columns={"latitude_deg": "latitude", "longitude_deg": "longitude", "gps_code": "icao_code"},
|
|
93
96
|
)
|
|
94
|
-
airports.fillna({"elevation_ft": 0}, inplace=True)
|
|
97
|
+
airports.fillna({"elevation_ft": 0.0}, inplace=True)
|
|
95
98
|
|
|
96
99
|
# Keep specific airport types used by commercial aviation
|
|
97
100
|
subset = ("large_airport", "medium_airport", "small_airport", "heliport")
|
|
@@ -1388,7 +1388,7 @@ class Flight(GeoVectorDataset):
|
|
|
1388
1388
|
|
|
1389
1389
|
jump_indices = _antimeridian_index(pd.Series(self["longitude"]))
|
|
1390
1390
|
|
|
1391
|
-
def _group_to_feature(group: pd.DataFrame) -> dict[str, str | dict[str, Any]]:
|
|
1391
|
+
def _group_to_feature(name: str, group: pd.DataFrame) -> dict[str, str | dict[str, Any]]:
|
|
1392
1392
|
# assigns a different value to each group of consecutive indices
|
|
1393
1393
|
subgrouping = group.index.to_series().diff().ne(1).cumsum()
|
|
1394
1394
|
|
|
@@ -1405,7 +1405,7 @@ class Flight(GeoVectorDataset):
|
|
|
1405
1405
|
geometry = {"type": "MultiLineString", "coordinates": multi_ls}
|
|
1406
1406
|
|
|
1407
1407
|
# adding in static properties
|
|
1408
|
-
properties: dict[str, Any] = {key:
|
|
1408
|
+
properties: dict[str, Any] = {key: name} if key is not None else {}
|
|
1409
1409
|
properties.update(self.constants)
|
|
1410
1410
|
return {"type": "Feature", "geometry": geometry, "properties": properties}
|
|
1411
1411
|
|
|
@@ -1415,11 +1415,11 @@ class Flight(GeoVectorDataset):
|
|
|
1415
1415
|
# create a single group containing all rows of dataframe
|
|
1416
1416
|
groups = self.dataframe.groupby(lambda _: 0)
|
|
1417
1417
|
|
|
1418
|
-
features =
|
|
1418
|
+
features = [_group_to_feature(*name_group) for name_group in groups]
|
|
1419
1419
|
return {"type": "FeatureCollection", "features": features}
|
|
1420
1420
|
|
|
1421
1421
|
def to_traffic(self) -> traffic.core.Flight:
|
|
1422
|
-
"""Convert to :class:`traffic.core.Flight`instance.
|
|
1422
|
+
"""Convert to :class:`traffic.core.Flight` instance.
|
|
1423
1423
|
|
|
1424
1424
|
Returns
|
|
1425
1425
|
-------
|
|
@@ -150,11 +150,8 @@ class MetBase(ABC, Generic[XArrayType]):
|
|
|
150
150
|
"""
|
|
151
151
|
longitude = self.indexes["longitude"].to_numpy()
|
|
152
152
|
if longitude.dtype != COORD_DTYPE:
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
"Instantiate with 'copy=True' to convert to float64. "
|
|
156
|
-
"Instantiate with 'validate=False' to skip validation."
|
|
157
|
-
)
|
|
153
|
+
msg = f"Longitude values must have dtype {COORD_DTYPE}. Instantiate with 'copy=True'."
|
|
154
|
+
raise ValueError(msg)
|
|
158
155
|
|
|
159
156
|
if self.is_wrapped:
|
|
160
157
|
# Relax verification if the longitude has already been processed and wrapped
|
|
@@ -194,11 +191,8 @@ class MetBase(ABC, Generic[XArrayType]):
|
|
|
194
191
|
"""
|
|
195
192
|
latitude = self.indexes["latitude"].to_numpy()
|
|
196
193
|
if latitude.dtype != COORD_DTYPE:
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
"Instantiate with 'copy=True' to convert to float64. "
|
|
200
|
-
"Instantiate with 'validate=False' to skip validation."
|
|
201
|
-
)
|
|
194
|
+
msg = f"Latitude values must have dtype {COORD_DTYPE}. Instantiate with 'copy=True'."
|
|
195
|
+
raise ValueError(msg)
|
|
202
196
|
|
|
203
197
|
if latitude[0] < -90.0:
|
|
204
198
|
raise ValueError(
|
|
@@ -233,8 +227,8 @@ class MetBase(ABC, Generic[XArrayType]):
|
|
|
233
227
|
if da.dims != self.dim_order:
|
|
234
228
|
if key is not None:
|
|
235
229
|
msg = (
|
|
236
|
-
f"Data dimension not transposed on variable '{key}'.
|
|
237
|
-
" 'copy=True'."
|
|
230
|
+
f"Data dimension not transposed on variable '{key}'. "
|
|
231
|
+
"Instantiate with 'copy=True'."
|
|
238
232
|
)
|
|
239
233
|
else:
|
|
240
234
|
msg = "Data dimension not transposed. Instantiate with 'copy=True'."
|
|
@@ -258,11 +252,8 @@ class MetBase(ABC, Generic[XArrayType]):
|
|
|
258
252
|
self._validate_latitude()
|
|
259
253
|
self._validate_transpose()
|
|
260
254
|
if self.data["level"].dtype != COORD_DTYPE:
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
"Instantiate with 'copy=True' to convert to float64. "
|
|
264
|
-
"Instantiate with 'validate=False' to skip validation."
|
|
265
|
-
)
|
|
255
|
+
msg = f"Level values must have dtype {COORD_DTYPE}. Instantiate with 'copy=True'."
|
|
256
|
+
raise ValueError(msg)
|
|
266
257
|
|
|
267
258
|
def _preprocess_dims(self, wrap_longitude: bool) -> None:
|
|
268
259
|
"""Confirm DataArray or Dataset include required dimension in a consistent format.
|
|
@@ -435,7 +426,7 @@ class MetBase(ABC, Generic[XArrayType]):
|
|
|
435
426
|
Assumes the longitude dimension is sorted (this is established by the
|
|
436
427
|
:class:`MetDataset` or :class:`MetDataArray` constructor).
|
|
437
428
|
|
|
438
|
-
.. versionchanged 0.26.0
|
|
429
|
+
.. versionchanged:: 0.26.0
|
|
439
430
|
|
|
440
431
|
The previous implementation checked for the minimum and maximum longitude
|
|
441
432
|
dimension values to be duplicated. The current implementation only checks for
|
|
@@ -492,7 +483,7 @@ class MetBase(ABC, Generic[XArrayType]):
|
|
|
492
483
|
|
|
493
484
|
Does not yet save in parallel.
|
|
494
485
|
|
|
495
|
-
.. versionchanged::0.34.1
|
|
486
|
+
.. versionchanged:: 0.34.1
|
|
496
487
|
|
|
497
488
|
If :attr:`cachestore` is None, this method assigns it
|
|
498
489
|
to new :class:`DiskCacheStore`.
|
|
@@ -1178,19 +1169,45 @@ class MetDataset(MetBase):
|
|
|
1178
1169
|
}
|
|
1179
1170
|
return self._get_pycontrails_attr_template("product", supported, examples)
|
|
1180
1171
|
|
|
1181
|
-
|
|
1182
|
-
|
|
1172
|
+
@overload
|
|
1173
|
+
def standardize_variables(
|
|
1174
|
+
self, variables: Iterable[MetVariable], inplace: Literal[False] = ...
|
|
1175
|
+
) -> Self: ...
|
|
1176
|
+
|
|
1177
|
+
@overload
|
|
1178
|
+
def standardize_variables(
|
|
1179
|
+
self, variables: Iterable[MetVariable], inplace: Literal[True]
|
|
1180
|
+
) -> None: ...
|
|
1181
|
+
|
|
1182
|
+
def standardize_variables(
|
|
1183
|
+
self, variables: Iterable[MetVariable], inplace: bool = False
|
|
1184
|
+
) -> Self | None:
|
|
1185
|
+
"""Standardize variable names.
|
|
1186
|
+
|
|
1187
|
+
.. versionchanged:: 0.54.7
|
|
1188
|
+
|
|
1189
|
+
By default, this method returns a new :class:`MetDataset` instead
|
|
1190
|
+
of renaming in place. To retain the old behavior, set ``inplace=True``.
|
|
1183
1191
|
|
|
1184
1192
|
Parameters
|
|
1185
1193
|
----------
|
|
1186
1194
|
variables : Iterable[MetVariable]
|
|
1187
1195
|
Data source variables
|
|
1196
|
+
inplace : bool, optional
|
|
1197
|
+
If True, rename variables in place. Otherwise, return a new
|
|
1198
|
+
:class:`MetDataset` with renamed variables.
|
|
1188
1199
|
|
|
1189
1200
|
See Also
|
|
1190
1201
|
--------
|
|
1191
1202
|
:func:`standardize_variables`
|
|
1192
1203
|
"""
|
|
1193
|
-
standardize_variables(self, variables)
|
|
1204
|
+
data_renamed = standardize_variables(self.data, variables)
|
|
1205
|
+
|
|
1206
|
+
if inplace:
|
|
1207
|
+
self.data = data_renamed
|
|
1208
|
+
return None
|
|
1209
|
+
|
|
1210
|
+
return type(self)._from_fastpath(data_renamed, cachestore=self.cachestore)
|
|
1194
1211
|
|
|
1195
1212
|
@classmethod
|
|
1196
1213
|
def from_coords(
|
|
@@ -2642,7 +2659,7 @@ def downselect(data: XArrayType, bbox: tuple[float, ...]) -> XArrayType:
|
|
|
2642
2659
|
return data.where(cond, drop=True)
|
|
2643
2660
|
|
|
2644
2661
|
|
|
2645
|
-
def standardize_variables(ds:
|
|
2662
|
+
def standardize_variables(ds: xr.Dataset, variables: Iterable[MetVariable]) -> xr.Dataset:
|
|
2646
2663
|
"""Rename all variables in dataset from short name to standard name.
|
|
2647
2664
|
|
|
2648
2665
|
This function does not change any variables in ``ds`` that are not found in ``variables``.
|
|
@@ -2652,8 +2669,7 @@ def standardize_variables(ds: DatasetType, variables: Iterable[MetVariable]) ->
|
|
|
2652
2669
|
Parameters
|
|
2653
2670
|
----------
|
|
2654
2671
|
ds : DatasetType
|
|
2655
|
-
An :class:`xr.Dataset
|
|
2656
|
-
passed, the underlying :class:`xr.Dataset` is modified in place.
|
|
2672
|
+
An :class:`xr.Dataset`.
|
|
2657
2673
|
variables : Iterable[MetVariable]
|
|
2658
2674
|
Data source variables
|
|
2659
2675
|
|
|
@@ -2662,14 +2678,6 @@ def standardize_variables(ds: DatasetType, variables: Iterable[MetVariable]) ->
|
|
|
2662
2678
|
DatasetType
|
|
2663
2679
|
Dataset with variables renamed to standard names
|
|
2664
2680
|
"""
|
|
2665
|
-
if isinstance(ds, xr.Dataset):
|
|
2666
|
-
return _standardize_variables(ds, variables)
|
|
2667
|
-
|
|
2668
|
-
ds.data = _standardize_variables(ds.data, variables)
|
|
2669
|
-
return ds
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
def _standardize_variables(ds: xr.Dataset, variables: Iterable[MetVariable]) -> xr.Dataset:
|
|
2673
2681
|
variables_dict: dict[Hashable, str] = {v.short_name: v.standard_name for v in variables}
|
|
2674
2682
|
name_dict = {var: variables_dict[var] for var in ds.data_vars if var in variables_dict}
|
|
2675
2683
|
return ds.rename(name_dict)
|
|
@@ -367,3 +367,21 @@ TOAOutgoingLongwaveFlux = MetVariable(
|
|
|
367
367
|
'"flux" implies per unit area, called "flux density" in physics.'
|
|
368
368
|
),
|
|
369
369
|
)
|
|
370
|
+
|
|
371
|
+
PRESSURE_LEVEL_VARIABLES = [
|
|
372
|
+
AirTemperature,
|
|
373
|
+
SpecificHumidity,
|
|
374
|
+
RelativeHumidity,
|
|
375
|
+
Geopotential,
|
|
376
|
+
GeopotentialHeight,
|
|
377
|
+
EastwardWind,
|
|
378
|
+
NorthwardWind,
|
|
379
|
+
VerticalVelocity,
|
|
380
|
+
MassFractionOfCloudLiquidWaterInAir,
|
|
381
|
+
MassFractionOfCloudIceInAir,
|
|
382
|
+
CloudAreaFractionInAtmosphereLayer,
|
|
383
|
+
]
|
|
384
|
+
|
|
385
|
+
SINGLE_LEVEL_VARIABLES = [SurfacePressure, TOANetDownwardShortwaveFlux, TOAOutgoingLongwaveFlux]
|
|
386
|
+
|
|
387
|
+
MET_VARIABLES = PRESSURE_LEVEL_VARIABLES + SINGLE_LEVEL_VARIABLES
|
|
@@ -22,8 +22,10 @@ import xarray as xr
|
|
|
22
22
|
from pycontrails.core.fleet import Fleet
|
|
23
23
|
from pycontrails.core.flight import Flight
|
|
24
24
|
from pycontrails.core.met import MetDataArray, MetDataset, MetVariable, originates_from_ecmwf
|
|
25
|
-
from pycontrails.core.met_var import SpecificHumidity
|
|
25
|
+
from pycontrails.core.met_var import MET_VARIABLES, SpecificHumidity
|
|
26
26
|
from pycontrails.core.vector import GeoVectorDataset
|
|
27
|
+
from pycontrails.datalib.ecmwf import ECMWF_VARIABLES
|
|
28
|
+
from pycontrails.datalib.gfs import GFS_VARIABLES
|
|
27
29
|
from pycontrails.utils.json import NumpyEncoder
|
|
28
30
|
from pycontrails.utils.types import type_guard
|
|
29
31
|
|
|
@@ -179,8 +181,10 @@ class Model(ABC):
|
|
|
179
181
|
|
|
180
182
|
#: Required meteorology pressure level variables.
|
|
181
183
|
#: Each element in the list is a :class:`MetVariable` or a ``tuple[MetVariable]``.
|
|
182
|
-
#: If element is a ``tuple[MetVariable]``, the variable depends on the data source
|
|
183
|
-
#:
|
|
184
|
+
#: If element is a ``tuple[MetVariable]``, the variable depends on the data source
|
|
185
|
+
#: and the tuple must include entries for a model-agnostic variable,
|
|
186
|
+
#: an ECMWF-specific variable, and a GFS-specific variable.
|
|
187
|
+
#: Only one of the three variable in the tuple is required for model evaluation.
|
|
184
188
|
met_variables: tuple[MetVariable | tuple[MetVariable, ...], ...]
|
|
185
189
|
|
|
186
190
|
#: Set of required parameters if processing already complete on ``met`` input.
|
|
@@ -276,6 +280,42 @@ class Model(ABC):
|
|
|
276
280
|
|
|
277
281
|
return hashlib.sha1(bytes(_hash, "utf-8")).hexdigest()
|
|
278
282
|
|
|
283
|
+
@classmethod
|
|
284
|
+
def generic_met_variables(cls) -> tuple[MetVariable, ...]:
|
|
285
|
+
"""Return a model-agnostic list of required meteorology variables.
|
|
286
|
+
|
|
287
|
+
Returns
|
|
288
|
+
-------
|
|
289
|
+
tuple[MetVariable]
|
|
290
|
+
List of model-agnostic variants of required variables
|
|
291
|
+
"""
|
|
292
|
+
available = set(MET_VARIABLES)
|
|
293
|
+
return tuple(_find_match(required, available) for required in cls.met_variables)
|
|
294
|
+
|
|
295
|
+
@classmethod
|
|
296
|
+
def ecmwf_met_variables(cls) -> tuple[MetVariable, ...]:
|
|
297
|
+
"""Return an ECMWF-specific list of required meteorology variables.
|
|
298
|
+
|
|
299
|
+
Returns
|
|
300
|
+
-------
|
|
301
|
+
tuple[MetVariable]
|
|
302
|
+
List of ECMWF-specific variants of required variables
|
|
303
|
+
"""
|
|
304
|
+
available = set(ECMWF_VARIABLES)
|
|
305
|
+
return tuple(_find_match(required, available) for required in cls.met_variables)
|
|
306
|
+
|
|
307
|
+
@classmethod
|
|
308
|
+
def gfs_met_variables(cls) -> tuple[MetVariable, ...]:
|
|
309
|
+
"""Return a GFS-specific list of required meteorology variables.
|
|
310
|
+
|
|
311
|
+
Returns
|
|
312
|
+
-------
|
|
313
|
+
tuple[MetVariable]
|
|
314
|
+
List of GFS-specific variants of required variables
|
|
315
|
+
"""
|
|
316
|
+
available = set(GFS_VARIABLES)
|
|
317
|
+
return tuple(_find_match(required, available) for required in cls.met_variables)
|
|
318
|
+
|
|
279
319
|
def _verify_met(self) -> None:
|
|
280
320
|
"""Verify integrity of :attr:`met`.
|
|
281
321
|
|
|
@@ -805,6 +845,42 @@ def _interp_grid_to_grid(
|
|
|
805
845
|
raise NotImplementedError(msg)
|
|
806
846
|
|
|
807
847
|
|
|
848
|
+
def _find_match(
|
|
849
|
+
required: MetVariable | Sequence[MetVariable], available: set[MetVariable]
|
|
850
|
+
) -> MetVariable:
|
|
851
|
+
"""Find match for required met variable in list of data-source-specific met variables.
|
|
852
|
+
|
|
853
|
+
Parameters
|
|
854
|
+
----------
|
|
855
|
+
required : MetVariable | Sequence[MetVariable]
|
|
856
|
+
Required met variable
|
|
857
|
+
|
|
858
|
+
available : Sequence[MetVariable]
|
|
859
|
+
Collection of data-source-specific met variables
|
|
860
|
+
|
|
861
|
+
Returns
|
|
862
|
+
-------
|
|
863
|
+
MetVariable
|
|
864
|
+
Match for required met variable in collection of data-source-specific met variables
|
|
865
|
+
|
|
866
|
+
Raises
|
|
867
|
+
------
|
|
868
|
+
KeyError
|
|
869
|
+
Raised if not match is found
|
|
870
|
+
"""
|
|
871
|
+
if isinstance(required, MetVariable):
|
|
872
|
+
return required
|
|
873
|
+
|
|
874
|
+
for var in required:
|
|
875
|
+
if var in available:
|
|
876
|
+
return var
|
|
877
|
+
|
|
878
|
+
required_keys = [v.standard_name for v in required]
|
|
879
|
+
available_keys = [v.standard_name for v in available]
|
|
880
|
+
msg = f"None of {required_keys} match variable in {available_keys}"
|
|
881
|
+
raise KeyError(msg)
|
|
882
|
+
|
|
883
|
+
|
|
808
884
|
def _raise_missing_met_var(var: MetVariable | Sequence[MetVariable]) -> NoReturn:
|
|
809
885
|
"""Raise KeyError on missing met variable.
|
|
810
886
|
|