Release Notes
This is the list of changes to RUBEM between each release. For full details, see the commit logs on the Github page.
For a list of known issues and their fixes, visit the Github issues page.
Unreleased
The format follows Keep a Changelog.
Added
Added
rubem calibrate: a differential evolution (SciPy) over the free calibration parameters, withw3derived from the other two weights, minimizing1000 (100 (1 - NSE))^2on the station series of one output variable (arnby default) against an observed series given in the table layout of the model’s time series or as a PCRaster time series with its header. Negative,-9999and PCRaster missing values are gaps; a spin-up window, per-run bounds (--bound), fixed parameters (--fix), the stations of the objective (--stations) and the initialization, strategy and polishing of the search are options. Every candidate runs in a fresh spawned worker through the Python API, and the run directory receivesobserved.csv,evaluations.csv,stations.csv,best_<variable>.csv,result.jsonand<config>-calibrated.json, with progress lines on the terminal. SciPy comes with the optional extrarubem[calibration]. The calibration page of the documentation describes the method, the evaluation budget, the fixed drainage network a calibration onarnneeds and the process model; adatasetpytest marker with theRUBEM_DATASET_DIRconvention carries a smoke test on the Ipojuca basin (#343).Added
rubem run --allow-blocking-problems, which runs the model even when the input validation finds blocking problems: the same checks run, every problem is still reported (the non-blocking ones as warnings, the blocking ones as errors, followed by one error line stating that the simulation continues despite them) and the run goes on instead of stopping with exit code 1. The option cannot be combined with-s, which skips the checks it reports (usage error, exit code 2), and the deprecatedrubem -c <config>spelling does not take it.ModelConfiguration(..., allow_blocking_problems=False)is the library counterpart and keeps the full list inModelConfiguration.problems;Model.from_fileandModel.from_configofrubem.apitake the same keyword and an isolated run rebuilds the configuration with it.rubem calibrate --allow-blocking-problems, andCalibrationSettings(allow_blocking_problems=True), do the same for a calibration, whose inputs are validated once before the search and never again by the workers; the value is recorded undersettingsinresult.json, since the parameters it reports were fitted on inputs the validation rejected (#352).Added
rubem.api, the public Python surface:Model.from_fileandModel.from_configload a configuration file or document,Model.run()runs the simulation in the current process andModel.run_isolated()in a fresh spawned subprocess, both returning aRunResultthat lists the rasters, time series and metadata the run wrote, enumerated from the configuration. Importing the module needs neither PCRaster nor GDAL; running without them raisesImportErrorwith the installation guidance.ConfigurationErrornow survives pickling with its problems (#341). The Python API page documents the stability policy, the process model and how to run in parallel.Added
rubem preprocess kp, which builds the Class A pan coefficient series from wind speed and relative humidity raster series and a fetch distance with the formula of the published model (supplement S29), through the shared raster I/O of the preprocessing tools; a member with a non-positive coefficient refuses the whole run, cells above the configuredkprange are warned about. The model’sget_pan_coef_et_open_water_areanow delegates to the same implementation (#330).Added the comparison of
GRID.grid(raster_info.grid_size) with the pixel size of the clone when the reference coordinate reference system is projected: the linear unit is converted to metres and a relative difference above1e-6on either axis blocks the run; a geographic or absent system leaves the declared value as given and logs the raster resolution (skipped with-s; #329). The user guide states thatgridis the metric cell size the user asserts.Added the
paperconformity tests (tests/paper, markerpaper): equation tests of the process functions against the journal supplement (S3, S5 to S20 and S22 to S33), model-level tests of the rules the model applies inline (open water, impervious and saturated cells, total and routed discharge, crop coefficient threshold) and an independent float64 reference of one monthly step compared cell by cell with the model on the synthetic dataset (#332).Added the validation of the weighted runoff coefficient domain
C_wp <= 1: for every pair of a land use class and a soil class the slope-free part of the coefficient is computed from the Manning roughness, the wilting point, the impervious and open water fractions and the weightsw1,w2andw3; a pair at or above 1 blocks the run, a pair that only the slope term can push above 1 is reported with the slope threshold, and a wilting point at or above 1 blocks (skipped with-s; #328). The user guide states the domain next to the weights.Added the optional
RASTERS.georeferenceraster whose coordinate reference system is written to the GeoTIFF outputs; the clone and the georeference must share the DEM geometry, rotated grids are refused when PCRaster maps are written, and a GeoTIFF that cannot be written is removed instead of being left half-written.Added content validation of the inputs (skipped with
-s): lookup tables must parse,dg,Zr,Tsat,manningand the rainy days must be positive, the rainy days must cover the twelve months,Tcc > Twfor every class;kpmust be positive and NDVI below 1 in every cell,ndvi_max > ndvi_minper cell, sample identifiers contiguous from 1; the precipitation, ETP and Kp series must cover every simulated step and the NDVI and land use series the first one. Blocking problems raiseConfigurationError;kc_max < kc_min, later NDVI/land use gaps and area fractions not adding up to 1 are reported as warnings.Added
ModelConfigurationFile, the legacy JSON file as a validated model: the spellings found in circulating files are accepted as aliases (K_sat,T_ini,w1,kcmin, …), unknown keys are reported and ignored, duplicated keys are reported (the last value still wins), and relative paths are anchored on the directory of the JSON file (ModelConfiguration.load(path)) or on an explicitbase_dir.Added the model of configuration file format 1.0 (
ModelConfigurationFileV1: strict keys,version,metadata, ISOsimulation_period, the dated, monthly and directory raster series specifications,model_simulation_outputwith per-format selections) and its conversions from and to the legacy file. The format is not yet read by the loader nor exposed on the command line.Resolved the raster series to one path per step through resolvers (directory, dated and monthly series;
MissingStepmarkers instead of exceptions), used by the model for every series; the legacy directory series resolve to the same PCRaster file names as before.Activated configuration format 1.0: a file with
versionis read as such (strict keys, duplicated keys rejected), raster series and time series are selected independently with their formats (CSV converts the.tssfiles, PCRasterTSS keeps them, both do both),metadata.jsonis written next to the outputs,rubem config schemaprints the 1.0 schema by default andrubem config migrateconverts a legacy file (paths rebased onto the destination, atomic write,--forceto overwrite).Started the preprocessing overhaul:
rubem preprocesssub-command (infodescribes a raster), shared raster I/O with explicit contracts (atomic writes, natural ordering, geometry checks, collision detection, all-no-data policy,manifest.csv), and the legacy scripts no longer run at import time.Added
rubem preprocess tif2map,tif2mapseriesandmapseries2tif(rubem.preprocessing.conversions): value scale by option, natural file order, PCRaster 8.3 naming, geometry checks against a clone, no-data policy, georeference for the GeoTIFF outputs; the legacy modulestif2map,tif2pcrtssandpcrtss2tifare deprecated.Added
rubem preprocess minmax(rubem.preprocessing.minmax_series): per-cell minimum and maximum of a raster series ignoring missing cells, with the geometry checked across the series; the legacyminmaxmodule is deprecated.Added
rubem preprocess krige(rubem.preprocessing.kriging_series, optionalrubem[preprocessing]extra): ordinary kriging of station series onto the clone grid, one map per step, reading the legacy matrix layout or a longstep;id;x;y;valuelayout, with the negative-value policy (clamp by default), the kriging metric derived from the clone’s coordinate reference system and the variogram settings; the legacykrigingmodule is deprecated.Accepted GeoTIFF input rasters and series (
.tif/.tiff): rasters are read through GDAL onto the clone grid, a GeoTIFF clone sets the grid through its geometry, GeoTIFF series members are named like the model outputs, sample locations may be a GeoTIFF, and every input raster must share the clone geometry and coordinate reference system.Added the spatial aggregation of the time series in configuration format 1.0 (
time_series_samples.aggregation):point(as before),subcatchment(the catchment upstream of each sample over the LDD) andzones(arasters.zonesraster, ids remapped to1..Nand recorded inzones_mapping.csv); non-point tables are namedtss_<variable>_<aggregation>.Added the optional
lai_maxlookup table (TABLES.lai_max, format 1.0lookup_tables.lai_max) with the maximum leaf area index of each land use class, selected by the constantlai_max_from_table(defaultfalse: thelai_maxconstant is used as before). When read, the table must be positive, at most the admissible maximum of the constant and keyed by the classes of the area fraction tables (skipped with-s); the switch without a table blocks the run even with-s, and a table without the switch is reported as ignored (#353).
Changed
The model overview states, next to the equations they modify, the six rules the model applies beyond the published formulation and confirmed by the model authors: the zero floor of the root zone storage, the saturated root zone of open water cells, the saturation-excess runoff
SR = P - I, the cap of the open water evapotranspiration at the precipitation and the zero floor of the open water runoff, the constant impervious evapotranspirationi_imp(1 to 3 mm), and the domainskp > 0and0 <= C_wp <= 1(#331).The station time series the model keeps as PCRaster
.tssfiles carry the PCRaster header (title, number of columns,timestepline and one line per station id), so PCRaster’s own tools read them; the CSV conversion reads the header, refuses a file without it or whose ids differ from the configured stations, and converts the data rows only, leaving the CSV tables unchanged (#347).The impervious area interception
i_impmust lie between 1 and 3 mm, the range of the published formulation (#327); the model overview and the user guide state the same range.Packaged RUBEM with
pyproject.toml:pip installsupport, therubemconsole script and a single PEP 440 version source.Stated the license expression consistently as
GPL-3.0-or-later(the source headers’ “version 3 or any later version”) inCITATION.cff, the README and the FAQ; the license itself is unchanged.Rebuilt the CI (lint, OS/Python matrix, documentation build, packaging smokes) and updated the documentation build mechanics.
Enabled time series per output variable and made the CSV conversion transactional over the run’s own
.tssfiles.Gave
rubem.cli.mainan argument list parameter, removed the PyInstaller launcher module, and made the GeoTIFF writer reject unsupported formats. Run the model withrubemorpython -m rubem; executing the package directory as a script (python rubem) is no longer supported.Moved the package to
pathlib(enforced by ruff’sPTHandUPrules); every public path parameter acceptsstroros.PathLike, andbytespaths are deprecated (accepted with aDeprecationWarningfor one minor release).Rebuilt the configuration value objects (
SimulationPeriod,RasterGrid,CalibrationParameters,InitialSoilConditions,ModelConstants) as frozen Pydantic models with the same keywords, attributes and messages;pydanticis now a runtime dependency. New checks: the grid size must be finite with a finite square, the FPAR bounds must satisfy0 < min < max < 1andlai_maxmust be positive.Rebuilt the output configuration objects as Pydantic models:
OutputVariablesholdsOutputVariableobjects (attribute access; the dictionary-styleget()is deprecated),OutputDataDirectorycreates the directory inensure_exists()rather than on construction, andOutputRasterBase.from_file()reads the geometry.Rebuilt the input file objects (
InputRasterFiles,InputRasterSeries,InputTableFiles) as frozen Pydantic models with the same keywords, attributes and exceptions; validation problems areProblemobjects andConfigurationErrorcarries the blocking ones.Rebuilt the application settings as a plain Pydantic model (
AppSettings.default()selects thePYTHON_ENVIRONMENTfile at call time; the ranges singleton is gone) and made the command line report an invalid configuration with its message instead of a traceback.Moved the command line to Typer:
rubem run -c <config> [-s]runs a simulation andrubem config schema --format legacyprints the JSON Schema of the configuration file;rubem -c <config>still works for one minor release with a deprecation warning.typeris a runtime dependency.Hardened the supply chain: every GitHub Action is pinned to a commit SHA and checked by a blocking
workflow-lintjob (actionlint, zizmor, pin check); checkouts no longer persist credentials; an OpenSSF Scorecard workflow publishes its results; releases are signed with Sigstore, carry a build provenance attestation, a CycloneDX SBOM of the published wheel and the conda inventory of the byte-exact environment.Wrote
metadata.jsononly after a successful format 1.0 run instead of while loading the configuration, made everyGENERATE_FILEflag required again in the legacy file (as before the Pydantic rewrite), and restrictedrubem preprocess krige --variogram-modeltospherical,exponentialandgaussian, the models the variogram fit and the interpolation share.
Fixed
Fixed the regression test oracle (corrected fixture inputs, structured comparators, byte-exact reproduction on a frozen environment).
Stopped changing the process working directory during a run; time series and raster outputs are addressed by absolute paths.
Exported time series only after a successful run, replaced library
print()calls with log records, and fixed the output summary flags.Failed clearly when the first NDVI or land-use raster cannot be read.
Honoured
RASTER_FILE_FORMAT.map_raster_series(PCRaster maps can now be disabled; a configuration with output variables but no raster format is rejected), added the optionalRASTER_FILE_FORMAT.no_data_valuefor the GeoTIFF series (default-9999), and matched raster series file names with the prefix taken literally.Corrected the spelling of
Interception.get_reflectances_simple_ratio,soil_moisture_content_wilting_pointand therubem.file._file_conversionsmodule; the old names still work for one minor release and emit aDeprecationWarning.Closed the validation gaps found in review: no-data values must fit a Float32 band, format 1.0 dates must be ISO strings, dated raster ranges are compared by month and sorted before the overlap check, lookup tables must have one key column with numeric interval bounds,
ndvi_maxcells equal to 1 are rejected, the blocking content rules only apply to the simulated window, the legacy file accepts the documentedKp,K_c_minandK_c_maxspellings, path-like values and rejects two spellings of one key, the legacy JSON schema advertises theDD/MM/YYYYdates, nested output variables agree withtssand their field, relative series directories are frozen at construction, a time-series-only configuration is no longer reported as producing no output, and the cached application settings are read-only.Reported a
ValueErrorraised by the run or by the CSV export as an unexpected failure (with its traceback) instead of an invalid configuration, gaverubem preprocess infothe same error handling as the other subcommands, and normalisedbytesand bytes-valued path-like inputs inas_path()andtss2csv().Preprocessing: directional maps keep fractional values, south-up or mirrored geometries are refused, geometry checks compare the coordinate reference system,
mapseries2tifchecks the geometry without a georeference and promotes the band type when the no-data value does not fit the source type, a stalemanifest.csvor skipped member never survives a rerun,minmaxrefuses identical output paths, and kriging fits the variogram with the great-circle distance on geographic coordinates, rejects non-finite station cells and stations sharing a coordinate.GeoTIFF inputs:
.mapLDD rasters are converted withpcr.lddagain, series members are checked against the clone’s coordinate reference system, members are found regardless of the extension case, flipped clone transforms are refused, sample and zone identifiers must fit a 32-bit integer, and the point-sampling field is released once the writers hold the file path.CI: the Scorecard job reads the repository again, the release SBOM is generated from an environment holding only the wheel, the pre-commit file hooks run in the lint job, and
.editorconfigleaves the PCRaster series members alone.CI: pushes to
mainno longer cancel each other (one concurrency group per commit; pull request runs still supersede each other), and the Codecov statuses carry explicit thresholds (codecov.yml: the project value may move by 0.5%, the patch status is informational; the hard gate stays pytest-cov’sfail_under).Outputs and inputs: a GeoTIFF output whose valid cell equals the no-data value fails the run instead of reading back as missing, a categorical GeoTIFF input (soil, land use, LDD, samples, zones) with a non-integer value or one outside the 32-bit integer range is refused at validation and at read time instead of being rounded or wrapped, a valid
Falsecell of a boolean GeoTIFF is no longer read as missing, and the.tssto CSV conversion checks the column count of every data row.Preprocessing:
minmaxwrites the common type of the series’ bands (Float64 sources no longer overflow toinfin a Float32 output), kriging removes a stalemanifest.csvbefore writing, and the unused--seedoption ofrubem preprocess krigeis gone (nothing in the kriging path draws random numbers, and it reseeded the process’s global NumPy generator).Configuration: the
loggingsettings of the cachedAppSettingsare read-only all the way down (get_settingandmodel_dumphand out plain copies), and the per-variable output flags follow Pydantic’s bool parsing ("false"disables a variable instead of enabling it; an unparsable string is rejected).Interception: positive monthly precipitation reaches the denominator of the interception-rate equation unchanged; the
1e-5guard against a zero precipitation was being added to every value (#319). The golden fixtures were regenerated (seetests/fixtures/AUDIT.md).Evapotranspiration: a cell whose NDVI equals
1.1 * NDVI_mintakes thekc_minbranch of the crop coefficient, as documented, instead of a crop coefficient of zero (#320). The reference dataset has no cell on the threshold, so the golden fixtures are unchanged.Baseflow: the recession baseflow is limited to the water available in the saturated zone (
TU_Sof the previous step plus the recharge), so the saturated-zone storage can no longer become negative (#322).
Removed
Replaced the PyInstaller bundles with sdist/wheel distributions verified by the release pipeline.
Version 0.9.0-beta.3
Date: Mar 21, 2024
@soaressgabriel Fix unsuccessful execution without station locations map (#123);
@soaressgabriel Implement a configuration system within the application that can handle multiple formats (#103);
@soaressgabriel Fix error in the description of the series of rasters resulting from the model simulation (#129);
@soaressgabriel Rename “Total Runoff” resulting raster series to “Accumulated Total Runoff” (#130);
@soaressgabriel Remove unused input directory specification from doc pages (#134);
@soaressgabriel [tests] Add integration test for Sphinx documentation build (#136);
@soaressgabriel [tests] Migrate tests from unittest to pytest (#137);
@soaressgabriel Add validation rules for input rasters (#111);
@dependabot [actions] Bump actions/checkout from 2 to 4 (#138);
@dependabot [actions] Bump github/codeql-action from 1 to 3 (#139);
@dependabot [actions] Bump actions/setup-python from 2 to 5 (#140);
@dependabot [actions] Bump conda-incubator/setup-miniconda from 2 to 3 (#141);
@dependabot [actions] Bump actions/stale from 3 to 9 (#142);
@dependabot [actions] Bump codecov/codecov-action from 2 to 4 (#143);
@soaressgabriel [doc] Add Zenodo DOI badges to README and documentation (#145);
@soaressgabriel Add optional specification of a LDD raster in the model simulation configuration (#132);
@soaressgabriel Make timespans human-readable (#148);
@soaressgabriel Fix checking for files in the output directory when it doesn’t exist (#149);
@soaressgabriel [readthedocs] Fix Read the Docs Sphinx build (#152);
@soaressgabriel Wrap PCRaster’s raster file, raster series and lookup table reading functions (#153);
@soaressgabriel Remove DEM raster (GeoTIFF) from simulation configuration and model report (#154);
@soaressgabriel Make sample points raster in model simulation configuration optional (#150);
@soaressgabriel Enable export of the resulting Total Runoff (RNF) raster series and time series (#147);
@soaressgabriel [doc] Update Code of Conduct links (#160);
@soaressgabriel [doc] Update README with latest information and links to doc (#161);
@soaressgabriel [doc] Update copyright information in LICENSE file (#162);
@soaressgabriel [doc] Use Citation File Format CITATION.cff instead of BibTeX entries (#164);
@soaressgabriel Configure logging settings based on a configuration file (#156);
@soaressgabriel Rename modules to hydrological_processes and update imports (#165);
@dependabot [actions] Bump softprops/action-gh-release from 1 to 2 (#168);
@soaressgabriel Refactor codebase and adopt common conventions of open source Python projects (#167);
@soaressgabriel [readthedocs] Update build os and Python versions in .readthedocs.yaml (#177);
@soaressgabriel [readthedocs] Fix Read the Docs Sphinx build II (#175);
@soaressgabriel Implement Relative import for source files within model directory (#172);
@soaressgabriel Add check if selected GDAL driver is available before using it (#173);
@soaressgabriel Implement start date alignment for input raster series (#178);
@soaressgabriel [actions] Update build release workflow (#185);
@soaressgabriel Improve handling of file paths for absolute paths internally (#187);
@soaressgabriel [actions] Fix file paths in build-release.yml (#188);
@soaressgabriel [actions] Fix zip file path in build-release workflow (#189);
@soaressgabriel [actions] Update hash computation command in build-release.yml (#190);
Version 0.2.3-beta.2
Date: Jan 24, 2024
@soaressgabriel: Fix error in the implementation of the Total Discharge equation (#106);
Version 0.2.2-beta.1
Date: May 17, 2023
@soaressgabriel: Add Paraíba do Sul dataset (#86);
@soaressgabriel: Update ‘Initial Soil Conditions’ subsection of the ‘Soil Parameters’ section of the user guide (#88);
@soaressgabriel: Update citation information (#90);
@soaressgabriel: Add missing information about conditions in the mathematical formulation of the model (#92);
@soaressgabriel: Update Sphinx documentation settings and packages (#82);
@soaressgabriel: Incorporate RuntimeError exception handling and logging in file reading operations (#98);
@soaressgabriel: Implement GitHub Actions Workflow for Building and Releasing Application (#99);
@soaressgabriel: Update of Issue and Pull Request Templates (#101);
Version 0.1.3-alpha
Date: March 23, 2022
@soaressgabriel: Fix errors and inconsistencies in doc pages (#82);
@soaressgabriel: Update copyright strings (#81);
@soaressgabriel: Replace download links for the datasets (#80);
Version 0.1.0-alpha
Date: November 23, 2021
@soaressgabriel: Update module doc string (#27);
@soaressgabriel: Add usage of configuration file via CLI (#6);
@soaressgabriel: Add reportMapSeries function (#29);
@soaressgabriel: Add user help documentation (#60);
@soaressgabriel: Add bug issue, feature request issue and pull request templates (#67);
@soaressgabriel: Add export format configuration (#31);
@soaressgabriel: Add dynamic readout of land use map-series files (#30);
@soaressgabriel: Add check if genTss files is enabled (#50);
@LINAMARIAOSORIO: Add documentation strings to code (#57);
@LINAMARIAOSORIO: Add input data preprocessing scripts (#58);
@soaressgabriel: Fix header of the CSV files (#33);
@soaressgabriel: Fix area measurement unit (#36);
@soaressgabriel: Fix bug that did not consider the entire month in the simulation (#39);
@LINAMARIAOSORIO: Fix unusual values of the Recharge (#43);
@LINAMARIAOSORIO: Fix types of argument and return variables of functions in their docstrings (#79);
@soaressgabriel: Adopt new project file structure (#52);
@LINAMARIAOSORIO: Remove Soil Porosity parameter (#44);
@soaressgabriel: Remove white background from favicon from user help page (#70);
@soaressgabriel: Refactoring unit tests (#77);
@soaressgabriel: Refactoring of core module (#76);
@soaressgabriel: Review of the source code base (#5);
@soaressgabriel: Clean up the source code base (#18);