Repository navigation
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_atandget_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()andDatabase.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 subclassesException, so existingexcept Exceptionhandlers 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: connectsmw_DemAllocpoints to the nearest junction, a junction of the nearest pipe or the nearest pipe (part of #120). Failures raisemikeplus.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
muidsargument on theInterpolationToolmethods, such asinterpolate_from_DEM, which restricts them to the given elements (#115). - User-defined columns are managed from
table.columns(#124):add_user_definedcreates, restores or leaves a column unchanged and returns itsm_UserDefinedColumnMUID;remove_user_definedhides a column as MIKE+ does, keeping its data, andrestore_user_definedbrings it back;user_definedanddetachedlist the shown and restorable columns.
Changed
Database.create()also writes a.muppproject file beside the database, so a new model opens in MIKE+, and it accepts a.mupppath. It raisesFileExistsErrorif a.muppof that name already exists, andoverwrite=Truedeletes that.mupptoo, losing its map layers and other settings (#121).- Table and column names in
select,insert,updateandorder_byare matched case-insensitively (#119). Two field names that differ only in casing now raiseValueError, andorder_byraisesValueErrorfor an unknown column, asselectdoes. - 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 raisesValueErrornaming the field. An empty string becomesNonefor 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
mikepluswith anything other than x64 Python on Windows or Linux now raisesImportError. Database.run()raisesRuntimeErrorwhen the engine exits with an error or doesn't write its result files, naming the engine's logs (#143).TopoRepairTool.run()raisesValueErrorunless the active model is CS_MIKE1D or WD_EPANET, instead of doing nothing (#146).CathSlopeLengthProcess.run()reports the tool's warnings withwarnings.warn(#145).ScenarioCollection.find_by_name()returns every scenario with the name, not at most one (#146).Database.close()returnsNonewhether or not the database was open (#146).- The documentation site moved to great-docs. API reference pages moved from
api/toreference/, 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, soDatabase.sridand new geometry use it instead of -1. It is also derived fromprojection_stringwhen MIKE+ recognises it. A geographic or unknownsrid(such as 4326, which MIKE+ silently turned into Google Maps - Mercator) raisesValueErrorbefore any file is touched (#141).- Opening a
.muppfile that has no.sqliteof 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 duplicatem_UserDefinedColumnrecord when called again for the same column. It now returns the record's MUID, and raisesValueErrorif the column already exists with a different data type (#124).table.columnsandinsert/updatesee user-defined columns added or removed after the table was first read, andinsert/updateset 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 raiseRuntimeErrorif it doesn't commit. from mikeplus.tables import *raisedAttributeError, and the table classes couldn't be imported frommikeplus.tables.Database.run()with a simulation MUID the model doesn't have ran the engine and then raised a .NETNullReferenceException. It now raisesValueErrorbefore starting the engine.InterpolationTool.interpolate_from_neighobouralways raisedAttributeError; it now honoursalongPath.- The
InterpolationToolmethods raisedTypeErrorwhenvalue_as_missingwas a number. Database.create(overwrite=True)deleted the existing database before rejectingsridtogether withprojection_string(#140).to_sql()andby_muid()didn't escape single quotes, andto_sql(True)gaveTruerather than1(#144).- Progress from
CathSlopeLengthProcessandConnectionRepairToolwas never printed, because the handler was attached after the tool ran (#145). Alternative.scenariosraisedAttributeErrorwhen the model had a scenario other than Base, and it, likeAlternative ==, confused alternatives of different groups that share an id (#142).- Iterating
db.scenariosreturned scenarios with the same name as one scenario repeated, and iterating anAlternativeGroupskipped alternatives below the base's children (#146). - User guide examples and docstrings that raised or contradicted the code, notably
db.run(sim_option=...)(notmodel_option),insert()running immediately, single-use queries, anddb.alternative_groups(notdb.scenarios.alternative_groups).
Full Changelog: v2026.0.0...v2026.1.0