Skip to content

Releases: HydroModPy/HydroModPy

v2.0.0a4

v2.0.0a4 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 29 Sep 18:19

Changed

  • Time-varying fields are stored in float32 with the mantissa rounded to 16 kept bits
    ([simulation.results.persistence] field_precision = "compact", the default; "exact" keeps
    float64). The error is at most 2**-17 of the value, under 1 mm on a 130 m head, and a rounded
    array carries the CF quantization attributes. release_flux and fluxes_from_budget are
    rebuilt on read from the budget terms instead of stored. A daily 6-year run of example 04 goes
    from 1375 to 397 MB, a monthly one from 16 to 5.5 MB; its NSE moves by 7e-8. Stores written
    before read as they did. A spin-up writes its cycles exact, since their heads start the next
    cycle and the production run.
  • A field is read over a range of timesteps with the store opened once
    (results.run.geographic.field_range, field_steps), and the flow-state figures use it: the
    15 figures of a daily example 04 run render in 17 s instead of about 2 min, the same pixels.
  • A calibration promotes a trial from the solve the trial already ran: the trial's MODFLOW
    folder is kept while it may be promoted (every trial under save_runs = "all", the
    save_best_n or the best otherwise), and the promotion resumes at extraction instead of
    writing inputs and solving again. The promoted run is the same, all Zarr arrays bit for bit,
    and is tagged promoted_from_trial:<N>; a trial that was not kept is replayed as before, with
    the reason logged. On the daily API grid of example 04 a promotion no longer spends its ~7 min
    of solve. The kept folders are released on every exit path.
  • The CLI banner draws every letter whole in its color. The slanted font joined the Hydro "o" to
    the "M" and the Mod "d" to the "P" with a shared stroke, so the color changed inside a letter
    and the "P" had no yellow stem. The art keeps a blank column at both joins, four columns wider.
  • Every file of example 04 draws more figures and writes exports to share/<run>/. Step 1
    declares three [[export]] blocks, steps 2 to 4 append theirs with [[export__append]], and
    step 5 drops them with export__delete = true to write its own eleven. project.toml exports
    the catchment and its network, the water table and the seepage cells of October 2002, the
    discharge and the budget, which every calibration writes for each run it promotes; the daily
    API grid writes its own, dated 2019. Step 2 keeps the per-cell recharge, which the distance map
    and the persistence maps of step 4 read. The composite calibration draws its cost profile and
    its distance crossing against K instead of four figures that did not apply to two parameters.

Fixed

  • The scan of data/<variable>/ before a run removes an orphan sidecar, one whose data file is
    gone, when it holds nothing the file does not give back (hash, CRS, bbox, undetermined licence).
    Git ignores the sidecars HydroModPy writes, so a data file a commit removed left its sidecar in
    every clone, and every hmp run of that workspace warned auto_scan skipped about it, lake
    sidecars included for a run without a lake. A sidecar with a stated licence or notes is kept
    and reported as kept; hmp data check says which of the two the next scan does.
  • A calibration whose gauge comes from an API cache promotes its runs again. A station read back
    from its cached _LOC.csv carried numpy values, and a one-station file reads an integer
    column as int64, which the catalog refused to write as JSON: every promotion of the daily API
    grid of example 04 failed on its second launch. A station location now holds plain Python
    values, whatever reader built it.
  • The catchment buffer no longer warns The resolution argument to buffer is deprecated under
    geopandas 1.2, which renamed it quad_segs; 1.1 still requires the old name, and the declared
    range covers both, so the buffer calls shapely directly.

v2.0.0a3

v2.0.0a3 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 29 Sep 09:22

Changed

  • On a terminal, a console log line starts with a glyph for its level, like the phase checkmarks:
    ✗ error, ! warning, › milestone, · debug. A long line wraps under its message, not
    under the glyph. The next: line of the run recap prints dim, without a glyph
    (core.progress.HINT). A pipe keeps the [WARNING] labels, and the log files are unchanged.

Fixed

  • hmp example add 04 merges the rows of the stations it reads (NANCON, NANCON_REA) into the
    workspace registries data/<variable>/<variable>_custom_LOC.csv. hmp workspace init writes
    those registries empty, so every hydrometry, recharge and runoff load failed and the full
    transient runs diverged. A row already there with other values is kept unless --force.
  • hydromodpy.__version__ reads the pyproject.toml of the checkout it is imported from before
    the installed metadata. An editable install keeps the number it was installed at, so a
    checkout bumped to 2.0.0a2 still reported 2.0.0a1 in hmp doctor, run provenance and PNG
    metadata.
  • Several runs of one project run at once. Each run, or each calibration session with its
    trials, phases and promotions, works in its own .hmp/scratch/<config>.p<pid>/
    (core.state.paths.run_scratch): its preprocessing, its solver folders and the recharge its
    trials share. .hmp/scratch/ was shared by the whole project, so on example 04 four runs
    started together lost three in build_geographic (a Whitebox panic, a missing
    dem_fill.tif, a missing outlet.shp), concurrent calibrations read the network another run
    wrote and shared one _shared_recharge across different recharges, and a run that ended
    swept the solver folders of all the others ("Solver output directory is missing", "CBC file
    not found"). A child process inherits its parent's folder through HMP_RUN_SCRATCH; the next
    run of the project removes the folders of killed runs. PREPROCESSING_DIR is replaced by
    core.state.paths.preprocessing_dir(root).
  • batch_size and parallel of a calibration and of a phase are user options, and parallel
    alone now runs trials side by side: a batch holds at least parallel trials, where a batch of
    one serialized them. Measured on the composite of example 04, 8 trials at parallel = 4 take
    278 s for 695 s of solves. run_calibration_api_daily.toml solves its five K at once.
  • scipy_nelder_mead runs on a port of SciPy 1.18.1's Nelder-Mead that evaluates the candidates of
    one step side by side (reflection, contractions, expansion, shrink points) and keeps only the
    values SciPy's rules read: the path, the answer, the evaluation count and the status are SciPy's,
    call for call, at every parallel. The candidates solved and not read stay in the history,
    marked speculative_unused in the journal, and spend no budget.
  • The root search uses parallel: its sweep is solved at once, and each round cuts the bracket
    into parallel + 1 parts in log instead of two, both roots of a two-bound search at the same
    time. On the Nancon bounds, one root takes 6 rounds (20 solves) at 4 against 15 rounds today,
    two roots 8 rounds (26) against 24. The root lies in the same stopping-width bracket; parallel = 1 repeats today's search trial for trial, and the counted budget follows the width.
  • Every phase takes the parallel and batch_size of [calibration] unless it sets its own
    (CalibrationConfig.parallel_for, batch_size_for): the phases a protocol writes declare none,
    so the section's value reached none of them.
  • Run completed: <name> [<id>] <n>s prints the run's duration, the duration_s the catalog
    stores, instead of the solver step alone (6 s printed for a 19 s run).
  • The help of [simulation] if_exists says what replace does: it trashes the predecessor,
    which keeps its name, and registers the new run under the next free name.vN. It said the
    new run took the name.
  • flux_timeseries, water_budget and the testbed budget metrics read the catchment budget
    zone, or the domain one when there is no catchment, and the figures name the frame. They
    summed both zones: the catchment lies inside the MODFLOW 6 domain, so its water was counted
    twice (1.68 m3/s of recharge drawn for 1.09 on the domain and 0.59 on the catchment).
  • seepage_network_confusion_map and network_extent_bounds_map count every legend class on
    the frame they declare. "no stream" counted the whole grid (20 548 cells) under "frame: the
    delineated catchment", and the both-bounds extents counted the domain (1234 cells) next to
    scored counts taken in the catchment (714).
  • A GeoPackage or Shapefile export of simulated_active_network holds the active cells only,
    with their attribute. It wrote every cell of the grid (21 406 polygons, 610 active, 5 MB).
  • The calibrated discharge adds a gridded runoff (SIM2, extent = "watershed"), reduced to its
    watershed mean as the run stores it. The objective read runoff stations only, so
    run_calibration_api_daily.toml scored the drain alone against the total gauged flow while
    its runs reported drain plus runoff, which pushed K onto the lower bound.
  • A network output whose time is a date is redrawn at that date by the figures of the run,
    on the period [s, e) that holds it, the state the trials scored. The derive path accepted
    last and first only, so the promotion of run_calibration_composite.toml
    (time = "2002-10-15") failed in its display step. The period rule moved to
    core.time.selection.resolve_state, shared by the calibration and the results layer.
  • Every run a calibration promotes keeps its watershed. The export step of the first promotion
    dropped the session's shared preprocessing tree, so with save_runs = "all" the next ones
    had no watershed: their catchment discharge summed the whole domain (PBIAS -95 % on the
    daily API grid of example 04) and 6 of 15 figures did not apply.
  • A calibration whose promotion fails says so and exits 21 (CalibrationError) from hmp run
    and hmp calibrate, after printing the results of the search, which are kept. It printed
    "done" and exited 0 while the promoted run was failed in the catalog.
  • The progress line of a bisection shows its bracket, then its root, instead of the lowest
    cost met, which is not the answer of a root search (BD Topage: best 71.8 at K = 1e-7 for a
    root at K = 5.9e-6).
  • A calibrated value no other trial comes close to prints "no other trial within the
    tolerance" instead of a zero-width interval [x, x].
  • A session journal names its project (the project folder, as its runs do) and the metrics of
    its objective blocks, and drops the variable/objective pair a block-scored phase leaves at
    its defaults. It wrote project = "calibration", objective_name = "nse" and
    variable = "head" for a network phase scored on distance_gap.
  • The calibration figures read what they need from the session journal:
    • parameter_cost_profile marks the trial the calibration returned, not the lowest cost:
      the BD Topage profile named K = 1e-7 for a returned K of 5.9e-6.
    • matching_hydrographic_network_card of a two-bound search shows Delta, the combined value,
      the validity and the cells without being passed the roots.
    • bisection_bracket_trace draws a two-bound search, both residual series and both roots.
    • parameter_cost_profile and calibration_progress share the interval of the calibration
      summary (one mesh cell for a distance cost, 5 % otherwise). The profile drew a +10 % rise
      instead, [8.094e-05, 8.115e-05] for a summary of [7.499e-05, 1e-4], and its rise
      option is removed.
    • The axes carry their units: K (m/s), |D_so - D_os| (m), 1 - NSElog (-).
  • A figure that finds while reading the run that it does not apply raises
    display.figure.FigureNotApplicable, and the batch skips it with its reason whatever
    on_error says. The one-parameter calibration figures do so on a session that sampled
    several parameters together: the composite of example 04 (K and Sy) failed its promotion on
    downslope_distance_crossing under on_error = "raise".
  • The figures of a run redraw the stream network with the mean recharge its trials scored
    with. The trials averaged the rate the forcing gives each period; the redraw averaged the
    budget, where a steady spin-up period holds the record mean in place of its month (8.656e-9
    against 9.075e-9 m/s on the monthly Nancon), so the drawn network was cut at another
    threshold than the scored one and "The mean recharge moved" was logged for an unchanged
    forcing. Both now apply one rule (core.stream_recharge) to the forcing, the redraw reading
    the station forcing the run stores; a real change of data or window still warns.

v2.0.0a2

v2.0.0a2 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 28 Sep 07:13

Added

  • [[export]]: one block per export request (variables, time, period, format, folder,
    file, crs, resolution, layer, nodata). The format follows the data: GeoTIFF for a field at
    one date, NetCDF for several dates, CSV for series and the budget, GeoPackage for vector layers.
    The catchment, the mapped networks, watershed_dem, the water budget and the virtual field
    simulated_active_network become exportable. format also takes package, stac, rocrate, prov.
  • hmp export SIM_REF [variables...] speaks the same words (--time, --period, --format, --file,
    --crs...), and hmp export SIM_REF --list prints what a run can export, by kind.
  • hydromodpy.core.time.selection and Run.step_at, Run.steps_for, Run.period_edges: one
    date-to-stress-period resolver for figures and exports.
  • [display] time and a per-figure time name the instant a map draws as a date, first or last;
    a steady calibration phase resolves any date of its record, so no phase override is needed.
    hmp.figure(..., time=...) and hmp viz show --time take it too.
  • A network calibration output takes an ISO date in time; normalize_cost = true on
    distance_gap and distance_mean divides by the validity length, so phase shares are real shares.
  • A calibration ends with a short recap in normal mode (one line per phase, best values with their
    interval, where the best runs are) and writes its methods paragraph to methods.md.
  • [geographic.snap_streams] in apply mode reaches every consumer of the mapped network:
    stream burning snaps the map on the raster's own D8 graph before burning it, a mesh built along
    a mapped network (rivers.source = "file") follows the snapped lines, and the network cells,
    metrics, CSV exports and reference-network figures read the snapped map the run stored.
    diagnose keeps the raw map everywhere while the snap is computed and reported.
  • A calibration session stores its root-search result (bracket, or roots with both roots,
    Delta and the combined value) in session.json; the protocol card and the calibration report
    read it back.
  • hmp calibrate --check says when stage two of the protocol scores the whole run, spin-up year
    included.
  • A network calibration output takes a minimal (permanent) map beside its maximal one, as a file
    (minimal_stream_geometry_path) or as the permanent reaches of the hydrography data family
    (minimal_observed_network = "data.hydrography", refused by name when the source says nothing
    about permanence). The maximal map is scored as the union of the two, and
    frac_minimal_outside_maximal is published.
  • The transient two-bound mode, [calibration.outputs.<name>.extent]. For each complete calendar
    year inside the phase's scoring_window, the maximal simulated mask holds the cells flowing at
    least maximal_flowing_steps timesteps and the minimal one the cells dry at most
    minimal_dry_steps timesteps (both 1 by default, counted in timesteps); the years are aggregated
    by year_quorum (0.5) and each bound is scored once with the distance criterion. A cell flows
    when it is in the downstream closure of the seepage and its routed discharge reaches
    visible_flow ("1 L/s" by default, or a share of the outlet discharge such as "1%").
    hydromodpy.core.stream_extent holds this one definition of flowing for the criterion and the
    figures.
  • Two bounds, one value: the bisection closes one root per bound on the same trials and returns
    their weighted geometric mean, log K = w_min log K*_min + w_max log K*_max (weights, 0.5 each),
    evaluated once so every published number comes from a solve. The report and hmp calibrate
    give both roots, both brackets and Delta = log10(K*_max / K*_min); a minimiser's cost is
    w_min |J_min| + w_max |J_max|. max_iter = "auto" budgets both roots.
  • [geographic.snap_streams] (off by default, diagnose, apply) moves the mapped network
    onto the talwegs of the criterion graph, flow-accumulation guided from downstream to upstream,
    within a radius in metres (2 h_obs by default), rejecting what it cannot attach. Trials publish
    the displacement (p50, p90), the rejected share, the length ratio and the floor F, the Doptim of
    the snapped map against the raw one; in apply Eq. 4 also bounds the displacement. A run
    stores its snapped map, and two figures, observed_network_snap_map and
    observed_network_snap_histogram, show what moved.
  • validity_length on a network output, "auto" or a length such as "150 m": Eq. 4 reads
    Doptim <= validity_length. "auto" is 2 h, with h = max(h_obs, observed_position_accuracy), and
    h + max(h, F) when a snap floor exists. Each trial publishes the length and what set it.
  • network_extent_bounds_map draws the maximal and minimal simulated extents of a transient run
    against its two maps, outside any calibration.
  • hydrographic_network_permanence draws the mapped network split by permanence: the permanent
    reaches (the minimal map) over the reaches the complete map adds, with the length and reach
    count of each class. It needs a hydrography source that says which reaches flow all year.
  • Preflight refuses an extent table on a steady search, a minimal map file that does not exist,
    and a data.hydrography minimal map without a declared hydrography source.
  • hmp run on an overview ends on the catchment, its area, the web report and the figures folder;
    --verbose keeps the full recap. The overview shows its phases and the data families load
    under one progress bar.

Changed

  • optimizer_kwargs is now method_options, and the protocol's *_engine_options are
    *_method_options; the old names load with a warning. Options are checked when the file loads
    and by hmp calibrate --check. The rename changes every calibration params_hash once.
  • The per-figure timestep is now time; old files load, hmp doctor --fix-config rewrites them.
    An unknown key in [display.overrides.<figure>] is refused at load.
  • An old [export] table of format toggles or [[export.artifacts]] loads as [[export]] blocks.
  • hmp calibrate --check prints only real departures from the paper; the full record is at -v.
    --expand prints the whole pasteable section. --list-phases prints shares below 1 % and names the
    station a point output observes.
  • A scoring window is accepted beside a network output read in one state; it is refused only when
    it does not hold that state. warmup and warmup_periods move to the expert profile.
  • Promoted calibration runs are named <simulation name>_<phase> instead of <method>_iter_NNNN.
  • Figures: seepage_map draws two classes; maps open on the catchment in projected metres; titles
    name the period drawn and say catchment outlet; the identity card drops its status and id rows
    and wraps long names; the network maps state the seepage threshold in words.
  • Normal console: the licence warning prints once per workspace; Run completed prints last; the
    figure summary warns only when a config option would have kept a skipped figure; the runoff and
    outlet messages are one sentence each.
  • [geographic].dem_correc_type defaults to "fill", the paper's FillDepressions, instead of
    "breach". A file that writes "breach" keeps it, and the Methods paragraph and
    hmp calibrate --check name it as a departure from the paper.
  • matching_hydrographic_network is version 1.2: the DEM is filled by default, stage two leaves
    the first year of the run out as spin-up unless the file declares a window, and the Eq. 4
    bound is a length. A pin on 1.1 is refused.
  • The protocol card reads the keys a trial published: both bounds side by side in the two-bound
    mode, the validation map beside the scored one in a one-state run.
  • Example 04: every TOML follows the current code (budget "auto", no retired key, comments on
    the criterion, the maps, the buffer and the protocol version brought up to date), the new
    options shown commented out; the burning of the routing DEM is dropped.
  • With both maps, a one-state network output is scored on the minimal map, as the WRR 2025 paper
    calibrates, and the maximal map is published as a validation outside the cost.
  • L_ref, the length that normalises roptim and sets the interval width of a network search, is
    h_obs, the median distance between neighbouring cell centres over the mapped cells of the
    catchment. Unchanged on a regular grid; the fine cell on a mesh refined along the streams.
  • roptim is always Doptim / h_obs, the paper's Eq. 3; a declared observed_position_accuracy
    enters the validity length only.
  • The persistence figures and simulated_active_network in persistence mode count a cell as
    flowing by the criterion's definition, and the stream-network maps redraw with the settings the
    run sealed, so they show the partition the trial scored.
  • Toggling [geographic.snap_streams] does not invalidate the geographic cache.
  • hmp config template without --modules writes every module, [calibration] and
    [mesh_catchment] included. They were left out so the template would validate as written,
    which it never did.

Removed

  • hmp data export, hmp data export-package and hmp catalog export: hmp export replaces them.
  • The [export] format toggles, output_dir, [[export.artifacts]] and var, fmt, dest.
  • roptim_max. The load-time migration and hmp doctor --fix-config drop roptim_max = 2, which
    validity_length = "auto" reproduces, and refuse any other value with the length to write.
  • geometry_from_run, replaced by network_maps_from_run, which returns every declared map.

Fixed

  • hmp calibrate --check names an option a phase-two method refuses, instead of failing after phase
    one spent its budget.
  • The network criterion no longer warns that the mean recharge moved on float noise.
  • The protocol card of the second promoted run draws...
Read more

v2.0.0a1

v2.0.0a1 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 28 Sep 01:19

Removed

  • reference_values from calibration protocols and from protocol_record.

  • The hydromodpy.optimizer entry-point group. A method it listed was refused
    anyway by the closed union of optim/method_config.py. Search methods ship
    with HydroModPy; a search of one's own runs from Python, as an object that
    satisfies Optimizer handed to CalibrationEngine(optimizer=...).

  • geographic.bottom_path, which nothing read. hmp doctor --fix-config and
    the loader move its path to [[data.substratum.sources]] and leave
    [domain.depth_model] as it was; a loader that skips the migration accepts
    the key, ignores it and warns. Dropping it from the geographic fingerprint
    rebuilds each geographic cache once.

  • examples/projects/02_nancon_watershed/run_sweep_sy.toml, a design draft for
    a sweep workflow that does not exist, and run_transient_prototype.py.draft
    leave the example.

  • examples/projects/19_cheze_reservoir, the lake test project of the Chèze
    reservoir, the three projects of examples/projects/new_to_sort, the Chèze
    diagnostic scripts of tools/diagnostics/ and tools/view_mesh_grid_3d.py
    leave the repository with the lake data only they read. None was cited by a
    test, the documentation or the example manifest.

  • The data-fetch process, hydromodpy/data/fetch/ and
    hydromodpy/schema/processes/data-fetch@1.json. data-request replaces it
    and serves every [data] variable instead of six sources. Only the request
    format changes. A data-fetch request named one source by a tagged id
    with its options beside it, and the extent at the top of inputs:

    {"process": {"id": "data-fetch", "version": "1.0.0"},
     "inputs": {"source": {"id": "hubeau-piezometry", "product": "level"},
                "mask": {"href": "/jobs/4711/outputs/watershed.gpkg"},
                "period": {"start": "2020-01-01", "end": "2020-12-31"}}}

    A data-request request carries [data] sections, written as in a project
    TOML, and the extent under extent (bbox with crs, mask, or
    station_ids); a plugin source goes under installed by name:

    {"process": {"id": "data-request", "version": "1.0.0"},
     "inputs": {"data": {"piezometry": {"sources": [{"source": "hubeau", "product": "level"}]}},
                "extent": {"mask": {"href": "/jobs/4711/outputs/watershed.gpkg"}},
                "period": {"start": "2020-01-01", "end": "2020-12-31"}}}

    The report moves from outputs/fetch.json to outputs/request.json, and
    the payload from one of outputs/points.parquet, fields.nc,
    features.gpkg, raster.tif to one outputs/<variable>_<source> file per
    variable and source. A chain links the mask as extent.mask instead of
    mask.

  • HubeauPiezometrySource, IgnDemSource and Sim2PrecipitationSource, and
    the source ids hubeau-piezometry, ign-bdalti and sim2-precipitation
    of hydromodpy.data.source.registry. Their only caller was data-fetch.
    Piezometry, the DEM and SIM2 are asked through their [data] section, in a
    project TOML or a data request; a plugin source goes under installed. The
    port keeps BdTopageSource, EuHydroSource and OsmSource.

  • hydromodpy.data.DataManagers, hydromodpy.data.loading.entry.DataEntry and
    hydromodpy.results.catalog.cross_db.entry_used_by, which nothing called.
    With them go the two layer tolerances data -> results and
    results -> data that the cross-database bridge needed; run.input_entries()
    remains the way from a run to the cache entries it read.

  • The 7-name facade of hydromodpy.calibration.runners, which nothing
    imported, and hydromodpy.calibration.protocols.registry.assert_version_is_available:
    the protocol version is checked in matching_hydrographic_network.py
    instead.

  • hydromodpy.display.renderer.save_figure, hydromodpy.display.theme.plot_params,
    hydromodpy.display.colormaps.check_no_banned_in_call, the module
    hydromodpy.display.geo.basemaps, and GeoFigureMixin.add_basemap with the
    crs attribute only it read. Nothing called them; a figure is saved by
    BaseFigure.plot.

  • The module hydromodpy.display.catchment_report.cli: the options of
    hmp report catchment live in hydromodpy/cli/commands/report.py,
    unchanged. python -m hydromodpy.display.catchment_report.pipeline and
    python -m hydromodpy.display.catchment_report.context go with it: use
    hmp report catchment <toml>, or build_context_from_report_config from
    Python for the context alone.

Added

  • BD Topage reaches carry a canonical permanence column (permanent, intermittent,
    ephemeral, dry, unknown, vocabulary in hydromodpy/data/source/permanence.py) beside
    PersistanceTH. The download writes its permanent reaches to
    hydrography_bdtopage_permanent_<hash>.gpkg beside hydrography_bdtopage_<hash>.gpkg, the run
    clips them to streams_permanent.shp beside streams.shp and keeps them as the
    reference_permanent hydrographic network. A network that says nothing about permanence has no
    permanent part.
  • CatchmentDomainProducts and the geographic cache manifest record buffer_rule,
    buffer_declared and buffer_area_increase, so a domain says how its margin was drawn.
  • A MODFLOW 6 twin validation case for the stream-network criterion. A planar hillslope run at
    a known K draws the mapped network, and a network-only bisection recovers that K within 1 per
    cent, with J at zero and consistent K/R, dsat, T/R and Toptim in the report
    (tests/validation/calibration/test_twin_matching_stream_network_modflow6.py, tolerances rows
    76 to 79).
  • observed_rasterization on a network calibration output. "crossing", the default, keeps a
    cell where a mapped line crosses the segment joining two edge-sharing cell centres: on a grid
    this is WhiteboxTools VectorLinesToRaster, the paper's tool, so a model that reproduces the map
    scores J = 0. "touch" replays sessions made before. line_crossing_cell_mask serves DIS,
    DISV and Voronoi meshes. The redrawn comparison figures read the same rule, and each trial
    publishes n_observed_cells and n_observed_features_fallback.
  • Secondary network diagnostics, outside the cost: D_so_over_D_os and the overlap indices of
    the authors' published code (overlap_Ea, overlap_Sa, overlap_Na, overlap_E,
    n_neither, L_sim_m, L_obs_m).
  • The calibration report records the Eq. 4 verdict of the returned trial (roptim_verdict), the
    final bracket of a bisection (bracket) and whether the search met its stopping rule
    (search); hmp calibrate prints each on one line. The bisection warns at start when
    max_iter is below what its bracket needs.
  • hmp calibrate --check warns when an objective scored only on network outputs moves more
    than one parameter, a T/R ridge. A network search that moves K is refused, at preflight and
    before the first solve, next to an active SFR or LAK, whose conductance does not follow K.
  • The staged report and the Methods paragraph publish the steady window stage one averaged the
    recharge over; a window shorter than 365 days warns.
  • matching_hydrographic_network declares six more departures: the outlet sealed into the
    target of D_so, the L_cap saturation and its 5 % guard, the log10 K bisection and its sweep,
    the support of D_os against the authors' published code, breach by default and the
    rasterisation rule.
  • The aquifer geometry can be calibrated. [calibration.parameters.thickness] searches the
    thickness of a constant_thickness depth model (log space) and
    [calibration.parameters.substratum_elevation] the elevation of a flat_substratum one
    (linear space); hmp config targets lists whichever the declared depth model carries. The
    file states the bounds. A parameter that reaches a raster depth model, or a field the
    declared kind does not expose, is refused and the error names the kind.
  • A stream-network trial publishes the paper's dsat as <output>.d_sat_m:
    the saturated thickness averaged by area over the catchment, at the state the
    network is read from. Beside it, d_aquifer_m, d_sat_over_d and
    d_sat_unset_fraction. A backend that serves no saturated thickness
    publishes none of them and still scores the network.
  • A calibration whose one moved parameter is flow.param.K.field.value,
    written as a value and scored on a network output, reports the derived
    values of Table 1 of Abherve et al. (2023): k_over_r, k_optim_m_s,
    d_sat_m, t_over_r_m and t_optim_m2_s, printed on one line by
    hmp calibrate. A search on any other parameter gets none of them.
  • A raster substratum: two depth models read the bottom of the aquifer from
    the new [data.substratum] variable, one user raster in metres.
    kind = "raster_substratum" takes its values as the substratum elevation,
    the raster twin of flat_substratum; kind = "raster_thickness" subtracts
    them from the top, the raster twin of constant_thickness, and takes a
    scale. Both take offset and min_thickness. The raster is reprojected
    onto the grid of the top and must cover every cell of the chosen extent (the
    catchment for domain_extent = "watershed", the buffered box for "box"),
    or the run stops and counts the missing cells. The domain-build process
    takes it as a substratum input, the mask being the extent there.
  • The data-request process (hmp process run data-request --job DIR), the
    job form of hmp data get: the managers' cache lives under $TMPDIR with an
    in-memory index, a custom source is refused before anything is written, a
    variable that fails fails the job with its typed exit code, and the declared
    hosts are those of hydromodpy/schema/sources.py. A chain link fills a
    nested member through a dotted path such as extent.mask.
  • The twelve v1 examples run in the current format, examples 06 to 11 included
    (particle tracking, analytical recession, expo...
Read more

HydroModPy v1.0.0

Choose a tag to compare

@Alex-Gauvain Alex-Gauvain released this 28 Aug 09:23

First stable release of HydroModPy, and the version described in the technical
note submitted to Hydrology and Earth System Sciences
(EGUsphere preprint). This is the
reference cited by the paper. The v1.0 branch stays open for 1.0.X bug fixes
so the paper link always points to a working release, while feature development
continues on main as HydroModPy v2.

Install the maintained paper version with pip install "hydromodpy==1.0.*",
which resolves to the latest 1.0.X patch and never upgrades to the v2 series.

Added

  • First PyPI release published from GitHub, with MODFLOW, MODPATH and MT3D-USGS binaries bundled in the wheel.
  • Release pipeline on GitHub Actions: tag/version guard, build, twine check --strict, PyPI Trusted Publishing (OIDC) and a GitHub release carrying the changelog notes.
  • Weekly cross-platform install and example smoke tests on Linux, Windows, macOS x86 and macOS arm, for Python 3.11 to 3.13.
  • Multi-version documentation served at https://docs.hydromodpy.fr/v1.0/, rebuilt on every push to the v1.0 branch.

Changed

  • Repository, issues and CI moved from GitLab to GitHub.
  • Documentation moved from ReadTheDocs to GitHub Pages under the docs.hydromodpy.fr domain.
  • README leads with the pip installation path; authors, affiliations and title aligned with the preprint.
  • Upper pin on numpy (<2.5) for pysheds compatibility, and dask added for multi-file xarray merges.
  • Development status classifier raised to 5 - Production/Stable.

Fixed

  • MODPATH particle flux is sampled with rasterio instead of whitebox.
  • Interactive matplotlib backend detected through backend_registry.
  • Watershed object is rebuilt when the stored pickle cannot be read.
  • Transport and PyHELP examples run headless, without user interaction.

Removed

  • GitLab CI pipeline and ReadTheDocs configuration.

HydroModPy v0.3.4

Choose a tag to compare

@bastien-boivin bastien-boivin released this 18 Feb 21:38

Added

  • Added requirements-docker-light.txt for pip-only Docker/server installs without IDE or visualization dependencies.
  • Added optional Dask handling in SIM2 (chunked xarray only when Dask is available).

Changed

  • HydroModPy now loads display modules only when display features are invoked.
  • Dockerfile updated for a light production flow using pip requirements.

Fixed

  • Improved PROJ database detection and fallback (including rasterio data dirs) to reduce proj.db layout errors in containers.

Originally released on GitLab on: 2026-01-05

HydroModPy v0.3.2

Choose a tag to compare

@bastien-boivin bastien-boivin released this 18 Feb 21:37

Changed

  • Reworked SIM2 workflow: coarse clip without reprojection to trim inputs, resample on that reduced dataset, then final clip/mask with reprojection for clean outputs without wasted time or RAM.
  • disk_clip now accepts .shp, .gpkg, and .geojson, and SIM2 filename parsing keeps the full variable name before _SIM2_.

Fixed

  • toolbox.load_to_xarray reprojects when dst_crs is provided even without a mask, matching the new SIM2 flow and avoiding extra memory use.
  • SIM2 resampling preserves encodings and applies masking with the reprojected DEM consistently.

Originally released on GitLab on: 2025-11-28

HydroModPy v0.3.1

Choose a tag to compare

@bastien-boivin bastien-boivin released this 18 Feb 21:37

Changed

  • Installation guide reorganized with ready-made command recipes, dual YAML options (runtime vs editable), and clearer guidance for conda-versus-pip setups.
  • README now flags v0.3.1 as the stable release and the conda YAMLs pin Python 3.11–3.13 explicitly.
  • Add spyder package to the conda environment for users of that IDE.

Fixed

  • pyproject.toml now lets setuptools auto-discover all hydromodpy* packages so pip install hydromodpy (and ReadTheDocs builds) no longer fail if optional submodules such as hydromodpy.modeling.gr4j are absent from the current branch.
  • Pinned NumPy to >= 2.0 and restricted supported Python to >= 3.11, < 3.14 to avoid incompatibilities with other packages.

Originally released on GitLab on: 2025-11-14

HydroModPy v0.3.0

Choose a tag to compare

@bastien-boivin bastien-boivin released this 18 Feb 21:36

Added

  • Logging system with a LogManager class. All print statements are replaced by structured logging.
  • CI/CD pipeline on GitLab for automated build, test, and publication on PyPI.
  • Single conda environment file that works on Linux, macOS, and Windows.
  • Automatic download of HELP3O binaries during the first call. No Fortran compiler is needed.
  • Packaging now includes executables, documentation, and example folders.
  • PROJ data paths are now set explicitly to avoid loading an outdated proj.db file.
  • The pyhelp command line tool sets the PYHELP_WORKDIR variable and supports a workdir argument. This fixes the crash of Example 10 on Windows.

Changed

  • Package renamed from src to hydromodpy. All imports are updated.
  • GDAL is replaced by rasterio to allow installation with pip only.
  • First release available with pip install hydromodpy.
  • Conda installation is now based on a single environment file that uses only conda-forge packages.
  • Examples 00 to 11 use the new hydromodpy imports.
  • PyHELP now relies on prebuilt binaries instead of local Fortran compilation.
  • Logging offers three modes: dev, verbose, and quiet.
  • Deepdish serialization is replaced by pickle.

Removed

  • Old and platform-specific environment files.
  • All Fortran compilation steps for PyHELP.
  • Unused FTP-AQUIFER scripts.
  • Hard-coded references to GDAL.
  • Legacy dependencies such as hydroeval and deepdish.

Fixed

  • Consistent naming of example folders.
  • Path handling now works on all supported systems.
  • Suppression of noisy logs from external libraries such as matplotlib and flopy.
  • PROJ data handling is stable in the PyHELP NetCDF writer.
  • Extraction of HELP3O binaries works correctly on macOS.

Originally released on GitLab on: 2025-11-14

HydroModPy v0.2.0

Choose a tag to compare

@bastien-boivin bastien-boivin released this 18 Feb 21:35

Added

  • Added MT3D-USGS support with the new transport modules, Example 09, and executables for Linux, macOS, and Windows.
  • Added the GR4J rainfall–runoff calibration toolkit, the PyHELP land-surface coupling package with Example 10, Example 11 (headless workflow), the regression-test suite, yearly intermittency output, MT3D seepage concentration/mass, and OS-specific conda env files.

Changed

  • Updated modflow/hydraulic handling to support elevation-based decay and the evapotranspiration extinction depth, refreshed modpath particle placement, expanded watershed_root with transport + calibration logic, improved timeseries input handling, and adjusted geographic/hydrography helpers.

Fixed

  • Updated SIM2 climate variables/units (soil drought index now included) and restored the watershed visualization legend and color bar.

Originally released on GitLab on: 2025-11-05