Skip to content

Releases: contrailcirrus/pycontrails

v0.54.4

13 Dec 05:38
Compare
Choose a tag to compare

Features

  • Improve the _altitude_interpolation function used within Flight.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:

    1. 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.
    2. 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.
    3. 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.
    4. 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.
    5. If there is a shallow climb (ROCD < 500 ft/min), then always assume that the flight will climb at the next time step.
    6. 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 in Flight.resample_and_fill. See the description of the new _altitude_interpolation function for the rationale behind this change.
  • Remove the copy argument from Fleet.from_seq. This argument was redundant and not used effectively in the implementation. The Fleet.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 the met data had single chunks along the level dimension.
  • Fix the CocipGrid met downselection process to accommodate cases where dt_integration is as large as the time step of the met data. Previously, due to out-of-bounds interpolation, the output of CocipGrid(met=met, rad=rad, dt_integration="1 hour") was zero everywhere when the met and rad 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 the PSAircraftEngineParams dataclass.
  • Ensure the PSGrid model maintains the precision of the source. Previously, float32 precision was lost per NEP 50.
  • Fix Fleet.resample_and_fill when the the "flight_id" field is included on Fleet.data (as opposed to Fleet.fl_attrs). Previously, this would raise a ValueError.
  • Use the supplied nominal_rocd parameter in Flight.resample_and_fill rather than constants.nominal_rocd (the default value of this parameter).

Internals

  • Add new AdvectionBuffers dataclass to override the zero-like values used in ModelParams with the buffer previously used in CocipParams. This is now a base class for CocipParams and DryAdvectionParams. In particular, the DryAdvection 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 the numpy 2.2 series.
  • Relax the tolerance passed into scipy.optimize.newton in ps_nominal_grid to avoid some convergence warnings. (These warnings were more distracting than informative.)
  • Remove the _verify_altitude check in Flight.resample_and_fill. This was often triggered by a flight with corrupt waypoints (ie, independent from the logic in Flight.resample_and_fill).

v0.54.3

21 Nov 21:43
Compare
Choose a tag to compare

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, and DryAdvection models. See the geo.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 the met 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 in ACCF.met_variables so that ERA5(..., 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. Install pycontrails-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 from PSFlightParams to AircraftPerformanceParams so it can be used by both the PS model and BADA.
  • Include engine_deterioration_factor in AircraftPerformanceGridParams.

v0.54.2

16 Oct 12:49
Compare
Choose a tag to compare

Features

  • Add cache_download parameter to the GFSForecast interface. When set to True, downloaded grib data is cached locally. This is consistent with the behavior of the ERA5ModelLevel and HRESModelLevel 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. Require typing-extensions for python < 3.12.
  • Upgrade some type hints for more modern python language features.

v0.54.1

08 Oct 20:45
Compare
Choose a tag to compare

Features

Breaking changes

  • Remove attrs["crs"] usage from GeoVectorDataset and child classes (Flight, Fleet). All spatial data is assumed to be EPSG:4326 (WGS84). This was previously assumed implicitly, but now the crs attribute is removed from the attrs dictionary.
  • Change the return type of GeoVectorDataset.transform_crs to a pair of numpy arrays representing x and y coordinates in the target CRS.
  • Remove deprecated MetDataset.variables property in favor of MetDataset.indexes.
  • Remove **kwargs in MetDataArray constructor.
  • Rename ARCOERA5 to ERA5ARCO for consistency with the ERA5 and ERA5ModelLevel interfaces.

Fixes

  • Fix the integration time step in CocipGrid.calc_evolve_one_step. The previous implementation assumed a time interval of params["dt_integration"]. This may not be the case for all source parameters (for example, this could occur if running CocipGrid over a collection of ADS-B waypoints).
  • Raise an exception in constructing MetDataset(ds, copy=False) when ds["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 use eastward_wind and northward_wind fields on the source if available. This is useful when the source has already been interpolated to met data.

v0.54.0

16 Sep 22:30
Compare
Choose a tag to compare

Features

  • Perform model-level to pressure-level conversion in-house instead of relying on metview. This update has several advantages:

    • The ARCOERA5 and ERA5ModelLevel interfaces no longer require metview to be installed. Similarly, grib files and the associated tooling can also largely be avoided.
    • The computation is performed using xarray and dask 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 through dask (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.

  • Update the ARCOERA5 and ERA5ModelLevel 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 the ARCOERA5 and ERA5ModelLevel constructors. Rename cache_grib -> cache_download.
  • Rename pressure_levels_at_model_levels -> model_level_reference_pressure. Add a new model_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 of black.
  • Run ruff linting and formatting over the notebook examples in the documentation.
  • Update development documentation with new links.

v0.53.1

21 Aug 19:03
Compare
Choose a tag to compare

Features

  • Support ERA5 downloads from CDS-Beta. The updated interface is backwards compatible with the legacy CDS server. The choice of CDS server is governed by the url parameter in the ERA5 constructor.

v0.53.0

13 Aug 22:02
Compare
Choose a tag to compare

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 and rasterio.

v0.52.3

08 Aug 16:18
7a3729d
Compare
Choose a tag to compare

Features

  • Add experimental preprocess_lowmem parameter to Cocip. When set to True, Cocip will attempt to reduce memory consumption during flight preprocessing and initial formation/persistence calculations by using an alternate implementation of MetDataArray.interpolate (see below).
  • Add lowmem keyword-only argument to MetDataArray.interpolate. When True, 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 in models.cocip.output_formats.
  • Fix bug in PycontrailsRegularGridInterpolator that caused errors when dispatching to 1-d linear interpolation from in rgi_cython.pyx.

Internals

  • Implement low-memory paths in Cocip.eval and MetDataArray.interpolate.

v0.52.2

01 Aug 14:39
dd9b453
Compare
Choose a tag to compare

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 the AircraftPerformance base class. When set to True, aircraft performance models with Flight sources will fill points below the lowest altitude in the met["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 to False.
  • Add experimental fill_low_altitude_with_zero_wind parameter on the AircraftPerformance base class. When set to True, 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 the 1ZM001 engine in the edb-gaseous-v29b-engines.csv.
  • Fix the step_threshold in Flight._altitude_interpolation. This correction is only relevant when passing in a non-default value for freq in Flight.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 return True.
  • Fix minor bug in cocip.output_formats.radiation_time_slice_statistics in which the function previously threw an error if t_end did not directly align with the time index in the rad 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 large Fleet, this method is now 5x faster.
  • Improve the runtime performance and memory footprint of Cocip._bundle_results. When running Cocip with a large Fleet source, Cocip.eval is now slightly faster and uses much less memory.

v0.52.1

08 Jul 18:01
Compare
Choose a tag to compare

Breaking changes

  • Remove lock=False as a default keyword argument to xr.open_mfdataset in the MetDataSource.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 and test_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 removing lock=False in MetDataSource.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.