Releases: contrailcirrus/pycontrails
v0.54.4
Features
-
Improve the
_altitude_interpolation
function used withinFlight.resample_and_fill
and ensure that it is consistent with the existing GAIA publication The function_altitude_interpolation
now accounts for various scenarios. For example:- Flight will automatically climb to an assumed cruise altitude if the first and next known waypoints are at very low altitudes with a large time gap.
- If there are large time gaps between known waypoints with a small altitude difference, then the flight will climb at the mid-point of the segment.
- If there are large time gaps and positive altitude difference, then the flight will climb at the start of its interpolation until the known cruising altitude and start its cruise phase.
- If there are large time gaps and negative altitude difference, then the flight will continue cruising and only starts to descend towards the end of the interpolation.
- If there is a shallow climb (ROCD < 500 ft/min), then always assume that the flight will climb at the next time step.
- If there is a shallow descent (-250 < ROCD < 0 ft/min), then always assume that the flight will descend at the final time step.
Conditions (3) to (6) is based on the logic that the aircraft will generally prefer to climb to a higher altitude as early as possible, and descend to a lower altitude as late as possible, because a higher altitude can reduce drag and fuel consumption.
Breaking changes
- Remove the optional input parameter
climb_descend_at_end
inFlight.resample_and_fill
. See the description of the new_altitude_interpolation
function for the rationale behind this change. - Remove the
copy
argument fromFleet.from_seq
. This argument was redundant and not used effectively in the implementation. TheFleet.from_seq
method always returns a copy of the input sequence.
Fixes
- Fix the
ERA5
interface when making a pressure-level request with a single pressure level. This change accommodates CDS-Beta server behavior. Previously, a ValueError was raised in this case. - Bypass the ValueError raised by
dask.array.gradient
when the input array is not correctly chunk along the level dimension. Previously,Cocip
would raise an error when computing tau cirrus in the case that themet
data had single chunks along the level dimension. - Fix the
CocipGrid
met downselection process to accommodate cases wheredt_integration
is as large as the time step of the met data. Previously, due to out-of-bounds interpolation, the output ofCocipGrid(met=met, rad=rad, dt_integration="1 hour")
was zero everywhere when themet
andrad
data had a time step of 1 hour. - By default, don't interpolate air temperature when running the
DryAdvection
model in a point-wise manner (no wind-shear simulation). - Use native python types (as opposed to
numpy
scalars) in thePSAircraftEngineParams
dataclass. - Ensure the
PSGrid
model maintains the precision of thesource
. Previously, float32 precision was lost per NEP 50. - Fix
Fleet.resample_and_fill
when the the "flight_id" field is included onFleet.data
(as opposed toFleet.fl_attrs
). Previously, this would raise a ValueError. - Use the supplied
nominal_rocd
parameter inFlight.resample_and_fill
rather thanconstants.nominal_rocd
(the default value of this parameter).
Internals
- Add new
AdvectionBuffers
dataclass to override the zero-like values used inModelParams
with the buffer previously used inCocipParams
. This is now a base class forCocipParams
andDryAdvectionParams
. In particular, theDryAdvection
now uses nonzero values for the met downselect buffers. - Change the order of advected points returned by
DryAdvection
to be consistent with the input order at each time step. - Add the
RUF
ruleset for linting and formatting the codebase. - Update type hints for
numpy
2.2 compatibility. Additional changes may be required after the next iteration of thenumpy
2.2 series. - Relax the tolerance passed into
scipy.optimize.newton
inps_nominal_grid
to avoid some convergence warnings. (These warnings were more distracting than informative.) - Remove the
_verify_altitude
check inFlight.resample_and_fill
. This was often triggered by a flight with corrupt waypoints (ie, independent from the logic inFlight.resample_and_fill
).
v0.54.3
Breaking changes
- Update the default load factor from 70% to 83% to be consistent with historical data. This is used whenever an aircraft performance model is run without a specified load factor.
- By default, the
CocipGrid.create_source
static method will return latitude values from -90 to 90 degrees. This change is motivated by the new advection scheme used near the poles. Previously, this method returned latitude values from -80 to 80 degrees.
Features
- Create new function
ps_grid.ps_nominal_optimize_mach
which computes the optimal mach number given a set of operating conditions. - Add a new
jet.aircraft_load_factor
function to estimate aircraft (passenger/cargo) load factor based on historical monthly and regional load factors provided by IATA. This improves upon the default load factor assumption. Historical load factor databases will be continuously updated as new data is released. - Use a 2D Cartesian-like plane to advect particles near the poles (>80° in latitude) to avoid numerical instabilities and singularities caused by convergence of meridians. This new advection scheme is used for contrail advection in the
Cocip
,CocipGrid
, andDryAdvection
models. See thegeo.advect_horizontal
function for more details.
Fixes
- Ensure the fuel type is preserved when calling
Flight.resample_and_fill
. - Update the CLIMaCCF dependency to pull the head of the main branch in CLIMaCCF. Update the installation instructions.
- Update the
ACCFParams.forecast_step
to None, which allows CLIMaCCF to automatically determine the forecast step based on themet
data. - Update the
ACCF
NOx parameter for the latest CLIMaCCF version. - Ensure a custom "horizontal_resolution" param passed into
ACCF
is not overwritten. - Remove duplicated variable in
ACCF.met_variables
. - Allow the
ACCF
model to accept relative humidity as a percentage or as a proportion. - Include
ecmwf.RelativeHumidity
inACCF.met_variables
so thatERA5(..., variables=ACCF.met_variables)
no longer raises an error.
Internals
- Improve computation of mach limits to accept vectorized input/output.
- Test against python 3.13 in the GitHub Actions CI. Use python 3.13 in the docs and doctest workflows.
- Publish to PyPI using trusted publishing.
- Update
pycontrails-bada
installation instructions. Installpycontrails-bada
from GCP artifact repository in the test workflow. - Floor the pycontrails version when running the docs workflow. This ensures that the hosted documentation references the last stable release.
- Update literature and bibliography in the documentation.
- Move the
engine_deterioration_factor
fromPSFlightParams
toAircraftPerformanceParams
so it can be used by both the PS model and BADA. - Include
engine_deterioration_factor
inAircraftPerformanceGridParams
.
v0.54.2
Features
- Add
cache_download
parameter to theGFSForecast
interface. When set toTrue
, downloaded grib data is cached locally. This is consistent with the behavior of theERA5ModelLevel
andHRESModelLevel
interfaces.
Fixes
- Update GFS variable names "uswrf" -> "suswrf" and "ulwrf" -> "sulwrf". This accommodates a breaking change introduced in eccodes 2.38.
Internals
- Remove
overrides
dependency. Requiretyping-extensions
for python < 3.12. - Upgrade some type hints for more modern python language features.
v0.54.1
Features
- Add CoCiP Grid notebook example to documentation.
- Implement
PSFlight.eval
on aFleet
source.
Breaking changes
- Remove
attrs["crs"]
usage fromGeoVectorDataset
and child classes (Flight
,Fleet
). All spatial data is assumed to be EPSG:4326 (WGS84). This was previously assumed implicitly, but now thecrs
attribute is removed from theattrs
dictionary. - Change the return type of
GeoVectorDataset.transform_crs
to a pair of numpy arrays representingx
andy
coordinates in the target CRS. - Remove deprecated
MetDataset.variables
property in favor ofMetDataset.indexes
. - Remove
**kwargs
inMetDataArray
constructor. - Rename
ARCOERA5
toERA5ARCO
for consistency with theERA5
andERA5ModelLevel
interfaces.
Fixes
- Fix the integration time step in
CocipGrid.calc_evolve_one_step
. The previous implementation assumed a time interval ofparams["dt_integration"]
. This may not be the case for allsource
parameters (for example, this could occur if runningCocipGrid
over a collection of ADS-B waypoints). - Raise an exception in constructing
MetDataset(ds, copy=False)
whends["level"]
has float32 dtype. Per interpolation conventions, all coordinate variables must have float64 dtype. (This was previously enforced in longitude and latitude, but was overlooked in the level coordinate.) - Allow
AircraftPerformance.ensure_true_airspeed_on_source
to useeastward_wind
andnorthward_wind
fields on thesource
if available. This is useful when thesource
has already been interpolated to met data.
v0.54.0
Features
-
Perform model-level to pressure-level conversion in-house instead of relying on
metview
. This update has several advantages:- The
ARCOERA5
andERA5ModelLevel
interfaces no longer requiremetview
to be installed. Similarly, grib files and the associated tooling can also largely be avoided. - The computation is performed using
xarray
anddask
tooling, which means the result can be computed lazily if desired. - The computation is defined using
numpy
operations (some of which release the GIL) and can be parallelized using threading throughdask
(this is the default behavior). - The computation is generally a bit faster than the
metview
implementation (this depends on the exact chunking of the model level meteorology data). This chunking can be tuned by the user to optimize runtime performance or memory usage.
See the
ml_to_pl
function for low-level details. - The
-
Update the
ARCOERA5
andERA5ModelLevel
interfaces to use the new model-level to pressure-level conversion. The ERA5 model level data is now downloaded as the netcdf format instead of grib. This format change decreases the download size.
Breaking changes
- Rename
levels
->model_levels
in theARCOERA5
andERA5ModelLevel
constructors. Renamecache_grib
->cache_download
. - Rename
pressure_levels_at_model_levels
->model_level_reference_pressure
. Add a newmodel_level_pressure
method that requires surface pressure data.
Fixes
- Update
ERA5ModelLevel
for the new CDS-Beta server.
Internals
- Use
ruff
to format the codebase in place ofblack
. - Run
ruff
linting and formatting over the notebook examples in the documentation. - Update development documentation with new links.
v0.53.1
v0.53.0
Breaking changes
- Drop python 3.9 support per NEP 29.
Features
- Build wheels for python 3.13. (These wheels are available on PyPI, but other pycontrails dependencies may not yet support python 3.13.)
Fixes
- Fix
PycontrailsRegularGridInterpolator
for compatibility with the latest scipy version.
Internals
- Defer import of
skimage
andrasterio
.
v0.52.3
Features
- Add experimental
preprocess_lowmem
parameter toCocip
. When set toTrue
,Cocip
will attempt to reduce memory consumption during flight preprocessing and initial formation/persistence calculations by using an alternate implementation ofMetDataArray.interpolate
(see below). - Add
lowmem
keyword-only argument toMetDataArray.interpolate
. WhenTrue
, attempt to reduce memory consumption by using an alternative interpolation strategy that loads at most two time steps of meteorology data into memory at a time.
Fixes
- Defer import of
matplotlib
inmodels.cocip.output_formats
. - Fix bug in
PycontrailsRegularGridInterpolator
that caused errors when dispatching to 1-d linear interpolation from inrgi_cython.pyx
.
Internals
- Implement low-memory paths in
Cocip.eval
andMetDataArray.interpolate
.
v0.52.2
Breaking changes
- Flight antimeridian crossings are now detected based on individual flight segments rather than minimum and maximum longitude values. This allows for correct detection of antimeridian crossings for flights that span more than 180 degrees longitude, and may change the output of
Flight.resample_and_fill
for such flights.
Features
- Add experimental
fill_low_alt_with_isa_temperature
parameter on theAircraftPerformance
base class. When set toTrue
, aircraft performance models withFlight
sources will fill points below the lowest altitude in themet["air_temperature]
data with the ISA temperature. This is useful when the met data does not extend to the surface. In this case, we can still estimate fuel flow and other performance metrics through the entire climb phase. By default, this parameter is set toFalse
. - Add experimental
fill_low_altitude_with_zero_wind
parameter on theAircraftPerformance
base class. When set toTrue
, aircraft performance models will estimate the true airspeed at low altitudes by assuming the wind speed is zero. - Add convenience
Flight.plot_profile
method.
Fixes
- Fix missing
Fuel Flow Idle (kg/sec)
value in the1ZM001
engine in theedb-gaseous-v29b-engines.csv
. - Fix the
step_threshold
inFlight._altitude_interpolation
. This correction is only relevant when passing in a non-default value forfreq
inFlight.resample_and_fill
. - Fix the
VectorDataset.__eq__
method to check for the same keys. Previously, if the other dataset had a superset of the instance keys, the method may still returnTrue
. - Fix minor bug in
cocip.output_formats.radiation_time_slice_statistics
in which the function previously threw an error ift_end
did not directly align with the time index in therad
dataset. - Remove the residual constraint in
cocip.output_formats.contrails_to_hi_res_grid
used during debugging. - Improve detection of antimeridian crossings for flights that span more than 180 degrees longitude.
Internals
- Improve the runtime performance of
Fleet.to_flight_list
. For a largeFleet
, this method is now 5x faster. - Improve the runtime performance and memory footprint of
Cocip._bundle_results
. When runningCocip
with a largeFleet
source,Cocip.eval
is now slightly faster and uses much less memory.
v0.52.1
Breaking changes
- Remove
lock=False
as a default keyword argument toxr.open_mfdataset
in theMetDataSource.open_dataset
method. This reverts a change from v0.44.1 and prevents segmentation faults when using recent versions of netCDF4 (1.7.0 and above). - GOES imagery is now loaded from a temporary file on disk rather than directly from memory when using
GOES.get
without a cachestore.
Internals
- Remove upper limits on netCDF4 and numpy versions.
- Remove h5netcdf dependency.
- Update doctests with numpy 2 scalar representation (see NEP 51). Doctests will now fail when run with numpy 1.
- Run certain tests in
test_ecmwf.py
andtest_met.py
using the single-threaded dask scheduler to prevent tests from hanging while waiting for a lock that is never released. (This issue was encountered previously, and removinglock=False
inMetDataSource.open_dataset
reverts the fix.) - Document pycontrails installation from conda-forge.
Fixes
- Ensure the
MetDataset
vertical coordinates"air_pressure"
and"altitude"
have the correct dtype.