imod.ipf - IPF file I/O

Functions for reading and writing iMOD Point Files (IDFs) to pandas.DataFrame.

The primary functions to use are imod.ipf.read() and imod.ipf.save(), though lower level functions are also available.

imod.ipf.read(path, kwargs={}, assoc_kwargs={})[source]

Read one or more IPF files to a single pandas.DataFrame, including associated (TXT) files.

The different IPF files can be from different model layers, and column names may differ between them.

Note that this function always returns a pandas.DataFrame. IPF files always contain spatial information, for which geopandas.GeoDataFrame is a better fit, in principle. However, GeoDataFrames are not the best fit for the associated data.

To perform spatial operations on the points, you’re likely best served by (temporarily) creating a GeoDataFrame, doing the spatial operation, and then using the output to select values in the original DataFrame. Please refer to the examples.

Parameters
  • path (pathlib.Path or str) – globpath for IPF files to read.

  • kwargs (dict) – Dictionary containing the pandas.read_csv() keyword arguments for the IPF files (e.g. {“delim_whitespace”: True})

  • assoc_kwargs (dict) – Dictionary containing the pandas.read_csv() keyword arguments for the associated (TXT) files (e.g. {“delim_whitespace”: True})

Returns

Return type

pandas.DataFrame

Examples

Read an IPF file into a dataframe:

>>> import imod
>>> df = imod.ipf.read("example.ipf")

Convert the x and y data into a GeoDataFrame, do a spatial operation, and use it to select points within a polygon. Note: gpd.points_from_xy() requires a geopandas version >= 0.5.

>>> import geopandas as gpd
>>> polygon = gpd.read_file("polygon.shp").geometry[0]
>>> ipf_points = gpd.GeoDataFrame(geometry=gpd.points_from_xy(df["x"], df["y"]))
>>> within_polygon = ipf_points.within(polygon)
>>> selection = df[within_polygon]

The same exercise is a little more complicated when associated files (like timeseries) are involved, since many duplicate values of x and y will exist. The easiest way to isolate these is by applying a groupby, and then taking first of x and y of every group:

>>> df = imod.ipf.read("example_with_time.ipf")
>>> first = df.groupby("id").first()  # replace "id" by what your ID column is called
>>> x = first["x"]
>>> y = first["y"]
>>> id_code = first.index  # id is a reserved keyword in python
>>> ipf_points = gpd.GeoDataFrame(geometry=gpd.points_from_xy(x, y))
>>> within_polygon = ipf_points.within(polygon)

Using the result is a little more complicated as well, since it has to be mapped back to many duplicate values of the original dataframe. There are two options. First, by using the index:

>>> within_polygon.index = id_code
>>> df = df.set_index("id")
>>> selection = df[within_polygon]

If you do not wish to change index on the original dataframe, use pandas.DataFrame.merge() instead.

>>> import pandas as pd
>>> within_polygon = pd.DataFrame({"within": within_polygon})
>>> within_polygon["id"] = id_code
>>> df = df.merge(within_polygon, on="id")
>>> df = df[df["within"]]
imod.ipf.read_associated(path, kwargs={})[source]

Read an IPF associated file (TXT).

Parameters
  • path (pathlib.Path or str) – Path to associated file.

  • kwargs (dict) – Dictionary containing the pandas.read_csv() keyword arguments for the associated (TXT) file (e.g. {“delim_whitespace”: True}).

Returns

Return type

pandas.DataFrame

imod.ipf.save(path, df, itype=None, assoc_ext='txt', nodata=1e+20)[source]

Saves the contents of a pandas DataFrame to one or more IPF files, and associated (TXT) files.

Can write multiple IPF files if one of the columns is named “layer”. In turn, multiple associated (TXT) files may written for each of these IPF files.

Parameters
  • path (pathlib.Path or str) – path of the written IPF file. Any associated files are written relative to this path, based on the ID column.

  • df (pandas.DataFrame) – DataFrame containing the data to write.

  • itype (int or str or None) –

    IPF type. Defaults to None, in which case no associated files are created. Possible other values, either integer or string:

    • 1 or "timeseries"

    • 2 or "borehole1d"

    • 3 or "cpt"

    • 4 or "borehole3d"

  • assoc_ext (str) – Extension of the associated files. Defaults to “txt”.

  • nodata (float) – The value given to nodata values. These are generally NaN (Not-a-Number) in pandas, but this leads to errors in iMOD(FLOW) for IDFs. Defaults to value of 1.0e20 instead.

Returns

Writes files.

Return type

None

imod.ipf.write(path, df, indexcolumn=0, assoc_ext='txt', nodata=1e+20)[source]

Writes a single IPF file.

Parameters
  • path (pathlib.Path or str) – path of the written IPF file. Any associated files are written relative to this path, based on the ID column.

  • df (pandas.DataFrame) – DataFrame containing the data to write.

  • indexcolumn (integer) – number of the column containg the paths to the associated (TXT) files. Defaults to a value of 0 (no associated files).

  • assoc_ext (str) – Extension of the associated files. Defaults to “txt”.

Returns

Writes a file.

Return type

None

imod.ipf.write_assoc(path, df, itype=1, nodata=1e+20)[source]

Writes a single IPF associated (TXT) file.

Parameters
  • path (pathlib.Path or str) – Path for the written associated file.

  • df (pandas.DataFrame) – DataFrame containing the data to write.

  • itype (int or str) –

    IPF type. Possible values, either integer or string:

    1 : “timeseries” 2 : “borehole1d” 3 : “cpt” 4 : “borehole3d”

  • nodata (float) – The value given to nodata values. These are generally NaN (Not-a-Number) in pandas, but this leads to errors in iMOD(FLOW) for IDFs. Defaults to value of 1.0e20 instead.

Returns

Writes a file.

Return type

None