Skip to content

Issue #326: Add ISG parser - #1951

Open
evetion wants to merge 4 commits into
masterfrom
isg-parser
Open

evetion wants to merge 4 commits into
masterfrom
isg-parser

Conversation

@evetion

@evetion evetion commented Oct 28, 2026 •

Copy link
Copy Markdown
Member

Fixes #326

Description

This adds an ISG reader in the hydrolib/geolib/ribasim style. That is, each file is represented by one class, as closely as possible. Responsibilities are abstracted into mixin classes and sometimes inherited. Details are in the README.md file. I've copied most docstrings (per method/attribute) directly from the pdf.

The ISG is read when present in a project, but it isn't (cannot be) used in writing.

I've used the iMOD tutorials for testing, I still need to

  • upload them to pooch(?)

@sonarqubecloud

Copy link
Copy Markdown

Comment thread docs/api/changelog.rst
:meth:`imod.formats.isg.ISG.read`, including segment geometry, cross-sections
and plots.
- :func:`imod.data.isg_tutorials` to load the SFR and LAK tutorials of the iMOD
User Manual, with ISG-files.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

iMOD Python currently doesn't support the SFR package for MODFLOW 6. So mentioning that will lead to confusion, I reckon. I'd keep it more generic:

:func:imod.data.isg_tutorials to load example ISG data from the iMOD5 tutorials.

@JoerivanEngelen JoerivanEngelen left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My review pt 2. Will continue later

Comment thread docs/api/io.rst
Comment on lines +33 to +43
isg.ISG
isg.ISP
isg.ISD1
isg.RivISD2
isg.SfrISD2
isg.ISC1
isg.ISC2
isg.IST1
isg.IST2
isg.ISQ1
isg.ISQ2

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you compare this to the other functions in the formats API, this is different. I don't really like the allcaps here, that makes it look like a constant. Up to now we didn't expose constants to the public API (That is: They are not in the documentation)

Comment thread imod/formats/isg/isg.py

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's quite a departure of how we implemented the readers for the IPF and IDF files, but I think this looks quite neat. Our users will appreciate the plotting and geometry functions.

Comment thread imod/formats/isg/isg.py
Comment on lines +97 to +100
"""
Number of data records in the ISD2-file that describes the timeserie of the
calculation point.
"""

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've never seen this kind of documentation to document dataclass variables. Is this common practice? We normally go for listing them under a PARAMETERS header in the main docstring.

@JoerivanEngelen JoerivanEngelen left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is quite a clean implementation, with some cool features for users: the quick access to geometries and plotting.

(I was thinking, this might be an interesting data model for the IPF file (iMOD Point File) as well. But might be overkill)

My main gripes are the following:

  • The docstring style of the dataclass differs from the way dataclass docstrings are implemented elsewhere, especially the arguments. Could you change that?
  • This is quite a different API than our users are used to. I think they would expect something like a function like imod.isg.read(path) to read their files. This would then return our custom dataclass instead of the vanilla geodataframe/dataframe/DataArray/Dataset that they are used to. Adding examples in the docstrings for the documentation, as well as adding examples to examples/user-guide/11-imod5-files.py
  • Some of the implementation notes added by the LLM to the docstring add confusion, as they are conflicting with previous text from the iMOD5 docs. In that case, I'd just like to know the truth, and a small internal note that the iMOD5 docs said something different which turned out to be untrue.

Comment thread pyproject.toml
"pandas",
"pooch",
"pydantic",
"pydantic>=2.7",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The developer env is specified in the pixi.toml, you might consider also adding setting this there to properly generate the pixi.lock. I see an update of the pixi.lock file, but no pixi.toml?

Comment thread .gitignore
Comment on lines +149 to +151
iMOD_User_Manual*.pdf
*.[Ii][Ss][GgPp]
*.[Ii][Ss][DdCcTtQq][12]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these files just for personal testing or generated in tests? I think we can leave this out of .gitignore, now that you are done, right?

Comment thread imod/formats/prj/prj.py
for entry in system_entries:
if entry["path"] not in models:
models[entry["path"]] = _try_read_with_func(ISG.read, entry["path"])
time, repeats = _process_ipf_time(entry, periods, repeats)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great that you could reuse _process_ipf_time here, perhaps good to rename this function than to something like _process_ipf_isg_time (I couldn't come up with a better name now, but hopefully you can think of something better)

Comment thread imod/formats/isg/views.py
Comment on lines +227 to +228
Zm + Zc / 100. Implementation note: Zc carries the sign, e.g. -23.43 is
stored as Zm=-23, Zc=-43.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at the example: he sign is in both Zm and Zc? That doesn't seem to be implied by "Zc carries the sign".

Comment thread imod/formats/isg/isg.py
ctime: Vector[np.str_] | None = None
"""
Time representation as hh:mm:ss. This additional record is only applicable
for double precision ISD2-files. It is not used yet!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean with "It is not used yet!" ? And when is it used?

Comment thread imod/formats/isg/isg.py
Comment on lines +637 to +639
Maximum size of each label is 52 characters.

Implementation note: iMOD reads 50 characters.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So which one is it in the end?

return self.geodataframe().plot(ax=ax, **kwargs)

@property
def __geo_interface__(self) -> dict[str, Any]:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this comes from https://geopandas.org/en/stable/docs/reference/api/geopandas.GeoDataFrame.__geo_interface__.html, but for what is this necessary? Do we need the magic method here to properly work with geopandas for plotting or something? If so, add that to the docstring please.

Comment thread imod/formats/isg/utils.py
return start + offset


def to_datetime(idate: np.ndarray, ctime: np.ndarray | None = None) -> pd.DatetimeIndex:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: There already is to_datetime function under imod.util.time (which is public API), which is called in quite a few places (via to_datetime_internal). Consider renaming this function (though it is under a different namespace) to distinguish it and avoid confusion.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add support for reading ISG files

2 participants