From e8b5439eed5aead29845385f57f54b599249a77b Mon Sep 17 00:00:00 2001 From: Martijn Visser Date: Fri, 13 Dec 2024 21:00:46 +0100 Subject: [PATCH 1/3] Remove unused outstate config option (#1967) Also the `subgrid` option was missing in the `docs.toml`. It is documented though, `outstate` was not. --- core/src/config.jl | 1 - core/test/docs.toml | 4 ++-- python/ribasim/ribasim/config.py | 1 - 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/core/src/config.jl b/core/src/config.jl index 1fc0012e2..7ea4ce0f4 100644 --- a/core/src/config.jl +++ b/core/src/config.jl @@ -119,7 +119,6 @@ end # Separate struct, as basin clashes with nodetype @option struct Results <: TableOption - outstate::Union{String, Nothing} = nothing compression::Bool = true compression_level::Int = 6 subgrid::Bool = false diff --git a/core/test/docs.toml b/core/test/docs.toml index ac155cebf..12c336535 100644 --- a/core/test/docs.toml +++ b/core/test/docs.toml @@ -45,9 +45,9 @@ evaporate_mass = true # optional, default true to simulate a correct mass balan verbosity = "info" # optional, default "info", can otherwise be "debug", "warn" or "error" [results] -# These results files are always written -compression = true # optional, default true, using zstd compression +compression = true # optional, default true, using zstd compression compression_level = 6 # optional, default 6 +subgrid = false # optional, default false [experimental] # Experimental features, disabled by default diff --git a/python/ribasim/ribasim/config.py b/python/ribasim/ribasim/config.py index a9acd3350..6a0555235 100644 --- a/python/ribasim/ribasim/config.py +++ b/python/ribasim/ribasim/config.py @@ -71,7 +71,6 @@ class Allocation(ChildModel): class Results(ChildModel): - outstate: str | None = None compression: bool = True compression_level: int = 6 subgrid: bool = False From c963001805333d342e30e796c98aaa1c198c482a Mon Sep 17 00:00:00 2001 From: Martijn Visser Date: Mon, 16 Dec 2024 12:32:13 +0100 Subject: [PATCH 2/3] Put level as the first column in basin.arrow (#1971) The iMOD timeseries plugin shows the first column by default. That is storage. Most users want to view level first, and have to switch manually. So this simply puts level first, such that we get: ![image](https://github.com/user-attachments/assets/92e5ae0e-a704-45fd-bf5a-09c35008f8a7) --- core/src/write.jl | 4 ++-- core/test/run_models_test.jl | 2 +- docs/reference/usage.qmd | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/src/write.jl b/core/src/write.jl index b81e5d01d..6edc3013b 100644 --- a/core/src/write.jl +++ b/core/src/write.jl @@ -119,8 +119,8 @@ function basin_table( )::@NamedTuple{ time::Vector{DateTime}, node_id::Vector{Int32}, - storage::Vector{Float64}, level::Vector{Float64}, + storage::Vector{Float64}, inflow_rate::Vector{Float64}, outflow_rate::Vector{Float64}, storage_rate::Vector{Float64}, @@ -167,8 +167,8 @@ function basin_table( return (; time, node_id, - storage, level, + storage, inflow_rate, outflow_rate, storage_rate, diff --git a/core/test/run_models_test.jl b/core/test/run_models_test.jl index 72c541320..696676119 100644 --- a/core/test/run_models_test.jl +++ b/core/test/run_models_test.jl @@ -45,8 +45,8 @@ ( :time, :node_id, - :storage, :level, + :storage, :inflow_rate, :outflow_rate, :storage_rate, diff --git a/docs/reference/usage.qmd b/docs/reference/usage.qmd index 2ea46dab7..d9f24c625 100644 --- a/docs/reference/usage.qmd +++ b/docs/reference/usage.qmd @@ -230,8 +230,8 @@ column | type | unit -------------- | ---------| ---- time | DateTime | - node_id | Int32 | - -storage | Float64 | $\text{m}^3$ level | Float64 | $\text{m}$ +storage | Float64 | $\text{m}^3$ inflow_rate | Float64 | $\text{m}^3/\text{s}$ outflow_rate | Float64 | $\text{m}^3/\text{s}$ storage_rate | Float64 | $\text{m}^3/\text{s}$ From fc02cfb5e0e2e7c8560b92224e92280a1ba859b7 Mon Sep 17 00:00:00 2001 From: Martijn Visser Date: Mon, 16 Dec 2024 12:33:15 +0100 Subject: [PATCH 3/3] Automatically name index (#1974) Fixes #1968 We let pandera check the index name with `check_name = True`. This adds a pandera parser called `_name_index` to set the index to the desired name before validating. This still keeps the index names, but offers more user convenience, since the index name is lost with many pandas operations. --- python/ribasim/ribasim/input_base.py | 2 -- python/ribasim/ribasim/schemas.py | 5 +++++ python/ribasim/tests/test_io.py | 5 +++++ python/ribasim/tests/test_model.py | 6 ++++++ utils/templates/schemas.py.jinja | 5 +++++ 5 files changed, 21 insertions(+), 2 deletions(-) diff --git a/python/ribasim/ribasim/input_base.py b/python/ribasim/ribasim/input_base.py index c6613c908..48e0e03fd 100644 --- a/python/ribasim/ribasim/input_base.py +++ b/python/ribasim/ribasim/input_base.py @@ -217,7 +217,6 @@ def _check_dataframe(cls, value: Any) -> Any: # Enable initialization with a DataFrame. if isinstance(value, pd.DataFrame | gpd.GeoDataFrame): - value.index.rename("fid", inplace=True) value = {"df": value} return value @@ -386,7 +385,6 @@ def _from_db(cls, path: Path, table: str): # tell pyarrow to map to pd.ArrowDtype rather than NumPy arrow_to_pandas_kwargs={"types_mapper": pd.ArrowDtype}, ) - df.index.rename(cls.tableschema()._index_name(), inplace=True) else: df = None diff --git a/python/ribasim/ribasim/schemas.py b/python/ribasim/ribasim/schemas.py index 2bcd22222..ac0292ccb 100644 --- a/python/ribasim/ribasim/schemas.py +++ b/python/ribasim/ribasim/schemas.py @@ -20,6 +20,11 @@ class Config: def _index_name(self) -> str: return "fid" + @pa.dataframe_parser + def _name_index(cls, df): + df.index.name = cls._index_name() + return df + @classmethod def migrate(cls, df: Any, schema_version: int) -> Any: f: Callable[[Any, Any], Any] = getattr( diff --git a/python/ribasim/tests/test_io.py b/python/ribasim/tests/test_io.py index 0320dca87..7c2dcf7b7 100644 --- a/python/ribasim/tests/test_io.py +++ b/python/ribasim/tests/test_io.py @@ -97,6 +97,11 @@ def test_extra_columns(): def test_index_tables(): p = pump.Static(flow_rate=[1.2]) assert p.df.index.name == "fid" + # Index name is applied by _name_index + df = p.df.reset_index(drop=True) + assert df.index.name is None + p.df = df + assert p.df.index.name == "fid" def test_extra_spatial_columns(): diff --git a/python/ribasim/tests/test_model.py b/python/ribasim/tests/test_model.py index f5e341561..9336b5275 100644 --- a/python/ribasim/tests/test_model.py +++ b/python/ribasim/tests/test_model.py @@ -112,6 +112,12 @@ def test_write_adds_fid_in_tables(basic, tmp_path): assert model_orig.edge.df.index.name == "edge_id" assert model_orig.edge.df.index.equals(pd.RangeIndex(1, nrow + 1)) + # Index name is applied by _name_index + df = model_orig.edge.df.copy() + df.index.name = "other" + model_orig.edge.df = df + assert model_orig.edge.df.index.name == "edge_id" + model_orig.write(tmp_path / "basic/ribasim.toml") with connect(tmp_path / "basic/database.gpkg") as connection: query = f"select * from {esc_id('Basin / profile')}" diff --git a/utils/templates/schemas.py.jinja b/utils/templates/schemas.py.jinja index 19b53c7ce..d986e4dc0 100644 --- a/utils/templates/schemas.py.jinja +++ b/utils/templates/schemas.py.jinja @@ -19,6 +19,11 @@ class _BaseSchema(pa.DataFrameModel): def _index_name(self) -> str: return "fid" + @pa.dataframe_parser + def _name_index(cls, df): + df.index.name = cls._index_name() + return df + @classmethod def migrate(cls, df: Any, schema_version: int) -> Any: f: Callable[[Any, Any], Any] = getattr(