Skip to content

v2026.1.0

Latest

Choose a tag to compare

@ryan-kipawa ryan-kipawa released this 08 Oct 07:51

What's Changed

This release adds transactions for faster batch edits, new water distribution tools and user-defined column management. Database.create() now writes a .mupp project file, and there are many fixes. MIKE+Py now requires Python 3.12 or later.

Added

  • mikeplus.utilities.get_nearest_river_at and get_nearest_river_chainage_at, which find the river (and chainage) nearest to a point, for example to couple river junction nodes to rivers (#112).
  • Database.begin_transaction() and Database.end_transaction(commit), which group many updates into one transaction and make batch edits much faster (#112).
  • mikeplus.DatabaseError, raised when creating, opening, closing or importing into a database fails. It subclasses Exception, so existing except Exception handlers still catch it.
  • Database.ensure_mupp(), which returns a database's MIKE+ project file (.mupp), writing one beside it if it has none (#121).
  • mikeplus.tools.DemandConnectionTool, the MIKE+ connection tool for demand allocations: connects mw_DemAlloc points to the nearest junction, a junction of the nearest pipe or the nearest pipe (part of #120). Failures raise mikeplus.DatabaseError.
  • mikeplus.tools.DemandAggregationTool, the water distribution Aggregation tool: aggregates demand allocations to junction demands or pipe demand coefficients, rejecting unknown allocation MUIDs (#120).
  • mikeplus.tools.CreateValvesFromPointsTool, the MIKE+ tool that creates water distribution valves from a point shapefile, snapping each point to a nearby junction or pipe (#120).
  • An optional muids argument on the InterpolationTool methods, such as interpolate_from_DEM, which restricts them to the given elements (#115).
  • User-defined columns are managed from table.columns (#124): add_user_defined creates, restores or leaves a column unchanged and returns its m_UserDefinedColumn MUID; remove_user_defined hides a column as MIKE+ does, keeping its data, and restore_user_defined brings it back; user_defined and detached list the shown and restorable columns.

Changed

  • Database.create() also writes a .mupp project file beside the database, so a new model opens in MIKE+, and it accepts a .mupp path. It raises FileExistsError if a .mupp of that name already exists, and overwrite=True deletes that .mupp too, losing its map layers and other settings (#121).
  • Table and column names in select, insert, update and order_by are matched case-insensitively (#119). Two field names that differ only in casing now raise ValueError, and order_by raises ValueError for an unknown column, as select does.
  • Strings are converted only when the destination column needs it. DateTime columns parse them; Double columns accept a single . or , as the decimal separator, so "1,234" is 1.234, and anything else raises ValueError naming the field. An empty string becomes None for both. Strings bound for other columns are passed through unchanged.
  • Minimum versions now follow SPEC 0: numpy 2.3, pandas 2.3 and pythonnet 3.0.5.
  • Importing mikeplus with anything other than x64 Python on Windows or Linux now raises ImportError.
  • Database.run() raises RuntimeError when the engine exits with an error or doesn't write its result files, naming the engine's logs (#143).
  • TopoRepairTool.run() raises ValueError unless the active model is CS_MIKE1D or WD_EPANET, instead of doing nothing (#146).
  • CathSlopeLengthProcess.run() reports the tool's warnings with warnings.warn (#145).
  • ScenarioCollection.find_by_name() returns every scenario with the name, not at most one (#146).
  • Database.close() returns None whether or not the database was open (#146).
  • The documentation site moved to great-docs. API reference pages moved from api/ to reference/, and the auto-generated table classes no longer have their own pages. User guide URLs are unchanged.

Removed

  • Support for Python 3.10 and 3.11. MIKE+Py now requires Python 3.12 or later.

Fixed

  • create() stores the SRID, so Database.srid and new geometry use it instead of -1. It is also derived from projection_string when MIKE+ recognises it. A geographic or unknown srid (such as 4326, which MIKE+ silently turned into Google Maps - Mercator) raises ValueError before any file is touched (#141).
  • Opening a .mupp file that has no .sqlite of the same name beside it failed to find the database it refers to.
  • select() accepts a single column name instead of splitting it into characters (#44).
  • BaseTable.add_user_defined_column() no longer writes a duplicate m_UserDefinedColumn record when called again for the same column. It now returns the record's MUID, and raises ValueError if the column already exists with a different data type (#124).
  • table.columns and insert/update see user-defined columns added or removed after the table was first read, and insert/update set values in user-defined columns that were already in the database when it was opened (#124).
  • SelectQuery.execute() is annotated as returning each row's values as a list keyed by MUID, which is what it returns, instead of a dict of dicts.
  • Strings that look like numbers, such as "760309", were written to text columns as datetimes.
  • Geometry updates through update() were not saved. They now go through MIKE+'s geometry command and raise RuntimeError if it doesn't commit.
  • from mikeplus.tables import * raised AttributeError, and the table classes couldn't be imported from mikeplus.tables.
  • Database.run() with a simulation MUID the model doesn't have ran the engine and then raised a .NET NullReferenceException. It now raises ValueError before starting the engine.
  • InterpolationTool.interpolate_from_neighobour always raised AttributeError; it now honours alongPath.
  • The InterpolationTool methods raised TypeError when value_as_missing was a number.
  • Database.create(overwrite=True) deleted the existing database before rejecting srid together with projection_string (#140).
  • to_sql() and by_muid() didn't escape single quotes, and to_sql(True) gave True rather than 1 (#144).
  • Progress from CathSlopeLengthProcess and ConnectionRepairTool was never printed, because the handler was attached after the tool ran (#145).
  • Alternative.scenarios raised AttributeError when the model had a scenario other than Base, and it, like Alternative ==, confused alternatives of different groups that share an id (#142).
  • Iterating db.scenarios returned scenarios with the same name as one scenario repeated, and iterating an AlternativeGroup skipped alternatives below the base's children (#146).
  • User guide examples and docstrings that raised or contradicted the code, notably db.run(sim_option=...) (not model_option), insert() running immediately, single-use queries, and db.alternative_groups (not db.scenarios.alternative_groups).

Full Changelog: v2026.0.0...v2026.1.0