model_output package#
Submodules#
ATS output readers#
Read ATS visualization HDF5 files (field / cycle / scalar cell values).
Supports current ats_vis_*_data.h5 and older visdump_data.h5 files.
The domain is read from the filename (ats_vis_data.h5 is the subsurface
domain, ats_vis_surface_data.h5 the surface), and a variable is found
under its plain name or with that domain’s prefix (domain-saturation_liquid),
as ATS names them; other names are selected with variable_map. Cell
centres come from the companion *_mesh.h5 file ATS writes beside the data.
- class PyHydroGeophysX.model_output.ats_output.ATSOutput(model_directory, filename=None, *, variable_map=None, cell_centers=None, time_unit=None)[source]#
Bases:
HDF5ModelOutputATS subsurface scalar output; returns one-dimensional cell arrays.
filenameis relative to model_directory or absolute. When omitted, exactly one of the standard subsurface filenames must exist.time_unitoverrides missing file metadata; otherwise an unknown unit remains None.- property mesh_filename#
The mesh file ATS writes beside the data file (
*_mesh.h5).
- class PyHydroGeophysX.model_output.ats_output.ATSPorosity(model_directory, filename=None, *, variable_map=None, cell_centers=None, time_unit=None)[source]#
Bases:
ATSOutputRead porosity with its own available cycles.
PFLOTRAN output readers#
Read PFLOTRAN snapshot HDF5 output with Time: <value> <unit> groups.
- class PyHydroGeophysX.model_output.pflotran_output.PFLOTRANOutput(model_directory, run_name=None, *, filename=None, variable_map=None, cell_centers=None)[source]#
Bases:
HDF5ModelOutputRead single-file or multiple-file snapshots in numerical time order.
Select a run using
run_name(matchesrun_name.h5and the numbered filesrun_name-NNN.h5of PFLOTRAN’s multiple-file output, and no other run’s files), or providefilenameexplicitly. Unstructured arrays and structured arrays retain their HDF5 shape and axes -(nx, ny, nz)for a structured grid, as PFLOTRAN writes it - andoutput_cell_centers()gives the cell centres in their C-order flattening. Mixed time units and duplicate snapshot times are rejected to avoid silently joining unrelated runs or restarts.- output_cell_centers(timestep_idx=0, *, axes=None)[source]#
Cell centres from the run’s own grid, in the C-order flattening of
load_timestep(timestep_idx).A structured grid’s
Coordinatesgroup holds the cell edges along x, y and z, and its fields are(nx, ny, nz); an unstructured grid’sDomaingroup holds the vertices and the XDMF cell connectivity. The snapshot’s own file is looked in first, then the run’s other files.
- class PyHydroGeophysX.model_output.pflotran_output.PFLOTRANPorosity(model_directory, run_name=None, *, filename=None, variable_map=None, cell_centers=None)[source]#
Bases:
PFLOTRANOutputRead snapshot porosity.
- class PyHydroGeophysX.model_output.pflotran_output.PFLOTRANSaturation(model_directory, run_name=None, *, filename=None, variable_map=None, cell_centers=None)[source]#
Bases:
PFLOTRANOutputRead liquid saturation without changing HDF5 axis order.
- class PyHydroGeophysX.model_output.pflotran_output.PFLOTRANWaterContent(model_directory, run_name=None, *, filename=None, variable_map=None, cell_centers=None)[source]#
Bases:
PFLOTRANOutputRead volumetric liquid water content calculated as porosity * saturation.
PyHydroGeophysX.model_output.base module#
Base classes for model output processing.
- class PyHydroGeophysX.model_output.base.HydroModelOutput(model_directory: str)[source]#
Bases:
ABCBase class for all hydrological model outputs.
- calculate_saturation(water_content: ndarray, porosity: float | ndarray) ndarray[source]#
Calculate saturation from water content and porosity.
- Parameters:
water_content – Water content array
porosity – Porosity value(s)
- Returns:
Saturation array
- abstractmethod get_timestep_info() List[Tuple][source]#
Get information about each timestep.
- Returns:
List of timestep information tuples
- abstractmethod load_time_range(start_idx: int = 0, end_idx: int | None = None, **kwargs) ndarray[source]#
Load data for a range of timesteps.
- Parameters:
start_idx – Starting timestep index
end_idx – Ending timestep index (exclusive)
**kwargs – Additional parameters specific to the model type
- Returns:
Data array for the specified timestep range
PyHydroGeophysX.model_output.modflow_output module#
Deprecated in 0.5.0 and removed in 0.6.0: a compatibility path that warns and
re-exports the MODFLOW readers from
PyHydroGeophysX.model_output.water_content, documented below.
PyHydroGeophysX.model_output.parflow_output module#
Module for processing ParFlow model outputs.
This module provides classes to handle specific types of ParFlow outputs, such as saturation and porosity, by reading ParFlow Binary Files (PFB). It includes a standalone PFB reader that works without the parflow package, falling back to the parflow package if available for maximum compatibility.
- class PyHydroGeophysX.model_output.parflow_output.ParflowOutput(model_directory: str, run_name: str)[source]#
Bases:
HydroModelOutputBase class for processing ParFlow model outputs.
This class handles common ParFlow output functionalities, such as identifying available timesteps and reading PFB files. It uses the standalone PFB reader that works without the parflow package installed.
- get_pfb_dimensions(pfb_file_path: str) Tuple[int, int, int][source]#
Reads a PFB file and returns its data dimensions (nz, ny, nx).
- Parameters:
pfb_file_path (str) – The full path to the PFB file.
- Returns:
- The dimensions of the data in the PFB file,
typically in (nz, ny, nx) order for ParFlow.
- Return type:
Tuple[int, int, int]
- Raises:
FileNotFoundError – If the pfb_file_path does not exist.
Exception – If self.read_pfb (from parflow.tools.io) fails to read the file.
- class PyHydroGeophysX.model_output.parflow_output.ParflowPorosity(model_directory: str, run_name: str)[source]#
Bases:
ParflowOutputProcesses porosity data from ParFlow simulations. Porosity in ParFlow is typically static (time-invariant) and stored in a single PFB file (e.g., <run_name>.out.porosity.pfb or similar).
- get_timestep_info() List[Tuple[int, float]][source]#
Returns timestep information, typically based on other ParFlow outputs (like saturation) as porosity itself is static.
- Returns:
- A list of (timestep_number, time_value) tuples,
derived from self.available_timesteps.
- Return type:
List[Tuple[int, float]]
- load_mask() ndarray[source]#
Load the domain mask data from a ParFlow model. The mask file (.out.mask.pfb) indicates active (1) and inactive (0) cells.
- Returns:
- A 3D NumPy array representing the domain mask (nz, ny, nx).
Values are typically 0 or 1.
- Return type:
np.ndarray
- Raises:
FileNotFoundError – If no standard mask PFB file can be found.
ValueError – If there’s an error reading or processing the PFB file.
- load_porosity() ndarray[source]#
Load the static porosity data from the ParFlow model.
It searches for common ParFlow porosity filename patterns within the model directory.
- Returns:
A 3D NumPy array of porosity values (nz, ny, nx).
- Return type:
np.ndarray
- Raises:
FileNotFoundError – If no standard porosity PFB file can be found.
ValueError – If there’s an error reading or processing the PFB file.
- load_time_range(start_idx: int = 0, end_idx: int | None = None, **kwargs: Any) ndarray[source]#
Load porosity data for a conceptual range of timesteps. Since porosity is time-invariant, this method returns a 4D array where the static 3D porosity data is repeated along the time axis.
The number of repetitions along the time axis (nt) is determined by the length of self.available_timesteps (discovered from saturation/pressure files) if end_idx is None, or by min(end_idx - start_idx, len(available_timesteps)). A minimum of 1 repetition is ensured if any timesteps are notionally available.
- Parameters:
start_idx (int, optional) – Starting timestep index (used to determine nt). Defaults to 0.
end_idx (Optional[int], optional) – Ending timestep index (exclusive, used for nt). Defaults to None (use all available timesteps).
**kwargs (Any) – Additional keyword arguments (not used).
- Returns:
- A 4D NumPy array of porosity values (nt, nz, ny, nx).
All slices along the time dimension are identical.
- Return type:
np.ndarray
- load_timestep(timestep_idx: int, **kwargs: Any) ndarray[source]#
Load porosity data. For ParFlow, porosity is typically time-invariant. This method returns the static porosity array, ignoring timestep_idx.
- Parameters:
timestep_idx (int) – Index of the timestep (ignored, as porosity is static).
**kwargs (Any) – Additional keyword arguments (not used).
- Returns:
A 3D NumPy array of porosity values (nz, ny, nx).
- Return type:
np.ndarray
- class PyHydroGeophysX.model_output.parflow_output.ParflowSaturation(model_directory: str, run_name: str)[source]#
Bases:
ParflowOutputProcesses saturation data from ParFlow simulations (.out.satur.*.pfb files).
- get_timestep_info() List[Tuple[int, float]][source]#
Provides information about available ParFlow timesteps.
For ParFlow, the timestep number from the filename often directly corresponds to the simulation time (e.g., if output is every 1 hour, timestep 24 is 24 hours). This method returns a list of tuples: (timestep_number, simulation_time). Currently, simulation_time is simply cast from timestep_number. More accurate time mapping would require parsing ParFlow timing files if complex.
- Returns:
- A list where each tuple is (timestep_number, time_value).
Time_value is float representation of timestep_number.
- Return type:
List[Tuple[int, float]]
- load_time_range(start_idx: int = 0, end_idx: int | None = None, **kwargs: Any) ndarray[source]#
Load saturation data for a specified range of zero-based timestep indices.
- Parameters:
start_idx (int, optional) – Starting zero-based timestep index. Defaults to 0.
end_idx (Optional[int], optional) – Ending zero-based timestep index (exclusive). If None, loads up to the last available timestep. Defaults to None.
**kwargs (Any) – Additional keyword arguments (not used).
- Returns:
- A 4D NumPy array of saturation values (num_timesteps, nz, ny, nx).
Returns an empty 4D array if the range is invalid or no data is found.
- Return type:
np.ndarray
- Raises:
ValueError – If no timesteps are available, or if the specified range is invalid (e.g., start_idx out of bounds, end_idx <= start_idx leading to empty range).
- load_timestep(timestep_idx: int, **kwargs: Any) ndarray[source]#
Load saturation data for a specific, zero-based timestep index.
- Parameters:
timestep_idx (int) – The zero-based index of the timestep to load from the list of available timesteps discovered during initialization.
**kwargs (Any) – Additional keyword arguments (not used by this method).
- Returns:
A 3D NumPy array of saturation values (nz, ny, nx).
- Return type:
np.ndarray
- Raises:
ValueError – If no timesteps are available or if timestep_idx is out of range.
- PyHydroGeophysX.model_output.parflow_output.read_pfb(filename: str) ndarray[source]#
Read a ParFlow Binary (PFB) file.
Attempts to use the parflow package if available, otherwise falls back to the standalone pure-Python reader.
- Parameters:
filename – Path to the .pfb file
- Returns:
3D array of shape (nz, ny, nx) containing the data
- Return type:
np.ndarray
- PyHydroGeophysX.model_output.parflow_output.read_pfb_standalone(filename: str) ndarray[source]#
Read a ParFlow Binary (PFB) file without requiring the parflow package.
This is a pure Python/NumPy implementation that parses the PFB file format directly. PFB files store 3D data in a hierarchical subgrid structure.
- Parameters:
filename – Path to the .pfb file
- Returns:
3D array of shape (nz, ny, nx) containing the data
- Return type:
np.ndarray
- Raises:
FileNotFoundError – If the file does not exist
ValueError – If the file format is invalid
PyHydroGeophysX.model_output.water_content module#
Module for processing MODFLOW model outputs.
- class PyHydroGeophysX.model_output.water_content.MODFLOWPorosity(model_directory: str, model_name: str)[source]#
Bases:
HydroModelOutputLegacy estimate of porosity from MODFLOW specific yield.
STO/UPW/LPF specific yield is drainable storage, not total porosity. This compatibility reader retains that proxy with a RuntimeWarning. Specific storage (inverse length) is never used as a porosity. Use an independently supplied porosity for quantitative petrophysical conversion. See the MODFLOW 6 GWF-STO and GWT-MST input guides.
- get_timestep_info() List[Tuple][source]#
Get information about each timestep in the model. Returns a minimal placeholder since porosity doesn’t vary with time.
- Returns:
List with single dummy timestep info
- load_porosity() ndarray[source]#
Estimate porosity using the legacy specific-yield proxy, with a warning.
Supports MODFLOW 6 and earlier versions. A missing storage package keeps the historical uniform 0.3 fallback, also with a RuntimeWarning. Specific storage is not a porosity and is never returned here.
- Returns:
3D array of porosity values (nlay, nrow, ncol)
- load_time_range(start_idx: int = 0, end_idx: int | None = None, **kwargs) ndarray[source]#
Load porosity for a range of timesteps. Since porosity is typically constant, this returns a stack of identical arrays.
- Parameters:
start_idx – Starting timestep index (unused)
end_idx – Ending timestep index (unused)
- Returns:
4D array of porosity values (nt, nlay, nrow, ncol) where all timesteps are identical
- load_timestep(timestep_idx: int, **kwargs) ndarray[source]#
Load porosity for a specific timestep. Note: For MODFLOW, porosity is typically constant over time, so this returns the same array regardless of timestep.
- Parameters:
timestep_idx – Index of the timestep (unused)
- Returns:
3D array of porosity values
- class PyHydroGeophysX.model_output.water_content.MODFLOWWaterContent(model_directory: str, idomain: ndarray)[source]#
Bases:
HydroModelOutputClass for processing water content data from MODFLOW simulations.
- get_timestep_info() List[Tuple[int, int, float, float]][source]#
Get information about each timestep in the WaterContent file.
- Returns:
List of tuples (kstp, kper, pertim, totim) for each timestep
- load_time_range(start_idx: int = 0, end_idx: int | None = None, nlay: int = 3) ndarray[source]#
Load water content for a range of timesteps.
- Parameters:
start_idx – Starting timestep index (default: 0)
end_idx – Ending timestep index (exclusive, default: None loads all)
nlay – Number of layers in the model (default: 3). Each record’s header states how many values it holds; a count other than nlay x the UZF cells raises ValueError instead of being read across the record boundary.
- Returns:
Water content array with shape (timesteps, nlay, nrows, ncols)
- load_timestep(timestep_idx: int, nlay: int = 3) ndarray[source]#
Load water content for a specific timestep.
- Parameters:
timestep_idx – Index of the timestep to load
nlay – Number of layers in the model
- Returns:
Water content array with shape (nlay, nrows, ncols)
- property sim_ws: str#
The simulation folder under its 0.3.0 name; use
model_directory.
- PyHydroGeophysX.model_output.water_content.binaryread(file: Any, vartype: type | List[Tuple[str, str]], shape: Tuple[int, ...] = (1,), charlen: int = 16) bytes | ndarray | void[source]#
Read one item from an open MODFLOW binary output file.
- Parameters:
file – Open file object in binary read mode (
file_objbefore 0.5.0). Any object withreadworks, anio.BytesIOincluded.vartype –
str, a NumPy dtype, or a structured dtype given as a list of(name, format)pairs.shape – Output shape for a plain dtype (default: (1,)).
charlen – Number of bytes read for
str(default: 16).
- Returns:
bytesforstr; for a structured dtype, the one record read, anumpy.voidwhose fields are read by name; otherwise an array ofshape. These are the types 0.3.0 returned.- Raises:
EOFError – When the file ends before the whole item is read.
Examples
>>> import io >>> header = [("kstp", "<i4"), ("kper", "<i4")] >>> record = binaryread(io.BytesIO(np.array([(3, 7)], dtype=header).tobytes()), header) >>> int(record["kstp"]), int(record["kper"]) (3, 7) >>> binaryread(io.BytesIO(np.arange(4.0).tobytes()), np.float64, shape=(2, 2)).tolist() [[0.0, 1.0], [2.0, 3.0]]
Module contents#
Module for processing model outputs from various hydrological models.
- class PyHydroGeophysX.model_output.ATSOutput(model_directory, filename=None, *, variable_map=None, cell_centers=None, time_unit=None)[source]#
Bases:
HDF5ModelOutputATS subsurface scalar output; returns one-dimensional cell arrays.
filenameis relative to model_directory or absolute. When omitted, exactly one of the standard subsurface filenames must exist.time_unitoverrides missing file metadata; otherwise an unknown unit remains None.- base_aliases = {'porosity': ('porosity', 'porosity.cell.0'), 'pressure': ('pressure', 'pressure.cell.0'), 'saturation': ('saturation_liquid', 'saturation_liquid.cell.0'), 'temperature': ('temperature', 'temperature.cell.0')}#
- property mesh_filename#
The mesh file ATS writes beside the data file (
*_mesh.h5).
- class PyHydroGeophysX.model_output.ATSPorosity(model_directory, filename=None, *, variable_map=None, cell_centers=None, time_unit=None)[source]#
Bases:
ATSOutputRead porosity with its own available cycles.
- variable = 'porosity'#
- class PyHydroGeophysX.model_output.ATSSaturation(model_directory, filename=None, *, variable_map=None, cell_centers=None, time_unit=None)[source]#
Bases:
ATSOutputRead liquid saturation in native ATS cell order.
- variable = 'saturation'#
- class PyHydroGeophysX.model_output.ATSWaterContent(model_directory, filename=None, *, variable_map=None, cell_centers=None, time_unit=None)[source]#
Bases:
ATSOutputRead volumetric liquid water content calculated as porosity * saturation.
- variable = 'water_content'#
- class PyHydroGeophysX.model_output.HydroModelOutput(model_directory: str)[source]#
Bases:
ABCBase class for all hydrological model outputs.
- calculate_saturation(water_content: ndarray, porosity: float | ndarray) ndarray[source]#
Calculate saturation from water content and porosity.
- Parameters:
water_content – Water content array
porosity – Porosity value(s)
- Returns:
Saturation array
- abstractmethod get_timestep_info() List[Tuple][source]#
Get information about each timestep.
- Returns:
List of timestep information tuples
- abstractmethod load_time_range(start_idx: int = 0, end_idx: int | None = None, **kwargs) ndarray[source]#
Load data for a range of timesteps.
- Parameters:
start_idx – Starting timestep index
end_idx – Ending timestep index (exclusive)
**kwargs – Additional parameters specific to the model type
- Returns:
Data array for the specified timestep range
- class PyHydroGeophysX.model_output.MODFLOWPorosity(model_directory: str, model_name: str)[source]#
Bases:
HydroModelOutputLegacy estimate of porosity from MODFLOW specific yield.
STO/UPW/LPF specific yield is drainable storage, not total porosity. This compatibility reader retains that proxy with a RuntimeWarning. Specific storage (inverse length) is never used as a porosity. Use an independently supplied porosity for quantitative petrophysical conversion. See the MODFLOW 6 GWF-STO and GWT-MST input guides.
- get_timestep_info() List[Tuple][source]#
Get information about each timestep in the model. Returns a minimal placeholder since porosity doesn’t vary with time.
- Returns:
List with single dummy timestep info
- load_porosity() ndarray[source]#
Estimate porosity using the legacy specific-yield proxy, with a warning.
Supports MODFLOW 6 and earlier versions. A missing storage package keeps the historical uniform 0.3 fallback, also with a RuntimeWarning. Specific storage is not a porosity and is never returned here.
- Returns:
3D array of porosity values (nlay, nrow, ncol)
- load_time_range(start_idx: int = 0, end_idx: int | None = None, **kwargs) ndarray[source]#
Load porosity for a range of timesteps. Since porosity is typically constant, this returns a stack of identical arrays.
- Parameters:
start_idx – Starting timestep index (unused)
end_idx – Ending timestep index (unused)
- Returns:
4D array of porosity values (nt, nlay, nrow, ncol) where all timesteps are identical
- load_timestep(timestep_idx: int, **kwargs) ndarray[source]#
Load porosity for a specific timestep. Note: For MODFLOW, porosity is typically constant over time, so this returns the same array regardless of timestep.
- Parameters:
timestep_idx – Index of the timestep (unused)
- Returns:
3D array of porosity values
- class PyHydroGeophysX.model_output.MODFLOWWaterContent(model_directory: str, idomain: ndarray)[source]#
Bases:
HydroModelOutputClass for processing water content data from MODFLOW simulations.
- get_timestep_info() List[Tuple[int, int, float, float]][source]#
Get information about each timestep in the WaterContent file.
- Returns:
List of tuples (kstp, kper, pertim, totim) for each timestep
- load_time_range(start_idx: int = 0, end_idx: int | None = None, nlay: int = 3) ndarray[source]#
Load water content for a range of timesteps.
- Parameters:
start_idx – Starting timestep index (default: 0)
end_idx – Ending timestep index (exclusive, default: None loads all)
nlay – Number of layers in the model (default: 3). Each record’s header states how many values it holds; a count other than nlay x the UZF cells raises ValueError instead of being read across the record boundary.
- Returns:
Water content array with shape (timesteps, nlay, nrows, ncols)
- load_timestep(timestep_idx: int, nlay: int = 3) ndarray[source]#
Load water content for a specific timestep.
- Parameters:
timestep_idx – Index of the timestep to load
nlay – Number of layers in the model
- Returns:
Water content array with shape (nlay, nrows, ncols)
- property sim_ws: str#
The simulation folder under its 0.3.0 name; use
model_directory.
- class PyHydroGeophysX.model_output.PFLOTRANOutput(model_directory, run_name=None, *, filename=None, variable_map=None, cell_centers=None)[source]#
Bases:
HDF5ModelOutputRead single-file or multiple-file snapshots in numerical time order.
Select a run using
run_name(matchesrun_name.h5and the numbered filesrun_name-NNN.h5of PFLOTRAN’s multiple-file output, and no other run’s files), or providefilenameexplicitly. Unstructured arrays and structured arrays retain their HDF5 shape and axes -(nx, ny, nz)for a structured grid, as PFLOTRAN writes it - andoutput_cell_centers()gives the cell centres in their C-order flattening. Mixed time units and duplicate snapshot times are rejected to avoid silently joining unrelated runs or restarts.- aliases = {'porosity': ('Porosity', 'Porosity [ ]', 'Porosity [-]'), 'pressure': ('Liquid_Pressure', 'Liquid_Pressure [Pa]'), 'saturation': ('Liquid_Saturation', 'Liquid_Saturation [ ]', 'Liquid_Saturation [-]'), 'temperature': ('Temperature', 'Temperature [C]')}#
- output_cell_centers(timestep_idx=0, *, axes=None)[source]#
Cell centres from the run’s own grid, in the C-order flattening of
load_timestep(timestep_idx).A structured grid’s
Coordinatesgroup holds the cell edges along x, y and z, and its fields are(nx, ny, nz); an unstructured grid’sDomaingroup holds the vertices and the XDMF cell connectivity. The snapshot’s own file is looked in first, then the run’s other files.
- class PyHydroGeophysX.model_output.PFLOTRANPorosity(model_directory, run_name=None, *, filename=None, variable_map=None, cell_centers=None)[source]#
Bases:
PFLOTRANOutputRead snapshot porosity.
- variable = 'porosity'#
- class PyHydroGeophysX.model_output.PFLOTRANSaturation(model_directory, run_name=None, *, filename=None, variable_map=None, cell_centers=None)[source]#
Bases:
PFLOTRANOutputRead liquid saturation without changing HDF5 axis order.
- variable = 'saturation'#
- class PyHydroGeophysX.model_output.PFLOTRANWaterContent(model_directory, run_name=None, *, filename=None, variable_map=None, cell_centers=None)[source]#
Bases:
PFLOTRANOutputRead volumetric liquid water content calculated as porosity * saturation.
- variable = 'water_content'#
- class PyHydroGeophysX.model_output.ParflowPorosity(model_directory: str, run_name: str)[source]#
Bases:
ParflowOutputProcesses porosity data from ParFlow simulations. Porosity in ParFlow is typically static (time-invariant) and stored in a single PFB file (e.g., <run_name>.out.porosity.pfb or similar).
- get_timestep_info() List[Tuple[int, float]][source]#
Returns timestep information, typically based on other ParFlow outputs (like saturation) as porosity itself is static.
- Returns:
- A list of (timestep_number, time_value) tuples,
derived from self.available_timesteps.
- Return type:
List[Tuple[int, float]]
- load_mask() ndarray[source]#
Load the domain mask data from a ParFlow model. The mask file (.out.mask.pfb) indicates active (1) and inactive (0) cells.
- Returns:
- A 3D NumPy array representing the domain mask (nz, ny, nx).
Values are typically 0 or 1.
- Return type:
np.ndarray
- Raises:
FileNotFoundError – If no standard mask PFB file can be found.
ValueError – If there’s an error reading or processing the PFB file.
- load_porosity() ndarray[source]#
Load the static porosity data from the ParFlow model.
It searches for common ParFlow porosity filename patterns within the model directory.
- Returns:
A 3D NumPy array of porosity values (nz, ny, nx).
- Return type:
np.ndarray
- Raises:
FileNotFoundError – If no standard porosity PFB file can be found.
ValueError – If there’s an error reading or processing the PFB file.
- load_time_range(start_idx: int = 0, end_idx: int | None = None, **kwargs: Any) ndarray[source]#
Load porosity data for a conceptual range of timesteps. Since porosity is time-invariant, this method returns a 4D array where the static 3D porosity data is repeated along the time axis.
The number of repetitions along the time axis (nt) is determined by the length of self.available_timesteps (discovered from saturation/pressure files) if end_idx is None, or by min(end_idx - start_idx, len(available_timesteps)). A minimum of 1 repetition is ensured if any timesteps are notionally available.
- Parameters:
start_idx (int, optional) – Starting timestep index (used to determine nt). Defaults to 0.
end_idx (Optional[int], optional) – Ending timestep index (exclusive, used for nt). Defaults to None (use all available timesteps).
**kwargs (Any) – Additional keyword arguments (not used).
- Returns:
- A 4D NumPy array of porosity values (nt, nz, ny, nx).
All slices along the time dimension are identical.
- Return type:
np.ndarray
- load_timestep(timestep_idx: int, **kwargs: Any) ndarray[source]#
Load porosity data. For ParFlow, porosity is typically time-invariant. This method returns the static porosity array, ignoring timestep_idx.
- Parameters:
timestep_idx (int) – Index of the timestep (ignored, as porosity is static).
**kwargs (Any) – Additional keyword arguments (not used).
- Returns:
A 3D NumPy array of porosity values (nz, ny, nx).
- Return type:
np.ndarray
- class PyHydroGeophysX.model_output.ParflowSaturation(model_directory: str, run_name: str)[source]#
Bases:
ParflowOutputProcesses saturation data from ParFlow simulations (.out.satur.*.pfb files).
- get_timestep_info() List[Tuple[int, float]][source]#
Provides information about available ParFlow timesteps.
For ParFlow, the timestep number from the filename often directly corresponds to the simulation time (e.g., if output is every 1 hour, timestep 24 is 24 hours). This method returns a list of tuples: (timestep_number, simulation_time). Currently, simulation_time is simply cast from timestep_number. More accurate time mapping would require parsing ParFlow timing files if complex.
- Returns:
- A list where each tuple is (timestep_number, time_value).
Time_value is float representation of timestep_number.
- Return type:
List[Tuple[int, float]]
- load_time_range(start_idx: int = 0, end_idx: int | None = None, **kwargs: Any) ndarray[source]#
Load saturation data for a specified range of zero-based timestep indices.
- Parameters:
start_idx (int, optional) – Starting zero-based timestep index. Defaults to 0.
end_idx (Optional[int], optional) – Ending zero-based timestep index (exclusive). If None, loads up to the last available timestep. Defaults to None.
**kwargs (Any) – Additional keyword arguments (not used).
- Returns:
- A 4D NumPy array of saturation values (num_timesteps, nz, ny, nx).
Returns an empty 4D array if the range is invalid or no data is found.
- Return type:
np.ndarray
- Raises:
ValueError – If no timesteps are available, or if the specified range is invalid (e.g., start_idx out of bounds, end_idx <= start_idx leading to empty range).
- load_timestep(timestep_idx: int, **kwargs: Any) ndarray[source]#
Load saturation data for a specific, zero-based timestep index.
- Parameters:
timestep_idx (int) – The zero-based index of the timestep to load from the list of available timesteps discovered during initialization.
**kwargs (Any) – Additional keyword arguments (not used by this method).
- Returns:
A 3D NumPy array of saturation values (nz, ny, nx).
- Return type:
np.ndarray
- Raises:
ValueError – If no timesteps are available or if timestep_idx is out of range.
- PyHydroGeophysX.model_output.binaryread(file: Any, vartype: type | List[Tuple[str, str]], shape: Tuple[int, ...] = (1,), charlen: int = 16) bytes | ndarray | void[source]#
Read one item from an open MODFLOW binary output file.
- Parameters:
file – Open file object in binary read mode (
file_objbefore 0.5.0). Any object withreadworks, anio.BytesIOincluded.vartype –
str, a NumPy dtype, or a structured dtype given as a list of(name, format)pairs.shape – Output shape for a plain dtype (default: (1,)).
charlen – Number of bytes read for
str(default: 16).
- Returns:
bytesforstr; for a structured dtype, the one record read, anumpy.voidwhose fields are read by name; otherwise an array ofshape. These are the types 0.3.0 returned.- Raises:
EOFError – When the file ends before the whole item is read.
Examples
>>> import io >>> header = [("kstp", "<i4"), ("kper", "<i4")] >>> record = binaryread(io.BytesIO(np.array([(3, 7)], dtype=header).tobytes()), header) >>> int(record["kstp"]), int(record["kper"]) (3, 7) >>> binaryread(io.BytesIO(np.arange(4.0).tobytes()), np.float64, shape=(2, 2)).tolist() [[0.0, 1.0], [2.0, 3.0]]