I/O Modules#
The I/O modules provide functionality for reading and writing IWFM model files in various formats.
Core I/O#
ASCII Module#
The ASCII module provides readers and writers for IWFM’s text-based file formats.
ASCII file I/O handlers for IWFM model files.
This module provides functions for reading and writing IWFM ASCII input files including node coordinates, element definitions, and stratigraphy data.
- pyiwfm.io.ascii.read_nodes(filepath)[source]#
Read node coordinates from an IWFM node file.
- Expected format (C2VSimFG format):
NNODES # Number of nodes FACT # Conversion factor (optional) ID X Y (one line per node)
- pyiwfm.io.ascii.read_elements(filepath)[source]#
Read element definitions from an IWFM element file.
- Expected format:
NELEM / Number of elements NSUBREGION / Number of subregions ID NAME (one line per subregion) ID V1 V2 V3 V4 SR (one line per element, V4=0 for triangles)
- Parameters:
- Returns:
Tuple of (elements dict, number of subregions, subregion names dict). The names dict maps subregion ID to name string (may be empty if no names could be parsed from the file).
- Raises:
FileFormatError – If file format is invalid
- Return type:
- pyiwfm.io.ascii.read_stratigraphy(filepath)[source]#
Read stratigraphy data from an IWFM stratigraphy file.
- IWFM format (matches Fortran Class_Stratigraphy.f90):
NL # Number of layers FACT # Conversion factor ID GS W(1) W(2) … (one line per node)
- Where W values are alternating aquitard/aquifer thicknesses:
W(1) = aquitard thickness layer 1 W(2) = aquifer thickness layer 1 W(3) = aquitard thickness layer 2 W(4) = aquifer thickness layer 2 etc.
Top and bottom elevations are computed from GS and cumulative thicknesses.
- Parameters:
- Returns:
Stratigraphy object
- Raises:
FileFormatError – If file format is invalid
- Return type:
- pyiwfm.io.ascii.write_nodes(filepath, nodes, header=None)[source]#
Write node coordinates to an IWFM node file.
- pyiwfm.io.ascii.write_elements(filepath, elements, n_subregions, header=None)[source]#
Write element definitions to an IWFM element file.
- pyiwfm.io.ascii.write_stratigraphy(filepath, stratigraphy, header=None)[source]#
Write stratigraphy data to an IWFM stratigraphy file.
- IWFM format uses THICKNESSES, not elevations:
NL / Number of layers FACT / Conversion factor ID GS W(1) W(2) … (one line per node)
- Where W values are alternating aquitard/aquifer thicknesses:
W(1) = aquitard thickness layer 1 (gs - top_layer_1) W(2) = aquifer thickness layer 1 (top_layer_1 - bottom_layer_1) W(3) = aquitard thickness layer 2 (bottom_layer_1 - top_layer_2) W(4) = aquifer thickness layer 2 (top_layer_2 - bottom_layer_2) etc.
- Parameters:
stratigraphy (Stratigraphy) – Stratigraphy object
header (str | None) – Optional header comment
Binary Module#
The binary module provides readers and writers for IWFM’s Fortran binary formats.
Binary file I/O handlers for IWFM model files.
This module provides classes for reading and writing IWFM binary files:
FortranBinaryReader/FortranBinaryWriter: Fortran unformatted sequential-access files (record markers around each write).StreamAccessBinaryReader: Raw byte-stream files matching IWFM’sACCESS='STREAM'(no record markers; caller supplies counts).
- pyiwfm.io.binary.read_fortran_record(f, endian='<')[source]#
Read a single Fortran unformatted record from an open file.
Fortran unformatted sequential files bracket each record with 4-byte integer markers that encode the record length in bytes.
- class pyiwfm.io.binary.FortranBinaryReader(filepath, endian='<')[source]#
Bases:
objectReader for Fortran unformatted binary files.
Handles the record markers that Fortran writes before and after each record.
- skip_records(n)[source]#
Skip n records without reading their data.
- Parameters:
n (int) – Number of records to skip
- get_position()[source]#
Get current file position.
- Returns:
Current byte offset in the file
- Return type:
- seek_to_position(pos)[source]#
Seek to a specific position in the file.
- Parameters:
pos (int) – Byte offset to seek to
- read_mixed_record(dtype_spec)[source]#
Read a record containing mixed data types.
- Parameters:
dtype_spec (list[tuple[str, int]]) – List of (dtype, count) tuples specifying the record format. dtype can be: ‘i4’ (int32), ‘i8’ (int64), ‘f4’ (float32), ‘f8’ (float64), ‘S’ followed by length (e.g., ‘S30’ for 30-char string)
- Returns:
Tuple of values read from the record
- Return type:
Example
>>> reader.read_mixed_record([('i4', 1), ('f8', 3), ('S30', 1)]) (42, array([1.0, 2.0, 3.0]), 'SOME_STRING')
- read_character_record(length)[source]#
Read a character record of specified length.
Unlike read_string, this reads exactly ‘length’ bytes from the record without assuming the entire record is the string.
- class pyiwfm.io.binary.FortranBinaryWriter(filepath, endian='<')[source]#
Bases:
objectWriter for Fortran unformatted binary files.
Writes record markers before and after each record.
- class pyiwfm.io.binary.StreamAccessBinaryReader(filepath, endian='<')[source]#
Bases:
objectReader for IWFM stream-access binary files (
ACCESS='STREAM').Unlike
FortranBinaryReader, IWFM preprocessor binary output is written withACCESS='STREAM'which produces raw bytes without the 4-byte record-length markers that Fortran sequential writes add. The caller must supply explicit counts for every array read.
HDF5 Module#
The HDF5 module provides readers and writers for HDF5-based storage.
HDF5 file I/O handlers for IWFM model files.
This module provides functions for reading and writing IWFM model data in HDF5 format, which provides efficient storage for large datasets and supports compression.
- class pyiwfm.io.hdf5.HDF5ModelWriter(filepath, compression='gzip')[source]#
Bases:
objectWriter for IWFM model data in HDF5 format.
- The HDF5 file structure:
- /mesh/
nodes/x, y, area, is_boundary elements/vertices, subregion, area subregions/id, name
- /stratigraphy/
gs_elev, top_elev, bottom_elev, active_node
- /timeseries/
{variable}/{location}/times, values
- /metadata/
name, version, created, …
- write_timeseries(ts, variable)[source]#
Write a time series to the HDF5 file.
- Parameters:
ts (TimeSeries) – TimeSeries to write
variable (str) – Variable name (e.g., ‘head’, ‘flow’)
- class pyiwfm.io.hdf5.HDF5ModelReader(filepath)[source]#
Bases:
objectReader for IWFM model data from HDF5 format.
- read_timeseries(variable, location)[source]#
Read a time series from the HDF5 file.
- Parameters:
- Returns:
TimeSeries instance
- Return type:
Base Classes#
Abstract base classes for readers and writers.
Base classes for IWFM file I/O.
This module provides abstract base classes for reading and writing IWFM model files in various formats, including support for comment preservation during round-trip operations.
- class pyiwfm.io.base.FileInfo(path, format, version=None, description='', metadata=<factory>)[source]#
Bases:
objectInformation about an IWFM file.
- __init__(path, format, version=None, description='', metadata=<factory>)#
- class pyiwfm.io.base.BaseReader(filepath)[source]#
Bases:
ABCAbstract base class for IWFM file readers.
- class pyiwfm.io.base.BaseWriter(filepath)[source]#
Bases:
ABCAbstract base class for IWFM file writers.
- class pyiwfm.io.base.ModelReader(filepath)[source]#
Bases:
BaseReaderAbstract base class for reading complete IWFM models.
- abstractmethod read()[source]#
Read the model from file(s).
- Returns:
Complete IWFMModel instance
- Return type:
- abstractmethod read_mesh()[source]#
Read only the mesh from the model files.
- Returns:
AppGrid instance
- Return type:
- class pyiwfm.io.base.ModelWriter(filepath)[source]#
Bases:
BaseWriterAbstract base class for writing complete IWFM models.
- abstractmethod write(model)[source]#
Write the model to file(s).
- Parameters:
model (IWFMModel) – IWFMModel instance to write
- abstractmethod write_mesh(mesh)[source]#
Write only the mesh.
- Parameters:
mesh (AppGrid) – AppGrid instance to write
- abstractmethod write_stratigraphy(stratigraphy)[source]#
Write only the stratigraphy.
- Parameters:
stratigraphy (Stratigraphy) – Stratigraphy instance to write
- class pyiwfm.io.base.BinaryReader(filepath, endian='<')[source]#
Bases:
BaseReaderBase class for reading IWFM binary files.
- RECORD_MARKER_SIZE = 4#
- class pyiwfm.io.base.BinaryWriter(filepath, endian='<')[source]#
Bases:
BaseWriterBase class for writing IWFM binary files.
- RECORD_MARKER_SIZE = 4#
- class pyiwfm.io.base.CommentAwareReader(filepath, preserve_comments=True)[source]#
Bases:
BaseReaderBase class for readers that preserve comments.
This class extends BaseReader to extract and preserve comments from IWFM input files during reading. The extracted comment metadata can be used later for round-trip preservation.
Example
>>> reader = MyCommentAwareReader("Preprocessor.in", preserve_comments=True) >>> data = reader.read() >>> metadata = reader.comment_metadata >>> metadata.save_for_file("Preprocessor.in")
- Variables:
preserve_comments – Whether to extract and store comments.
_comment_metadata – Extracted comment metadata (lazy-loaded).
- property comment_metadata: CommentMetadata | None#
Get extracted comment metadata.
Returns None if preserve_comments is False or if comments have not been extracted yet.
- class pyiwfm.io.base.CommentAwareWriter(filepath, comment_metadata=None, use_templates_for_missing=True)[source]#
Bases:
BaseWriterBase class for writers that can restore preserved comments.
This class extends BaseWriter to support injecting preserved comments into output files, enabling round-trip preservation of user comments.
Example
>>> # Load metadata from sidecar file >>> metadata = CommentMetadata.load_for_file("Preprocessor.in") >>> writer = MyCommentAwareWriter("output/Preprocessor.in", metadata) >>> writer.write(data)
- Variables:
comment_metadata – CommentMetadata to use for restoration.
use_templates_for_missing – If True, use template defaults when no preserved comments exist.
- __init__(filepath, comment_metadata=None, use_templates_for_missing=True)[source]#
Initialize the comment-aware writer.
- Parameters:
filepath (Path | str) – Path to the output file.
comment_metadata (CommentMetadata | None) – CommentMetadata with preserved comments.
use_templates_for_missing (bool) – If True, use default templates when no preserved comments exist.
Writer Base#
Template-based writer base classes used by all component writers.
Enhanced base writer classes for IWFM file generation.
This module provides abstract base classes for writing IWFM files, supporting both text and DSS output formats, with optional comment preservation for round-trip operations.
- class pyiwfm.io.writer_base.TemplateWriter(output_dir, template_engine=None, comment_metadata=None)[source]#
Bases:
ABCBase class for template-based IWFM file writers.
Uses Jinja2 templates for file headers and structure, with numpy for efficient large data array output.
Supports optional comment preservation via CommentMetadata. When comment_metadata is provided, preserved comments from the original file will be injected into the output.
- __init__(output_dir, template_engine=None, comment_metadata=None)[source]#
Initialize the template writer.
- Parameters:
output_dir (Path | str) – Directory for output files
template_engine (TemplateEngine | None) – Optional TemplateEngine instance
comment_metadata (CommentMetadata | None) – Optional CommentMetadata for comment preservation
- property comment_writer: CommentWriter#
Get or create the comment writer.
- Returns:
CommentWriter instance configured with our comment_metadata.
- render_header_with_comments(template_name, section_name=None, **context)[source]#
Render a template header with preserved comments.
If comment_metadata is available and contains preserved comments, those comments are used instead of or in addition to the template.
- write_data_block(file, data, fmt='%14.6f', header_comment=None)[source]#
Write a numpy array as a formatted data block.
- write_indexed_data(file, ids, data, id_fmt='%5d', data_fmt='%14.6f')[source]#
Write indexed data (ID column + data columns).
- class pyiwfm.io.writer_base.TimeSeriesSpec(name, dates, values, units='', location='', parameter='', interval='1DAY')[source]#
Bases:
objectSpecification for a time series to write.
- __init__(name, dates, values, units='', location='', parameter='', interval='1DAY')#
- class pyiwfm.io.writer_base.TimeSeriesWriter(output_config, output_dir)[source]#
Bases:
objectWriter for time series data with text/DSS format support.
Can write time series to: - ASCII text files (one or more columns) - HEC-DSS files (requires heclib)
- __init__(output_config, output_dir)[source]#
Initialize the time series writer.
- Parameters:
output_config (TimeSeriesOutputConfig) – Configuration for output format
- write_timeseries(ts_spec, text_file=None)[source]#
Write a single time series.
- Parameters:
ts_spec (TimeSeriesSpec) – Time series specification
text_file (str | Path | None) – Text file name (required if format includes TEXT)
- class pyiwfm.io.writer_base.ComponentWriter(output_dir, ts_config=None, template_engine=None, comment_metadata=None)[source]#
Bases:
TemplateWriterBase class for IWFM component writers (GW, Streams, Lakes, etc.).
Provides common functionality for writing component input files with support for both text and DSS time series formats.
Supports optional comment preservation via CommentMetadata.
- __init__(output_dir, ts_config=None, template_engine=None, comment_metadata=None)[source]#
Initialize the component writer.
- Parameters:
output_dir (Path | str) – Directory for output files
ts_config (TimeSeriesOutputConfig | None) – Time series output configuration
template_engine (TemplateEngine | None) – Optional TemplateEngine instance
comment_metadata (CommentMetadata | None) – Optional CommentMetadata for comment preservation
- property ts_writer: TimeSeriesWriter#
Get or create the time series writer.
- write_component_header(file, component_name, version='', description='')[source]#
Write a standard component file header.
- class pyiwfm.io.writer_base.IWFMModelWriter(model, output_dir, ts_format=OutputFormat.TEXT, template_engine=None, comment_metadata=None)[source]#
Bases:
ABCAbstract base class for writing complete IWFM models.
Coordinates all component writers to produce a complete, valid IWFM input file set.
Supports optional comment preservation via FileCommentMetadata.
- __init__(model, output_dir, ts_format=OutputFormat.TEXT, template_engine=None, comment_metadata=None)[source]#
Initialize the model writer.
- Parameters:
model (IWFMModel) – IWFMModel instance to write
output_dir (Path | str) – Directory for output files
ts_format (OutputFormat) – Output format for time series (TEXT, DSS, or BOTH)
template_engine (TemplateEngine | None) – Optional TemplateEngine instance
comment_metadata (CommentMetadata | None) – Optional CommentMetadata for comment preservation
Writer Configuration#
Configuration dataclasses for the model writer system.
File configuration classes for IWFM model I/O.
These dataclasses define the file structure and naming conventions for IWFM model input/output, supporting both text and DSS formats.
- class pyiwfm.io.config.OutputFormat(*values)[source]#
Bases:
EnumOutput format for time series data.
- TEXT = 'text'#
- DSS = 'dss'#
- BOTH = 'both'#
- class pyiwfm.io.config.TimeSeriesOutputConfig(format=OutputFormat.TEXT, dss_file=None, dss_a_part='', dss_f_part='PYIWFM')[source]#
Bases:
objectConfiguration for time series output format.
- format: OutputFormat = 'text'#
- __init__(format=OutputFormat.TEXT, dss_file=None, dss_a_part='', dss_f_part='PYIWFM')#
- class pyiwfm.io.config.PreProcessorFileConfig(output_dir, main_file='Preprocessor.in', node_file='Nodes.dat', element_file='Elements.dat', stratigraphy_file='Stratigraphy.dat', stream_config_file='StreamConfig.dat', lake_config_file='LakeConfig.dat', binary_output_file='Preprocessor.bin', stream_version='5.0', lake_version='5.0')[source]#
Bases:
objectConfiguration for PreProcessor input/output files.
Defines file names for all preprocessor components.
- __init__(output_dir, main_file='Preprocessor.in', node_file='Nodes.dat', element_file='Elements.dat', stratigraphy_file='Stratigraphy.dat', stream_config_file='StreamConfig.dat', lake_config_file='LakeConfig.dat', binary_output_file='Preprocessor.bin', stream_version='5.0', lake_version='5.0')#
- class pyiwfm.io.config.GWFileConfig(output_dir, main_file='Groundwater.dat', aquifer_params_file='AquiferParameters.dat', bc_main_file='BoundaryConditions.dat', specified_head_bc_file='SpecifiedHeadBC.dat', specified_flow_bc_file='SpecifiedFlowBC.dat', general_head_bc_file='GeneralHeadBC.dat', constrained_ghbc_file='ConstrainedGHBC.dat', pumping_main_file='Pumping.dat', well_spec_file='WellSpecs.dat', element_pumping_file='ElementPumping.dat', pumping_rates_file='PumpingRates.dat', tile_drain_file='TileDrains.dat', subsidence_file='Subsidence.dat', ts_config=<factory>)[source]#
Bases:
objectConfiguration for groundwater component files.
Supports both text and DSS output formats for time series.
- ts_config: TimeSeriesOutputConfig#
- __init__(output_dir, main_file='Groundwater.dat', aquifer_params_file='AquiferParameters.dat', bc_main_file='BoundaryConditions.dat', specified_head_bc_file='SpecifiedHeadBC.dat', specified_flow_bc_file='SpecifiedFlowBC.dat', general_head_bc_file='GeneralHeadBC.dat', constrained_ghbc_file='ConstrainedGHBC.dat', pumping_main_file='Pumping.dat', well_spec_file='WellSpecs.dat', element_pumping_file='ElementPumping.dat', pumping_rates_file='PumpingRates.dat', tile_drain_file='TileDrains.dat', subsidence_file='Subsidence.dat', ts_config=<factory>)#
- class pyiwfm.io.config.StreamFileConfig(output_dir, version='5.0', main_file='Streams.dat', inflow_file='StreamInflows.dat', diversion_spec_file='DiversionSpecs.dat', diversion_data_file='DiversionData.dat', bypass_spec_file='BypassSpecs.dat', bypass_data_file='BypassData.dat', surface_area_file='StreamSurfaceArea.dat', ts_config=<factory>)[source]#
Bases:
objectConfiguration for stream component files.
- ts_config: TimeSeriesOutputConfig#
- __init__(output_dir, version='5.0', main_file='Streams.dat', inflow_file='StreamInflows.dat', diversion_spec_file='DiversionSpecs.dat', diversion_data_file='DiversionData.dat', bypass_spec_file='BypassSpecs.dat', bypass_data_file='BypassData.dat', surface_area_file='StreamSurfaceArea.dat', ts_config=<factory>)#
- class pyiwfm.io.config.LakeFileConfig(output_dir, version='5.0', main_file='Lakes.dat', max_elevation_file='MaxLakeElevations.dat', lake_elements_file='LakeElements.dat', lake_outflow_file='LakeOutflows.dat', ts_config=<factory>)[source]#
Bases:
objectConfiguration for lake component files.
- ts_config: TimeSeriesOutputConfig#
- __init__(output_dir, version='5.0', main_file='Lakes.dat', max_elevation_file='MaxLakeElevations.dat', lake_elements_file='LakeElements.dat', lake_outflow_file='LakeOutflows.dat', ts_config=<factory>)#
- class pyiwfm.io.config.RootZoneFileConfig(output_dir, version='5.0', main_file='RootZone.dat', ag_water_supply_file='AgWaterSupply.dat', moisture_source_file='MoistureSource.dat', irrigation_period_file='IrrigationPeriod.dat', return_flow_file='ReturnFlow.dat', reuse_fraction_file='ReuseFraction.dat', nonponded_main_file='NonPondedCrops.dat', nonponded_area_file='NonPondedArea.dat', irrigation_target_file='IrrigationTarget.dat', min_soil_moisture_file='MinSoilMoisture.dat', min_perc_factor_file='MinPercFactor.dat', root_depth_file='RootDepth.dat', ponded_main_file='PondedCrops.dat', ponded_area_file='PondedArea.dat', pond_depth_file='PondDepth.dat', pond_operation_file='PondOperation.dat', native_main_file='NativeRiparian.dat', native_area_file='NativeArea.dat', urban_main_file='Urban.dat', urban_area_file='UrbanArea.dat', urban_water_use_file='UrbanWaterUse.dat', urban_population_file='UrbanPopulation.dat', ts_config=<factory>)[source]#
Bases:
objectConfiguration for root zone component files.
- ts_config: TimeSeriesOutputConfig#
- __init__(output_dir, version='5.0', main_file='RootZone.dat', ag_water_supply_file='AgWaterSupply.dat', moisture_source_file='MoistureSource.dat', irrigation_period_file='IrrigationPeriod.dat', return_flow_file='ReturnFlow.dat', reuse_fraction_file='ReuseFraction.dat', nonponded_main_file='NonPondedCrops.dat', nonponded_area_file='NonPondedArea.dat', irrigation_target_file='IrrigationTarget.dat', min_soil_moisture_file='MinSoilMoisture.dat', min_perc_factor_file='MinPercFactor.dat', root_depth_file='RootDepth.dat', ponded_main_file='PondedCrops.dat', ponded_area_file='PondedArea.dat', pond_depth_file='PondDepth.dat', pond_operation_file='PondOperation.dat', native_main_file='NativeRiparian.dat', native_area_file='NativeArea.dat', urban_main_file='Urban.dat', urban_area_file='UrbanArea.dat', urban_water_use_file='UrbanWaterUse.dat', urban_population_file='UrbanPopulation.dat', ts_config=<factory>)#
- class pyiwfm.io.config.SmallWatershedFileConfig(output_dir, version='4.1', main_file='SmallWatersheds.dat')[source]#
Bases:
objectConfiguration for small watershed component files.
- __init__(output_dir, version='4.1', main_file='SmallWatersheds.dat')#
- class pyiwfm.io.config.UnsatZoneFileConfig(output_dir, main_file='UnsatZone.dat')[source]#
Bases:
objectConfiguration for unsaturated zone component files.
- __init__(output_dir, main_file='UnsatZone.dat')#
- class pyiwfm.io.config.SimulationFileConfig(output_dir, main_file='Simulation.in', precip_file='Precipitation.dat', et_file='Evapotranspiration.dat', crop_coef_file='CropCoefficients.dat', supply_adjust_file='SupplyAdjustment.dat', _groundwater=None, _streams=None, _lakes=None, _rootzone=None, _small_watersheds=None, _unsatzone=None, ts_format=OutputFormat.TEXT, dss_file='Simulation.dss', gw_version='4.0', stream_version='5.0', lake_version='5.0', rootzone_version='5.0', small_watershed_version='4.1')[source]#
Bases:
objectConfiguration for complete simulation file set.
Orchestrates all component configurations.
- ts_format: OutputFormat = 'text'#
- property groundwater: GWFileConfig#
- property streams: StreamFileConfig#
- property lakes: LakeFileConfig#
- property rootzone: RootZoneFileConfig#
- property small_watersheds: SmallWatershedFileConfig#
- property unsatzone: UnsatZoneFileConfig#
- __init__(output_dir, main_file='Simulation.in', precip_file='Precipitation.dat', et_file='Evapotranspiration.dat', crop_coef_file='CropCoefficients.dat', supply_adjust_file='SupplyAdjustment.dat', _groundwater=None, _streams=None, _lakes=None, _rootzone=None, _small_watersheds=None, _unsatzone=None, ts_format=OutputFormat.TEXT, dss_file='Simulation.dss', gw_version='4.0', stream_version='5.0', lake_version='5.0', rootzone_version='5.0', small_watershed_version='4.1')#
- class pyiwfm.io.config.BudgetFileConfig(output_dir, main_file='Budget.in')[source]#
Bases:
objectConfiguration for budget post-processor files.
- __init__(output_dir, main_file='Budget.in')#
- class pyiwfm.io.config.ZBudgetFileConfig(output_dir, main_file='ZBudget.in', zone_definition_file='ZoneDefinitions.dat')[source]#
Bases:
objectConfiguration for zone budget post-processor files.
- __init__(output_dir, main_file='ZBudget.in', zone_definition_file='ZoneDefinitions.dat')#
- class pyiwfm.io.config.ModelOutputConfig(output_dir, model_name='IWFM_Model', ts_format=OutputFormat.TEXT, stream_version='5.0', lake_version='5.0', rootzone_version='5.0', preprocessor_subdir='Preprocessor', simulation_subdir='Simulation', _preprocessor=None, _simulation=None)[source]#
Bases:
objectComplete model output configuration.
Coordinates preprocessor and simulation file configs.
- ts_format: OutputFormat = 'text'#
- property preprocessor: PreProcessorFileConfig#
- property simulation: SimulationFileConfig#
- __init__(output_dir, model_name='IWFM_Model', ts_format=OutputFormat.TEXT, stream_version='5.0', lake_version='5.0', rootzone_version='5.0', preprocessor_subdir='Preprocessor', simulation_subdir='Simulation', _preprocessor=None, _simulation=None)#
- class pyiwfm.io.config.ModelWriteConfig(output_dir, ts_format=OutputFormat.TEXT, dss_file='model.dss', dss_a_part='', dss_f_part='PYIWFM', copy_source_ts=True, model_name='IWFM_Model', gw_version='4.0', stream_version='4.0', lake_version='4.0', rootzone_version='4.12', file_paths=<factory>)[source]#
Bases:
objectConfiguration for writing a complete IWFM model with per-file path control.
Every output file has a standardized key and a default relative path (producing a nested layout). Users can override any path via the
file_pathsdict. The writer usesget_path()for absolute paths andget_relative_path()for IWFM-compatible relative references between config files.Examples
Default nested layout:
config = ModelWriteConfig(output_dir=Path("C:/models/my_model"))
Flat layout (all files in one directory):
config = ModelWriteConfig.flat(output_dir=Path("C:/models/flat"))
Custom layout:
config = ModelWriteConfig(output_dir=Path("C:/models/custom")) config.set_file("gw_main", "groundwater/main.dat") config.set_file("stream_main", "surface/streams.dat")
- ts_format: OutputFormat = 'text'#
- DEFAULT_PATHS: ClassVar[dict[str, str]] = {'dss_ts_file': 'Simulation/climate_data.dss', 'elements': 'Preprocessor/Elements.dat', 'et': 'Simulation/ET.dat', 'gw_bc_main': 'Simulation/GW/BC_MAIN.dat', 'gw_bound_tsd': 'Simulation/GW/BoundTSD.dat', 'gw_elem_pump': 'Simulation/GW/ElemPump.dat', 'gw_main': 'Simulation/GW/GW_MAIN.dat', 'gw_pump_main': 'Simulation/GW/Pump_MAIN.dat', 'gw_spec_flow_bc': 'Simulation/GW/SpecFlowBC.dat', 'gw_spec_head_bc': 'Simulation/GW/SpecHeadBC.dat', 'gw_subsidence': 'Simulation/GW/Subsidence.dat', 'gw_tile_drain': 'Simulation/GW/TileDrain.dat', 'gw_ts_pumping': 'Simulation/GW/TSPumping.dat', 'gw_well_spec': 'Simulation/GW/WellSpec.dat', 'irig_frac': 'Simulation/IrigFrac.dat', 'lake_config': 'Preprocessor/LakeConfig.dat', 'lake_main': 'Simulation/Lake/Lake_MAIN.dat', 'lake_max_elev': 'Simulation/Lake/MaxLakeElev.dat', 'nodes': 'Preprocessor/Nodes.dat', 'precipitation': 'Simulation/Precip.dat', 'preprocessor_bin': 'Simulation/PreProcessor.bin', 'preprocessor_main': 'Preprocessor/Preprocessor.in', 'results_diver_detail': 'Results/DiverDetail.hdf', 'results_final_lake_elev': 'Results/FinalLakeElev.out', 'results_final_uz': 'Results/FinalUZ.out', 'results_gw_budget': 'Results/GW.hdf', 'results_gw_head': 'Results/GWHeadAll.out', 'results_gw_zbudget': 'Results/GW_ZBud.hdf', 'results_lake_budget': 'Results/LakeBud.hdf', 'results_lwu_budget': 'Results/LWU.hdf', 'results_lwu_zbudget': 'Results/LWU_ZBud.hdf', 'results_pump_output': 'Results/ElemWellPumping.out', 'results_rz_budget': 'Results/RootZone.hdf', 'results_rz_zbudget': 'Results/RootZone_ZBud.hdf', 'results_strm_budget': 'Results/StrmBud.hdf', 'results_strm_hyd': 'Results/StrmHyd.out', 'results_strm_node_budget': 'Results/StrmNodeBud.hdf', 'results_uz_budget': 'Results/UZBud.hdf', 'results_uz_zbudget': 'Results/UZZBud.hdf', 'rootzone_irig_period': 'Simulation/RootZone/IrigPeriod.dat', 'rootzone_main': 'Simulation/RootZone/RootZone_MAIN.dat', 'rootzone_native': 'Simulation/RootZone/NativeRiparian.dat', 'rootzone_nonponded': 'Simulation/RootZone/NonPondedCrops.dat', 'rootzone_ponded': 'Simulation/RootZone/PondedCrops.dat', 'rootzone_return_flow': 'Simulation/RootZone/ReturnFlowFrac.dat', 'rootzone_reuse': 'Simulation/RootZone/ReuseFrac.dat', 'rootzone_surface_flow_dest': 'Simulation/RootZone/SurfaceFlowDest.dat', 'rootzone_urban': 'Simulation/RootZone/Urban.dat', 'simulation_main': 'Simulation/Simulation_MAIN.IN', 'stratigraphy': 'Preprocessor/Stratigraphy.dat', 'stream_bypass_specs': 'Simulation/Stream/BypassSpecs.dat', 'stream_config': 'Preprocessor/StreamConfig.dat', 'stream_diver_specs': 'Simulation/Stream/DiverSpecs.dat', 'stream_diversions': 'Simulation/Stream/Diversions.dat', 'stream_inflow': 'Simulation/Stream/StreamInflow.dat', 'stream_main': 'Simulation/Stream/Stream_MAIN.dat', 'supply_adjust': 'Simulation/SupplyAdjust.dat', 'swshed_main': 'Simulation/SmallWatersheds/SWatersheds.dat', 'unsatzone_main': 'Simulation/UnsatZone.dat'}#
- get_relative_path(from_key, to_key)[source]#
Compute relative path from one file’s directory to another file.
This produces the path string that IWFM writes in its config files. For example, Simulation_MAIN.IN references GW_MAIN.dat as
GW\GW_MAIN.dat.Uses
os.path.relpathto handle arbitrary directory structures including paths that require..traversal.
- set_file(file_key, relative_path)[source]#
Set a custom path for a file key (relative to output_dir).
- classmethod nested(output_dir, **kwargs)[source]#
Create config with standard nested layout (default).
- __init__(output_dir, ts_format=OutputFormat.TEXT, dss_file='model.dss', dss_a_part='', dss_f_part='PYIWFM', copy_source_ts=True, model_name='IWFM_Model', gw_version='4.0', stream_version='4.0', lake_version='4.0', rootzone_version='4.12', file_paths=<factory>)#
Writer Configuration Base#
Shared base dataclass (BaseComponentWriterConfig) for all component writer
configs (groundwater, streams, lakes, root zone, small watersheds, unsaturated
zone). Provides common fields: output_dir, version, length_factor,
length_unit, volume_factor, volume_unit, subdir.
Base configuration for IWFM component file writers.
Provides BaseComponentWriterConfig, a dataclass base that
encapsulates the fields common to every component writer config
(groundwater, streams, lakes, root zone, small watersheds, and
unsaturated zone).
Subclasses override _get_subdir() and _get_main_file()
to provide the component-specific defaults, while inheriting the
output_dir, version, component_dir, and main_path
interface.
- class pyiwfm.io.writer_config_base.BaseComponentWriterConfig(output_dir, version='4.0')[source]#
Bases:
objectBase configuration shared by all IWFM component writers.
- Variables:
output_dir (
Path) – Base output directory (typically<model>/Simulation).version (
str) – IWFM component version string (e.g."4.0").
- __init__(output_dir, version='4.0')#
PreProcessor I/O#
PreProcessor Module#
The preprocessor module provides functions for loading and saving complete IWFM models.
PreProcessor file I/O handlers for IWFM models.
This module provides functions for reading and writing IWFM PreProcessor input files, which define the model structure and input file paths.
- class pyiwfm.io.preprocessor.PreProcessorConfig(base_dir, model_name='', nodes_file=None, elements_file=None, stratigraphy_file=None, subregions_file=None, streams_file=None, lakes_file=None, groundwater_file=None, rootzone_file=None, pumping_file=None, output_dir=None, budget_output_file=None, heads_output_file=None, n_layers=1, length_unit='FT', area_unit='ACRES', volume_unit='AF', metadata=<factory>)[source]#
Bases:
objectConfiguration from an IWFM PreProcessor main input file.
Contains paths to all component input files and model settings.
- __init__(base_dir, model_name='', nodes_file=None, elements_file=None, stratigraphy_file=None, subregions_file=None, streams_file=None, lakes_file=None, groundwater_file=None, rootzone_file=None, pumping_file=None, output_dir=None, budget_output_file=None, heads_output_file=None, n_layers=1, length_unit='FT', area_unit='ACRES', volume_unit='AF', metadata=<factory>)#
- pyiwfm.io.preprocessor.read_preprocessor_main(filepath)[source]#
Read an IWFM PreProcessor main input file.
The main input file contains paths to all component input files and basic model configuration.
- Expected format (simplified):
Model Name / Description nodes.dat / NODES_FILE elements.dat / ELEMENTS_FILE stratigraphy.dat / STRAT_FILE …
- pyiwfm.io.preprocessor.read_subregions_file(filepath)[source]#
Read subregion definitions from a subregions file.
- Expected format:
NSUBREGION / Number of subregions ID NAME (one line per subregion)
- pyiwfm.io.preprocessor.write_preprocessor_main(filepath, config, header=None)[source]#
Write an IWFM PreProcessor main input file.
- Parameters:
config (PreProcessorConfig) – PreProcessorConfig with file paths and settings
header (str | None) – Optional header comment
- pyiwfm.io.preprocessor.save_model_to_preprocessor(model, output_dir, model_name=None)[source]#
Save an IWFMModel to PreProcessor input files.
Creates all necessary input files in the output directory.
- Parameters:
- Returns:
PreProcessorConfig with paths to created files
- Return type:
- pyiwfm.io.preprocessor.save_complete_model(model, output_dir, timeseries_format='ascii', dss_file=None, file_paths=None)[source]#
Save a complete IWFM model to all input files.
This is the main function for exporting a complete model, including all component files (groundwater, streams, lakes, rootzone), time series, and the preprocessor/simulation control files.
Delegates to
CompleteModelWriterfor the actual writing.- Parameters:
model (IWFMModel) – IWFMModel to save
timeseries_format (str) – Format for time series data (“ascii” or “dss”)
dss_file (Path | str | None) – Path to DSS file for time series (if format is “dss”)
file_paths (dict[str, str] | None) – Optional dict of {file_key: relative_path} overrides. If None, uses default nested layout.
- Returns:
Dictionary mapping file type to output path
- Return type:
Example
>>> from pyiwfm.io import save_complete_model >>> files = save_complete_model(model, Path("./model_output")) >>> print(f"Wrote {len(files)} files")
PreProcessor Binary#
Reader for IWFM preprocessor binary output files.
PreProcessor Binary File Reader for IWFM.
This module reads the binary output file produced by the IWFM PreProcessor.
The binary file uses ACCESS='STREAM' (raw bytes, no Fortran record
markers) and contains pre-processed mesh, stratigraphy, and component data
that enables faster simulation startup.
- class pyiwfm.io.preprocessor_binary.AppNodeData(id, area, boundary_node, n_connected_node, n_face_id, surrounding_elements, connected_nodes, face_ids, elem_id_on_ccw_side, irrotational_coeff)[source]#
Bases:
objectPre-processed application node data.
- __init__(id, area, boundary_node, n_connected_node, n_face_id, surrounding_elements, connected_nodes, face_ids, elem_id_on_ccw_side, irrotational_coeff)#
- class pyiwfm.io.preprocessor_binary.AppElementData(id, subregion, area, face_ids, vertex_areas, vertex_area_fractions, integral_del_shp_i_del_shp_j, integral_rot_del_shp_i_del_shp_j)[source]#
Bases:
objectPre-processed application element data.
- __init__(id, subregion, area, face_ids, vertex_areas, vertex_area_fractions, integral_del_shp_i_del_shp_j, integral_rot_del_shp_i_del_shp_j)#
- class pyiwfm.io.preprocessor_binary.AppFaceData(nodes, elements, boundary, lengths)[source]#
Bases:
objectPre-processed application face data.
- __init__(nodes, elements, boundary, lengths)#
- class pyiwfm.io.preprocessor_binary.SubregionData(id, name, n_elements, n_neighbor_regions, area, region_elements, neighbor_region_ids, neighbor_n_boundary_faces, neighbor_boundary_faces)[source]#
Bases:
objectPre-processed subregion data.
- __init__(id, name, n_elements, n_neighbor_regions, area, region_elements, neighbor_region_ids, neighbor_n_boundary_faces, neighbor_boundary_faces)#
- class pyiwfm.io.preprocessor_binary.StratigraphyData(n_layers, ground_surface_elev, top_elev, bottom_elev, active_node, active_layer_above, active_layer_below, top_active_layer, bottom_active_layer)[source]#
Bases:
objectPre-processed stratigraphy data.
- __init__(n_layers, ground_surface_elev, top_elev, bottom_elev, active_node, active_layer_above, active_layer_below, top_active_layer, bottom_active_layer)#
- class pyiwfm.io.preprocessor_binary.StreamGWConnectorData(n_stream_nodes, gw_nodes, layers)[source]#
Bases:
objectPre-processed stream-GW connector data.
- __init__(n_stream_nodes, gw_nodes, layers)#
- class pyiwfm.io.preprocessor_binary.LakeGWConnectorData(n_lakes, lake_elements, lake_nodes)[source]#
Bases:
objectPre-processed lake-GW connector data.
- __init__(n_lakes, lake_elements, lake_nodes)#
- class pyiwfm.io.preprocessor_binary.StreamLakeConnectorData(n_connections, stream_nodes, lake_ids)[source]#
Bases:
objectPre-processed stream-lake connector data.
- __init__(n_connections, stream_nodes, lake_ids)#
- class pyiwfm.io.preprocessor_binary.StreamData(n_reaches, n_stream_nodes, reach_ids, reach_names, reach_upstream_nodes, reach_downstream_nodes, reach_outflow_dest)[source]#
Bases:
objectPre-processed stream data.
- __init__(n_reaches, n_stream_nodes, reach_ids, reach_names, reach_upstream_nodes, reach_downstream_nodes, reach_outflow_dest)#
- class pyiwfm.io.preprocessor_binary.LakeData(n_lakes, lake_ids, lake_names, lake_max_elevations, lake_elements)[source]#
Bases:
objectPre-processed lake data.
- __init__(n_lakes, lake_ids, lake_names, lake_max_elevations, lake_elements)#
- class pyiwfm.io.preprocessor_binary.PreprocessorBinaryData(n_nodes=0, n_elements=0, n_faces=0, n_subregions=0, n_boundary_faces=0, x=<factory>, y=<factory>, n_vertex=<factory>, vertex=<factory>, app_nodes=<factory>, app_elements=<factory>, app_faces=None, boundary_face_list=<factory>, subregions=<factory>, stratigraphy=None, stream_lake_connector=None, stream_gw_connector=None, lake_gw_connector=None, lakes=None, streams=None, matrix_n_equations=0, matrix_connectivity=<factory>)[source]#
Bases:
objectComplete preprocessor binary output structure.
- app_nodes: list[AppNodeData]#
- app_elements: list[AppElementData]#
- app_faces: AppFaceData | None = None#
- subregions: list[SubregionData]#
- stratigraphy: StratigraphyData | None = None#
- stream_lake_connector: StreamLakeConnectorData | None = None#
- stream_gw_connector: StreamGWConnectorData | None = None#
- lake_gw_connector: LakeGWConnectorData | None = None#
- streams: StreamData | None = None#
- __init__(n_nodes=0, n_elements=0, n_faces=0, n_subregions=0, n_boundary_faces=0, x=<factory>, y=<factory>, n_vertex=<factory>, vertex=<factory>, app_nodes=<factory>, app_elements=<factory>, app_faces=None, boundary_face_list=<factory>, subregions=<factory>, stratigraphy=None, stream_lake_connector=None, stream_gw_connector=None, lake_gw_connector=None, lakes=None, streams=None, matrix_n_equations=0, matrix_connectivity=<factory>)#
- class pyiwfm.io.preprocessor_binary.PreprocessorBinaryReader(endian='<')[source]#
Bases:
objectReader for IWFM PreProcessor binary output files.
The preprocessor binary uses
ACCESS='STREAM'(raw bytes, no Fortran record markers). All arrays are written with explicit lengths that must be derived from dimension counts read earlier in the file.Section read order (matching IWFM Fortran
WritePreprocessedData):AppGrid — dimensions, coordinates, connectivity, per-node/element data, face data, boundary faces, subregions
Stratigraphy — NLayers, TopActiveLayer, ActiveNode, GSElev, TopElev, BottomElev (2-D arrays in Fortran column-major order)
StrmLakeConnector — 3 sub-connectors (stream→lake, lake→stream, lake→lake), each with count + source/dest arrays
StrmGWConnector — version int, then gw_node/layer arrays
LakeGWConnector — per-lake element/node arrays
AppLake — version int, per-lake data with rating tables
AppStream — version int, per-node rating tables, per-reach metadata
Matrix — sparse structure (optional)
PreProcessor Writer#
Writer for IWFM preprocessor input files (nodes, elements, stratigraphy).
PreProcessor file writers for IWFM models.
This module provides writers for all preprocessor input files, enabling complete round-trip read/write of IWFM models.
- class pyiwfm.io.preprocessor_writer.PreProcessorWriter(model, config, template_engine=None)[source]#
Bases:
TemplateWriterWriter for IWFM PreProcessor input files.
Writes complete preprocessor file sets including: - Main control file - Node coordinates - Element configuration - Stratigraphy data - Stream configuration (optional) - Lake configuration (optional)
Example
>>> from pyiwfm.core.model import IWFMModel >>> from pyiwfm.io.preprocessor_writer import PreProcessorWriter >>> from pyiwfm.io.config import PreProcessorFileConfig >>> >>> # Load a model >>> model = IWFMModel.from_preprocessor("model/Preprocessor.in") >>> >>> # Write to new location >>> config = PreProcessorFileConfig(output_dir="output/Preprocessor") >>> writer = PreProcessorWriter(model, config) >>> writer.write_all()
- __init__(model, config, template_engine=None)[source]#
Initialize the preprocessor writer.
- Parameters:
model (
IWFMModel) – Model to writeconfig (
PreProcessorFileConfig) – Output file configurationtemplate_engine (
TemplateEngine, optional) – Custom template engine
- write_all()[source]#
Write all preprocessor files.
- Returns:
Mapping of file type to output path
- Return type:
dict[str,Path]
- write_main()[source]#
Write the main preprocessor control file.
- Returns:
Path to written file
- Return type:
Path
- write_nodes()[source]#
Write the node coordinates file.
- Returns:
Path to written file
- Return type:
Path
- write_elements()[source]#
Write the element configuration file.
- Returns:
Path to written file
- Return type:
Path
- write_stratigraphy()[source]#
Write the stratigraphy data file.
IWFM stratigraphy format uses THICKNESSES, not elevations: - ID, GSElev, W(1), W(2), W(3), W(4), … - W(2*i-1) = aquitard thickness above layer i (from previous bottom or GS to layer top) - W(2*i) = aquifer thickness of layer i (from layer top to layer bottom)
For NLayers layers, each row has 2 + 2*NLayers columns.
- Returns:
Path to written file
- Return type:
Path
- pyiwfm.io.preprocessor_writer.write_preprocessor_files(model, output_dir, stream_version='5.0', lake_version='5.0')[source]#
Write all preprocessor files for a model.
- Parameters:
- Returns:
Mapping of file type to output path
- Return type:
dict[str,Path]
Example
>>> from pyiwfm.core.model import IWFMModel >>> from pyiwfm.io.preprocessor_writer import write_preprocessor_files >>> >>> model = IWFMModel.from_preprocessor("model/Preprocessor.in") >>> results = write_preprocessor_files(model, "output/Preprocessor") >>> print(results["main"]) output/Preprocessor/Preprocessor.in
- pyiwfm.io.preprocessor_writer.write_nodes_file(output_path, node_ids, x_coords, y_coords, coord_factor=1.0)[source]#
Write a standalone nodes file.
- pyiwfm.io.preprocessor_writer.write_elements_file(output_path, element_ids, vertices, subregions, subregion_names=None)[source]#
Write a standalone elements file.
- Parameters:
- Returns:
Path to written file
- Return type:
Path
- pyiwfm.io.preprocessor_writer.write_stratigraphy_file(output_path, node_ids, ground_surface, layer_tops, layer_bottoms, elev_factor=1.0)[source]#
Write a standalone stratigraphy file in IWFM format.
IWFM stratigraphy uses THICKNESSES, not elevations: - ID, GSElev, W(1), W(2), W(3), W(4), … - W(2*i-1) = aquitard thickness above layer i - W(2*i) = aquifer thickness of layer i
- Parameters:
output_path (
Pathorstr) – Output file pathnode_ids (
NDArray[np.intp]) – Node IDsground_surface (
NDArray[np.float64]) – Ground surface elevations (n_nodes,)layer_tops (
NDArray[np.float64]) – Layer top elevations (n_nodes, n_layers)layer_bottoms (
NDArray[np.float64]) – Layer bottom elevations (n_nodes, n_layers)elev_factor (
float) – Elevation conversion factor
- Returns:
Path to written file
- Return type:
Path
Simulation I/O#
Simulation Module#
The simulation module provides readers and writers for IWFM simulation control files.
Simulation control I/O handlers for IWFM model files.
This module provides functions for reading and writing IWFM simulation control files including the main simulation input file, time stepping, and output control settings.
- class pyiwfm.io.simulation.SimulationConfig(model_name='IWFM_Model', title_lines=<factory>, start_date=<factory>, end_date=<factory>, time_step_length=1, time_step_unit=TimeUnit.DAY, restart_flag=0, output_interval=1, budget_output_interval=1, heads_output_interval=1, preprocessor_file=None, binary_preprocessor_file=None, groundwater_file=None, streams_file=None, lakes_file=None, rootzone_file=None, unsaturated_zone_file=None, small_watershed_file=None, irrigation_fractions_file=None, supply_adjust_file=None, precipitation_file=None, et_file=None, kc_file=None, output_dir=None, restart_output_flag=0, debug_flag=0, cache_size=500000, matrix_solver=2, relaxation=1.0, max_iterations=50, max_supply_iterations=50, convergence_tolerance=1e-06, convergence_volume=0.0, convergence_supply=0.001, supply_adjust_option=0, metadata=<factory>)[source]#
Bases:
objectConfiguration for an IWFM simulation.
- Variables:
model_name (str) – Name of the model
start_date (datetime.datetime) – Simulation start datetime
end_date (datetime.datetime) – Simulation end datetime
time_step_length (int) – Length of each time step
time_step_unit (pyiwfm.core.timeseries.TimeUnit) – Unit of time step (DAY, HOUR, etc.)
restart_flag (int) – Restart option (0=No, 1=Yes)
output_interval (int) – Output interval (multiple of time step)
preprocessor_file (pathlib.Path | None) – Path to preprocessor main file
binary_preprocessor_file (pathlib.Path | None) – Path to preprocessor binary output
groundwater_file (pathlib.Path | None) – Path to groundwater component file
streams_file (pathlib.Path | None) – Path to streams component file
lakes_file (pathlib.Path | None) – Path to lakes component file
rootzone_file (pathlib.Path | None) – Path to rootzone component file
unsaturated_zone_file (pathlib.Path | None) – Path to unsaturated zone component file
small_watershed_file (pathlib.Path | None) – Path to small watershed component file
irrigation_fractions_file (pathlib.Path | None) – Path to irrigation fractions data file
supply_adjust_file (pathlib.Path | None) – Path to supply adjustment specification file
precipitation_file (pathlib.Path | None) – Path to precipitation data file
et_file (pathlib.Path | None) – Path to evapotranspiration data file
kc_file (pathlib.Path | None) – Path to crop/habitat coefficient data file
output_dir (pathlib.Path | None) – Directory for output files
restart_output_flag (int) – Generate restart file (0=No, 1=Yes)
debug_flag (int) – Debug output level (-1, 0, or 1)
cache_size (int) – Cache size limit for time series entries
matrix_solver (int) – Matrix solver option (1=SOR, 2=Conjugate gradient)
relaxation (float) – Relaxation factor for iterative solver
max_iterations (int) – Maximum flow convergence iterations
max_supply_iterations (int) – Maximum supply adjustment iterations
convergence_tolerance (float) – Flow convergence tolerance (STOPC)
convergence_volume (float) – Volume convergence tolerance (STOPCVL)
convergence_supply (float) – Supply adjustment convergence tolerance (STOPCSP)
supply_adjust_option (int) – Water supply adjustment flag
- __init__(model_name='IWFM_Model', title_lines=<factory>, start_date=<factory>, end_date=<factory>, time_step_length=1, time_step_unit=TimeUnit.DAY, restart_flag=0, output_interval=1, budget_output_interval=1, heads_output_interval=1, preprocessor_file=None, binary_preprocessor_file=None, groundwater_file=None, streams_file=None, lakes_file=None, rootzone_file=None, unsaturated_zone_file=None, small_watershed_file=None, irrigation_fractions_file=None, supply_adjust_file=None, precipitation_file=None, et_file=None, kc_file=None, output_dir=None, restart_output_flag=0, debug_flag=0, cache_size=500000, matrix_solver=2, relaxation=1.0, max_iterations=50, max_supply_iterations=50, convergence_tolerance=1e-06, convergence_volume=0.0, convergence_supply=0.001, supply_adjust_option=0, metadata=<factory>)#
- class pyiwfm.io.simulation.SimulationFileConfig(output_dir, main_file='simulation.in', time_series_dir='timeseries')[source]#
Bases:
objectConfiguration for simulation file paths.
- Variables:
output_dir (pathlib.Path) – Directory for output files
main_file (str) – Main simulation input file name
time_series_dir (str) – Directory for time series files
- __init__(output_dir, main_file='simulation.in', time_series_dir='timeseries')#
- class pyiwfm.io.simulation.SimulationWriter(file_config)[source]#
Bases:
objectWriter for IWFM simulation control files.
Writes the main simulation input file and related control files.
Example
>>> file_config = SimulationFileConfig(output_dir=Path("./model")) >>> writer = SimulationWriter(file_config) >>> filepath = writer.write(sim_config)
- __init__(file_config)[source]#
Initialize the simulation writer.
- Parameters:
file_config (SimulationFileConfig) – File configuration
- write(config, header=None)[source]#
Write the main simulation input file.
- Parameters:
config (SimulationConfig) – Simulation configuration
header (str | None) – Optional header comment
- Returns:
Path to written file
- Return type:
- class pyiwfm.io.simulation.SimulationReader[source]#
Bases:
objectReader for IWFM simulation control files.
- class pyiwfm.io.simulation.IWFMSimulationReader[source]#
Bases:
objectReader for IWFM simulation main files in positional sequential format.
Reads the actual IWFM Fortran format where values appear in fixed order (titles, file paths, time settings, solver parameters) as defined in
SIM_ReadMainControlDatainPackage_Model.f90.This reader handles both C2VSimFG-style files with
/ descriptioncomments and bare positional files without descriptions.
- pyiwfm.io.simulation.read_iwfm_simulation(filepath, base_dir=None)[source]#
Read IWFM simulation main file in positional format.
This reads files in the native IWFM Fortran format where values appear in a fixed order (titles, file paths, time settings, solver parameters).
- Parameters:
- Returns:
SimulationConfig with all configuration data
- Return type:
- pyiwfm.io.simulation.write_simulation(config, output_dir, file_config=None)[source]#
Write simulation control file.
- Parameters:
config (SimulationConfig) – Simulation configuration
file_config (SimulationFileConfig | None) – Optional file configuration
- Returns:
Path to written file
- Return type:
Simulation Writer#
Writer for IWFM simulation main control files.
Simulation Main File Writer for IWFM models.
This module provides the main writer for IWFM simulation main input files, orchestrating the writing of the main control file that references all component input files.
- class pyiwfm.io.simulation_writer.SimulationMainConfig(output_dir, main_file='Simulation_MAIN.IN', preprocessor_bin='PreProcessor.bin', gw_main='GW\\GW_MAIN.dat', stream_main='Stream\\Stream_MAIN.dat', lake_main='Lake\\Lake_MAIN.dat', rootzone_main='RootZone\\RootZone_MAIN.dat', swshed_main='', unsatzone_main='', irig_frac='IrigFrac.dat', supply_adjust='SupplyAdjust.dat', precip_file='Precip.dat', et_file='ET.dat', kc_file='', begin_date='09/30/1990_24:00', end_date='09/30/2000_24:00', time_step='1DAY', restart=0, istrt=0, kdeb=0, cache_size=500000, matrix_solver=2, relaxation=1.0, max_iterations=1500, max_supply_iter=50, convergence_head=0.0001, convergence_volume=0.001, convergence_supply=0.001, supply_adjust_option=11, title1='IWFM', title2='Generated by pyiwfm', title3='')[source]#
Bases:
objectConfiguration for simulation main file writing.
- Variables:
output_dir (
Path) – Base output directory for simulation files
- __init__(output_dir, main_file='Simulation_MAIN.IN', preprocessor_bin='PreProcessor.bin', gw_main='GW\\GW_MAIN.dat', stream_main='Stream\\Stream_MAIN.dat', lake_main='Lake\\Lake_MAIN.dat', rootzone_main='RootZone\\RootZone_MAIN.dat', swshed_main='', unsatzone_main='', irig_frac='IrigFrac.dat', supply_adjust='SupplyAdjust.dat', precip_file='Precip.dat', et_file='ET.dat', kc_file='', begin_date='09/30/1990_24:00', end_date='09/30/2000_24:00', time_step='1DAY', restart=0, istrt=0, kdeb=0, cache_size=500000, matrix_solver=2, relaxation=1.0, max_iterations=1500, max_supply_iter=50, convergence_head=0.0001, convergence_volume=0.001, convergence_supply=0.001, supply_adjust_option=11, title1='IWFM', title2='Generated by pyiwfm', title3='')#
- class pyiwfm.io.simulation_writer.SimulationMainWriter(model, config, template_engine=None)[source]#
Bases:
TemplateWriterWriter for IWFM Simulation Main Input File.
Writes the main simulation control file that references all component files.
Example
>>> from pyiwfm.io.simulation_writer import SimulationMainWriter, SimulationMainConfig >>> config = SimulationMainConfig(output_dir=Path("model/Simulation")) >>> writer = SimulationMainWriter(model, config) >>> path = writer.write_main()
- __init__(model, config, template_engine=None)[source]#
Initialize the simulation main writer.
- Parameters:
model (
IWFMModel) – Model to writeconfig (
SimulationMainConfig) – Output file configurationtemplate_engine (
TemplateEngine, optional) – Custom template engine
- pyiwfm.io.simulation_writer.write_simulation_main(model, output_dir, config=None)[source]#
Write simulation main file for a model.
- Parameters:
model (
IWFMModel) – Model to writeoutput_dir (
Pathorstr) – Output directoryconfig (
SimulationMainConfig, optional) – File configuration
- Returns:
Path to written file
- Return type:
Path
Groundwater I/O#
Groundwater Module#
The groundwater module provides readers and writers for IWFM groundwater component files.
Groundwater component I/O handlers for IWFM model files.
This module provides functions for reading and writing IWFM groundwater component files including wells, pumping, boundary conditions, aquifer parameters, tile drains, and subsidence data.
- class pyiwfm.io.groundwater.KhAnomalyEntry(element_id, kh_per_layer)[source]#
Bases:
objectSingle Kh anomaly overwrite for one element.
- Variables:
- __init__(element_id, kh_per_layer)#
- class pyiwfm.io.groundwater.ParametricGridData(n_nodes, n_elements, elements, node_coords, node_values, node_range_str='', raw_node_lines=<factory>)[source]#
Bases:
objectRaw parametric grid data parsed from the GW main file.
- Variables:
n_nodes (int) – Number of parametric grid nodes.
n_elements (int) – Number of parametric grid elements.
elements (list[tuple[int, ...]]) – Element vertex index tuples (0-based into node arrays).
node_coords (numpy.ndarray[tuple[Any, ...], numpy.dtype[numpy.float64]]) – Parametric node coordinates, shape (n_nodes, 2).
node_values (numpy.ndarray[tuple[Any, ...], numpy.dtype[numpy.float64]]) – Parameter values per node, shape (n_nodes, n_layers, n_params). The 5 parameters are: Kh, Ss, Sy, AquitardKv, Kv.
node_range_str (str) – Raw node range string from file (e.g., “1-441”).
raw_node_lines (list[str]) – Raw text lines for each parametric node (before parsing).
- __init__(n_nodes, n_elements, elements, node_coords, node_values, node_range_str='', raw_node_lines=<factory>)#
- class pyiwfm.io.groundwater.FaceFlowSpec(id, layer, node_a, node_b, name='')[source]#
Bases:
objectElement face flow output specification.
Parsed from the inline face flow data in the GW main file. Format per line: ID IOUTFL IOUTFA IOUTFB NAME
- Variables:
- __init__(id, layer, node_a, node_b, name='')#
- class pyiwfm.io.groundwater.GWFileConfig(output_dir, wells_file='wells.dat', pumping_file='pumping.dat', aquifer_params_file='aquifer_params.dat', boundary_conditions_file='boundary_conditions.dat', tile_drains_file='tile_drains.dat', subsidence_file='subsidence.dat', initial_heads_file='initial_heads.dat')[source]#
Bases:
objectConfiguration for groundwater component files.
- Variables:
output_dir (pathlib.Path) – Directory for output files
wells_file (str) – Wells definition file name
pumping_file (str) – Pumping time series file name
aquifer_params_file (str) – Aquifer parameters file name
boundary_conditions_file (str) – Boundary conditions file name
tile_drains_file (str) – Tile drains file name
subsidence_file (str) – Subsidence parameters file name
initial_heads_file (str) – Initial heads file name
- __init__(output_dir, wells_file='wells.dat', pumping_file='pumping.dat', aquifer_params_file='aquifer_params.dat', boundary_conditions_file='boundary_conditions.dat', tile_drains_file='tile_drains.dat', subsidence_file='subsidence.dat', initial_heads_file='initial_heads.dat')#
- class pyiwfm.io.groundwater.GroundwaterWriter(config)[source]#
Bases:
objectWriter for IWFM groundwater component files.
Writes all groundwater-related input files including wells, pumping time series, boundary conditions, aquifer parameters, etc.
Example
>>> config = GWFileConfig(output_dir=Path("./model")) >>> writer = GroundwaterWriter(config) >>> files = writer.write(gw_component)
- __init__(config)[source]#
Initialize the groundwater writer.
- Parameters:
config (GWFileConfig) – File configuration
- write_pumping_timeseries(filepath, times, pumping_rates, well_ids=None, units='TAF', factor=1.0, header=None)[source]#
Write pumping time series file.
- Parameters:
- Returns:
Path to written file
- Return type:
- class pyiwfm.io.groundwater.GroundwaterReader[source]#
Bases:
objectReader for IWFM groundwater component files.
- class pyiwfm.io.groundwater.GWMainFileConfig(version='', bc_file=None, tile_drain_file=None, pumping_file=None, subsidence_file=None, overwrite_file=None, raw_paths=<factory>, head_output_factor=1.0, head_output_unit='FEET', volume_output_factor=1.0, volume_output_unit='TAF', velocity_output_factor=1.0, velocity_output_unit='', velocity_output_file=None, vertical_flow_output_file=None, head_all_output_file=None, head_tecplot_file=None, velocity_tecplot_file=None, budget_output_file=None, zbudget_output_file=None, final_heads_file=None, debug_flag=0, coord_factor=1.0, hydrograph_output_file=None, hydrograph_locations=<factory>, n_face_flow_outputs=0, face_flow_output_file=None, face_flow_specs=<factory>, aquifer_params=None, n_param_groups=0, aq_factors_line='', aq_time_unit_kh='', aq_time_unit_v='', aq_time_unit_l='', tecplot_print_flag=1, kh_anomalies=<factory>, kh_anomaly_factor=1.0, kh_anomaly_time_unit='', return_flow_flag=0, parametric_grids=<factory>, initial_heads=None)[source]#
Bases:
objectConfiguration parsed from GW component main file.
The groundwater component main file is a dispatcher that references sub-files for boundary conditions, tile drains, pumping, and subsidence. It also contains inline hydrograph output location data.
- Variables:
version (str) – File format version (e.g., “4.0”)
bc_file (pathlib.Path | None) – Path to boundary conditions file
tile_drain_file (pathlib.Path | None) – Path to tile drains file
pumping_file (pathlib.Path | None) – Path to pumping file
subsidence_file (pathlib.Path | None) – Path to subsidence file
overwrite_file (pathlib.Path | None) – Path to parameter overwrite file (optional)
head_output_factor (float) – Conversion factor for head output
head_output_unit (str) – Unit string for head output
volume_output_factor (float) – Conversion factor for volume output
volume_output_unit (str) – Unit string for volume output
debug_flag (int) – Debug output flag
coord_factor (float) – Coordinate conversion factor for hydrographs
hydrograph_output_file (pathlib.Path | None) – Path to hydrograph output file
hydrograph_locations (list[pyiwfm.components.groundwater.HydrographLocation]) – List of GW observation point locations
- hydrograph_locations: list[HydrographLocation]#
- face_flow_specs: list[FaceFlowSpec]#
- aquifer_params: AquiferParameters | None = None#
- kh_anomalies: list[KhAnomalyEntry]#
- parametric_grids: list[ParametricGridData]#
- __init__(version='', bc_file=None, tile_drain_file=None, pumping_file=None, subsidence_file=None, overwrite_file=None, raw_paths=<factory>, head_output_factor=1.0, head_output_unit='FEET', volume_output_factor=1.0, volume_output_unit='TAF', velocity_output_factor=1.0, velocity_output_unit='', velocity_output_file=None, vertical_flow_output_file=None, head_all_output_file=None, head_tecplot_file=None, velocity_tecplot_file=None, budget_output_file=None, zbudget_output_file=None, final_heads_file=None, debug_flag=0, coord_factor=1.0, hydrograph_output_file=None, hydrograph_locations=<factory>, n_face_flow_outputs=0, face_flow_output_file=None, face_flow_specs=<factory>, aquifer_params=None, n_param_groups=0, aq_factors_line='', aq_time_unit_kh='', aq_time_unit_v='', aq_time_unit_l='', tecplot_print_flag=1, kh_anomalies=<factory>, kh_anomaly_factor=1.0, kh_anomaly_time_unit='', return_flow_flag=0, parametric_grids=<factory>, initial_heads=None)#
- class pyiwfm.io.groundwater.GWMainFileReader[source]#
Bases:
objectReader for IWFM groundwater component main file.
The GW main file is a hierarchical dispatcher that contains: 1. Version header (e.g., #4.0) 2. Paths to sub-files (BC, tile drains, pumping, subsidence) 3. Output conversion factors and units 4. Inline hydrograph location data
This reader parses the main file to extract configuration and hydrograph locations. It does NOT parse the sub-files - use the dedicated readers (e.g., GroundwaterReader.read_wells) for those.
- pyiwfm.io.groundwater.write_groundwater(gw, output_dir, config=None)[source]#
Write groundwater component to files.
- pyiwfm.io.groundwater.read_subsidence(filepath)[source]#
Read subsidence parameters from file.
- Parameters:
- Returns:
List of Subsidence objects
- Return type:
- pyiwfm.io.groundwater.read_gw_main_file(filepath, base_dir=None)[source]#
Read IWFM groundwater component main file.
The GW main file is a hierarchical dispatcher that contains paths to sub-files (boundary conditions, pumping, etc.) and inline hydrograph location data.
- Parameters:
- Returns:
GWMainFileConfig with parsed values including hydrograph locations
- Return type:
Example
>>> config = read_gw_main_file("C2VSimFG_Groundwater.dat") >>> print(f"Version: {config.version}") >>> print(f"Hydrograph locations: {len(config.hydrograph_locations)}") >>> if config.pumping_file: ... wells = read_wells(config.pumping_file)
Groundwater Writer#
Writer for IWFM groundwater component files using Jinja2 templates.
Groundwater Component Writer for IWFM models.
This module provides the main writer for IWFM groundwater component files, orchestrating the writing of all groundwater-related input files including: - Main groundwater control file (GW_MAIN.dat) - Boundary conditions (BC_MAIN.dat, SpecHeadBC.dat, SpecFlowBC.dat) - Pumping files (Pump_MAIN.dat, ElemPump.dat, WellSpec.dat, TSPumping.dat) - Tile drains (TileDrain.dat) - Subsidence parameters (Subsidence.dat) - Aquifer parameters (included in GW_MAIN.dat or separate file) - Hydrograph specifications - Face flow output - Kh anomaly section - GW return flows
- class pyiwfm.io.gw_writer.GWWriterConfig(output_dir, version='4.0', gw_subdir='GW', main_file='GW_MAIN.dat', bc_main_file='BC_MAIN.dat', pump_main_file='Pump_MAIN.dat', tile_drain_file='TileDrain.dat', subsidence_file='Subsidence.dat', elem_pump_file='ElemPump.dat', well_spec_file='WellSpec.dat', ts_pumping_file='TSPumping.dat', spec_head_bc_file='SpecHeadBC.dat', spec_flow_bc_file='SpecFlowBC.dat', bound_tsd_file='BoundTSD.dat', gw_budget_file='../Results/GW.hdf', gw_zbudget_file='../Results/GW_ZBud.hdf', gw_head_file='../Results/GWHeadAll.out', gw_hyd_file='../Results/GWHyd.out', gw_velocity_file='../Results/GWVelocities.out', vertical_flow_file='../Results/VerticalFlow.out', final_heads_file='../Results/FinalGWHeads.out', tecplot_head_file='../Results/TecPlotGW.out', pump_output_file='../Results/Pumping.out', face_flow_file='../Results/FaceFlows.out', td_output_file='../Results/TileDrainHyd.out', bc_output_file='../Results/BCOutput.out', length_factor=1.0, length_unit='ft.', volume_factor=2.29568e-05, volume_unit='ac.ft.', velocity_factor=1.0, velocity_unit='fpd')[source]#
Bases:
BaseComponentWriterConfigConfiguration for groundwater component file writing.
- Variables:
- __init__(output_dir, version='4.0', gw_subdir='GW', main_file='GW_MAIN.dat', bc_main_file='BC_MAIN.dat', pump_main_file='Pump_MAIN.dat', tile_drain_file='TileDrain.dat', subsidence_file='Subsidence.dat', elem_pump_file='ElemPump.dat', well_spec_file='WellSpec.dat', ts_pumping_file='TSPumping.dat', spec_head_bc_file='SpecHeadBC.dat', spec_flow_bc_file='SpecFlowBC.dat', bound_tsd_file='BoundTSD.dat', gw_budget_file='../Results/GW.hdf', gw_zbudget_file='../Results/GW_ZBud.hdf', gw_head_file='../Results/GWHeadAll.out', gw_hyd_file='../Results/GWHyd.out', gw_velocity_file='../Results/GWVelocities.out', vertical_flow_file='../Results/VerticalFlow.out', final_heads_file='../Results/FinalGWHeads.out', tecplot_head_file='../Results/TecPlotGW.out', pump_output_file='../Results/Pumping.out', face_flow_file='../Results/FaceFlows.out', td_output_file='../Results/TileDrainHyd.out', bc_output_file='../Results/BCOutput.out', length_factor=1.0, length_unit='ft.', volume_factor=2.29568e-05, volume_unit='ac.ft.', velocity_factor=1.0, velocity_unit='fpd')#
- class pyiwfm.io.gw_writer.GWComponentWriter(model, config, template_engine=None)[source]#
Bases:
TemplateWriterWriter for IWFM Groundwater Component files.
Writes all groundwater-related input files for IWFM simulation.
Example
>>> from pyiwfm.io.gw_writer import GWComponentWriter, GWWriterConfig >>> config = GWWriterConfig(output_dir=Path("model/Simulation")) >>> writer = GWComponentWriter(model, config) >>> files = writer.write_all()
- __init__(model, config, template_engine=None)[source]#
Initialize the groundwater component writer.
- Parameters:
model (
IWFMModel) – Model to writeconfig (
GWWriterConfig) – Output file configurationtemplate_engine (
TemplateEngine, optional) – Custom template engine
- write_all(write_defaults=True)[source]#
Write all groundwater component files.
- Parameters:
write_defaults (
bool) – If True, write default files even when no groundwater component is loaded (useful for generating simulation skeleton)- Returns:
Mapping of file type to output path
- Return type:
dict[str,Path]
- write_main()[source]#
Write the main groundwater control file.
- Returns:
Path to written file
- Return type:
Path
- write_bc_main()[source]#
Write the boundary conditions main file.
- Returns:
Path to written file
- Return type:
Path
- write_pump_main()[source]#
Write the pumping main file.
- Returns:
Path to written file
- Return type:
Path
- write_tile_drains()[source]#
Write the tile drains file.
- Returns:
Path to written file
- Return type:
Path
- write_subsidence()[source]#
Write the subsidence parameters file.
- Returns:
Path to written file
- Return type:
Path
- write_well_specs()[source]#
Write the well specification file.
- Returns:
Path to written file
- Return type:
Path
- write_elem_pump_specs()[source]#
Write the element-based pumping specification file.
- Returns:
Path to written file
- Return type:
Path
- write_ts_pumping(dates=None, data=None)[source]#
Write the pumping time series data file using IWFMTimeSeriesDataWriter.
- Parameters:
dates (
list[str], optional) – IWFM timestampsdata (
NDArray[np.float64], optional) – Pumping data array (n_times, n_cols)
- Returns:
Path to written file
- Return type:
Path
- pyiwfm.io.gw_writer.write_gw_component(model, output_dir, config=None)[source]#
Write groundwater component files for a model.
- Parameters:
model (
IWFMModel) – Model to writeoutput_dir (
Pathorstr) – Output directoryconfig (
GWWriterConfig, optional) – File configuration
- Returns:
Mapping of file type to output path
- Return type:
dict[str,Path]
Groundwater Boundary Conditions#
Reader for groundwater boundary condition files (specified head, general head).
Groundwater Boundary Conditions Reader for IWFM.
This module reads the IWFM groundwater boundary conditions file, which contains four types of boundary conditions: 1. Specified Flow BCs (fixed flux at nodes) 2. Specified Head BCs (fixed head at nodes) 3. General Head BCs (head-dependent flow) 4. Constrained General Head BCs (head-dependent with constraints)
The main BC file is a dispatcher that references sub-files for each BC type, plus an optional time series data file for dynamic BCs.
- class pyiwfm.io.gw_boundary.SpecifiedFlowBC(node_id, layer, ts_column=0, base_flow=0.0)[source]#
Bases:
objectSpecified flow boundary condition at a node.
- Variables:
- __init__(node_id, layer, ts_column=0, base_flow=0.0)#
- class pyiwfm.io.gw_boundary.SpecifiedHeadBC(node_id, layer, ts_column=0, head_value=0.0)[source]#
Bases:
objectSpecified head boundary condition at a node.
- Variables:
- __init__(node_id, layer, ts_column=0, head_value=0.0)#
- class pyiwfm.io.gw_boundary.GeneralHeadBC(node_id, layer, ts_column=0, external_head=0.0, conductance=0.0)[source]#
Bases:
objectGeneral head boundary condition at a node.
Flow is computed as: Q = conductance * (external_head - gw_head)
- Variables:
- __init__(node_id, layer, ts_column=0, external_head=0.0, conductance=0.0)#
- class pyiwfm.io.gw_boundary.ConstrainedGeneralHeadBC(node_id, layer, ts_column=0, external_head=0.0, conductance=0.0, constraining_head=0.0, max_flow_ts_column=0, max_flow=0.0)[source]#
Bases:
objectConstrained general head boundary condition at a node.
Like GeneralHeadBC but with a constraining head and maximum flow.
- Variables:
node_id (int) – GW node ID
layer (int) – Aquifer layer (1-based)
ts_column (int) – Time series column for external head (0 = static)
external_head (float) – External head value
conductance (float) – BC conductance
constraining_head (float) – Head below which the constraining head is used
max_flow_ts_column (int) – Time series column for max flow (0 = static)
max_flow (float) – Maximum BC flow
- __init__(node_id, layer, ts_column=0, external_head=0.0, conductance=0.0, constraining_head=0.0, max_flow_ts_column=0, max_flow=0.0)#
- class pyiwfm.io.gw_boundary.GWBoundaryConfig(sp_flow_file=None, sp_head_file=None, gh_file=None, cgh_file=None, ts_data_file=None, specified_flow_bcs=<factory>, sp_flow_factor=1.0, sp_flow_time_unit='', specified_head_bcs=<factory>, sp_head_factor=1.0, general_head_bcs=<factory>, gh_head_factor=1.0, gh_conductance_factor=1.0, gh_time_unit='', constrained_gh_bcs=<factory>, cgh_head_factor=1.0, cgh_max_flow_factor=1.0, cgh_head_time_unit='', cgh_conductance_factor=1.0, cgh_conductance_time_unit='', n_bc_output_nodes=0, bc_output_file=None, bc_output_file_raw='', bc_output_specs=<factory>)[source]#
Bases:
objectComplete GW boundary conditions configuration.
- Variables:
sp_flow_file (pathlib.Path | None) – Path to specified flow BC sub-file
sp_head_file (pathlib.Path | None) – Path to specified head BC sub-file
gh_file (pathlib.Path | None) – Path to general head BC sub-file
cgh_file (pathlib.Path | None) – Path to constrained general head BC sub-file
ts_data_file (pathlib.Path | None) – Path to time series BC data file
specified_flow_bcs (list[pyiwfm.io.gw_boundary.SpecifiedFlowBC]) – List of specified flow BCs
sp_flow_factor (float) – Conversion factor for specified flow
sp_flow_time_unit (str) – Time unit for specified flow
specified_head_bcs (list[pyiwfm.io.gw_boundary.SpecifiedHeadBC]) – List of specified head BCs
sp_head_factor (float) – Conversion factor for specified head
general_head_bcs (list[pyiwfm.io.gw_boundary.GeneralHeadBC]) – List of general head BCs
gh_head_factor (float) – Head conversion factor for general head
gh_conductance_factor (float) – Conductance conversion factor
gh_time_unit (str) – Time unit for general head
constrained_gh_bcs (list[pyiwfm.io.gw_boundary.ConstrainedGeneralHeadBC]) – List of constrained general head BCs
cgh_head_factor (float) – Head conversion factor
cgh_max_flow_factor (float) – Max flow conversion factor
cgh_head_time_unit (str) – Time unit for head
cgh_conductance_factor (float) – Conductance conversion factor
cgh_conductance_time_unit (str) – Time unit for conductance
- specified_flow_bcs: list[SpecifiedFlowBC]#
- specified_head_bcs: list[SpecifiedHeadBC]#
- general_head_bcs: list[GeneralHeadBC]#
- constrained_gh_bcs: list[ConstrainedGeneralHeadBC]#
- __init__(sp_flow_file=None, sp_head_file=None, gh_file=None, cgh_file=None, ts_data_file=None, specified_flow_bcs=<factory>, sp_flow_factor=1.0, sp_flow_time_unit='', specified_head_bcs=<factory>, sp_head_factor=1.0, general_head_bcs=<factory>, gh_head_factor=1.0, gh_conductance_factor=1.0, gh_time_unit='', constrained_gh_bcs=<factory>, cgh_head_factor=1.0, cgh_max_flow_factor=1.0, cgh_head_time_unit='', cgh_conductance_factor=1.0, cgh_conductance_time_unit='', n_bc_output_nodes=0, bc_output_file=None, bc_output_file_raw='', bc_output_specs=<factory>)#
- class pyiwfm.io.gw_boundary.GWBoundaryReader[source]#
Bases:
ReaderMixinReader for IWFM groundwater boundary conditions files.
The main BC file contains 5 lines of sub-file paths: 1. Specified flow BC file 2. Specified head BC file 3. General head BC file 4. Constrained general head BC file 5. Time series BC data file
Each sub-file has its own header with counts and conversion factors, followed by per-BC data rows.
Groundwater Pumping#
Reader for groundwater pumping specification files.
Groundwater Pumping Reader for IWFM.
This module reads the IWFM groundwater pumping files, which define: 1. Well specifications (location, perforation intervals, radius) 2. Well pumping specifications (rates, distribution, destinations) 3. Element-based pumping specifications 4. Element groups for pumping destinations 5. Time series pumping data references
The pumping main file references sub-files for wells, element pumping, and a time series data file containing the actual pumping rates.
- class pyiwfm.io.gw_pumping.WellSpec(id, x, y, radius=0.0, perf_top=0.0, perf_bottom=0.0, name='')[source]#
Bases:
objectWell physical specification.
- Variables:
- __init__(id, x, y, radius=0.0, perf_top=0.0, perf_bottom=0.0, name='')#
- class pyiwfm.io.gw_pumping.WellPumpingSpec(well_id, pump_column=0, pump_fraction=1.0, dist_method=0, dest_type=-1, dest_id=0, irig_frac_column=0, adjust_column=0, pump_max_column=0, pump_max_fraction=0.0)[source]#
Bases:
objectWell pumping specification.
- Variables:
well_id (int) – Well ID (must match a WellSpec)
pump_column (int) – Column in time series pumping file
pump_fraction (float) – Fraction of pumping at this column
dist_method (int) – Distribution method (0-4)
dest_type (int) – Destination type (-1, 0, 1, 2, 3)
dest_id (int) – Destination ID (element, subregion, or group)
irig_frac_column (int) – Column for irrigation fraction
adjust_column (int) – Column for supply adjustment
pump_max_column (int) – Column for maximum pumping
pump_max_fraction (float) – Fraction of maximum pumping
- __init__(well_id, pump_column=0, pump_fraction=1.0, dist_method=0, dest_type=-1, dest_id=0, irig_frac_column=0, adjust_column=0, pump_max_column=0, pump_max_fraction=0.0)#
- class pyiwfm.io.gw_pumping.ElementPumpingSpec(element_id, pump_column=0, pump_fraction=1.0, dist_method=0, layer_factors=<factory>, dest_type=-1, dest_id=0, irig_frac_column=0, adjust_column=0, pump_max_column=0, pump_max_fraction=0.0)[source]#
Bases:
objectElement-based pumping specification.
- Variables:
element_id (int) – Element ID
pump_column (int) – Column in time series pumping file
pump_fraction (float) – Fraction of pumping at this column
dist_method (int) – Distribution method (0-4)
dest_type (int) – Destination type (-1, 0, 1, 2, 3)
dest_id (int) – Destination ID
irig_frac_column (int) – Column for irrigation fraction
adjust_column (int) – Column for supply adjustment
pump_max_column (int) – Column for maximum pumping
pump_max_fraction (float) – Fraction of maximum pumping
- __init__(element_id, pump_column=0, pump_fraction=1.0, dist_method=0, layer_factors=<factory>, dest_type=-1, dest_id=0, irig_frac_column=0, adjust_column=0, pump_max_column=0, pump_max_fraction=0.0)#
- class pyiwfm.io.gw_pumping.ElementGroup(id, elements=<factory>)[source]#
Bases:
objectGroup of elements for pumping destination.
- __init__(id, elements=<factory>)#
- class pyiwfm.io.gw_pumping.PumpingConfig(version='', well_file=None, elem_pump_file=None, ts_data_file=None, output_file=None, well_specs=<factory>, well_pumping_specs=<factory>, well_groups=<factory>, factor_xy=1.0, factor_radius=1.0, factor_length=1.0, elem_pumping_specs=<factory>, elem_groups=<factory>, pump_factor=1.0)[source]#
Bases:
objectComplete pumping configuration.
- Variables:
version (str) – File format version
well_file (pathlib.Path | None) – Path to well specification file
elem_pump_file (pathlib.Path | None) – Path to element pumping specification file
ts_data_file (pathlib.Path | None) – Path to time series pumping data file
output_file (pathlib.Path | None) – Path to pumping output file
well_specs (list[pyiwfm.io.gw_pumping.WellSpec]) – Well physical specifications
well_pumping_specs (list[pyiwfm.io.gw_pumping.WellPumpingSpec]) – Well pumping specifications
well_groups (list[pyiwfm.io.gw_pumping.ElementGroup]) – Element groups for well destinations
factor_xy (float) – Coordinate conversion factor
factor_radius (float) – Radius conversion factor
factor_length (float) – Perforation length conversion factor
elem_pumping_specs (list[pyiwfm.io.gw_pumping.ElementPumpingSpec]) – Element pumping specifications
elem_groups (list[pyiwfm.io.gw_pumping.ElementGroup]) – Element groups for element pumping destinations
pump_factor (float) – Pumping rate conversion factor
- well_pumping_specs: list[WellPumpingSpec]#
- well_groups: list[ElementGroup]#
- elem_pumping_specs: list[ElementPumpingSpec]#
- elem_groups: list[ElementGroup]#
- __init__(version='', well_file=None, elem_pump_file=None, ts_data_file=None, output_file=None, well_specs=<factory>, well_pumping_specs=<factory>, well_groups=<factory>, factor_xy=1.0, factor_radius=1.0, factor_length=1.0, elem_pumping_specs=<factory>, elem_groups=<factory>, pump_factor=1.0)#
- class pyiwfm.io.gw_pumping.PumpingReader[source]#
Bases:
ReaderMixinReader for IWFM pumping files.
The pumping system reads from a main file that references: - Well specification file - Element pumping specification file - Time series pumping data file
Groundwater Tile Drains#
Reader for groundwater tile drain specification files.
Groundwater Tile Drain and Sub-Irrigation Reader for IWFM.
This module reads the IWFM tile drain/sub-irrigation file, which contains: 1. Tile drain specifications (node, elevation, conductance, destination) 2. Sub-irrigation specifications (node, elevation, conductance)
Both are in the same input file: tile drains first, then sub-irrigation.
- class pyiwfm.io.gw_tiledrain.TileDrainSpec(id, gw_node, elevation, conductance, dest_type=1, dest_id=0)[source]#
Bases:
objectTile drain specification.
- Variables:
- __init__(id, gw_node, elevation, conductance, dest_type=1, dest_id=0)#
- class pyiwfm.io.gw_tiledrain.SubIrrigationSpec(id, gw_node, elevation, conductance)[source]#
Bases:
objectSub-irrigation (subsurface irrigation) specification.
- Variables:
- __init__(id, gw_node, elevation, conductance)#
- class pyiwfm.io.gw_tiledrain.TileDrainHydroSpec(id, id_type=1, name='')[source]#
Bases:
objectTile drain / sub-irrigation hydrograph output specification.
- Variables:
- __init__(id, id_type=1, name='')#
- class pyiwfm.io.gw_tiledrain.TileDrainConfig(version='', n_drains=0, drain_height_factor=1.0, drain_conductance_factor=1.0, drain_time_unit='', tile_drains=<factory>, n_sub_irrigation=0, subirig_height_factor=1.0, subirig_conductance_factor=1.0, subirig_time_unit='', sub_irrigations=<factory>, n_td_hydro=0, td_hydro_volume_factor=1.0, td_hydro_volume_unit='', td_output_file='', td_hydro_specs=<factory>)[source]#
Bases:
objectComplete tile drain and sub-irrigation configuration.
- Variables:
version (str) – File format version (e.g., “4.0”)
n_drains (int) – Number of tile drains
drain_height_factor (float) – Height conversion factor for drains
drain_conductance_factor (float) – Conductance conversion factor for drains
drain_time_unit (str) – Time unit for drain conductance
tile_drains (list[pyiwfm.io.gw_tiledrain.TileDrainSpec]) – List of tile drain specifications
n_sub_irrigation (int) – Number of sub-irrigation locations
subirig_height_factor (float) – Height conversion factor
subirig_conductance_factor (float) – Conductance conversion factor
subirig_time_unit (str) – Time unit for sub-irrigation conductance
sub_irrigations (list[pyiwfm.io.gw_tiledrain.SubIrrigationSpec]) – List of sub-irrigation specifications
n_td_hydro (int) – Number of hydrograph outputs
td_hydro_volume_factor (float) – Volume conversion factor for output
td_hydro_volume_unit (str) – Volume output unit
td_output_file (str) – Output file path (raw string from file)
td_hydro_specs (list[pyiwfm.io.gw_tiledrain.TileDrainHydroSpec]) – List of hydrograph output specifications
- tile_drains: list[TileDrainSpec]#
- sub_irrigations: list[SubIrrigationSpec]#
- td_hydro_specs: list[TileDrainHydroSpec]#
- __init__(version='', n_drains=0, drain_height_factor=1.0, drain_conductance_factor=1.0, drain_time_unit='', tile_drains=<factory>, n_sub_irrigation=0, subirig_height_factor=1.0, subirig_conductance_factor=1.0, subirig_time_unit='', sub_irrigations=<factory>, n_td_hydro=0, td_hydro_volume_factor=1.0, td_hydro_volume_unit='', td_output_file='', td_hydro_specs=<factory>)#
- class pyiwfm.io.gw_tiledrain.TileDrainReader[source]#
Bases:
ReaderMixinReader for IWFM tile drain/sub-irrigation file.
The file contains tile drains first, then sub-irrigation data.
Groundwater Subsidence#
Reader for groundwater subsidence parameter files.
Groundwater Subsidence Reader for IWFM.
This module reads the IWFM subsidence parameter files, which define compaction-related parameters for each aquifer node-layer. Four versions are supported:
Version 4.0: Basic subsidence with elastic/inelastic storage, interbed thickness, and pre-compaction head.
Version 4.1: Same as 4.0 but adds AllSubsidenceAtAllNodes HDF5 output file path (read before IC filename).
Version 5.0: Enhanced with vertical interbed conductivity, number of equivalent delay interbeds, and preferred discretization thickness.
Version 5.1: Same as 5.0 but adds AllSubsidenceAtAllNodes HDF5 output file path (read before IC filename).
- class pyiwfm.io.gw_subsidence.SubsidenceHydrographSpec(id=0, hydtyp=0, layer=1, x=0.0, y=0.0, name='')[source]#
Bases:
objectSubsidence hydrograph output location.
- Variables:
- __init__(id=0, hydtyp=0, layer=1, x=0.0, y=0.0, name='')#
- class pyiwfm.io.gw_subsidence.SubsidenceNodeParams(node_id=0, elastic_sc=<factory>, inelastic_sc=<factory>, interbed_thick=<factory>, interbed_thick_min=<factory>, precompact_head=<factory>, kv_sub=<factory>, n_eq=<factory>)[source]#
Bases:
objectSubsidence parameters for one node across all layers.
- Variables:
node_id (int) – GW node ID
elastic_sc (list[float]) – Elastic storage coefficient per layer
inelastic_sc (list[float]) – Inelastic storage coefficient per layer
interbed_thick_min (list[float]) – Minimum interbed thickness per layer
precompact_head (list[float]) – Pre-compaction head per layer
kv_sub (list[float]) – Vertical conductivity of interbeds per layer (v5.0 only)
n_eq (list[float]) – Number of equivalent delay interbeds per layer (v5.0 only)
- __init__(node_id=0, elastic_sc=<factory>, inelastic_sc=<factory>, interbed_thick=<factory>, interbed_thick_min=<factory>, precompact_head=<factory>, kv_sub=<factory>, n_eq=<factory>)#
- class pyiwfm.io.gw_subsidence.ParametricSubsidenceData(node_range_str, n_nodes, n_elements, elements, node_coords, node_values)[source]#
Bases:
objectRaw parametric grid data for subsidence parameters.
- Variables:
node_range_str (str) – Original node range string (e.g.
"1-441").n_nodes (int) – Number of parametric grid nodes.
n_elements (int) – Number of parametric grid elements.
elements (list[tuple[int, ...]]) – Element vertex index tuples (0-based into node arrays).
node_coords (numpy.ndarray[tuple[Any, ...], numpy.dtype[numpy.float64]]) – Parametric node coordinates, shape (n_nodes, 2).
node_values (numpy.ndarray[tuple[Any, ...], numpy.dtype[numpy.float64]]) – Parameter values per node, shape (n_nodes, n_layers, n_params). The 5 params are: ElasticSC, InelasticSC, InterbedThick, InterbedThickMin, PreCompactHead.
- __init__(node_range_str, n_nodes, n_elements, elements, node_coords, node_values)#
- class pyiwfm.io.gw_subsidence.SubsidenceConfig(version='', all_subs_out_file=None, ic_file=None, tecplot_file=None, final_subs_file=None, output_factor=1.0, output_unit='FEET', interbed_dz=0.0, n_parametric_grids=0, conversion_factors=<factory>, n_hydrograph_outputs=0, hydrograph_coord_factor=1.0, hydrograph_output_file=None, hydrograph_specs=<factory>, _raw_all_subs_out_file='', _raw_ic_file='', _raw_tecplot_file='', _raw_final_subs_file='', _raw_hydrograph_output_file='', parametric_grids=<factory>, node_params=<factory>, n_nodes=0, n_layers=0, ic_factor=1.0, ic_interbed_thick=None, ic_precompact_head=None)[source]#
Bases:
objectComplete subsidence configuration.
- Variables:
version (str) – File format version (4.0, 4.1, 5.0, or 5.1)
all_subs_out_file (pathlib.Path | None) – Path to AllSubsidenceAtAllNodes HDF5 output (v4.1/v5.1 only)
ic_file (pathlib.Path | None) – Path to initial conditions file
tecplot_file (pathlib.Path | None) – Path to Tecplot output file
final_subs_file (pathlib.Path | None) – Path to end-of-simulation output file
output_factor (float) – Output unit conversion factor
output_unit (str) – Output unit string
interbed_dz (float) – Preferred interbed discretization thickness (v5.0 only)
n_parametric_grids (int) – Number of parametric grids (0 = direct input)
conversion_factors (list[float]) – Conversion factor array (6 for v4.0, 7 for v5.0)
node_params (list[pyiwfm.io.gw_subsidence.SubsidenceNodeParams]) – List of SubsidenceNodeParams (one per node)
n_nodes (int) – Number of nodes with subsidence data
n_layers (int) – Number of aquifer layers
ic_factor (float) – IC file conversion factor
ic_interbed_thick (numpy.ndarray[tuple[Any, ...], numpy.dtype[numpy.float64]] | None) – IC interbed thickness array (n_nodes, n_layers)
ic_precompact_head (numpy.ndarray[tuple[Any, ...], numpy.dtype[numpy.float64]] | None) – IC pre-compaction head array (n_nodes, n_layers)
- hydrograph_specs: list[SubsidenceHydrographSpec]#
- parametric_grids: list[ParametricSubsidenceData]#
- node_params: list[SubsidenceNodeParams]#
- __init__(version='', all_subs_out_file=None, ic_file=None, tecplot_file=None, final_subs_file=None, output_factor=1.0, output_unit='FEET', interbed_dz=0.0, n_parametric_grids=0, conversion_factors=<factory>, n_hydrograph_outputs=0, hydrograph_coord_factor=1.0, hydrograph_output_file=None, hydrograph_specs=<factory>, _raw_all_subs_out_file='', _raw_ic_file='', _raw_tecplot_file='', _raw_final_subs_file='', _raw_hydrograph_output_file='', parametric_grids=<factory>, node_params=<factory>, n_nodes=0, n_layers=0, ic_factor=1.0, ic_interbed_thick=None, ic_precompact_head=None)#
- class pyiwfm.io.gw_subsidence.SubsidenceReader[source]#
Bases:
ReaderMixinReader for IWFM subsidence parameter files.
Supports versions 4.0, 4.1, 5.0, and 5.1. Version is auto-detected from the file header. Versions 4.1 and 5.1 add an AllSubsidenceAtAllNodes HDF5 output file path before the IC filename.
Stream I/O#
Streams Module#
The streams module provides readers and writers for IWFM stream network component files.
Stream network I/O handlers for IWFM model files.
This module provides functions for reading and writing IWFM stream network component files including stream nodes, reaches, diversions, bypasses, and rating curves.
- class pyiwfm.io.streams.StreamBedParamRow(node_id, conductivity=0.0, bed_thickness=0.0, wetted_perimeter=None, gw_node=0)[source]#
Bases:
objectPer-node stream bed parameters from the main file.
v4.2 column order: IR, WETPR, IRGW, CSTRM, DSTRM (5 columns) v4.0 column order: IR, CSTRM, DSTRM, WETPR (4 columns) v4.1/v5.0: IR, CSTRM, DSTRM (3 columns)
- __init__(node_id, conductivity=0.0, bed_thickness=0.0, wetted_perimeter=None, gw_node=0)#
- class pyiwfm.io.streams.CrossSectionRow(node_id, bottom_elev=0.0, B0=0.0, s=0.0, n=0.04, max_flow_depth=10.0)[source]#
Bases:
objectPer-node v5.0 cross-section data from the main file.
- __init__(node_id, bottom_elev=0.0, B0=0.0, s=0.0, n=0.04, max_flow_depth=10.0)#
- class pyiwfm.io.streams.StreamInitialConditionRow(node_id, value=0.0)[source]#
Bases:
objectPer-node v5.0 initial condition.
- __init__(node_id, value=0.0)#
- class pyiwfm.io.streams.StreamFileConfig(output_dir, stream_nodes_file='stream_nodes.dat', reaches_file='reaches.dat', diversions_file='diversions.dat', bypasses_file='bypasses.dat', rating_curves_file='rating_curves.dat', inflows_file='stream_inflows.dat')[source]#
Bases:
objectConfiguration for stream component files.
- Variables:
output_dir (pathlib.Path) – Directory for output files
stream_nodes_file (str) – Stream nodes file name
reaches_file (str) – Reaches definition file name
diversions_file (str) – Diversions file name
bypasses_file (str) – Bypasses file name
rating_curves_file (str) – Rating curves file name
inflows_file (str) – Inflow time series file name
- __init__(output_dir, stream_nodes_file='stream_nodes.dat', reaches_file='reaches.dat', diversions_file='diversions.dat', bypasses_file='bypasses.dat', rating_curves_file='rating_curves.dat', inflows_file='stream_inflows.dat')#
- class pyiwfm.io.streams.StreamWriter(config)[source]#
Bases:
objectWriter for IWFM stream network component files.
Writes all stream-related input files including nodes, reaches, diversions, bypasses, and rating curves.
Example
>>> config = StreamFileConfig(output_dir=Path("./model")) >>> writer = StreamWriter(config) >>> files = writer.write(stream_component)
- __init__(config)[source]#
Initialize the stream writer.
- Parameters:
config (StreamFileConfig) – File configuration
- write_inflows_timeseries(filepath, times, inflows, node_ids=None, units='CFS', factor=1.0, header=None)[source]#
Write stream inflows time series file.
- Parameters:
- Returns:
Path to written file
- Return type:
- class pyiwfm.io.streams.StreamReader[source]#
Bases:
objectReader for IWFM stream network component files.
- class pyiwfm.io.streams.StreamMainFileConfig(version='', inflow_file=None, diversion_spec_file=None, bypass_spec_file=None, diversion_file=None, budget_output_file=None, diversion_budget_file=None, hydrograph_count=0, hydrograph_output_type=0, hydrograph_output_file=None, hydrograph_specs=<factory>, final_flow_file=None, hydrograph_flow_factor=1.0, hydrograph_flow_unit='', hydrograph_elev_factor=1.0, hydrograph_elev_unit='', node_budget_count=0, node_budget_output_file=None, node_budget_ids=<factory>, conductivity_factor=1.0, conductivity_time_unit='', length_factor=1.0, bed_params=<factory>, interaction_type=None, evap_area_file=None, evap_node_specs=<factory>, roughness_factor=1.0, cross_section_length_factor=1.0, cross_section_data=<factory>, ic_type=0, ic_time_unit='', ic_factor=1.0, initial_conditions=<factory>)[source]#
Bases:
objectConfiguration parsed from Stream component main file.
The stream component main file is a dispatcher that references sub-files for inflows, diversions, and bypasses. It also contains inline hydrograph output specifications.
- Variables:
version (str) – File format version (e.g., “4.2”)
inflow_file (pathlib.Path | None) – Path to stream inflow time series file
diversion_spec_file (pathlib.Path | None) – Path to diversion specifications file
bypass_spec_file (pathlib.Path | None) – Path to bypass specifications file
diversion_file (pathlib.Path | None) – Path to diversion time series file
budget_output_file (pathlib.Path | None) – Path to stream reach budget output
diversion_budget_file (pathlib.Path | None) – Path to diversion detail budget output
hydrograph_count (int) – Number of hydrograph output locations
hydrograph_output_type (int) – 0=flow, 1=stage, 2=both
hydrograph_output_file (pathlib.Path | None) – Path to hydrograph output file
hydrograph_specs (list[tuple[int, str]]) – List of (node_id, name) tuples for output locations
- bed_params: list[StreamBedParamRow]#
- cross_section_data: list[CrossSectionRow]#
- initial_conditions: list[StreamInitialConditionRow]#
- __init__(version='', inflow_file=None, diversion_spec_file=None, bypass_spec_file=None, diversion_file=None, budget_output_file=None, diversion_budget_file=None, hydrograph_count=0, hydrograph_output_type=0, hydrograph_output_file=None, hydrograph_specs=<factory>, final_flow_file=None, hydrograph_flow_factor=1.0, hydrograph_flow_unit='', hydrograph_elev_factor=1.0, hydrograph_elev_unit='', node_budget_count=0, node_budget_output_file=None, node_budget_ids=<factory>, conductivity_factor=1.0, conductivity_time_unit='', length_factor=1.0, bed_params=<factory>, interaction_type=None, evap_area_file=None, evap_node_specs=<factory>, roughness_factor=1.0, cross_section_length_factor=1.0, cross_section_data=<factory>, ic_type=0, ic_time_unit='', ic_factor=1.0, initial_conditions=<factory>)#
- class pyiwfm.io.streams.StreamMainFileReader[source]#
Bases:
objectReader for IWFM stream component main file.
The Stream main file is a hierarchical dispatcher that contains: 1. Version header (e.g., #4.2) 2. Paths to sub-files (inflows, diversions, bypasses) 3. Output file paths 4. Inline hydrograph output specifications
- class pyiwfm.io.streams.StreamReachSpec(id, n_nodes, outflow_node=0, name='', node_ids=<factory>, node_to_gw_node=<factory>, node_rating_tables=<factory>, node_bottom_elevations=<factory>)[source]#
Bases:
objectStream reach specification from preprocessor StreamsSpec file.
Contains the reach definition including node-to-GW-node mappings for stream-aquifer interaction.
- Variables:
id (int) – Reach ID
n_nodes (int) – Number of stream nodes in this reach
outflow_node (int) – Outflow destination (0=boundary, -n=lake n, +n=reach n)
name (str) – Reach name/description
node_ids (list[int]) – List of stream node IDs in this reach
node_to_gw_node (dict[int, int]) – Mapping of stream_node_id -> gw_node_id
node_rating_tables (dict[int, tuple[list[float], list[float]]]) – Maps stream_node_id -> (stages, flows)
node_bottom_elevations (dict[int, float]) – Maps stream_node_id -> bottom elevation
- __init__(id, n_nodes, outflow_node=0, name='', node_ids=<factory>, node_to_gw_node=<factory>, node_rating_tables=<factory>, node_bottom_elevations=<factory>)#
- class pyiwfm.io.streams.StreamSpecReader[source]#
Bases:
objectReader for IWFM preprocessor StreamsSpec file.
The StreamsSpec file defines the stream network geometry including: - Number of reaches and rating table points - Reach definitions with node lists - Stream-GW node mappings for each stream node
- pyiwfm.io.streams.write_stream(stream, output_dir, config=None)[source]#
Write stream component to files.
- pyiwfm.io.streams.read_stream_main_file(filepath, base_dir=None)[source]#
Read IWFM stream component main file.
The Stream main file is a hierarchical dispatcher that contains paths to sub-files (inflows, diversions, bypasses) and inline hydrograph output specifications.
- Parameters:
- Returns:
StreamMainFileConfig with parsed values
- Return type:
Example
>>> config = read_stream_main_file("C2VSimFG_Streams.dat") >>> print(f"Version: {config.version}") >>> print(f"Hydrograph outputs: {config.hydrograph_count}")
- pyiwfm.io.streams.read_stream_spec(filepath)[source]#
Read IWFM preprocessor StreamsSpec file.
The StreamsSpec file defines the stream network geometry including reach definitions and stream-GW node mappings.
- Parameters:
- Returns:
Tuple of (n_reaches, n_rating_points, list of StreamReachSpec)
- Return type:
tuple[int, int, list[StreamReachSpec]]
Example
>>> n_reaches, n_rtb, reaches = read_stream_spec("StreamsSpec.dat") >>> print(f"Loaded {n_reaches} reaches") >>> for reach in reaches: ... print(f" Reach {reach.id}: {reach.n_nodes} nodes")
Stream Writer#
Writer for IWFM stream component files using Jinja2 templates.
Stream Component Writer for IWFM models.
This module provides the main writer for IWFM stream component files, orchestrating the writing of all stream-related input files including: - Main stream control file (Stream_MAIN.dat) - Stream inflows time series - Diversion specifications - Bypass specifications - Stream bed parameters
- class pyiwfm.io.stream_writer.StreamWriterConfig(output_dir, version='4.0', stream_subdir='Stream', main_file='Stream_MAIN.dat', inflow_file='StreamInflow.dat', diver_specs_file='DiverSpecs.dat', bypass_specs_file='BypassSpecs.dat', diversions_file='Diversions.dat', strm_budget_file='../Results/StrmBud.hdf', strm_node_budget_file='../Results/StrmNodeBud.hdf', strm_hyd_file='../Results/StrmHyd.out', diver_detail_file='../Results/DiverDetail.hdf', flow_factor=2.2957e-05, flow_unit='ac.ft./day', length_factor=1.0, length_unit='ft', conductivity=10.0, bed_thickness=1.0, wetted_perimeter=150.0, conductivity_factor=1.0, conductivity_time_unit='1day', bed_length_factor=1.0, interaction_type=1, final_flow_file='', roughness_factor=1.0, cross_section_length_factor=1.0, ic_type=0, ic_time_unit='', ic_factor=1.0, evap_area_file='')[source]#
Bases:
BaseComponentWriterConfigConfiguration for stream component file writing.
- Variables:
- __init__(output_dir, version='4.0', stream_subdir='Stream', main_file='Stream_MAIN.dat', inflow_file='StreamInflow.dat', diver_specs_file='DiverSpecs.dat', bypass_specs_file='BypassSpecs.dat', diversions_file='Diversions.dat', strm_budget_file='../Results/StrmBud.hdf', strm_node_budget_file='../Results/StrmNodeBud.hdf', strm_hyd_file='../Results/StrmHyd.out', diver_detail_file='../Results/DiverDetail.hdf', flow_factor=2.2957e-05, flow_unit='ac.ft./day', length_factor=1.0, length_unit='ft', conductivity=10.0, bed_thickness=1.0, wetted_perimeter=150.0, conductivity_factor=1.0, conductivity_time_unit='1day', bed_length_factor=1.0, interaction_type=1, final_flow_file='', roughness_factor=1.0, cross_section_length_factor=1.0, ic_type=0, ic_time_unit='', ic_factor=1.0, evap_area_file='')#
- class pyiwfm.io.stream_writer.StreamComponentWriter(model, config, template_engine=None)[source]#
Bases:
TemplateWriterWriter for IWFM Stream Component files.
Writes all stream-related input files for IWFM simulation.
Example
>>> from pyiwfm.io.stream_writer import StreamComponentWriter, StreamWriterConfig >>> config = StreamWriterConfig(output_dir=Path("model/Simulation")) >>> writer = StreamComponentWriter(model, config) >>> files = writer.write_all()
- __init__(model, config, template_engine=None)[source]#
Initialize the stream component writer.
- Parameters:
model (
IWFMModel) – Model to writeconfig (
StreamWriterConfig) – Output file configurationtemplate_engine (
TemplateEngine, optional) – Custom template engine
- write_all(write_defaults=True)[source]#
Write all stream component files.
- Parameters:
write_defaults (
bool) – If True, write default files even when no stream component is loaded (useful for generating simulation skeleton)- Returns:
Mapping of file type to output path
- Return type:
dict[str,Path]
- write_main()[source]#
Write the main stream control file.
- Returns:
Path to written file
- Return type:
Path
- write_diver_specs()[source]#
Write the diversion specifications file.
Writes IWFM 14-column (no spills) diversion specification format including NDIVER, per-diversion parameters, element groups, and recharge zones.
- Returns:
Path to written file
- Return type:
Path
- write_bypass_specs()[source]#
Write the bypass specifications file.
IWFM format: - NBYPASS, FACTX, TUNITX, FACTY, TUNITY (header) - Per bypass: ID, IA, TYPEDEST, DEST, IDIVC, DIVRL, DIVNL, NAME - Rating table rows (DIVX, DIVY) if IDIVC < 0 - Seepage/recharge zone data for each bypass
- Returns:
Path to written file
- Return type:
Path
- write_stream_inflow_ts(dates=None, data=None, column_mapping=None)[source]#
Write the stream inflow time series data file.
- Parameters:
dates (
list[str], optional) – IWFM timestampsdata (
NDArray[np.float64], optional) – Inflow data array (n_times, n_cols)column_mapping (
list[str], optional) – Column mapping rows (ID, IRST)
- Returns:
Path to written file
- Return type:
Path
- pyiwfm.io.stream_writer.write_stream_component(model, output_dir, config=None)[source]#
Write stream component files for a model.
- Parameters:
model (
IWFMModel) – Model to writeoutput_dir (
Pathorstr) – Output directoryconfig (
StreamWriterConfig, optional) – File configuration
- Returns:
Mapping of file type to output path
- Return type:
dict[str,Path]
Stream Diversion#
Reader for stream diversion specification files.
Stream Diversion Specification Reader for IWFM.
This module reads the IWFM diversion specification file, which defines diversion definitions with source nodes, delivery destinations, element groups, and recharge zone destinations for recoverable losses.
The file format supports two variants: 14-column (legacy, without spill fields) and 16-column (with spill column and fraction).
Reference: Class_Diversion.f90 - Diversion_New()
- class pyiwfm.io.stream_diversion.DiversionSpec(id=0, stream_node=0, max_diver_col=0, frac_max_diver=1.0, recv_loss_col=0, frac_recv_loss=0.0, non_recv_loss_col=0, frac_non_recv_loss=0.0, spill_col=0, frac_spill=0.0, dest_type=3, dest_id=0, delivery_col=0, frac_delivery=1.0, irrig_frac_col=0, adjustment_col=0, name='')[source]#
Bases:
objectSpecification for a single stream diversion.
- Variables:
id (int) – Diversion ID
stream_node (int) – Stream node where diversion originates (0=outside model)
max_diver_col (int) – Column in diversions file for max diversion rate
frac_max_diver (float) – Fraction of max diversion to apply
recv_loss_col (int) – Column for recoverable loss (0=not used)
frac_recv_loss (float) – Fraction of recoverable loss
non_recv_loss_col (int) – Column for non-recoverable loss (0=not used)
frac_non_recv_loss (float) – Fraction of non-recoverable loss
spill_col (int) – Column for spill rates (0=not used, only in 16-col format)
frac_spill (float) – Fraction of spill (only in 16-col format)
dest_type (int) – Delivery destination type (1=element, 2=subregion, 3=outside, 4=elementset)
dest_id (int) – Destination element/subregion/set ID
delivery_col (int) – Column for delivery amounts (0=not used)
frac_delivery (float) – Fraction of delivery
irrig_frac_col (int) – Column for irrigation fraction
adjustment_col (int) – Column for adjustment data
name (str) – Diversion name (up to 20 chars)
- __init__(id=0, stream_node=0, max_diver_col=0, frac_max_diver=1.0, recv_loss_col=0, frac_recv_loss=0.0, non_recv_loss_col=0, frac_non_recv_loss=0.0, spill_col=0, frac_spill=0.0, dest_type=3, dest_id=0, delivery_col=0, frac_delivery=1.0, irrig_frac_col=0, adjustment_col=0, name='')#
- class pyiwfm.io.stream_diversion.ElementGroup(id=0, elements=<factory>)[source]#
Bases:
objectA group of elements used as a diversion delivery destination.
- __init__(id=0, elements=<factory>)#
- class pyiwfm.io.stream_diversion.RechargeZoneDest(diversion_id=0, n_zones=0, zone_ids=<factory>, zone_fractions=<factory>)[source]#
Bases:
objectRecharge zone destination for recoverable loss or spill.
- Variables:
- __init__(diversion_id=0, n_zones=0, zone_ids=<factory>, zone_fractions=<factory>)#
- class pyiwfm.io.stream_diversion.DiversionSpecConfig(n_diversions=0, diversions=<factory>, n_element_groups=0, element_groups=<factory>, recharge_zones=<factory>, spill_zones=<factory>, has_spills=False)[source]#
Bases:
objectComplete diversion specification configuration.
- Variables:
n_diversions (int) – Number of diversions
diversions (list[pyiwfm.io.stream_diversion.DiversionSpec]) – List of diversion specifications
n_element_groups (int) – Number of element groups
element_groups (list[pyiwfm.io.stream_diversion.ElementGroup]) – List of element groups
recharge_zones (list[pyiwfm.io.stream_diversion.RechargeZoneDest]) – List of recharge zone destinations (for recoverable loss)
spill_zones (list[pyiwfm.io.stream_diversion.RechargeZoneDest]) – List of spill zone destinations (for spills)
has_spills (bool) – Whether the file uses 16-column format with spills
- diversions: list[DiversionSpec]#
- element_groups: list[ElementGroup]#
- recharge_zones: list[RechargeZoneDest]#
- spill_zones: list[RechargeZoneDest]#
- __init__(n_diversions=0, diversions=<factory>, n_element_groups=0, element_groups=<factory>, recharge_zones=<factory>, spill_zones=<factory>, has_spills=False)#
- class pyiwfm.io.stream_diversion.DiversionSpecReader[source]#
Bases:
ReaderMixinReader for IWFM diversion specification files.
Supports both 14-column (legacy) and 16-column (with spills) formats. Auto-detects the format based on the number of columns in the first diversion data line.
Stream Bypass#
Reader for stream bypass specification files.
Stream Bypass Specification Reader for IWFM.
This module reads the IWFM bypass specification file, which defines conversion factors for flow and bypass values, bypass definitions with source/destination nodes, rating tables, and recoverable/non-recoverable loss fractions. Bypass destination types are 1 (stream node) or 2 (lake).
Reference: Class_Bypass.f90 - Bypass_New()
- class pyiwfm.io.stream_bypass.BypassRatingTable(flows=<factory>, fractions=<factory>)[source]#
Bases:
objectRating table for a bypass (inline definition).
- Variables:
flows (numpy.ndarray[tuple[Any, ...], numpy.dtype[numpy.float64]]) – Array of flow values
fractions (numpy.ndarray[tuple[Any, ...], numpy.dtype[numpy.float64]]) – Array of bypass fraction at each flow level
- __init__(flows=<factory>, fractions=<factory>)#
- class pyiwfm.io.stream_bypass.BypassSpec(id=0, export_stream_node=0, dest_type=1, dest_id=0, rating_table_col=0, frac_recoverable=0.0, frac_non_recoverable=0.0, name='', inline_rating=None)[source]#
Bases:
objectSpecification for a single bypass.
- Variables:
id (int) – Bypass ID
export_stream_node (int) – Stream node where bypass originates (0=outside model)
dest_type (int) – Destination type (1=stream node, 2=lake)
dest_id (int) – Destination stream node ID or lake ID
rating_table_col (int) – Column in diversions file for rating. Positive means pre-defined rating from diversions file, negative means
abs(col)inline rating table points, zero means no rating table.frac_recoverable (float) – Fraction of bypass that is recoverable loss
frac_non_recoverable (float) – Fraction of bypass that is non-recoverable loss
name (str) – Bypass name (up to 20 chars)
inline_rating (pyiwfm.io.stream_bypass.BypassRatingTable | None) – Inline rating table (if rating_table_col < 0)
- inline_rating: BypassRatingTable | None = None#
- __init__(id=0, export_stream_node=0, dest_type=1, dest_id=0, rating_table_col=0, frac_recoverable=0.0, frac_non_recoverable=0.0, name='', inline_rating=None)#
- class pyiwfm.io.stream_bypass.BypassSeepageZone(bypass_id=0, n_elements=0, element_ids=<factory>, element_fractions=<factory>)[source]#
Bases:
objectSeepage/recharge zone for a bypass.
- Variables:
- __init__(bypass_id=0, n_elements=0, element_ids=<factory>, element_fractions=<factory>)#
- class pyiwfm.io.stream_bypass.BypassSpecConfig(n_bypasses=0, flow_factor=1.0, flow_time_unit='', bypass_factor=1.0, bypass_time_unit='', bypasses=<factory>, seepage_zones=<factory>)[source]#
Bases:
objectComplete bypass specification configuration.
- Variables:
n_bypasses (int) – Number of bypasses
flow_factor (float) – Flow conversion factor for stream flows
flow_time_unit (str) – Time unit for stream flows
bypass_factor (float) – Flow conversion factor for bypass values
bypass_time_unit (str) – Time unit for bypass values
bypasses (list[pyiwfm.io.stream_bypass.BypassSpec]) – List of bypass specifications
seepage_zones (list[pyiwfm.io.stream_bypass.BypassSeepageZone]) – List of seepage zone destinations (per bypass)
- bypasses: list[BypassSpec]#
- seepage_zones: list[BypassSeepageZone]#
- __init__(n_bypasses=0, flow_factor=1.0, flow_time_unit='', bypass_factor=1.0, bypass_time_unit='', bypasses=<factory>, seepage_zones=<factory>)#
- class pyiwfm.io.stream_bypass.BypassSpecReader[source]#
Bases:
ReaderMixinReader for IWFM bypass specification files.
The bypass file defines flow routing that bypasses portions of the stream network, with optional inline rating tables.
Stream Inflow#
Reader for stream inflow data files.
Stream Inflow Reader for IWFM.
This module reads the IWFM stream inflow file header, which maps inflow time-series columns to stream nodes. The actual time-series data follows in standard IWFM time-series format.
The header contains: 1. Conversion factor for all inflow values 2. Time unit 3. Number of inflow series 4. Per-series: [InflowID] StreamNodeID mapping
Reference: Class_StrmInflow.f90 - New()
- class pyiwfm.io.stream_inflow.InflowSpec(inflow_id=0, stream_node=0)[source]#
Bases:
objectSpecification for a single inflow point.
- Variables:
- __init__(inflow_id=0, stream_node=0)#
- class pyiwfm.io.stream_inflow.InflowConfig(conversion_factor=1.0, time_unit='', n_inflows=0, inflow_specs=<factory>)[source]#
Bases:
objectConfiguration from stream inflow file header.
- Variables:
conversion_factor (float) – Multiplication factor for all inflow values
time_unit (str) – Time unit string (e.g., “MONTH”, “DAY”)
n_inflows (int) – Number of inflow time series
inflow_specs (list[pyiwfm.io.stream_inflow.InflowSpec]) – List of inflow specifications (column-to-node mapping)
- inflow_specs: list[InflowSpec]#
- __init__(conversion_factor=1.0, time_unit='', n_inflows=0, inflow_specs=<factory>)#
- class pyiwfm.io.stream_inflow.InflowReader[source]#
Bases:
ReaderMixinReader for IWFM stream inflow file header.
Reads only the header (conversion factor, time unit, number of series, and per-series node mapping). Does not parse the time-series data.
Lake I/O#
Lakes Module#
The lakes module provides readers and writers for IWFM lake component files.
Lake component I/O handlers for IWFM model files.
This module provides functions for reading and writing IWFM lake component files including lake definitions, lake elements, rating curves, and outflows.
- class pyiwfm.io.lakes.LakeFileConfig(output_dir, lakes_file='lakes.dat', lake_elements_file='lake_elements.dat', rating_curves_file='lake_rating_curves.dat', outflows_file='lake_outflows.dat')[source]#
Bases:
objectConfiguration for lake component files.
- Variables:
output_dir (pathlib.Path) – Directory for output files
lakes_file (str) – Lake definitions file name
lake_elements_file (str) – Lake elements file name
rating_curves_file (str) – Lake rating curves file name
outflows_file (str) – Lake outflows file name
- __init__(output_dir, lakes_file='lakes.dat', lake_elements_file='lake_elements.dat', rating_curves_file='lake_rating_curves.dat', outflows_file='lake_outflows.dat')#
- class pyiwfm.io.lakes.LakeWriter(config)[source]#
Bases:
objectWriter for IWFM lake component files.
Writes all lake-related input files including definitions, elements, rating curves, and outflows.
Example
>>> config = LakeFileConfig(output_dir=Path("./model")) >>> writer = LakeWriter(config) >>> files = writer.write(lake_component)
- __init__(config)[source]#
Initialize the lake writer.
- Parameters:
config (LakeFileConfig) – File configuration
- class pyiwfm.io.lakes.LakeReader[source]#
Bases:
objectReader for IWFM lake component files.
- class pyiwfm.io.lakes.LakeParamSpec(lake_id=0, conductance_coeff=0.0, depth_denom=1.0, max_elev_col=0, et_col=0, precip_col=0, name='')[source]#
Bases:
objectPer-lake parameters from the simulation lake main file.
- Variables:
lake_id (int) – Lake ID
conductance_coeff (float) – Dimensionless conductance coefficient (CLAKE)
depth_denom (float) – Lake depth denominator (DLAKE)
max_elev_col (int) – Column index in max elevation file
et_col (int) – Column index in ET time series file
precip_col (int) – Column index in precipitation file
name (str) – Lake identification name
- __init__(lake_id=0, conductance_coeff=0.0, depth_denom=1.0, max_elev_col=0, et_col=0, precip_col=0, name='')#
- class pyiwfm.io.lakes.OutflowRatingPoint(elevation=0.0, outflow=0.0)[source]#
Bases:
objectA single point in a lake outflow rating table (v5.0).
- Variables:
- __init__(elevation=0.0, outflow=0.0)#
- class pyiwfm.io.lakes.LakeOutflowRating(lake_id=0, points=<factory>)[source]#
Bases:
objectOutflow rating table for a lake (v5.0 only).
- Variables:
lake_id (int) – Lake ID
points (list[pyiwfm.io.lakes.OutflowRatingPoint]) – List of (elevation, outflow) rating points
- points: list[OutflowRatingPoint]#
- __init__(lake_id=0, points=<factory>)#
- class pyiwfm.io.lakes.LakeMainFileConfig(version='', max_elev_file=None, budget_output_file=None, final_elev_file=None, conductance_factor=1.0, conductance_time_unit='', depth_factor=1.0, lake_params=<factory>, elev_factor=1.0, outflow_factor=1.0, outflow_time_unit='', outflow_ratings=<factory>)[source]#
Bases:
objectConfiguration parsed from Lake component main simulation file.
The lake main file configures lake hydrological parameters and data source file paths for the simulation.
- Variables:
version (str) – File format version (e.g., “4.0” or “5.0”)
max_elev_file (pathlib.Path | None) – Path to max lake elevation time series file
budget_output_file (pathlib.Path | None) – Path to lake budget output file
final_elev_file (pathlib.Path | None) – Path to end-of-simulation elevation output file
conductance_factor (float) – Conductance factor K (FactK)
conductance_time_unit (str) – Time unit for conductance
depth_factor (float) – Lake depth parameter L (FactL)
lake_params (list[pyiwfm.io.lakes.LakeParamSpec]) – Per-lake parameter specifications
elev_factor (float) – Elevation conversion factor (v5.0 only)
outflow_factor (float) – Outflow rate conversion factor (v5.0 only)
outflow_time_unit (str) – Time unit for outflow rating tables (v5.0 only)
outflow_ratings (list[pyiwfm.io.lakes.LakeOutflowRating]) – Outflow rating tables per lake (v5.0 only)
- lake_params: list[LakeParamSpec]#
- outflow_ratings: list[LakeOutflowRating]#
- __init__(version='', max_elev_file=None, budget_output_file=None, final_elev_file=None, conductance_factor=1.0, conductance_time_unit='', depth_factor=1.0, lake_params=<factory>, elev_factor=1.0, outflow_factor=1.0, outflow_time_unit='', outflow_ratings=<factory>)#
- class pyiwfm.io.lakes.LakeMainFileReader[source]#
Bases:
objectReader for IWFM lake component main simulation file.
The Lake main file is a hierarchical dispatcher that contains: 1. Version header (e.g., #4.0) 2. Paths to sub-files (max elevation TS, budget output, final elevation) 3. Conductance and depth parameters 4. Per-lake parameter lines 5. (v5.0) Outflow rating tables
Supports both version 4.0 and 5.0 formats.
- pyiwfm.io.lakes.read_lake_main_file(filepath, base_dir=None)[source]#
Read IWFM lake component main simulation file.
- Parameters:
- Returns:
LakeMainFileConfig with parsed values
- Return type:
Lake Writer#
Writer for IWFM lake component files using Jinja2 templates.
Lake Component Writer for IWFM models.
This module provides the main writer for IWFM lake component files, orchestrating the writing of all lake-related input files including: - Main lake control file (Lake_MAIN.dat) for v4.0 and v5.0 - Maximum lake elevation time series (v4.0) - Lake budget output configuration - v5.0 outflow rating tables
- class pyiwfm.io.lake_writer.LakeWriterConfig(output_dir, version='4.0', lake_subdir='Lake', main_file='Lake_MAIN.dat', max_elev_file='MaxLakeElev.dat', lake_budget_file='../Results/LakeBud.hdf', final_elev_file='../Results/FinalLakeElev.out', conductivity_factor=1.0, conductivity_time_unit='1day', length_factor=1.0, rating_elev_factor=1.0, rating_flow_factor=1.0, rating_flow_time_unit='1DAY', bed_conductivity=2.0, bed_thickness=1.0)[source]#
Bases:
BaseComponentWriterConfigConfiguration for lake component file writing.
- Variables:
- __init__(output_dir, version='4.0', lake_subdir='Lake', main_file='Lake_MAIN.dat', max_elev_file='MaxLakeElev.dat', lake_budget_file='../Results/LakeBud.hdf', final_elev_file='../Results/FinalLakeElev.out', conductivity_factor=1.0, conductivity_time_unit='1day', length_factor=1.0, rating_elev_factor=1.0, rating_flow_factor=1.0, rating_flow_time_unit='1DAY', bed_conductivity=2.0, bed_thickness=1.0)#
- class pyiwfm.io.lake_writer.LakeComponentWriter(model, config, template_engine=None)[source]#
Bases:
TemplateWriterWriter for IWFM Lake Component files.
Writes all lake-related input files for IWFM simulation.
Example
>>> from pyiwfm.io.lake_writer import LakeComponentWriter, LakeWriterConfig >>> config = LakeWriterConfig(output_dir=Path("model/Simulation")) >>> writer = LakeComponentWriter(model, config) >>> files = writer.write_all()
- __init__(model, config, template_engine=None)[source]#
Initialize the lake component writer.
- Parameters:
model (
IWFMModel) – Model to writeconfig (
LakeWriterConfig) – Output file configurationtemplate_engine (
TemplateEngine, optional) – Custom template engine
- write_all(write_defaults=True)[source]#
Write all lake component files.
- Parameters:
write_defaults (
bool) – If True, write default files even when no lake component is loaded (useful for generating simulation skeleton)- Returns:
Mapping of file type to output path
- Return type:
dict[str,Path]
- write_main()[source]#
Write the main lake control file.
- Returns:
Path to written file
- Return type:
Path
- write_max_lake_elev_ts(dates=None, data=None)[source]#
Write the maximum lake elevation time series file (v4.0).
- Parameters:
dates (
list[str], optional) – IWFM timestampsdata (
NDArray[np.float64], optional) – Max elevation data array (n_times, n_lakes)
- Returns:
Path to written file
- Return type:
Path
- pyiwfm.io.lake_writer.write_lake_component(model, output_dir, config=None)[source]#
Write lake component files for a model.
- Parameters:
model (
IWFMModel) – Model to writeoutput_dir (
Pathorstr) – Output directoryconfig (
LakeWriterConfig, optional) – File configuration
- Returns:
Mapping of file type to output path
- Return type:
dict[str,Path]
Root Zone I/O#
Root Zone Module#
The root zone module provides readers and writers for IWFM root zone component files.
Root zone component I/O handlers for IWFM model files.
This module provides functions for reading and writing IWFM root zone component files including crop types, soil parameters, land use assignments, and soil moisture data.
- class pyiwfm.io.rootzone.ElementSoilParamRow(element_id, wilting_point, field_capacity, total_porosity, lambda_param, hydraulic_conductivity, kunsat_method, precip_column, precip_factor, generic_moisture_column, surface_flow_dest_type=0, surface_flow_dest_id=0, k_ponded=-1.0, capillary_rise=0.0, dest_ag=0, dest_urban_in=0, dest_urban_out=0, dest_nvrv=0)[source]#
Bases:
objectPer-element soil parameters from the root zone main file.
Column layout varies by version — see
RootZoneMainFileReader._read_element_soil_params().- __init__(element_id, wilting_point, field_capacity, total_porosity, lambda_param, hydraulic_conductivity, kunsat_method, precip_column, precip_factor, generic_moisture_column, surface_flow_dest_type=0, surface_flow_dest_id=0, k_ponded=-1.0, capillary_rise=0.0, dest_ag=0, dest_urban_in=0, dest_urban_out=0, dest_nvrv=0)#
- class pyiwfm.io.rootzone.RootZoneFileConfig(output_dir, crop_types_file='crop_types.dat', soil_params_file='soil_params.dat', landuse_file='landuse.dat', ag_landuse_file='ag_landuse.dat', urban_landuse_file='urban_landuse.dat', native_landuse_file='native_landuse.dat', soil_moisture_file='initial_soil_moisture.dat')[source]#
Bases:
objectConfiguration for root zone component files.
- Variables:
output_dir (pathlib.Path) – Directory for output files
crop_types_file (str) – Crop types file name
soil_params_file (str) – Soil parameters file name
landuse_file (str) – Land use assignments file name
ag_landuse_file (str) – Agricultural land use file name
urban_landuse_file (str) – Urban land use file name
native_landuse_file (str) – Native/riparian land use file name
soil_moisture_file (str) – Initial soil moisture file name
- __init__(output_dir, crop_types_file='crop_types.dat', soil_params_file='soil_params.dat', landuse_file='landuse.dat', ag_landuse_file='ag_landuse.dat', urban_landuse_file='urban_landuse.dat', native_landuse_file='native_landuse.dat', soil_moisture_file='initial_soil_moisture.dat')#
- class pyiwfm.io.rootzone.RootZoneWriter(config)[source]#
Bases:
objectWriter for IWFM root zone component files.
Writes all root zone-related input files including crop types, soil parameters, and land use assignments.
Example
>>> config = RootZoneFileConfig(output_dir=Path("./model")) >>> writer = RootZoneWriter(config) >>> files = writer.write(rootzone_component)
- __init__(config)[source]#
Initialize the root zone writer.
- Parameters:
config (RootZoneFileConfig) – File configuration
- class pyiwfm.io.rootzone.RootZoneReader[source]#
Bases:
objectReader for IWFM root zone component files.
- class pyiwfm.io.rootzone.RootZoneMainFileConfig(version='', convergence_tolerance=1e-08, max_iterations=2000, length_conversion=1.0, gw_uptake_enabled=False, nonponded_crop_file=None, ponded_crop_file=None, urban_file=None, native_veg_file=None, return_flow_file=None, reuse_file=None, irrigation_period_file=None, generic_moisture_file=None, ag_water_demand_file=None, lwu_budget_file=None, rz_budget_file=None, lwu_zone_budget_file=None, rz_zone_budget_file=None, lu_area_scale_file=None, final_moisture_file=None, k_factor=1.0, k_exdth_factor=1.0, k_time_unit='', surface_flow_dest_file=None, element_soil_params=<factory>)[source]#
Bases:
objectConfiguration parsed from RootZone component main file.
The root zone component main file is a dispatcher that contains solver parameters and paths to sub-files for crop, urban, and native vegetation data.
- Variables:
version (str) – File format version (e.g., “4.0”, “4.11”)
convergence_tolerance (float) – Root zone solver convergence tolerance
max_iterations (int) – Maximum solver iterations
length_conversion (float) – Length unit conversion factor (FACTCN)
gw_uptake_enabled (bool) – Whether ET from GW is enabled (v4.11+ only)
nonponded_crop_file (pathlib.Path | None) – Path to non-ponded agricultural crop file
ponded_crop_file (pathlib.Path | None) – Path to ponded agricultural crop file
urban_file (pathlib.Path | None) – Path to urban land use file
native_veg_file (pathlib.Path | None) – Path to native/riparian vegetation file
return_flow_file (pathlib.Path | None) – Path to return flow fractions file
reuse_file (pathlib.Path | None) – Path to water reuse specifications file
irrigation_period_file (pathlib.Path | None) – Path to irrigation period file
generic_moisture_file (pathlib.Path | None) – Path to generic moisture data file
ag_water_demand_file (pathlib.Path | None) – Path to agricultural water supply requirement file
lwu_budget_file (pathlib.Path | None) – Path to land and water use budget output
rz_budget_file (pathlib.Path | None) – Path to root zone budget output
lwu_zone_budget_file (pathlib.Path | None) – Path to LWU zone budget output (v4.11+ only)
rz_zone_budget_file (pathlib.Path | None) – Path to RZ zone budget output (v4.11+ only)
lu_area_scale_file (pathlib.Path | None) – Path to land use area scaling output (v4.11+ only)
final_moisture_file (pathlib.Path | None) – Path to end-of-simulation soil moisture output
- element_soil_params: list[ElementSoilParamRow]#
- __init__(version='', convergence_tolerance=1e-08, max_iterations=2000, length_conversion=1.0, gw_uptake_enabled=False, nonponded_crop_file=None, ponded_crop_file=None, urban_file=None, native_veg_file=None, return_flow_file=None, reuse_file=None, irrigation_period_file=None, generic_moisture_file=None, ag_water_demand_file=None, lwu_budget_file=None, rz_budget_file=None, lwu_zone_budget_file=None, rz_zone_budget_file=None, lu_area_scale_file=None, final_moisture_file=None, k_factor=1.0, k_exdth_factor=1.0, k_time_unit='', surface_flow_dest_file=None, element_soil_params=<factory>)#
- class pyiwfm.io.rootzone.RootZoneMainFileReader[source]#
Bases:
objectReader for IWFM rootzone component main file.
The RootZone main file is a hierarchical dispatcher that contains: 1. Version header (e.g., #4.11) 2. Solver parameters (convergence, iterations) 3. Paths to sub-files for different land use types 4. Output file paths
- read(filepath, base_dir=None, n_elements=0)[source]#
Parse RootZone main file.
Supports v4.0 through v4.13 formats. v4.1+ adds capillary rise; v4.11+ adds ET-from-GW flag and zone budget files; v4.12+ adds per-landuse surface flow destinations.
- Parameters:
filepath (Path | str) – Path to the RootZone component main file
base_dir (Path | None) – Base directory for resolving relative paths. If None, uses the parent directory of filepath.
n_elements (int) – Expected number of elements (from mesh). If > 0, the soil parameter parser will read exactly this many rows instead of relying on column-count heuristics.
- Returns:
RootZoneMainFileConfig with parsed values
- Return type:
- pyiwfm.io.rootzone.write_rootzone(rootzone, output_dir, config=None)[source]#
Write root zone component to files.
- pyiwfm.io.rootzone.read_soil_params(filepath)[source]#
Read soil parameters from file.
- Parameters:
- Returns:
Dictionary mapping element ID to SoilParameters object
- Return type:
- pyiwfm.io.rootzone.read_rootzone_main_file(filepath, base_dir=None)[source]#
Read IWFM rootzone component main file.
The RootZone main file is a hierarchical dispatcher that contains solver parameters and paths to sub-files for different land use types.
- Parameters:
- Returns:
RootZoneMainFileConfig with parsed values
- Return type:
Example
>>> config = read_rootzone_main_file("C2VSimFG_RootZone.dat") >>> print(f"Version: {config.version}") >>> print(f"GW uptake: {config.gw_uptake_enabled}") >>> if config.nonponded_crop_file: ... print(f"Crop file: {config.nonponded_crop_file}")
Root Zone Writer#
Writer for IWFM root zone component files using Jinja2 templates.
Root Zone Component Writer for IWFM models.
This module provides the main writer for IWFM root zone component files, orchestrating the writing of all root zone-related input files including: - Main root zone control file (RootZone_MAIN.dat) - Soil parameters for each element - Return flow fractions - Irrigation periods
- class pyiwfm.io.rootzone_writer.RootZoneWriterConfig(output_dir, version='4.12', rootzone_subdir='RootZone', main_file='RootZone_MAIN.dat', return_flow_file='ReturnFlowFrac.dat', reuse_file='ReuseFrac.dat', irig_period_file='IrigPeriod.dat', surface_flow_dest_file='SurfaceFlowDest.dat', lwu_budget_file='../Results/LWU.hdf', rz_budget_file='../Results/RootZone.hdf', lwu_zbudget_file='../Results/LWU_ZBud.hdf', rz_zbudget_file='../Results/RootZone_ZBud.hdf', convergence=0.001, max_iterations=150, inch_to_length_factor=0.0833333, gw_uptake=0, wilting_point=0.0, field_capacity=0.2, total_porosity=0.45, pore_size_index=0.62, hydraulic_conductivity=2.6, k_ponded=-1.0, rhc_method=2, capillary_rise=0.0, k_factor=0.03281, cprise_factor=1.0, k_time_unit='1hour', final_moisture_file='')[source]#
Bases:
BaseComponentWriterConfigConfiguration for root zone component file writing.
- Variables:
- __init__(output_dir, version='4.12', rootzone_subdir='RootZone', main_file='RootZone_MAIN.dat', return_flow_file='ReturnFlowFrac.dat', reuse_file='ReuseFrac.dat', irig_period_file='IrigPeriod.dat', surface_flow_dest_file='SurfaceFlowDest.dat', lwu_budget_file='../Results/LWU.hdf', rz_budget_file='../Results/RootZone.hdf', lwu_zbudget_file='../Results/LWU_ZBud.hdf', rz_zbudget_file='../Results/RootZone_ZBud.hdf', convergence=0.001, max_iterations=150, inch_to_length_factor=0.0833333, gw_uptake=0, wilting_point=0.0, field_capacity=0.2, total_porosity=0.45, pore_size_index=0.62, hydraulic_conductivity=2.6, k_ponded=-1.0, rhc_method=2, capillary_rise=0.0, k_factor=0.03281, cprise_factor=1.0, k_time_unit='1hour', final_moisture_file='')#
- class pyiwfm.io.rootzone_writer.RootZoneComponentWriter(model, config, template_engine=None)[source]#
Bases:
TemplateWriterWriter for IWFM Root Zone Component files.
Writes all root zone-related input files for IWFM simulation.
Example
>>> from pyiwfm.io.rootzone_writer import RootZoneComponentWriter, RootZoneWriterConfig >>> config = RootZoneWriterConfig(output_dir=Path("model/Simulation")) >>> writer = RootZoneComponentWriter(model, config) >>> files = writer.write_all()
- __init__(model, config, template_engine=None)[source]#
Initialize the root zone component writer.
- Parameters:
model (
IWFMModel) – Model to writeconfig (
RootZoneWriterConfig) – Output file configurationtemplate_engine (
TemplateEngine, optional) – Custom template engine
- write_all(write_defaults=True)[source]#
Write all root zone component files.
- Parameters:
write_defaults (
bool) – If True, write default files even when no root zone component is loaded (useful for generating simulation skeleton)- Returns:
Mapping of file type to output path
- Return type:
dict[str,Path]
- write_main()[source]#
Write the main root zone control file.
- Returns:
Path to written file
- Return type:
Path
- pyiwfm.io.rootzone_writer.write_rootzone_component(model, output_dir, config=None)[source]#
Write root zone component files for a model.
- Parameters:
model (
IWFMModel) – Model to writeoutput_dir (
Pathorstr) – Output directoryconfig (
RootZoneWriterConfig, optional) – File configuration
- Returns:
Mapping of file type to output path
- Return type:
dict[str,Path]
Root Zone v4.x#
Readers and writers specific to IWFM v4.x root zone format.
v4.x sub-file readers and writers for IWFM RootZone component.
This module handles the per-element, v4.0-v4.13 Fortran file formats
for the four land-use sub-files (non-ponded ag, ponded ag, urban,
native/riparian). These formats differ from the v5.0/subregion-based
readers in rootzone_nonponded.py etc.
The existing v5.0 readers and their 1100+ passing tests are left untouched; this module provides parallel v4.x-specific I/O.
- class pyiwfm.io.rootzone_v4x.RootDepthRow(crop_index, max_root_depth, fractions_column)[source]#
Bases:
objectRoot depth entry for one crop.
- __init__(crop_index, max_root_depth, fractions_column)#
- class pyiwfm.io.rootzone_v4x.ElementCropRow(element_id, values=<factory>)[source]#
Bases:
objectPer-element row with one value per crop (or per category).
- __init__(element_id, values=<factory>)#
- class pyiwfm.io.rootzone_v4x.AgInitialConditionRow(element_id, precip_fraction, moisture_contents=<factory>)[source]#
Bases:
objectInitial condition row: element_id, precip_fraction, MC per crop.
- __init__(element_id, precip_fraction, moisture_contents=<factory>)#
- class pyiwfm.io.rootzone_v4x.NonPondedCropConfigV4x(n_crops=0, demand_from_moisture_flag=1, crop_codes=<factory>, area_data_file=None, n_budget_crops=0, budget_crop_codes=<factory>, lwu_budget_file=None, rz_budget_file=None, root_depth_fractions_file=None, root_depth_factor=1.0, root_depth_data=<factory>, curve_numbers=<factory>, etc_pointers=<factory>, supply_req_pointers=<factory>, irrigation_pointers=<factory>, min_soil_moisture_file=None, min_moisture_pointers=<factory>, target_soil_moisture_file=None, target_moisture_pointers=<factory>, return_flow_pointers=<factory>, reuse_pointers=<factory>, leaching_factors_file=None, leaching_pointers=<factory>, initial_conditions=<factory>)[source]#
Bases:
objectConfiguration parsed from a v4.x non-ponded agricultural sub-file.
- root_depth_data: list[RootDepthRow]#
- curve_numbers: list[ElementCropRow]#
- etc_pointers: list[ElementCropRow]#
- supply_req_pointers: list[ElementCropRow]#
- irrigation_pointers: list[ElementCropRow]#
- min_moisture_pointers: list[ElementCropRow]#
- target_moisture_pointers: list[ElementCropRow]#
- return_flow_pointers: list[ElementCropRow]#
- reuse_pointers: list[ElementCropRow]#
- leaching_pointers: list[ElementCropRow]#
- initial_conditions: list[AgInitialConditionRow]#
- __init__(n_crops=0, demand_from_moisture_flag=1, crop_codes=<factory>, area_data_file=None, n_budget_crops=0, budget_crop_codes=<factory>, lwu_budget_file=None, rz_budget_file=None, root_depth_fractions_file=None, root_depth_factor=1.0, root_depth_data=<factory>, curve_numbers=<factory>, etc_pointers=<factory>, supply_req_pointers=<factory>, irrigation_pointers=<factory>, min_soil_moisture_file=None, min_moisture_pointers=<factory>, target_soil_moisture_file=None, target_moisture_pointers=<factory>, return_flow_pointers=<factory>, reuse_pointers=<factory>, leaching_factors_file=None, leaching_pointers=<factory>, initial_conditions=<factory>)#
- class pyiwfm.io.rootzone_v4x.PondedCropConfigV4x(area_data_file=None, n_budget_crops=0, budget_crop_codes=<factory>, lwu_budget_file=None, rz_budget_file=None, root_depth_factor=1.0, root_depths=<factory>, curve_numbers=<factory>, etc_pointers=<factory>, supply_req_pointers=<factory>, irrigation_pointers=<factory>, ponding_depth_file=None, operations_flow_file=None, ponding_depth_pointers=<factory>, decomp_water_pointers=<factory>, return_flow_pointers=<factory>, reuse_pointers=<factory>, initial_conditions=<factory>)[source]#
Bases:
objectConfiguration parsed from a v4.x ponded agricultural sub-file.
Fixed 5 crop types: rice (3 decomp variants) + refuge (2 types).
- curve_numbers: list[ElementCropRow]#
- etc_pointers: list[ElementCropRow]#
- supply_req_pointers: list[ElementCropRow]#
- irrigation_pointers: list[ElementCropRow]#
- ponding_depth_pointers: list[ElementCropRow]#
- decomp_water_pointers: list[ElementCropRow]#
- return_flow_pointers: list[ElementCropRow]#
- reuse_pointers: list[ElementCropRow]#
- initial_conditions: list[AgInitialConditionRow]#
- __init__(area_data_file=None, n_budget_crops=0, budget_crop_codes=<factory>, lwu_budget_file=None, rz_budget_file=None, root_depth_factor=1.0, root_depths=<factory>, curve_numbers=<factory>, etc_pointers=<factory>, supply_req_pointers=<factory>, irrigation_pointers=<factory>, ponding_depth_file=None, operations_flow_file=None, ponding_depth_pointers=<factory>, decomp_water_pointers=<factory>, return_flow_pointers=<factory>, reuse_pointers=<factory>, initial_conditions=<factory>)#
- class pyiwfm.io.rootzone_v4x.UrbanElementRowV4x(element_id, pervious_fraction, curve_number, pop_column, per_cap_column, demand_fraction, etc_column, return_flow_column, reuse_column, water_use_column)[source]#
Bases:
objectPer-element urban data (10-column row).
- __init__(element_id, pervious_fraction, curve_number, pop_column, per_cap_column, demand_fraction, etc_column, return_flow_column, reuse_column, water_use_column)#
- class pyiwfm.io.rootzone_v4x.UrbanInitialRowV4x(element_id, precip_fraction, moisture_content)[source]#
Bases:
objectUrban initial conditions: element_id, precip_frac, moisture.
- __init__(element_id, precip_fraction, moisture_content)#
- class pyiwfm.io.rootzone_v4x.UrbanConfigV4x(area_data_file=None, root_depth_factor=1.0, root_depth=0.0, population_file=None, per_capita_water_use_file=None, water_use_specs_file=None, element_data=<factory>, initial_conditions=<factory>)[source]#
Bases:
objectConfiguration parsed from a v4.x urban land-use sub-file.
- element_data: list[UrbanElementRowV4x]#
- initial_conditions: list[UrbanInitialRowV4x]#
- __init__(area_data_file=None, root_depth_factor=1.0, root_depth=0.0, population_file=None, per_capita_water_use_file=None, water_use_specs_file=None, element_data=<factory>, initial_conditions=<factory>)#
- class pyiwfm.io.rootzone_v4x.NativeRiparianElementRowV4x(element_id, native_cn, riparian_cn, native_etc_column, riparian_etc_column, riparian_stream_node=0)[source]#
Bases:
objectPer-element native/riparian data (5 or 6-column row).
The 6th column (
riparian_stream_node) is the stream node index for riparian ET from stream (ISTRMRV), present in v4.1+ files.- __init__(element_id, native_cn, riparian_cn, native_etc_column, riparian_etc_column, riparian_stream_node=0)#
- class pyiwfm.io.rootzone_v4x.NativeRiparianInitialRowV4x(element_id, native_moisture, riparian_moisture)[source]#
Bases:
objectNative/riparian initial conditions (3-column row).
- __init__(element_id, native_moisture, riparian_moisture)#
- class pyiwfm.io.rootzone_v4x.NativeRiparianConfigV4x(area_data_file=None, root_depth_factor=1.0, native_root_depth=0.0, riparian_root_depth=0.0, element_data=<factory>, initial_conditions=<factory>)[source]#
Bases:
objectConfiguration parsed from a v4.x native/riparian sub-file.
- element_data: list[NativeRiparianElementRowV4x]#
- initial_conditions: list[NativeRiparianInitialRowV4x]#
- __init__(area_data_file=None, root_depth_factor=1.0, native_root_depth=0.0, riparian_root_depth=0.0, element_data=<factory>, initial_conditions=<factory>)#
- class pyiwfm.io.rootzone_v4x.NonPondedCropReaderV4x(n_elements=0)[source]#
Bases:
_V4xReaderBaseReader for IWFM v4.x non-ponded agricultural crop sub-file.
Reads the 24-section file produced by
Class_NonPondedAgLandUse_v40::New().
- class pyiwfm.io.rootzone_v4x.PondedCropReaderV4x(n_elements=0)[source]#
Bases:
_V4xReaderBaseReader for IWFM v4.x ponded agricultural crop sub-file.
Fixed 5 crop types (3 rice + 2 refuge).
- N_PONDED_CROPS = 5#
- class pyiwfm.io.rootzone_v4x.UrbanReaderV4x(n_elements=0)[source]#
Bases:
_V4xReaderBaseReader for IWFM v4.x urban land-use sub-file.
- class pyiwfm.io.rootzone_v4x.NativeRiparianReaderV4x(n_elements=0)[source]#
Bases:
_V4xReaderBaseReader for IWFM v4.x native/riparian vegetation sub-file.
- class pyiwfm.io.rootzone_v4x.NonPondedCropWriterV4x[source]#
Bases:
_V4xWriterBaseWriter for IWFM v4.x non-ponded agricultural crop sub-file.
- class pyiwfm.io.rootzone_v4x.PondedCropWriterV4x[source]#
Bases:
_V4xWriterBaseWriter for IWFM v4.x ponded agricultural crop sub-file.
- class pyiwfm.io.rootzone_v4x.UrbanWriterV4x[source]#
Bases:
_V4xWriterBaseWriter for IWFM v4.x urban land-use sub-file.
- class pyiwfm.io.rootzone_v4x.NativeRiparianWriterV4x[source]#
Bases:
_V4xWriterBaseWriter for IWFM v4.x native/riparian vegetation sub-file.
- pyiwfm.io.rootzone_v4x.read_nonponded_v4x(filepath, base_dir=None, n_elements=0)[source]#
Read a v4.x non-ponded agricultural crop sub-file.
- pyiwfm.io.rootzone_v4x.read_ponded_v4x(filepath, base_dir=None, n_elements=0)[source]#
Read a v4.x ponded agricultural crop sub-file.
Root Zone Non-Ponded Crops#
Reader for non-ponded (dry) crop land use parameters.
Non-ponded agricultural crop sub-file reader for IWFM RootZone component.
This module reads the IWFM non-ponded agricultural crop file (AGNPFL), which is referenced by the RootZone component main file. The file contains crop definitions, curve numbers, ET-column pointers, irrigation period references, soil moisture targets, return-flow / reuse fractions, and initial conditions.
The same binary format (Class_AgLandUse_v50) is used by both the
non-ponded and ponded crop files in IWFM v5.0.
- class pyiwfm.io.rootzone_nonponded.CurveNumberRow(subregion_id, cn_values=<factory>)[source]#
Bases:
objectCurve-number data for one subregion.
- Variables:
- __init__(subregion_id, cn_values=<factory>)#
- class pyiwfm.io.rootzone_nonponded.EtcPointerRow(subregion_id, etc_columns=<factory>)[source]#
Bases:
objectET-column pointers for one subregion.
- Variables:
- __init__(subregion_id, etc_columns=<factory>)#
- class pyiwfm.io.rootzone_nonponded.IrrigationPointerRow(subregion_id, irrig_columns=<factory>)[source]#
Bases:
objectIrrigation-period column pointers for one subregion.
- Variables:
- __init__(subregion_id, irrig_columns=<factory>)#
- class pyiwfm.io.rootzone_nonponded.SoilMoisturePointerRow(subregion_id, columns=<factory>)[source]#
Bases:
objectSoil-moisture column pointers for one subregion.
- Variables:
- __init__(subregion_id, columns=<factory>)#
- class pyiwfm.io.rootzone_nonponded.SupplyReturnReuseRow(subregion_id, supply_column=0, return_flow_column=0, reuse_column=0)[source]#
Bases:
objectWater-supply, return-flow and reuse column pointers for one subregion.
- Variables:
- __init__(subregion_id, supply_column=0, return_flow_column=0, reuse_column=0)#
- class pyiwfm.io.rootzone_nonponded.InitialConditionRow(subregion_id, precip_fractions=<factory>, moisture_contents=<factory>)[source]#
Bases:
objectInitial soil-moisture conditions for one subregion.
For each soil type there are two values: - fraction of initial soil moisture due to precipitation (0–1) - initial soil-moisture content (0–1)
- Variables:
- __init__(subregion_id, precip_fractions=<factory>, moisture_contents=<factory>)#
- class pyiwfm.io.rootzone_nonponded.NonPondedCropConfig(n_crops=0, subregional_area_file=None, elemental_area_file=None, area_output_factor=1.0, area_output_unit='', area_output_file=None, root_depth_factor=1.0, root_depths=<factory>, curve_numbers=<factory>, etc_pointers=<factory>, irrigation_period_file=None, irrigation_pointers=<factory>, min_soil_moisture_file=None, min_moisture_pointers=<factory>, target_soil_moisture_file=None, target_moisture_pointers=<factory>, water_demand_file=None, demand_from_moisture_flag=1, supply_return_reuse=<factory>, initial_conditions=<factory>)[source]#
Bases:
objectConfiguration parsed from a non-ponded agricultural crop sub-file.
- Variables:
n_crops (int) – Number of non-ponded crops.
subregional_area_file (pathlib.Path | None) – Path to subregional crop-area data file.
elemental_area_file (pathlib.Path | None) – Path to elemental agricultural area file.
area_output_factor (float) – Length / area output conversion factor.
area_output_unit (str) – Output unit label (e.g. “ACRES”).
area_output_file (pathlib.Path | None) – Path to average-crop output file.
root_depth_factor (float) – Conversion factor for rooting depths.
root_depths (list[float]) – Rooting depth for each crop (length
n_crops).curve_numbers (list[pyiwfm.io.rootzone_nonponded.CurveNumberRow]) – Curve-number rows (one per subregion).
etc_pointers (list[pyiwfm.io.rootzone_nonponded.EtcPointerRow]) – ET-column pointers (one row per subregion).
irrigation_period_file (pathlib.Path | None) – Path to irrigation-period data file.
irrigation_pointers (list[pyiwfm.io.rootzone_nonponded.IrrigationPointerRow]) – Irrigation-period column pointers.
min_soil_moisture_file (pathlib.Path | None) – Path to minimum soil-moisture data file.
min_moisture_pointers (list[pyiwfm.io.rootzone_nonponded.SoilMoisturePointerRow]) – Minimum soil-moisture column pointers.
target_soil_moisture_file (pathlib.Path | None) – Path to target soil-moisture data file (optional).
target_moisture_pointers (list[pyiwfm.io.rootzone_nonponded.SoilMoisturePointerRow]) – Target soil-moisture column pointers.
water_demand_file (pathlib.Path | None) – Path to agricultural water-demand data file (optional).
demand_from_moisture_flag (int) – Demand-computation flag (1 = begin, 2 = end).
supply_return_reuse (list[pyiwfm.io.rootzone_nonponded.SupplyReturnReuseRow]) – Supply / return-flow / reuse rows.
initial_conditions (list[pyiwfm.io.rootzone_nonponded.InitialConditionRow]) – Initial soil-moisture condition rows.
- curve_numbers: list[CurveNumberRow]#
- etc_pointers: list[EtcPointerRow]#
- irrigation_pointers: list[IrrigationPointerRow]#
- min_moisture_pointers: list[SoilMoisturePointerRow]#
- target_moisture_pointers: list[SoilMoisturePointerRow]#
- supply_return_reuse: list[SupplyReturnReuseRow]#
- initial_conditions: list[InitialConditionRow]#
- __init__(n_crops=0, subregional_area_file=None, elemental_area_file=None, area_output_factor=1.0, area_output_unit='', area_output_file=None, root_depth_factor=1.0, root_depths=<factory>, curve_numbers=<factory>, etc_pointers=<factory>, irrigation_period_file=None, irrigation_pointers=<factory>, min_soil_moisture_file=None, min_moisture_pointers=<factory>, target_soil_moisture_file=None, target_moisture_pointers=<factory>, water_demand_file=None, demand_from_moisture_flag=1, supply_return_reuse=<factory>, initial_conditions=<factory>)#
- class pyiwfm.io.rootzone_nonponded.NonPondedCropReader(n_subregions=None)[source]#
Bases:
objectReader for IWFM non-ponded agricultural crop sub-file.
This parses the positional-sequential file referenced as AGNPFL in the RootZone component main file. The format matches
Class_AgLandUse_v50::New()in the Fortran source.- Parameters:
n_subregions (int | None) – Number of subregions in the model. If provided, tabular sections read exactly this many rows (skipping comments within). If
None, sections are delimited by comment lines (i.e. a comment line after data rows ends the section).
- read(filepath, base_dir=None)[source]#
Parse the non-ponded crop file.
- Parameters:
- Returns:
Populated
NonPondedCropConfig.- Return type:
- pyiwfm.io.rootzone_nonponded.read_nonponded_crop(filepath, base_dir=None, n_subregions=None)[source]#
Read an IWFM non-ponded agricultural crop sub-file.
- Parameters:
- Returns:
NonPondedCropConfigwith parsed values.- Return type:
Root Zone Ponded Crops#
Reader for ponded (rice/wetland) crop land use parameters.
Ponded agricultural crop sub-file reader for IWFM RootZone component.
This module reads the IWFM ponded agricultural crop file (PFL), which
is referenced by the RootZone component main file. In IWFM v5.0 the
ponded crop file uses the same Class_AgLandUse_v50 format as the
non-ponded crop file, so this module re-exports the non-ponded reader
with ponded-specific type aliases.
- Typical ponded crops in C2VSimFG:
Rice (flood-decomposed, non-flood-decomposed, no-decomposition)
Refuge (seasonal, permanent)
- pyiwfm.io.rootzone_ponded.PondedCropConfig#
Alias for
NonPondedCropConfig— same file format.
- class pyiwfm.io.rootzone_ponded.PondedCropReader(n_subregions=None)[source]#
Bases:
NonPondedCropReaderReader for IWFM ponded agricultural crop sub-file.
Inherits from
NonPondedCropReadersince IWFM v5.0 uses the sameClass_AgLandUse_v50format for both ponded and non-ponded crop files.
- pyiwfm.io.rootzone_ponded.read_ponded_crop(filepath, base_dir=None, n_subregions=None)[source]#
Read an IWFM ponded agricultural crop sub-file.
- Parameters:
- Returns:
PondedCropConfigwith parsed values.- Return type:
Root Zone Urban#
Reader for urban land use parameters.
Urban land-use sub-file reader for IWFM RootZone component.
This module reads the IWFM urban land-use file (URBFL), which is referenced by the RootZone component main file. The file contains urban area data references, root depth, curve numbers, water demand and water-use specification references, per-subregion management data, per-element surface-flow destinations, and initial soil-moisture conditions.
Format matches Class_UrbanLandUse_v50::New() in the Fortran source.
- class pyiwfm.io.rootzone_urban.UrbanCurveNumberRow(subregion_id, cn_values=<factory>)[source]#
Bases:
objectCurve-number data for one subregion (urban).
- Variables:
- __init__(subregion_id, cn_values=<factory>)#
- class pyiwfm.io.rootzone_urban.UrbanManagementRow(subregion_id, pervious_fraction=1.0, demand_column=0, water_use_column=0, etc_column=0, return_flow_column=0, reuse_column=0)[source]#
Bases:
objectPer-subregion urban water management data.
- Variables:
subregion_id (int) – Subregion identifier (1-based).
pervious_fraction (float) – Fraction of pervious area (0–1).
demand_column (int) – Column index into water-demand data file.
water_use_column (int) – Column index into water-use specs file.
etc_column (int) – Column index into ET data file.
return_flow_column (int) – Column index into return-flow fractions.
reuse_column (int) – Column index into reuse fractions.
- __init__(subregion_id, pervious_fraction=1.0, demand_column=0, water_use_column=0, etc_column=0, return_flow_column=0, reuse_column=0)#
- class pyiwfm.io.rootzone_urban.SurfaceFlowDestRow(element_id, dest_type=1, dest_id=0)[source]#
Bases:
objectPer-element surface-flow destination.
- Variables:
- __init__(element_id, dest_type=1, dest_id=0)#
- class pyiwfm.io.rootzone_urban.UrbanInitialConditionRow(subregion_id, precip_fractions=<factory>, moisture_contents=<factory>)[source]#
Bases:
objectInitial soil-moisture conditions for one subregion.
- Variables:
- __init__(subregion_id, precip_fractions=<factory>, moisture_contents=<factory>)#
- class pyiwfm.io.rootzone_urban.UrbanLandUseConfig(area_data_file=None, root_depth_factor=1.0, root_depth=0.0, curve_numbers=<factory>, demand_file=None, water_use_specs_file=None, management=<factory>, surface_flow_destinations=<factory>, initial_conditions=<factory>)[source]#
Bases:
objectConfiguration parsed from an urban land-use sub-file.
- Variables:
area_data_file (pathlib.Path | None) – Path to urban-area time-series data file.
root_depth_factor (float) – Conversion factor for root depth.
root_depth (float) – Urban root depth (already multiplied by factor).
curve_numbers (list[pyiwfm.io.rootzone_urban.UrbanCurveNumberRow]) – Curve-number rows (one per subregion).
demand_file (pathlib.Path | None) – Path to urban water-demand data file.
water_use_specs_file (pathlib.Path | None) – Path to urban water-use specifications file.
management (list[pyiwfm.io.rootzone_urban.UrbanManagementRow]) – Per-subregion management / pointer data.
surface_flow_destinations (list[pyiwfm.io.rootzone_urban.SurfaceFlowDestRow]) – Per-element surface-flow destinations.
initial_conditions (list[pyiwfm.io.rootzone_urban.UrbanInitialConditionRow]) – Initial soil-moisture condition rows.
- curve_numbers: list[UrbanCurveNumberRow]#
- management: list[UrbanManagementRow]#
- surface_flow_destinations: list[SurfaceFlowDestRow]#
- initial_conditions: list[UrbanInitialConditionRow]#
- __init__(area_data_file=None, root_depth_factor=1.0, root_depth=0.0, curve_numbers=<factory>, demand_file=None, water_use_specs_file=None, management=<factory>, surface_flow_destinations=<factory>, initial_conditions=<factory>)#
- class pyiwfm.io.rootzone_urban.UrbanLandUseReader(n_subregions=None, n_elements=None)[source]#
Bases:
objectReader for IWFM urban land-use sub-file.
Parses the positional-sequential file referenced as URBFL in the RootZone component main file.
- Parameters:
- read(filepath, base_dir=None)[source]#
Parse the urban land-use file.
- Parameters:
- Returns:
Populated
UrbanLandUseConfig.- Return type:
- pyiwfm.io.rootzone_urban.read_urban_landuse(filepath, base_dir=None, n_subregions=None, n_elements=None)[source]#
Read an IWFM urban land-use sub-file.
- Parameters:
- Returns:
UrbanLandUseConfigwith parsed values.- Return type:
Root Zone Native/Riparian#
Reader for native and riparian vegetation parameters.
Native / riparian vegetation sub-file reader for IWFM RootZone component.
This module reads the IWFM native and riparian vegetation file (NVRVFL), which is referenced by the RootZone component main file. The file contains land-use area references, root depths for native and riparian vegetation, curve numbers for both vegetation types, ET-column pointers, and initial soil-moisture conditions.
Format matches Class_NativeRiparianLandUse_v50::New() in the
Fortran source.
- class pyiwfm.io.rootzone_native.NativeRiparianCNRow(subregion_id, native_cn=<factory>, riparian_cn=<factory>)[source]#
Bases:
objectCurve-number data for one subregion (native + riparian).
- Variables:
- __init__(subregion_id, native_cn=<factory>, riparian_cn=<factory>)#
- class pyiwfm.io.rootzone_native.NativeRiparianEtcRow(subregion_id, native_etc_column=0, riparian_etc_column=0)[source]#
Bases:
objectET-column pointers for one subregion.
- Variables:
- __init__(subregion_id, native_etc_column=0, riparian_etc_column=0)#
- class pyiwfm.io.rootzone_native.NativeRiparianInitialRow(subregion_id, native_moisture=<factory>, riparian_moisture=<factory>)[source]#
Bases:
objectInitial soil-moisture conditions for one subregion.
Values alternate between native and riparian per soil type:
native_soil1 riparian_soil1 native_soil2 riparian_soil2 …- Variables:
- __init__(subregion_id, native_moisture=<factory>, riparian_moisture=<factory>)#
- class pyiwfm.io.rootzone_native.NativeRiparianConfig(area_data_file=None, root_depth_factor=1.0, native_root_depth=0.0, riparian_root_depth=0.0, curve_numbers=<factory>, etc_pointers=<factory>, initial_conditions=<factory>)[source]#
Bases:
objectConfiguration parsed from a native/riparian vegetation sub-file.
- Variables:
area_data_file (pathlib.Path | None) – Path to vegetation-area time-series data file.
root_depth_factor (float) – Conversion factor for root depths.
native_root_depth (float) – Native vegetation root depth (with factor applied).
riparian_root_depth (float) – Riparian vegetation root depth (with factor applied).
curve_numbers (list[pyiwfm.io.rootzone_native.NativeRiparianCNRow]) – Curve-number rows (one per subregion).
etc_pointers (list[pyiwfm.io.rootzone_native.NativeRiparianEtcRow]) – ET-column pointer rows (one per subregion).
initial_conditions (list[pyiwfm.io.rootzone_native.NativeRiparianInitialRow]) – Initial soil-moisture condition rows.
- curve_numbers: list[NativeRiparianCNRow]#
- etc_pointers: list[NativeRiparianEtcRow]#
- initial_conditions: list[NativeRiparianInitialRow]#
- __init__(area_data_file=None, root_depth_factor=1.0, native_root_depth=0.0, riparian_root_depth=0.0, curve_numbers=<factory>, etc_pointers=<factory>, initial_conditions=<factory>)#
- class pyiwfm.io.rootzone_native.NativeRiparianReader(n_subregions=None)[source]#
Bases:
objectReader for IWFM native/riparian vegetation sub-file.
Parses the positional-sequential file referenced as NVRVFL in the RootZone component main file.
- Parameters:
n_subregions (int | None) – Number of subregions (for exact row counts).
- read(filepath, base_dir=None)[source]#
Parse the native/riparian vegetation file.
- Parameters:
- Returns:
Populated
NativeRiparianConfig.- Return type:
- pyiwfm.io.rootzone_native.read_native_riparian(filepath, base_dir=None, n_subregions=None)[source]#
Read an IWFM native/riparian vegetation sub-file.
- Parameters:
- Returns:
NativeRiparianConfigwith parsed values.- Return type:
Supplemental Package I/O#
Small Watershed Module#
Reader for IWFM small watershed component files.
Small Watershed Main File Reader for IWFM.
This module reads the IWFM small watershed component main file, which defines watershed-level modeling parameters including: 1. Output file paths (budget, final results) 2. Number of small watersheds and their geospatial data 3. Root zone parameters (soil properties, curve numbers) 4. Aquifer parameters (storage, recession coefficients) 5. Initial conditions
Reference: Class_AppSmallWatershed_v40.f90 - Class_AppSmallWatershed_v40_New()
- class pyiwfm.io.small_watershed.WatershedGWNode(gw_node_id=0, max_perc_rate=0.0, is_baseflow=False, layer=0)[source]#
Bases:
objectGroundwater node connection for a small watershed.
- Variables:
- __init__(gw_node_id=0, max_perc_rate=0.0, is_baseflow=False, layer=0)#
- class pyiwfm.io.small_watershed.WatershedSpec(id=0, area=0.0, dest_stream_node=0, gw_nodes=<factory>)[source]#
Bases:
objectGeospatial specification for a single small watershed.
- Variables:
id (int) – Watershed ID
area (float) – Watershed area (converted by area factor)
dest_stream_node (int) – Destination stream node for outflow
gw_nodes (list[pyiwfm.io.small_watershed.WatershedGWNode]) – List of connected groundwater nodes
- gw_nodes: list[WatershedGWNode]#
- __init__(id=0, area=0.0, dest_stream_node=0, gw_nodes=<factory>)#
- class pyiwfm.io.small_watershed.WatershedRootZoneParams(id=0, precip_col=0, precip_factor=1.0, et_col=0, crop_coeff_col=0, wilting_point=0.0, field_capacity=0.0, total_porosity=0.0, lambda_param=0.0, root_depth=0.0, hydraulic_cond=0.0, kunsat_method=0, curve_number=0.0)[source]#
Bases:
objectRoot zone parameters for a single small watershed.
- Variables:
id (int) – Watershed ID
precip_col (int) – Precipitation time-series column index
precip_factor (float) – Precipitation conversion factor
et_col (int) – ET time-series column index
wilting_point (float) – Soil wilting point
field_capacity (float) – Soil field capacity
total_porosity (float) – Total porosity
lambda_param (float) – Pore size distribution parameter
root_depth (float) – Root zone depth
hydraulic_cond (float) – Hydraulic conductivity
kunsat_method (int) – Unsaturated K method code
curve_number (float) – SCS curve number
- __init__(id=0, precip_col=0, precip_factor=1.0, et_col=0, crop_coeff_col=0, wilting_point=0.0, field_capacity=0.0, total_porosity=0.0, lambda_param=0.0, root_depth=0.0, hydraulic_cond=0.0, kunsat_method=0, curve_number=0.0)#
- class pyiwfm.io.small_watershed.WatershedInitialCondition(id=0, soil_moisture=0.0, gw_storage=0.0)[source]#
Bases:
objectInitial conditions for a single small watershed.
- Variables:
- __init__(id=0, soil_moisture=0.0, gw_storage=0.0)#
- class pyiwfm.io.small_watershed.WatershedAquiferParams(id=0, gw_threshold=0.0, max_gw_storage=0.0, surface_flow_coeff=0.0, baseflow_coeff=0.0)[source]#
Bases:
objectAquifer parameters for a single small watershed.
- Variables:
- __init__(id=0, gw_threshold=0.0, max_gw_storage=0.0, surface_flow_coeff=0.0, baseflow_coeff=0.0)#
- class pyiwfm.io.small_watershed.SmallWatershedMainConfig(version='', budget_output_file=None, final_results_file=None, n_watersheds=0, area_factor=1.0, flow_factor=1.0, flow_time_unit='', watershed_specs=<factory>, rz_solver_tolerance=1e-08, rz_max_iterations=2000, rz_length_factor=1.0, rz_cn_factor=1.0, rz_k_factor=1.0, rz_k_time_unit='', rootzone_params=<factory>, aq_gw_factor=1.0, aq_time_factor=1.0, aq_time_unit='', aquifer_params=<factory>, ic_factor=1.0, initial_conditions=<factory>)[source]#
Bases:
objectConfiguration parsed from Small Watershed component main file.
- Variables:
version (str) – File format version
budget_output_file (pathlib.Path | None) – Path to budget output file
final_results_file (pathlib.Path | None) – Path to final simulation results file
n_watersheds (int) – Number of small watersheds
area_factor (float) – Area conversion factor
flow_factor (float) – Flow rate conversion factor
flow_time_unit (str) – Time unit for flow rates
watershed_specs (list[pyiwfm.io.small_watershed.WatershedSpec]) – Geospatial specs per watershed
rz_solver_tolerance (float) – Root zone solver tolerance
rz_max_iterations (int) – Root zone solver max iterations
rz_length_factor (float) – Root zone length conversion factor
rz_cn_factor (float) – Curve number conversion factor
rz_k_factor (float) – Hydraulic conductivity conversion factor
rz_k_time_unit (str) – Time unit for hydraulic conductivity
rootzone_params (list[pyiwfm.io.small_watershed.WatershedRootZoneParams]) – Root zone parameters per watershed
aq_gw_factor (float) – GW conversion factor
aq_time_factor (float) – Time conversion factor
aq_time_unit (str) – Time unit for recession coefficients
aquifer_params (list[pyiwfm.io.small_watershed.WatershedAquiferParams]) – Aquifer parameters per watershed
- watershed_specs: list[WatershedSpec]#
- rootzone_params: list[WatershedRootZoneParams]#
- aquifer_params: list[WatershedAquiferParams]#
- initial_conditions: list[WatershedInitialCondition]#
- __init__(version='', budget_output_file=None, final_results_file=None, n_watersheds=0, area_factor=1.0, flow_factor=1.0, flow_time_unit='', watershed_specs=<factory>, rz_solver_tolerance=1e-08, rz_max_iterations=2000, rz_length_factor=1.0, rz_cn_factor=1.0, rz_k_factor=1.0, rz_k_time_unit='', rootzone_params=<factory>, aq_gw_factor=1.0, aq_time_factor=1.0, aq_time_unit='', aquifer_params=<factory>, ic_factor=1.0, initial_conditions=<factory>)#
- class pyiwfm.io.small_watershed.SmallWatershedMainReader[source]#
Bases:
ReaderMixinReader for IWFM small watershed component main file.
Parses the complete small watershed configuration including geospatial data, root zone parameters, aquifer parameters, and output file paths.
Small Watershed Writer#
Writer for IWFM small watershed component files using Jinja2 templates.
Small Watershed Component Writer for IWFM models.
This module provides the writer for IWFM small watershed component files, generating the main file with geospatial data, root zone parameters, and aquifer parameters for all watershed units.
- class pyiwfm.io.small_watershed_writer.SmallWatershedWriterConfig(output_dir, version='4.0', swshed_subdir='SmallWatershed', main_file='SmallWatershed_MAIN.dat', budget_file='../Results/SWShedBud.hdf', final_results_file='../Results/FinalSWShed.out')[source]#
Bases:
BaseComponentWriterConfigConfiguration for small watershed component file writing.
- Variables:
- __init__(output_dir, version='4.0', swshed_subdir='SmallWatershed', main_file='SmallWatershed_MAIN.dat', budget_file='../Results/SWShedBud.hdf', final_results_file='../Results/FinalSWShed.out')#
- class pyiwfm.io.small_watershed_writer.SmallWatershedComponentWriter(model, config, template_engine=None)[source]#
Bases:
TemplateWriterWriter for IWFM Small Watershed Component files.
Writes the small watershed main file including geospatial data, root zone parameters, and aquifer parameters.
Example
>>> from pyiwfm.io.small_watershed_writer import ( ... SmallWatershedComponentWriter, SmallWatershedWriterConfig, ... ) >>> config = SmallWatershedWriterConfig(output_dir=Path("model/Simulation")) >>> writer = SmallWatershedComponentWriter(model, config) >>> files = writer.write_all()
- __init__(model, config, template_engine=None)[source]#
Initialize the template writer.
- Parameters:
output_dir – Directory for output files
template_engine (TemplateEngine | None) – Optional TemplateEngine instance
comment_metadata – Optional CommentMetadata for comment preservation
- pyiwfm.io.small_watershed_writer.write_small_watershed_component(model, output_dir, config=None)[source]#
Write small watershed component files for a model.
- Parameters:
model (
IWFMModel) – Model to write.output_dir (
Pathorstr) – Output directory.config (
SmallWatershedWriterConfig, optional) – File configuration.
- Returns:
Mapping of file type to output path.
- Return type:
dict[str,Path]
Unsaturated Zone Module#
Reader for IWFM unsaturated zone component files.
Unsaturated Zone Main File Reader for IWFM.
This module reads the IWFM unsaturated zone component main file, which defines vadose zone modeling parameters including: 1. Number of unsaturated layers 2. Solver parameters 3. Budget output file paths 4. Layer properties (per element) 5. Initial soil moisture conditions
The unsaturated zone is an optional component used for detailed vadose zone dynamics between the root zone and groundwater.
Reference: Package_AppUnsatZone.f90 - New()
- class pyiwfm.io.unsaturated_zone.UnsatZoneElementData(element_id, thickness_max, total_porosity, lambda_param, hyd_cond, kunsat_method)[source]#
Bases:
objectPer-element unsaturated zone parameters for all layers.
Fortran format per line:
ElemID, [ThickMax_L1, Porosity_L1, Lambda_L1, HydCond_L1, KMethod_L1, ...(repeat per layer)]. Total values per line:1 + 5 * n_layers.- Variables:
element_id (int) – 1-based element ID.
thickness_max (numpy.ndarray[tuple[Any, ...], numpy.dtype[numpy.float64]]) – Maximum thickness per layer, shape (n_layers,).
total_porosity (numpy.ndarray[tuple[Any, ...], numpy.dtype[numpy.float64]]) – Total porosity per layer, shape (n_layers,).
lambda_param (numpy.ndarray[tuple[Any, ...], numpy.dtype[numpy.float64]]) – Pore size distribution parameter per layer, shape (n_layers,).
hyd_cond (numpy.ndarray[tuple[Any, ...], numpy.dtype[numpy.float64]]) – Saturated hydraulic conductivity per layer, shape (n_layers,).
kunsat_method (numpy.ndarray[tuple[Any, ...], numpy.dtype[numpy.int32]]) – Unsaturated K method per layer, shape (n_layers,).
- __init__(element_id, thickness_max, total_porosity, lambda_param, hyd_cond, kunsat_method)#
- class pyiwfm.io.unsaturated_zone.UnsatZoneMainConfig(version='', n_layers=0, solver_tolerance=1e-08, max_iterations=2000, budget_file=None, zbudget_file=None, final_results_file=None, n_parametric_grids=0, coord_factor=1.0, thickness_factor=1.0, hyd_cond_factor=1.0, time_unit='', element_data=<factory>, initial_soil_moisture=<factory>)[source]#
Bases:
objectConfiguration parsed from Unsaturated Zone component main file.
- Variables:
version (str) – File format version
n_layers (int) – Number of unsaturated zone layers (0=disabled)
solver_tolerance (float) – Solver convergence tolerance
max_iterations (int) – Maximum solver iterations
budget_file (pathlib.Path | None) – Path to HDF5 budget output file
zbudget_file (pathlib.Path | None) – Path to HDF5 zone budget output file
final_results_file (pathlib.Path | None) – Path to final simulation results file
n_parametric_grids (int) – Number of parametric grids (0=direct input)
coord_factor (float) – Conversion factor for x-y coordinates
thickness_factor (float) – Conversion factor for layer thickness
hyd_cond_factor (float) – Conversion factor for hydraulic conductivity
time_unit (str) – Time unit for hydraulic conductivity
element_data (list[pyiwfm.io.unsaturated_zone.UnsatZoneElementData]) – Per-element unsaturated zone parameters
initial_soil_moisture (dict[int, numpy.ndarray[tuple[Any, ...], numpy.dtype[numpy.float64]]]) – Initial soil moisture per element per layer. Maps element_id -> moisture array. Key 0 means uniform for all.
- element_data: list[UnsatZoneElementData]#
- __init__(version='', n_layers=0, solver_tolerance=1e-08, max_iterations=2000, budget_file=None, zbudget_file=None, final_results_file=None, n_parametric_grids=0, coord_factor=1.0, thickness_factor=1.0, hyd_cond_factor=1.0, time_unit='', element_data=<factory>, initial_soil_moisture=<factory>)#
- class pyiwfm.io.unsaturated_zone.UnsatZoneMainReader[source]#
Bases:
objectReader for IWFM unsaturated zone component main file.
Parses the full file including header configuration, per-element parameter data (when NGROUP=0), and initial conditions.
Unsaturated Zone Writer#
Writer for IWFM unsaturated zone component files using Jinja2 templates.
Unsaturated Zone Component Writer for IWFM models.
This module provides the writer for IWFM unsaturated zone component files, generating the main file with solver parameters, per-element layer properties, and initial soil moisture conditions.
- class pyiwfm.io.unsaturated_zone_writer.UnsatZoneWriterConfig(output_dir, version='4.0', unsatzone_subdir='UnsatZone', main_file='UnsatZone_MAIN.dat', budget_file='../Results/UZBud.hdf', zbudget_file='../Results/UZZBud.hdf', final_results_file='../Results/FinalUZ.out')[source]#
Bases:
BaseComponentWriterConfigConfiguration for unsaturated zone component file writing.
- Variables:
output_dir (pathlib.Path) – Base output directory
unsatzone_subdir (str) – Subdirectory name for unsat zone files
version (str) – IWFM component version
main_file (str) – Main file name
budget_file (str) – Budget output file path
zbudget_file (str) – Zone budget output file path
final_results_file (str) – Final results output file path
- __init__(output_dir, version='4.0', unsatzone_subdir='UnsatZone', main_file='UnsatZone_MAIN.dat', budget_file='../Results/UZBud.hdf', zbudget_file='../Results/UZZBud.hdf', final_results_file='../Results/FinalUZ.out')#
- class pyiwfm.io.unsaturated_zone_writer.UnsatZoneComponentWriter(model, config, template_engine=None)[source]#
Bases:
TemplateWriterWriter for IWFM Unsaturated Zone Component files.
Writes the unsaturated zone main file including solver parameters, per-element layer properties, and initial soil moisture conditions.
Example
>>> from pyiwfm.io.unsaturated_zone_writer import ( ... UnsatZoneComponentWriter, UnsatZoneWriterConfig, ... ) >>> config = UnsatZoneWriterConfig(output_dir=Path("model/Simulation")) >>> writer = UnsatZoneComponentWriter(model, config) >>> files = writer.write_all()
- __init__(model, config, template_engine=None)[source]#
Initialize the template writer.
- Parameters:
output_dir – Directory for output files
template_engine (TemplateEngine | None) – Optional TemplateEngine instance
comment_metadata – Optional CommentMetadata for comment preservation
- pyiwfm.io.unsaturated_zone_writer.write_unsaturated_zone_component(model, output_dir, config=None)[source]#
Write unsaturated zone component files for a model.
- Parameters:
model (
IWFMModel) – Model to write.output_dir (
Pathorstr) – Output directory.config (
UnsatZoneWriterConfig, optional) – File configuration.
- Returns:
Mapping of file type to output path.
- Return type:
dict[str,Path]
Supply Adjustment#
Reader and writer for IWFM supply adjustment (irrigation) files.
Supply adjustment file reader and writer for IWFM.
- IWFM supply adjustment files use the IntTSDataInFileType format:
Header comments
NCOLADJ (number of columns)
NSPADJ (time step update frequency)
NFQADJ (data repetition frequency)
DSSFL (DSS filename, blank for inline)
Data lines: timestamp + integer adjustment codes (00, 01, 10)
- The adjustment codes are two-digit integers:
1st digit: 0 = no agriculture adjustment, 1 = adjust agriculture
2nd digit: 0 = no urban adjustment, 1 = adjust urban
Combined: 00=none, 01=urban only, 10=ag only, 11=both (deprecated)
- class pyiwfm.io.supply_adjust.SupplyAdjustment(n_columns=0, nsp=1, nfq=0, dss_file='', times=<factory>, values=<factory>, header_lines=<factory>)[source]#
Bases:
objectParsed supply adjustment specification data.
- Variables:
n_columns (int) – Number of adjustment columns (NCOLADJ).
nsp (int) – Time step update frequency (NSPADJ).
nfq (int) – Data repetition frequency (NFQADJ).
dss_file (str) – DSS filename (empty string if inline data).
times (list[datetime.datetime]) – List of timestamps for each data row.
values (list[list[int]]) – List of rows, each row is a list of integer adjustment codes.
- __init__(n_columns=0, nsp=1, nfq=0, dss_file='', times=<factory>, values=<factory>, header_lines=<factory>)#
- pyiwfm.io.supply_adjust.read_supply_adjustment(filepath)[source]#
Read a supply adjustment file.
Parses the IWFM integer time series format (NCOL, NSP, NFQ, DSSFL) followed by timestamp + integer data rows.
- Parameters:
- Returns:
SupplyAdjustment with parsed data.
- Raises:
FileNotFoundError – If file does not exist.
ValueError – If file format is invalid.
- Return type:
- pyiwfm.io.supply_adjust.write_supply_adjustment(data, filepath)[source]#
Write a supply adjustment file.
Writes the IWFM integer time series format: NCOL, NSP, NFQ, DSSFL, followed by timestamp + integer data rows.
- Parameters:
data (SupplyAdjustment) – SupplyAdjustment data to write.
- Returns:
Path to the written file.
- Return type:
Time Series I/O#
Time Series ASCII Module#
The time series ASCII module provides readers and writers for IWFM ASCII time series files.
ASCII time series I/O handlers for IWFM model files.
This module provides functions for reading and writing IWFM ASCII time series files using the standard 16-character timestamp format (MM/DD/YYYY_HH:MM). IWFM uses 24:00 to represent midnight (end of day).
- pyiwfm.io.timeseries_ascii.format_iwfm_timestamp(dt)[source]#
Format a datetime as an IWFM timestamp string.
IWFM uses the format MM/DD/YYYY_HH:MM (16 characters). Midnight (00:00) is represented as 24:00 of the previous day. For example, 2050-11-01 00:00 becomes
10/31/2050_24:00.- Parameters:
dt (datetime | datetime64) – datetime object or numpy datetime64
- Returns:
Formatted timestamp string (16 chars)
- Return type:
- pyiwfm.io.timeseries_ascii.parse_iwfm_timestamp(ts_str)[source]#
Parse an IWFM timestamp string to datetime.
IWFM timestamps are exactly 16 characters: MM/DD/YYYY_HH:MM The 24:00 convention means midnight at the end of the given day, which is converted to 00:00 of the next day internally.
- Parameters:
ts_str (str) – Timestamp string (16 chars, MM/DD/YYYY_HH:MM)
- Returns:
datetime object
- Raises:
ValueError – If timestamp format is invalid
- Return type:
- pyiwfm.io.timeseries_ascii.parse_iwfm_datetime(date_str)[source]#
Parse an IWFM datetime string to Python datetime (lenient).
Unlike
parse_iwfm_timestamp(), which raises on invalid input, this function tries 8 format variants and returnsNoneon failure. Handles the IWFM_24:00end-of-day convention as well as ISO and date-only formats.
- pyiwfm.io.timeseries_ascii.iwfm_date_to_iso(date_str)[source]#
Convert IWFM date string to ISO
YYYY-MM-DDformat.
- class pyiwfm.io.timeseries_ascii.TimeSeriesFileConfig(n_columns, column_ids, units='', factor=1.0, header_lines=None)[source]#
Bases:
objectConfiguration for an IWFM time series file.
- Variables:
- __init__(n_columns, column_ids, units='', factor=1.0, header_lines=None)#
- class pyiwfm.io.timeseries_ascii.TimeSeriesWriter(value_format='%14.6f', timestamp_format='%m/%d/%Y_%H:%M')[source]#
Bases:
objectWriter for IWFM ASCII time series files.
- IWFM time series files have the format:
C Header comments NDATA / Number of data columns FACTOR / Conversion factor MM/DD/YYYY_HH:MM:SS val1 val2 val3 …
Example
>>> writer = TimeSeriesWriter() >>> writer.write( ... filepath="pumping.dat", ... times=times, ... values=values, ... column_ids=[1, 2, 3], ... units="TAF" ... )
- __init__(value_format='%14.6f', timestamp_format='%m/%d/%Y_%H:%M')[source]#
Initialize the time series writer.
- write(filepath, times, values, column_ids=None, units='', factor=1.0, header=None)[source]#
Write time series data to an IWFM ASCII file.
- Parameters:
times (Sequence[datetime] | ndarray[tuple[Any, ...], dtype[datetime64]]) – Sequence of datetime values
values (ndarray[tuple[Any, ...], dtype[float64]]) – 2D array of values (n_times, n_columns) or 1D for single column
column_ids (list[str | int] | None) – Optional list of column identifiers
units (str) – Units string for header
factor (float) – Conversion factor (written to file)
header (str | None) – Optional header comment
- write_from_timeseries(filepath, ts, header=None, factor=1.0)[source]#
Write a TimeSeries object to file.
- Parameters:
ts (TimeSeries) – TimeSeries object
header (str | None) – Optional header comment
factor (float) – Conversion factor
- write_from_collection(filepath, collection, header=None, factor=1.0)[source]#
Write a TimeSeriesCollection to a single file.
All time series must have the same timestamps.
- Parameters:
collection (TimeSeriesCollection) – TimeSeriesCollection object
header (str | None) – Optional header comment
factor (float) – Conversion factor
- class pyiwfm.io.timeseries_ascii.TimeSeriesReader[source]#
Bases:
objectReader for IWFM ASCII time series files.
Example
>>> reader = TimeSeriesReader() >>> times, values, config = reader.read("pumping.dat")
- read_to_timeseries(filepath, name='', location='')[source]#
Read file and return as TimeSeries object.
- Parameters:
- Returns:
TimeSeries object
- Return type:
- pyiwfm.io.timeseries_ascii.write_timeseries(filepath, times, values, column_ids=None, units='', factor=1.0, header=None)[source]#
Write time series data to an IWFM ASCII file.
- Parameters:
times (Sequence[datetime] | ndarray[tuple[Any, ...], dtype[datetime64]]) – Sequence of datetime values
values (ndarray[tuple[Any, ...], dtype[float64]]) – 2D array of values (n_times, n_columns)
column_ids (list[str | int] | None) – Optional list of column identifiers
units (str) – Units string for header
factor (float) – Conversion factor
header (str | None) – Optional header comment
Time Series Module#
Unified time series reader supporting multiple formats.
Unified Time Series I/O Infrastructure for IWFM.
This module provides a unified interface for reading and writing time series data across all supported formats (ASCII, DSS, HDF5). It enables format-agnostic handling of IWFM time series data with automatic format detection and conversion.
- class pyiwfm.io.timeseries.TimeSeriesFileType(*values)[source]#
Bases:
EnumSupported time series file formats.
- ASCII = 'ascii'#
- DSS = 'dss'#
- HDF5 = 'hdf5'#
- BINARY = 'binary'#
- class pyiwfm.io.timeseries.TimeUnit(*values)[source]#
Bases:
EnumStandard time units for IWFM.
- SECOND = 'second'#
- MINUTE = 'minute'#
- HOUR = 'hour'#
- DAY = 'day'#
- WEEK = 'week'#
- MONTH = 'month'#
- YEAR = 'year'#
- class pyiwfm.io.timeseries.TimeSeriesMetadata(file_type=TimeSeriesFileType.ASCII, n_columns=0, column_ids=<factory>, variable_name='', data_unit='', time_unit='', conversion_factor=1.0, is_rate_data=False, recycling_interval=0, start_time=None, end_time=None, n_timesteps=0, source_path=None)[source]#
Bases:
objectMetadata for a time series file.
- Variables:
file_type (pyiwfm.io.timeseries.TimeSeriesFileType) – Type of the source file
n_columns (int) – Number of data columns
column_ids (list[str | int]) – Identifier for each column (location/entity ID)
variable_name (str) – Name of the variable (e.g., “Pumping”, “Head”)
data_unit (str) – Physical units of the data
time_unit (str) – Time unit for the series
conversion_factor (float) – Factor applied during read
is_rate_data (bool) – Whether data represents rates (flow/time)
recycling_interval (int) – Number of months to recycle (0 = no recycling)
start_time (datetime.datetime | None) – Start of time series
end_time (datetime.datetime | None) – End of time series
n_timesteps (int) – Number of timesteps
source_path (pathlib.Path | None) – Original file path
- file_type: TimeSeriesFileType = 'ascii'#
- __init__(file_type=TimeSeriesFileType.ASCII, n_columns=0, column_ids=<factory>, variable_name='', data_unit='', time_unit='', conversion_factor=1.0, is_rate_data=False, recycling_interval=0, start_time=None, end_time=None, n_timesteps=0, source_path=None)#
- class pyiwfm.io.timeseries.UnifiedTimeSeriesConfig(filepath, file_type=None, n_columns=None, column_ids=None, data_unit='', time_unit='', conversion_factor=1.0, is_rate_data=False, recycling_interval=0, start_filter=None, end_filter=None, dss_pathname=None, hdf5_dataset=None)[source]#
Bases:
objectConfiguration for unified time series reading.
- Variables:
filepath (pathlib.Path) – Path to the time series file
file_type (pyiwfm.io.timeseries.TimeSeriesFileType | None) – Type of file (auto-detected if None)
n_columns (int | None) – Expected number of columns (for validation)
data_unit (str) – Expected data unit
time_unit (str) – Expected time unit
conversion_factor (float) – Factor to apply to values
is_rate_data (bool) – Whether to normalize by timestep
recycling_interval (int) – Recycle period (0 = no recycling)
start_filter (datetime.datetime | None) – Only read data after this time
end_filter (datetime.datetime | None) – Only read data before this time
dss_pathname (str | None) – DSS pathname pattern (for DSS files)
hdf5_dataset (str | None) – HDF5 dataset path (for HDF5 files)
- file_type: TimeSeriesFileType | None = None#
- __init__(filepath, file_type=None, n_columns=None, column_ids=None, data_unit='', time_unit='', conversion_factor=1.0, is_rate_data=False, recycling_interval=0, start_filter=None, end_filter=None, dss_pathname=None, hdf5_dataset=None)#
- class pyiwfm.io.timeseries.BaseTimeSeriesReader[source]#
Bases:
ABCAbstract base class for time series readers.
- class pyiwfm.io.timeseries.AsciiTimeSeriesAdapter[source]#
Bases:
BaseTimeSeriesReaderAdapter for ASCII time series files.
- class pyiwfm.io.timeseries.DssTimeSeriesAdapter[source]#
Bases:
BaseTimeSeriesReaderAdapter for HEC-DSS time series files.
- class pyiwfm.io.timeseries.Hdf5TimeSeriesAdapter[source]#
Bases:
BaseTimeSeriesReaderAdapter for HDF5 time series files.
- class pyiwfm.io.timeseries.UnifiedTimeSeriesReader[source]#
Bases:
objectUnified reader for all time series formats.
This class provides a single interface for reading time series data from ASCII, DSS, and HDF5 files with automatic format detection and consistent output format.
Example
>>> reader = UnifiedTimeSeriesReader() >>> config = UnifiedTimeSeriesConfig(filepath=Path("pumping.dat")) >>> times, values, metadata = reader.read(config)
>>> # Or with auto-detection >>> times, values, metadata = reader.read_file("pumping.dat")
- read(config)[source]#
Read time series data using configuration.
- Parameters:
config (UnifiedTimeSeriesConfig) – UnifiedTimeSeriesConfig with file path and options
- Returns:
Tuple of (times, values, metadata)
- Return type:
tuple[ndarray[tuple[Any, …], dtype[datetime64]], ndarray[tuple[Any, …], dtype[float64]], TimeSeriesMetadata]
- read_file(filepath, file_type=None, **kwargs)[source]#
Convenience method to read a time series file.
- Parameters:
file_type (TimeSeriesFileType | None) – File type (auto-detected if None)
**kwargs (Any) – Additional options passed to adapter
- Returns:
Tuple of (times, values, metadata)
- Return type:
tuple[ndarray[tuple[Any, …], dtype[datetime64]], ndarray[tuple[Any, …], dtype[float64]], TimeSeriesMetadata]
- read_to_collection(filepath, column_ids=None, variable='', file_type=None, **kwargs)[source]#
Read file and return as TimeSeriesCollection.
- Parameters:
- Returns:
TimeSeriesCollection
- Return type:
- read_metadata(filepath, file_type=None, **kwargs)[source]#
Read only metadata without loading full data.
- Parameters:
file_type (TimeSeriesFileType | None) – File type (auto-detected if None)
**kwargs (Any) – Additional options
- Returns:
TimeSeriesMetadata
- Return type:
- class pyiwfm.io.timeseries.RecyclingTimeSeriesReader(base_reader=None)[source]#
Bases:
objectReader that handles IWFM time series recycling.
IWFM supports repeating time series patterns. For example, monthly data for a single year can be recycled across the entire simulation period.
- pyiwfm.io.timeseries.detect_timeseries_format(filepath)[source]#
Detect time series file format.
- Parameters:
- Returns:
TimeSeriesFileType enum value
- Return type:
- pyiwfm.io.timeseries.read_timeseries_unified(filepath, file_type=None, **kwargs)[source]#
Read time series from any supported format.
- Parameters:
file_type (TimeSeriesFileType | None) – Optional explicit file type
**kwargs (Any) – Format-specific options
- Returns:
Tuple of (times, values, metadata)
- Return type:
tuple[ndarray[tuple[Any, …], dtype[datetime64]], ndarray[tuple[Any, …], dtype[float64]], TimeSeriesMetadata]
- pyiwfm.io.timeseries.get_timeseries_metadata(filepath, file_type=None, **kwargs)[source]#
Get time series metadata without reading full data.
- Parameters:
file_type (TimeSeriesFileType | None) – Optional explicit file type
**kwargs (Any) – Format-specific options
- Returns:
TimeSeriesMetadata
- Return type:
Time Series Writer#
Writer for IWFM time series data files.
Generic IWFM time series data file writer.
All IWFM time series files (pumping, inflows, ET, precip, diversions, crop coefficients, return flow fractions, reuse fractions, irrigation periods, ag water demand, max lake elevation, stream surface area, etc.) share a common structure:
Comment header
NCOL, FACT, [TUNIT], NSP, NFQ, DSSFL
Optional column mapping section
Date-indexed data rows or DSS pathnames
This module provides a single writer + dataclass that handles all variants.
- class pyiwfm.io.timeseries_writer.DSSPathItem(index, path)[source]#
Bases:
objectA single DSS pathname entry for column mapping.
- __init__(index, path)#
- class pyiwfm.io.timeseries_writer.TimeSeriesDataConfig(title='', ncol=0, factor=1.0, time_unit='', has_time_unit=False, nsp=1, nfq=0, dss_file='', ncol_tag='NCOL', factor_tag='FACT', time_unit_tag='TUNIT', nsp_tag='NSP', nfq_tag='NFQ', description_lines=<factory>, column_mapping=<factory>, column_header='', dates=None, data=None, data_header='Time Series Data', data_fmt='%14.6f', dss_paths=<factory>)[source]#
Bases:
objectConfiguration for a generic IWFM time series data file.
This covers all IWFM TS file types: pumping, inflows, ET, precip, diversions, crop coefficients, return flow fractions, reuse fractions, irrigation periods, ag water demand, max lake elevation, stream surface area, generic moisture, etc.
- dss_paths: list[DSSPathItem]#
- __init__(title='', ncol=0, factor=1.0, time_unit='', has_time_unit=False, nsp=1, nfq=0, dss_file='', ncol_tag='NCOL', factor_tag='FACT', time_unit_tag='TUNIT', nsp_tag='NSP', nfq_tag='NFQ', description_lines=<factory>, column_mapping=<factory>, column_header='', dates=None, data=None, data_header='Time Series Data', data_fmt='%14.6f', dss_paths=<factory>)#
- class pyiwfm.io.timeseries_writer.IWFMTimeSeriesDataWriter(engine=None)[source]#
Bases:
objectGeneric writer for IWFM time series data files.
Handles: TSPumping, StreamInflow, DiversionData, Precip, ET, CropCoeff, IrrigPeriod, ReturnFlowFrac, ReuseFrac, AgWaterDemand, MaxLakeElev, StreamSurfaceArea, GenericMoisture, etc.
Example
>>> from pyiwfm.io.timeseries_writer import ( ... IWFMTimeSeriesDataWriter, TimeSeriesDataConfig, ... ) >>> config = TimeSeriesDataConfig( ... title="Pumping Time Series", ... ncol=3, ... factor=1.0, ... nsp=1, ... nfq=0, ... ncol_tag="NCOLPUMP", ... factor_tag="FACTPUMP", ... nsp_tag="NSPPUMP", ... nfq_tag="NFQPUMP", ... dates=["10/01/1990_24:00", "10/02/1990_24:00"], ... data=np.array([[100.0, 200.0, 300.0], ... [110.0, 210.0, 310.0]]), ... ) >>> writer = IWFMTimeSeriesDataWriter() >>> writer.write(config, Path("TSPumping.dat"))
- write(config, filepath)[source]#
Write a complete IWFM time series data file.
- Parameters:
config (
TimeSeriesDataConfig) – File specificationfilepath (
Path) – Output file path
- Returns:
Path to written file
- Return type:
Path
- write_dss_mode(config, filepath)[source]#
Write with DSS pathname references instead of inline data.
This is a convenience wrapper that ensures use_dss is True.
- Parameters:
config (
TimeSeriesDataConfig) – File specification (must have dss_paths populated)filepath (
Path) – Output file path
- Returns:
Path to written file
- Return type:
Path
- pyiwfm.io.timeseries_writer.make_pumping_ts_config(ncol, factor=1.0, nsp=1, nfq=0, **kwargs)[source]#
Create a TimeSeriesDataConfig pre-configured for pumping TS files.
- pyiwfm.io.timeseries_writer.make_stream_inflow_ts_config(ncol, factor=1.0, nsp=1, nfq=0, **kwargs)[source]#
Create a TimeSeriesDataConfig pre-configured for stream inflow TS.
- pyiwfm.io.timeseries_writer.make_diversion_ts_config(ncol, factor=1.0, nsp=1, nfq=0, **kwargs)[source]#
Create a TimeSeriesDataConfig pre-configured for diversion data TS.
- pyiwfm.io.timeseries_writer.make_precip_ts_config(ncol, factor=1.0, nsp=1, nfq=0, **kwargs)[source]#
Create a TimeSeriesDataConfig pre-configured for precipitation TS.
- pyiwfm.io.timeseries_writer.make_et_ts_config(ncol, factor=1.0, nsp=1, nfq=0, **kwargs)[source]#
Create a TimeSeriesDataConfig pre-configured for ET TS files.
- pyiwfm.io.timeseries_writer.make_crop_coeff_ts_config(ncol, nsp=1, nfq=0, **kwargs)[source]#
Create a TimeSeriesDataConfig pre-configured for crop coeff TS.
- pyiwfm.io.timeseries_writer.make_return_flow_ts_config(ncol, nsp=1, nfq=0, **kwargs)[source]#
Create a TimeSeriesDataConfig for return flow fraction TS.
- pyiwfm.io.timeseries_writer.make_reuse_ts_config(ncol, nsp=1, nfq=0, **kwargs)[source]#
Create a TimeSeriesDataConfig for reuse fraction TS.
- pyiwfm.io.timeseries_writer.make_irig_period_ts_config(ncol, nsp=1, nfq=0, **kwargs)[source]#
Create a TimeSeriesDataConfig for irrigation period TS.
- pyiwfm.io.timeseries_writer.make_ag_water_demand_ts_config(ncol, factor=1.0, nsp=1, nfq=0, **kwargs)[source]#
Create a TimeSeriesDataConfig for ag water demand TS.
Budget / Results I/O#
Budget Module#
Reader for IWFM budget output files (HDF5 and binary formats).
Budget file reader for IWFM simulation output.
This module provides classes for reading IWFM budget binary and HDF5 files, which contain water balance data for groundwater, streams, lakes, root zone, and other model components.
Example
Read a groundwater budget file:
>>> from pyiwfm.io.budget import BudgetReader
>>> reader = BudgetReader("GW_Budget.hdf")
>>> print(reader.descriptor)
'GROUNDWATER BUDGET'
>>> print(reader.locations)
['Subregion 1', 'Subregion 2', ...]
>>> df = reader.get_dataframe(location="Subregion 1")
- class pyiwfm.io.budget.TimeStepInfo(track_time=True, delta_t=1.0, delta_t_minutes=1440, unit='1DAY', start_datetime=None, start_time=0.0, n_timesteps=0)[source]#
Bases:
objectTime step information from budget file.
- __init__(track_time=True, delta_t=1.0, delta_t_minutes=1440, unit='1DAY', start_datetime=None, start_time=0.0, n_timesteps=0)#
- class pyiwfm.io.budget.ASCIIOutputInfo(title_len=160, n_titles=0, titles=<factory>, title_persist=<factory>, format_spec='', n_column_header_lines=3)[source]#
Bases:
objectASCII output formatting information.
- __init__(title_len=160, n_titles=0, titles=<factory>, title_persist=<factory>, format_spec='', n_column_header_lines=3)#
- class pyiwfm.io.budget.LocationData(n_columns=0, storage_units=0, column_headers=<factory>, column_types=<factory>, column_widths=<factory>, dss_pathnames=<factory>, dss_data_types=<factory>)[source]#
Bases:
objectData structure for a single budget location.
- __init__(n_columns=0, storage_units=0, column_headers=<factory>, column_types=<factory>, column_widths=<factory>, dss_pathnames=<factory>, dss_data_types=<factory>)#
- class pyiwfm.io.budget.BudgetHeader(descriptor='', timestep=<factory>, n_areas=0, areas=<factory>, ascii_output=<factory>, n_locations=0, location_names=<factory>, location_data=<factory>, file_position=0)[source]#
Bases:
objectComplete budget file header information.
- timestep: TimeStepInfo#
- ascii_output: ASCIIOutputInfo#
- location_data: list[LocationData]#
- __init__(descriptor='', timestep=<factory>, n_areas=0, areas=<factory>, ascii_output=<factory>, n_locations=0, location_names=<factory>, location_data=<factory>, file_position=0)#
- pyiwfm.io.budget.julian_to_datetime(julian_day)[source]#
Convert Julian day to Python datetime.
IWFM uses astronomical Julian dates. Excel Julian dates have an offset of 2415020 days.
- pyiwfm.io.budget.excel_julian_to_datetime(excel_julian)[source]#
Convert Excel-style Julian day to Python datetime.
Excel day 1 = January 1, 1900.
- class pyiwfm.io.budget.BudgetReader(filepath)[source]#
Bases:
objectReader for IWFM budget files (binary or HDF5 format).
This class reads budget output files generated by IWFM simulation, including groundwater, stream, lake, and root zone budgets.
- Parameters:
filepath (
strorPath) – Path to the budget file (.bin or .hdf/.h5).- Variables:
filepath (
Path) – Path to the budget file.format (
str) – File format (‘binary’ or ‘hdf5’).header (
BudgetHeader) – Parsed header information.descriptor (
str) – Budget type descriptor (e.g., ‘GROUNDWATER BUDGET’).locations (
list[str]) – List of location names.n_timesteps (
int) – Number of time steps in the file.
Examples
>>> reader = BudgetReader("GW_Budget.hdf") >>> print(reader.descriptor) 'GROUNDWATER BUDGET' >>> print(reader.locations) ['Subregion 1', 'Subregion 2', 'Subregion 3'] >>> >>> # Get column headers for a location >>> headers = reader.get_column_headers("Subregion 1") >>> print(headers) ['Deep Percolation', 'Stream-GW Interaction', ...] >>> >>> # Read data as numpy array >>> times, data = reader.get_values("Subregion 1") >>> >>> # Read data as pandas DataFrame >>> df = reader.get_dataframe("Subregion 1")
- get_values(location=0, columns=None)[source]#
Read budget values for a location.
- Parameters:
- Returns:
Tuple of (times, values) where: - times: 1D array of time values (or datetimes as floats) - values: 2D array of shape (n_timesteps, n_columns)
- Return type:
tuple[NDArray[np.float64],NDArray[np.float64]]
- get_dataframe(location=0, columns=None, *, length_factor=1.0, area_factor=1.0, volume_factor=1.0)[source]#
Read budget values as a pandas DataFrame.
When all conversion factors are left at their default of
1.0the raw simulation values are returned unchanged. Pass non-unity factors (FACTLTOU / FACTAROU / FACTVLOU) to get unit-converted output — each column is multiplied by the factor that matches its IWFM data-type code (volume, area, or length).- Parameters:
columns (
list, optional) – Column indices or names to read. If None, reads all columns.length_factor (
float) – Multiplier for length columns (type 5). Default1.0.area_factor (
float) – Multiplier for area columns (type 4). Default1.0.volume_factor (
float) – Multiplier for volume columns (types 1-3, 6-11). Default1.0.
- Returns:
DataFrame with datetime index and budget columns.
- Return type:
pd.DataFrame
- get_all_dataframes()[source]#
Read budget data for all locations as DataFrames.
- Returns:
Dictionary mapping location name to DataFrame.
- Return type:
dict[str,pd.DataFrame]
ZBudget Module#
Reader for IWFM zone budget output files.
Zone budget (ZBudget) file reader for IWFM simulation output.
This module provides classes for reading IWFM zone budget HDF5 files, which contain spatially aggregated water balance data by user-defined zones.
Example
Read a zone budget file:
>>> from pyiwfm.io.zbudget import ZBudgetReader
>>> reader = ZBudgetReader("GWZBud.hdf")
>>> print(reader.zones)
['Zone 1', 'Zone 2', 'Zone 3']
>>> df = reader.get_dataframe(zone="Zone 1")
- class pyiwfm.io.zbudget.ZBudgetHeader(software_version='', descriptor='', vert_flows_at_node=False, face_flows_defined=False, storages_defined=False, compute_error=False, n_data=0, data_types=<factory>, data_names=<factory>, data_hdf_paths=<factory>, n_layers=0, n_elements=0, n_timesteps=0, start_datetime=None, delta_t_minutes=1440, time_unit='1DAY', elem_data_columns=<factory>)[source]#
Bases:
objectZone budget file header information.
- __init__(software_version='', descriptor='', vert_flows_at_node=False, face_flows_defined=False, storages_defined=False, compute_error=False, n_data=0, data_types=<factory>, data_names=<factory>, data_hdf_paths=<factory>, n_layers=0, n_elements=0, n_timesteps=0, start_datetime=None, delta_t_minutes=1440, time_unit='1DAY', elem_data_columns=<factory>)#
- class pyiwfm.io.zbudget.ZoneInfo(id, name, n_elements=0, element_ids=<factory>, area=0.0, adjacent_zones=<factory>)[source]#
Bases:
objectInformation about a zone.
- __init__(id, name, n_elements=0, element_ids=<factory>, area=0.0, adjacent_zones=<factory>)#
- class pyiwfm.io.zbudget.ZBudgetReader(filepath)[source]#
Bases:
objectReader for IWFM zone budget HDF5 files.
Zone budget files contain spatially aggregated water balance data for user-defined zones (groups of elements).
- Parameters:
filepath (
strorPath) – Path to the zone budget HDF5 file.- Variables:
filepath (
Path) – Path to the zone budget file.header (
ZBudgetHeader) – Parsed header information.zones (
list[str]) – List of zone names.data_names (
list[str]) – List of budget data column names.
Examples
>>> reader = ZBudgetReader("GWZBud.hdf") >>> print(reader.descriptor) 'GROUNDWATER ZONE BUDGET' >>> print(reader.zones) ['Zone 1', 'Zone 2', 'Zone 3'] >>> >>> # Get data column names >>> print(reader.data_names) ['Deep Percolation', 'Pumping', 'Subsurface Inflow', ...] >>> >>> # Read data for a zone >>> df = reader.get_dataframe(zone="Zone 1", layer=1)
- get_element_data(data_name, layer=1)[source]#
Read raw element-level data for a budget component.
- Parameters:
- Returns:
2D array of shape
(n_timesteps, n_items). For datasets that cover all elements,n_items == n_elements. For sparse datasets (e.g. Streams),n_items < n_elements— useheader.elem_data_columnsto map element IDs to column indices.- Return type:
NDArray[np.float64]
- get_zone_data(zone, data_name=None, layer=1)[source]#
Read aggregated zone budget data.
- Parameters:
- Returns:
Tuple of (times, values) where: - times: 1D array of time values - values: 1D or 2D array of zone budget values
- Return type:
tuple[NDArray[np.float64],NDArray[np.float64]]
- get_dataframe(zone, layer=1, data_columns=None, *, volume_factor=1.0)[source]#
Read zone budget data as a pandas DataFrame.
When volume_factor is left at its default of
1.0the raw simulation values are returned unchanged. Pass the FACTVLOU value to get unit-converted output.- Parameters:
- Returns:
DataFrame with datetime index and budget columns.
- Return type:
pd.DataFrame
- get_water_balance(zone, layer=1, inflow_columns=None, outflow_columns=None)[source]#
Calculate water balance for a zone.
- Parameters:
- Returns:
DataFrame with inflows, outflows, and balance.
- Return type:
pd.DataFrame
Budget Control File Parser#
Parser for IWFM budget post-processor control files (.bud / .in).
Budget control file parser for IWFM post-processing.
Reads a .bud / .in budget control file that specifies which HDF5
budget output files to process, unit conversion factors, time windows,
and which locations to export.
- class pyiwfm.io.budget_control.BudgetOutputSpec(hdf_file, output_file, output_interval=None, location_ids=<factory>)[source]#
Bases:
objectSpecification for a single budget output in the control file.
- __init__(hdf_file, output_file, output_interval=None, location_ids=<factory>)#
- class pyiwfm.io.budget_control.BudgetControlConfig(length_factor=1.0, length_unit='FEET', area_factor=1.0, area_unit='AC', volume_factor=1.0, volume_unit='AC.FT.', cache_size=100, begin_date=None, end_date=None, budgets=<factory>)[source]#
Bases:
objectParsed budget control file.
- __init__(length_factor=1.0, length_unit='FEET', area_factor=1.0, area_unit='AC', volume_factor=1.0, volume_unit='AC.FT.', cache_size=100, begin_date=None, end_date=None, budgets=<factory>)#
- budgets: list[BudgetOutputSpec]#
List of budget output specifications.
ZBudget Control File Parser#
Parser for IWFM zone budget post-processor control files.
Zone budget (ZBudget) control file parser for IWFM post-processing.
Reads a zbudget control file that specifies which HDF5 zone-budget output files to process, zone definition files, unit conversion factors, and which zones to export.
- class pyiwfm.io.zbudget_control.ZBudgetOutputSpec(zone_def_file=None, hdf_file=<factory>, output_file=<factory>, output_interval=None, zone_ids=<factory>)[source]#
Bases:
objectSpecification for a single zone-budget output in the control file.
- __init__(zone_def_file=None, hdf_file=<factory>, output_file=<factory>, output_interval=None, zone_ids=<factory>)#
- class pyiwfm.io.zbudget_control.ZBudgetControlConfig(area_factor=1.0, area_unit='AC', volume_factor=1.0, volume_unit='AC.FT.', cache_size=100, begin_date=None, end_date=None, zbudgets=<factory>)[source]#
Bases:
objectParsed zone-budget control file.
- __init__(area_factor=1.0, area_unit='AC', volume_factor=1.0, volume_unit='AC.FT.', cache_size=100, begin_date=None, end_date=None, zbudgets=<factory>)#
- zbudgets: list[ZBudgetOutputSpec]#
List of zone-budget output specifications.
Budget Utilities#
Shared helpers for unit conversion, title-line formatting, and time filtering used by both budget and zone budget Excel export.
Shared utilities for budget and zone-budget Excel export and unit conversion.
Provides unit conversion factor application, title-line marker substitution,
and time-range filtering used by both budget_excel and zbudget_excel.
- pyiwfm.io.budget_utils.apply_unit_conversion(values, column_types, length_factor=1.0, area_factor=1.0, volume_factor=1.0)[source]#
Apply IWFM unit conversion factors to budget data columns.
- Parameters:
values (
NDArray[np.float64]) – 2-D array of shape(n_timesteps, n_columns).column_types (
list[int]) – IWFM data-type code for each column (seeBudget_Parameters.f90).length_factor (
float) – Multiplicative factor for length columns (type 5).area_factor (
float) – Multiplicative factor for area columns (type 4).volume_factor (
float) – Multiplicative factor for volume columns (types 1-3, 6-11).
- Returns:
Converted array (new copy; input is not modified).
- Return type:
NDArray[np.float64]
- pyiwfm.io.budget_utils.format_title_lines(titles, location_name, area, length_unit, area_unit, volume_unit)[source]#
Substitute IWFM unit markers in title strings.
Recognised markers:
@UNITVL@,@UNITAR@,@UNITLT@,@LOCNAME@,@AREA@.- Parameters:
titles (
list[str]) – Raw title lines fromBudgetHeader.ascii_output.titles.location_name (
str) – Name inserted for@LOCNAME@.area (
floatorNone) – Area value inserted for@AREA@.Nonebecomes"N/A".length_unit (
str) – Unit strings inserted for the corresponding markers.area_unit (
str) – Unit strings inserted for the corresponding markers.volume_unit (
str) – Unit strings inserted for the corresponding markers.
- Returns:
Title lines with all markers replaced.
- Return type:
list[str]
- pyiwfm.io.budget_utils.filter_time_range(df, begin_date, end_date)[source]#
Filter a DataFrame to the requested time window.
- Parameters:
df (
pd.DataFrame) – DataFrame whose index is aDatetimeIndex.begin_date (
strorNone) – IWFM datetime strings (MM/DD/YYYY_HH:MM).Nonemeans no bound in that direction.end_date (
strorNone) – IWFM datetime strings (MM/DD/YYYY_HH:MM).Nonemeans no bound in that direction.
- Returns:
Filtered copy (or the original if neither bound applies).
- Return type:
pd.DataFrame
Budget Excel Export#
Excel workbook generation from budget HDF5 data (one sheet per location).
Budget Excel export for IWFM post-processing.
Generates Excel workbooks from IWFM budget HDF5 data with one sheet per
location, title lines, bold headers, and auto-fitted column widths —
matching the reference implementation in SGMOModeling/pywfm-budget-excel.
- pyiwfm.io.budget_excel.budget_to_excel(reader, output_path, length_factor=1.0, area_factor=1.0, volume_factor=1.0, length_unit='FEET', area_unit='AC', volume_unit='AC.FT.', location_ids=None, begin_date=None, end_date=None, output_interval=None)[source]#
Export budget data to an Excel workbook.
One sheet per location. Each sheet contains:
Title lines (bold) from
ASCIIOutputInfowith unit substitution.Column headers (bold).
Data rows with unit conversion applied.
Auto-fitted column widths.
- Parameters:
reader (
BudgetReader) – Open budget reader.output_path (
Pathorstr) – Destination.xlsxfile.length_factor (
float) – FACTLTOU / FACTAROU / FACTVLOU from the control file.area_factor (
float) – FACTLTOU / FACTAROU / FACTVLOU from the control file.volume_factor (
float) – FACTLTOU / FACTAROU / FACTVLOU from the control file.length_unit (
str) – UNITLTOU / UNITAROU / UNITVLOU for title-line substitution.area_unit (
str) – UNITLTOU / UNITAROU / UNITVLOU for title-line substitution.volume_unit (
str) – UNITLTOU / UNITAROU / UNITVLOU for title-line substitution.location_ids (
list[int]orNone) – 1-based location IDs to include.Noneor[-1]→ all.begin_date (
strorNone) – IWFM datetime strings for time filtering.end_date (
strorNone) – IWFM datetime strings for time filtering.output_interval (
strorNone) – Not yet implemented — reserved for future resampling.
- Returns:
The written workbook path.
- Return type:
Path
ZBudget Excel Export#
Excel workbook generation from zone budget HDF5 data (one sheet per zone).
Zone budget Excel export for IWFM post-processing.
Generates Excel workbooks from IWFM zone-budget HDF5 data with one sheet per zone, title lines, bold headers, and auto-fitted column widths.
- pyiwfm.io.zbudget_excel.zbudget_to_excel(reader, output_path, area_factor=1.0, volume_factor=1.0, area_unit='AC', volume_unit='AC.FT.', zone_ids=None, zone_def_file=None, begin_date=None, end_date=None, output_interval=None, layer=1)[source]#
Export zone budget data to an Excel workbook.
One sheet per zone. Same formatting as budget export: title area (bold), column headers (bold), data rows, auto-fit widths.
- Parameters:
reader (
ZBudgetReader) – Open zone-budget reader.output_path (
Pathorstr) – Destination.xlsxfile.area_factor (
float) – FACTAROU / FACTVLOU from the control file.volume_factor (
float) – FACTAROU / FACTVLOU from the control file.area_unit (
str) – UNITAROU / UNITVLOU for title substitution.volume_unit (
str) – UNITAROU / UNITVLOU for title substitution.zone_ids (
list[int]orNone) – 1-based zone IDs to include.Noneor[-1]→ all.zone_def_file (
PathorstrorNone) – External zone definition file (not yet used — reserved).begin_date (
strorNone) – IWFM datetime strings for time filtering.end_date (
strorNone) – IWFM datetime strings for time filtering.output_interval (
strorNone) – Reserved for future resampling.layer (
int) – Model layer (1-based).
- Returns:
The written workbook path.
- Return type:
Path
Model I/O#
Model Loader#
Complete model loading from simulation and preprocessor files.
Complete IWFM Model Loader.
This module provides a unified entry point for loading a complete IWFM model from simulation and preprocessor files. It handles the hierarchical file structure where the simulation main file references component main files, which in turn reference sub-files for specific data.
The loader supports two simulation file formats:
- Description-based format (pyiwfm writer format with / KEYWORD suffixes)
- Positional sequential format (native IWFM Fortran format)
Includes optional comment preservation for round-trip file operations.
- class pyiwfm.io.model_loader.ModelLoadResult(model=None, simulation_config=None, errors=<factory>, warnings=<factory>)[source]#
Bases:
objectResult of loading an IWFM model.
- Variables:
- simulation_config: SimulationConfig | None = None#
- __init__(model=None, simulation_config=None, errors=<factory>, warnings=<factory>)#
- class pyiwfm.io.model_loader.CompleteModelLoader(simulation_file, preprocessor_file=None, use_positional_format=None)[source]#
Bases:
objectLoad a complete IWFM model from simulation and preprocessor files.
This class provides a high-level API for loading IWFM models that automatically handles: - Detection of simulation file format (description-based vs positional) - Hierarchical file resolution (main files -> sub-files) - Component loading with graceful error handling - Metadata collection from all loaded components
Example:
loader = CompleteModelLoader( simulation_file="Simulation/C2VSimFG.in", preprocessor_file="Preprocessor/C2VSimFG_PreProcessor.in", ) result = loader.load() if result.success: model = result.model print(f"Loaded {model.n_nodes} nodes")
- __init__(simulation_file, preprocessor_file=None, use_positional_format=None)[source]#
Initialize the model loader.
- Parameters:
simulation_file (Path | str) – Path to the simulation main input file
preprocessor_file (Path | str | None) – Path to the preprocessor main input file. If None, the loader will try to find it from the simulation config or use binary preprocessor output.
use_positional_format (bool | None) – Force positional format reading (True), description-based reading (False), or auto-detect (None).
- load()[source]#
Load the complete IWFM model.
- Returns:
ModelLoadResult with the loaded model and any errors
- Return type:
- load_model()[source]#
Load the complete model, raising on failure.
- Returns:
IWFMModel instance
- Raises:
RuntimeError – If model loading fails
- Return type:
- pyiwfm.io.model_loader.load_complete_model(simulation_file, preprocessor_file=None, use_positional_format=None)[source]#
Load a complete IWFM model from simulation and preprocessor files.
This is a convenience function that creates a CompleteModelLoader and loads the model, raising on failure.
- Parameters:
- Returns:
IWFMModel instance
- Raises:
RuntimeError – If model loading fails
- Return type:
- class pyiwfm.io.model_loader.ModelLoadResultWithComments(model=None, simulation_config=None, errors=<factory>, warnings=<factory>, comment_metadata=<factory>)[source]#
Bases:
ModelLoadResultResult of loading an IWFM model with comment preservation.
Extends ModelLoadResult to include extracted comment metadata for all loaded files.
- Variables:
comment_metadata (dict[str, CommentMetadata]) – Dictionary mapping file type to CommentMetadata. Keys include “preprocessor_main”, “simulation_main”, “gw_main”, etc.
- comment_metadata: dict[str, CommentMetadata]#
- get_file_comments(file_type)[source]#
Get comment metadata for a specific file type.
- Parameters:
file_type (str) – File type key (e.g., “preprocessor_main”).
- Returns:
CommentMetadata if available, None otherwise.
- Return type:
CommentMetadata | None
- __init__(model=None, simulation_config=None, errors=<factory>, warnings=<factory>, comment_metadata=<factory>)#
- class pyiwfm.io.model_loader.CommentAwareModelLoader(simulation_file, preprocessor_file=None, use_positional_format=None, preserve_comments=True)[source]#
Bases:
CompleteModelLoaderLoad an IWFM model with comment preservation.
Extends CompleteModelLoader to extract and preserve comments from all loaded input files. The preserved comments can be used for round-trip file operations.
Example:
loader = CommentAwareModelLoader( simulation_file="Simulation/Main.in", preprocessor_file="Preprocessor/Main.in", ) result = loader.load() if result.success: model = result.model comments = result.comment_metadata # Later: write model with preserved comments write_model_with_comments(model, "output/", comments)
- __init__(simulation_file, preprocessor_file=None, use_positional_format=None, preserve_comments=True)[source]#
Initialize the comment-aware model loader.
- Parameters:
- pyiwfm.io.model_loader.load_model_with_comments(simulation_file, preprocessor_file=None, use_positional_format=None)[source]#
Load an IWFM model with comment preservation.
This is a convenience function that loads a model and extracts comments from all input files for round-trip preservation.
- Parameters:
- Returns:
Tuple of (IWFMModel, comment_metadata_dict)
- Raises:
RuntimeError – If model loading fails
- Return type:
Example:
model, comments = load_model_with_comments("Simulation/Main.in") # Modify model... model.nodes.add_node(...) # Write back with preserved comments write_model_with_comments(model, "output/", comment_metadata=comments)
Model Writer#
Complete model writer that orchestrates all component writers.
Complete Model Writer for IWFM models.
This module provides the main writer for exporting a complete IWFM model to disk with per-file path control and time series format conversion.
Supports optional comment preservation for round-trip operations.
- Classes:
ModelWriteResult: Result of a complete model write operation. TimeSeriesCopier: Copies/converts time series files between locations. CompleteModelWriter: Orchestrates all component writers.
- Functions:
write_model: Convenience function for writing a complete model. write_model_with_comments: Write model with preserved comments. save_model_with_comments: High-level API for comment-preserving writes.
- class pyiwfm.io.model_writer.ModelWriteResult(files=<factory>, errors=<factory>, warnings=<factory>)[source]#
Bases:
objectResult of a complete model write operation.
- Variables:
- __init__(files=<factory>, errors=<factory>, warnings=<factory>)#
- class pyiwfm.io.model_writer.TimeSeriesCopier(model, config)[source]#
Bases:
objectCopies or converts time series files from source to destination.
Handles format conversion between text and DSS formats when the target format differs from the source format.
- class pyiwfm.io.model_writer.CompleteModelWriter(model, config, comment_metadata=None, preserve_comments=True)[source]#
Bases:
objectOrchestrates all component writers to produce a complete IWFM model.
Uses
ModelWriteConfigfor all path resolution, enabling arbitrary directory structures. Each component writer receives paths derived from the config, and cross-file references useget_relative_path().Supports optional comment preservation via comment_metadata parameter. When provided, preserved comments from the original files will be injected into the output files.
Example:
config = ModelWriteConfig(output_dir=Path("C:/models/output")) writer = CompleteModelWriter(model, config) result = writer.write_all() if result.success: print(f"Wrote {len(result.files)} files")
Example with comment preservation:
model, comments = load_model_with_comments("Simulation/Main.in") config = ModelWriteConfig(output_dir=Path("output")) writer = CompleteModelWriter(model, config, comment_metadata=comments) result = writer.write_all()
- __init__(model, config, comment_metadata=None, preserve_comments=True)[source]#
Initialize the complete model writer.
- Parameters:
model (IWFMModel) – IWFMModel instance to write.
config (ModelWriteConfig) – Configuration for output paths and formats.
comment_metadata (dict[str, CommentMetadata] | None) – Dictionary mapping file type to CommentMetadata. Keys should match file type names (e.g., “preprocessor_main”, “gw_main”, “stream_main”).
preserve_comments (bool) – If True and comment_metadata is provided, inject preserved comments into output files.
- get_file_comments(file_type)[source]#
Get comment metadata for a specific file type.
- Parameters:
file_type (str) – File type key (e.g., “preprocessor_main”).
- Returns:
CommentMetadata if available and preservation is enabled.
- Return type:
CommentMetadata | None
- pyiwfm.io.model_writer.write_model(model, output_dir, file_paths=None, ts_format='text', **kwargs)[source]#
Write a complete IWFM model to disk.
This is the main convenience function for writing a model. It creates a
ModelWriteConfigand delegates toCompleteModelWriter.- Parameters:
model (IWFMModel) – IWFMModel instance to write.
output_dir (Path | str) – Base output directory.
file_paths (dict[str, str] | None) – Optional dict of {file_key: relative_path} overrides. If None, uses default nested layout.
ts_format (str) – Time series format -
"text"or"dss".**kwargs (Any) – Additional arguments passed to
ModelWriteConfig.
- Returns:
ModelWriteResult with written files, errors, and warnings.
- Return type:
Example:
result = write_model(model, "C:/models/output") if result.success: print(f"Model written to {len(result.files)} files")
- pyiwfm.io.model_writer.write_model_with_comments(model, output_dir, comment_metadata=None, file_paths=None, ts_format='text', save_sidecars=True, **kwargs)[source]#
Write a complete IWFM model with preserved comments.
This is like write_model() but with support for comment preservation. When comment_metadata is provided, preserved comments from the original files are injected into the output files.
- Parameters:
model (IWFMModel) – IWFMModel instance to write.
output_dir (Path | str) – Base output directory.
comment_metadata (dict[str, CommentMetadata] | None) – Dictionary mapping file type to CommentMetadata. Typically obtained from load_model_with_comments().
file_paths (dict[str, str] | None) – Optional dict of {file_key: relative_path} overrides.
ts_format (str) – Time series format -
"text"or"dss".save_sidecars (bool) – If True, save comment metadata as sidecar files alongside the output files for future round-trips.
**kwargs (Any) – Additional arguments passed to
ModelWriteConfig.
- Returns:
ModelWriteResult with written files, errors, and warnings.
- Return type:
Example:
# Load model with comments model, comments = load_model_with_comments("Simulation/Main.in") # Modify the model model.nodes.add_node(...) # Write back with preserved comments result = write_model_with_comments( model, "output/", comment_metadata=comments, )
- pyiwfm.io.model_writer.save_model_with_comments(model, output_dir, comment_metadata=None)[source]#
High-level API for writing a model with preserved comments.
This is the simplest API for round-trip model operations with comment preservation.
- Parameters:
model (IWFMModel) – IWFMModel instance to write.
output_dir (Path | str) – Base output directory.
comment_metadata (dict[str, CommentMetadata] | None) – Dictionary mapping file type to CommentMetadata. If None, writes without comment preservation (uses templates).
- Returns:
Dictionary mapping file type to written path.
- Raises:
RuntimeError – If writing fails with errors.
- Return type:
Example:
# Load model with comments model, comments = load_model_with_comments("Simulation/Main.in") # Modify the model model.nodes.add_node(...) # Write back with preserved comments files = save_model_with_comments(model, "output/", comments) print(f"Wrote files: {list(files.keys())}") # Or write NEW model without preserved comments (uses templates) new_files = save_model_with_comments(new_model, "output/")
Model Packager#
Package an IWFM model directory into a distributable ZIP archive with
an embedded manifest.json.
Package IWFM model directories into distributable ZIP archives.
- class pyiwfm.io.model_packager.ModelPackageResult(archive_path, files_included=<factory>, total_size_bytes=0, manifest=<factory>)[source]#
Bases:
objectResult of a model packaging operation.
- Variables:
archive_path (
Path) – Path to the created ZIP archive.files_included (
list[Path]) – Absolute paths of all files that were added to the archive.total_size_bytes (
int) – Total uncompressed size of included files in bytes.manifest (
dict[str,str]) – Mapping of relative path (inside ZIP) to the file-type category.
- __init__(archive_path, files_included=<factory>, total_size_bytes=0, manifest=<factory>)#
- pyiwfm.io.model_packager.collect_model_files(model_dir, *, include_executables=False, include_results=False)[source]#
Collect all model files from a directory tree.
Walks model_dir recursively and returns files relevant to an IWFM model, excluding output/cache directories by default.
- Parameters:
- Returns:
Sorted list of absolute paths to included files.
- Return type:
list[Path]
- pyiwfm.io.model_packager.package_model(model_dir, output_path=None, *, include_executables=False, include_results=False, compression=8, compresslevel=6)[source]#
Package an IWFM model directory into a ZIP archive.
Creates a ZIP file preserving the directory structure (
Preprocessor/,Simulation/, etc.) with amanifest.jsonembedded in the archive.- Parameters:
model_dir (
Path) – Root directory of the IWFM model.output_path (
Path | None) – Path for the output ZIP file. IfNone, defaults to<model_dir_name>.zipin the parent of model_dir.include_executables (
bool) – IfTrue, include.exe,.dll, and.sofiles.include_results (
bool) – IfTrue, include theResults/directory and HDF5 output files.compression (
int) – ZIP compression method (defaultZIP_DEFLATED).compresslevel (
int) – Compression level (0-9, default 6).
- Returns:
Result with archive path, file list, size, and manifest.
- Return type:
- Raises:
FileNotFoundError – If model_dir does not exist or is not a directory.
Infrastructure#
IWFM Reader Utilities#
Central module for IWFM file line-reading, comment handling, version parsing,
and path resolution. All io/ reader modules import helpers from here
rather than defining their own copies.
Unified IWFM file line-reading utilities.
Matches the I/O approach in IWFM Fortran source code (GeneralUtilities.f90, Class_AsciiFileType.f90).
Every io/ reader should import helpers from this module rather than
defining its own copy.
- pyiwfm.io.iwfm_reader.is_comment_line(line)[source]#
Check if line is an IWFM full-line comment or blank.
Matches IWFM’s
SkipComment()which skips lines starting withC,c, or*in column 1 (the first character of the raw line). Lines with leading whitespace are data lines even if the first non-space character isC.A Windows drive-letter prefix (
C:\) is not treated as a comment.
- pyiwfm.io.iwfm_reader.strip_inline_comment(line)[source]#
Strip inline comment from an IWFM data line.
Returns
(value, description).Matches IWFM’s
FindInlineCommentPosition()+StripTextUntilCharacter()(GeneralUtilities.f90:716-782). Only/preceded by whitespace is treated as a comment delimiter.#is not a comment character in IWFM.
- pyiwfm.io.iwfm_reader.next_data_value(f, line_counter=None)[source]#
Read next non-comment line and strip inline comment.
Use for scalar or string data (file paths, parameters) where inline
/ descriptionshould be removed.Matches IWFM pattern:
SkipComment()+READ+StripTextUntilCharacter().
- pyiwfm.io.iwfm_reader.next_data_line(f, line_counter=None)[source]#
Read next non-comment line without stripping inline comments.
Use for numeric data rows (arrays, tables) where Fortran’s free-format
READhandles inline comments by reading exactly N values and ignoring the rest of the line.The caller should
split()and take the first N tokens.
- pyiwfm.io.iwfm_reader.next_data_or_empty(f, line_counter=None)[source]#
Read next non-comment data value, or
""at EOF.Like
next_data_value()but returns""instead of raising on EOF, and returns""for blank lines. Useful for optional file paths that may be represented by blank lines.
- pyiwfm.io.iwfm_reader.parse_int(value, context='', line_number=None)[source]#
Parse a string as an integer with descriptive error on failure.
- pyiwfm.io.iwfm_reader.parse_float(value, context='', line_number=None)[source]#
Parse a string as a float with descriptive error on failure.
- pyiwfm.io.iwfm_reader.resolve_path(base_dir: Path, filepath: str) Path[source]#
- pyiwfm.io.iwfm_reader.resolve_path(base_dir: Path, filepath: str, *, allow_empty: Literal[False]) Path
- pyiwfm.io.iwfm_reader.resolve_path(base_dir: Path, filepath: str, *, allow_empty: Literal[True]) Path | None
- pyiwfm.io.iwfm_reader.resolve_path(base_dir: Path, filepath: str, *, allow_empty: bool) Path | None
Resolve a file path relative to base_dir.
IWFM paths can be absolute or relative (relative to the main input file’s directory).
- Parameters:
- pyiwfm.io.iwfm_reader.parse_version(version)[source]#
Parse a version string like
'4.12'or'4-12'into(4, 12).Handles both
.and-as separators so the same function works for root zone versions (4.12) and stream versions (4-21).
- class pyiwfm.io.iwfm_reader.ReaderMixin[source]#
Bases:
objectMixin providing standard IWFM line-reading helpers for reader classes.
Any class that mixes this in must initialise
self._line_num = 0before calling these methods (typically in__init__or at the start ofread()).
- class pyiwfm.io.iwfm_reader.LineBuffer(lines)[source]#
Bases:
objectRead-ahead buffer for positional-sequential IWFM files.
Supports pushing a line back so that a tabular reader can stop at a boundary and leave the next line available for the caller.
- next_data()[source]#
Return next non-comment data value (inline comment stripped).
Raises
FileFormatErroron EOF.
Comment Metadata#
Stores extracted comment metadata for use during file writing.
Comment metadata storage for IWFM input files.
This module provides data classes for storing and serializing comments extracted from IWFM input files, enabling round-trip preservation of user-defined comments when reading and writing models.
The comment metadata is stored in JSON sidecar files (.iwfm_comments.json) alongside the original input files.
- Classes:
PreserveMode: Enum for comment preservation levels. SectionComments: Comments associated with a specific file section. CommentMetadata: Complete comment metadata for an IWFM file.
- class pyiwfm.io.comment_metadata.PreserveMode(*values)[source]#
Bases:
EnumComment preservation level.
- Variables:
NONE – Do not preserve any comments.
HEADERS – Preserve only file header blocks.
FULL – Preserve all comments including inline comments.
- NONE = 'none'#
- HEADERS = 'headers'#
- FULL = 'full'#
- class pyiwfm.io.comment_metadata.SectionComments(section_name, header_comments=<factory>, inline_comments=<factory>, data_comments=<factory>, trailing_comments=<factory>)[source]#
Bases:
objectComments associated with a specific section of an IWFM file.
A section is a logical grouping within an IWFM file, such as “NODES”, “ELEMENTS”, “STRATIGRAPHY”, etc. Each section can have: - Header comments that appear before the section data - Inline comments on data lines - Data comments keyed by element ID - Trailing comments after the section data
- Variables:
section_name (str) – Name/identifier of the section.
header_comments (list[str]) – Comment lines appearing before section data.
inline_comments (dict[str, str]) – Map of line key to inline comment text. Keys are typically field names or column headers.
data_comments (dict[str, str]) – Map of data identifier to comment text. Keys use format “type:id” (e.g., “node:157”, “elem:42”).
trailing_comments (list[str]) – Comment lines appearing after section data.
- __init__(section_name, header_comments=<factory>, inline_comments=<factory>, data_comments=<factory>, trailing_comments=<factory>)#
- class pyiwfm.io.comment_metadata.CommentMetadata(version='1.0', source_file='', iwfm_version='', preserve_mode=PreserveMode.FULL, header_block=<factory>, sections=<factory>, file_metadata=<factory>)[source]#
Bases:
objectComplete comment metadata for an IWFM input file.
This class stores all extracted comments from an IWFM input file, organized by section. It supports JSON serialization for storage in sidecar files.
- Variables:
version (str) – Metadata format version (for future compatibility).
source_file (str) – Name of the original source file.
iwfm_version (str) – IWFM version string if detected.
preserve_mode (pyiwfm.io.comment_metadata.PreserveMode) – Level of comment preservation.
sections (dict[str, pyiwfm.io.comment_metadata.SectionComments]) – Dictionary mapping section names to SectionComments.
file_metadata (dict[str, Any]) – Additional key-value metadata from the file.
- preserve_mode: PreserveMode = 'full'#
- sections: dict[str, SectionComments]#
- SIDECAR_SUFFIX = '.iwfm_comments.json'#
- classmethod load(path)[source]#
Load comment metadata from a JSON file.
- Parameters:
- Returns:
CommentMetadata instance if file exists and is valid, None otherwise.
- Return type:
CommentMetadata | None
- classmethod sidecar_path(source_path)[source]#
Get the sidecar file path for a source file.
The sidecar file is stored alongside the source file with the suffix ‘.iwfm_comments.json’.
- classmethod load_for_file(source_path)[source]#
Load comment metadata for an IWFM input file.
Looks for a sidecar file alongside the source file.
- Parameters:
- Returns:
CommentMetadata if sidecar exists and is valid, None otherwise.
- Return type:
CommentMetadata | None
- get_section(section_name)[source]#
Get comments for a specific section.
- Parameters:
section_name (str) – Name of the section.
- Returns:
SectionComments if found, None otherwise.
- Return type:
SectionComments | None
- get_or_create_section(section_name)[source]#
Get or create comments for a specific section.
- Parameters:
section_name (str) – Name of the section.
- Returns:
SectionComments instance (existing or newly created).
- Return type:
- merge(other)[source]#
Merge comments from another metadata instance.
Used when combining comments from multiple source files during model loading.
- Parameters:
other (CommentMetadata) – Another CommentMetadata instance to merge from.
- __init__(version='1.0', source_file='', iwfm_version='', preserve_mode=PreserveMode.FULL, header_block=<factory>, sections=<factory>, file_metadata=<factory>)#
- class pyiwfm.io.comment_metadata.FileCommentMetadata(files=<factory>)[source]#
Bases:
objectContainer for comment metadata across multiple IWFM files.
When loading a complete IWFM model, this class holds the comment metadata for all component files, keyed by file type.
- Variables:
files (dict[str, pyiwfm.io.comment_metadata.CommentMetadata]) – Dictionary mapping file type to CommentMetadata. Keys are standardized names like “preprocessor_main”, “gw_main”, “stream_main”, etc.
- files: dict[str, CommentMetadata]#
- classmethod load_all(file_paths)[source]#
Load comment metadata for all files.
- __init__(files=<factory>)#
Comment Writer#
Injects preserved comments back into written IWFM files.
Comment restoration for IWFM input files.
This module provides tools for restoring preserved comments when writing IWFM input files, enabling round-trip preservation of user-defined comments.
- Classes:
CommentWriter: Main class for restoring comments during file writing.
- class pyiwfm.io.comment_writer.CommentWriter(metadata=None, use_fallback=True)[source]#
Bases:
objectRestore comments when writing IWFM input files.
This class provides methods for injecting preserved comments into generated IWFM output files. It works with CommentMetadata extracted by CommentExtractor.
The writer supports: - Restoring file header blocks - Adding section header comments - Appending inline comments to data lines - Inserting trailing comments after sections
Example
>>> from pyiwfm.io.comment_metadata import CommentMetadata >>> metadata = CommentMetadata.load_for_file("Preprocessor.in") >>> writer = CommentWriter(metadata) >>> header = writer.restore_header() >>> print(header)
- Variables:
metadata – The CommentMetadata to use for restoration.
use_fallback – If True, use default formatting when no comments exist.
- DEFAULT_BANNER = 'C******************************************************************************'#
- DEFAULT_DIVIDER = 'C------------------------------------------------------------------------------'#
- __init__(metadata=None, use_fallback=True)[source]#
Initialize the comment writer.
- Parameters:
metadata (CommentMetadata | None) – CommentMetadata to use for restoration. If None, no comments will be restored.
use_fallback (bool) – If True, use default formatting when no preserved comments exist for a section.
- restore_section_header(section_name, fallback_lines=None)[source]#
Restore header comments for a section.
- restore_section_trailing(section_name, fallback_lines=None)[source]#
Restore trailing comments for a section.
- format_data_with_comment(data, section_name, key, fallback_comment=None)[source]#
Format a data line with its preserved inline comment.
- Parameters:
- Returns:
Formatted line with inline comment if available.
- Return type:
- format_value_with_keyword(value, keyword, section_name=None, width=20)[source]#
Format a value line with / KEYWORD suffix.
Tries to restore the original comment format if preserved, otherwise uses the standard / KEYWORD format.
- write_section_header_to_file(file, section_name, fallback_lines=None)[source]#
Write section header comments to a file.
- write_section_trailing_to_file(file, section_name, fallback_lines=None)[source]#
Write section trailing comments to a file.
- class pyiwfm.io.comment_writer.CommentInjector(metadata=None)[source]#
Bases:
objectInject comments into template-rendered content.
This class post-processes template output to inject preserved comments, allowing templates to generate structure while preserving user comments.
Example
>>> injector = CommentInjector(metadata) >>> output = injector.inject_header(rendered_content)
- __init__(metadata=None)[source]#
Initialize the comment injector.
- Parameters:
metadata (CommentMetadata | None) – CommentMetadata containing preserved comments.
- inject_header(content, header_marker='C*****')[source]#
Inject preserved header into content.
Replaces the template-generated header (identified by marker) with the preserved header if available.
- inject_section_comments(content, section_name, section_marker)[source]#
Inject section comments into content.
Finds the section by marker and injects preserved comments.
Parametric Grid#
Parametric grid interpolation utilities.
Parametric grid interpolation for IWFM aquifer parameters.
When NGROUP > 0 in the GW main file, aquifer parameters are defined on
a coarser parametric finite-element mesh and interpolated onto the model
nodes. This module implements the FE interpolation algorithm used in
IWFM’s ParametricGrid.f90.
- The parametric grid uses standard linear shape functions:
Triangles: barycentric (area) coordinates
Quadrilaterals: bilinear isoparametric mapping
- class pyiwfm.io.parametric_grid.ParamNode(node_id, x, y, values)[source]#
Bases:
objectA parametric grid node with coordinates and parameter values.
- Variables:
node_id (int) – Node identifier (1-based from file).
x (float) – X coordinate.
y (float) – Y coordinate.
values (numpy.ndarray[tuple[Any, ...], numpy.dtype[numpy.float64]]) – Parameter values, shape
(n_layers, n_params).
- __init__(node_id, x, y, values)#
- class pyiwfm.io.parametric_grid.ParamElement(elem_id, vertices)[source]#
Bases:
objectA parametric grid element (triangle or quad).
- Variables:
- __init__(elem_id, vertices)#
- class pyiwfm.io.parametric_grid.ParametricGrid(nodes, elements)[source]#
Bases:
objectLightweight FE grid for parametric interpolation.
Mirrors IWFM’s
ParametricGridmodule. Supports point-in-element testing, shape function evaluation, and parameter interpolation at arbitrary (x, y) points.- Parameters:
nodes (
list[ParamNode]) – Parametric grid nodes with coordinates and parameter values.elements (
list[ParamElement]) – Parametric grid elements referencing node indices.
- interpolate(x, y)[source]#
Interpolate parameter values at point
(x, y).Searches all elements to find the one containing the point, then computes shape-function-weighted parameter values.
- Returns:
Array of shape
(n_layers, n_params)with interpolated values, orNoneif the point is outside the grid.- Return type:
NDArray[np.float64]orNone
HEC-DSS Module#
The DSS module provides support for reading and writing HEC-DSS 7 files.
Note
The HEC-DSS 7 C library is bundled with pyiwfm on Windows
(io/dss/lib/hecdss.dll). On Linux, compile from source using
dss-build/ or set the HECDSS_LIB environment variable to point
to your libhecdss.so.
DSS Package#
HEC-DSS support for pyiwfm.
This package provides Python bindings for reading and writing HEC-DSS 7 files, which are commonly used for time series data storage in water resources modeling.
The HEC-DSS library must be installed separately. Set the HECDSS_LIB environment variable to point to the library location.
Example
>>> from pyiwfm.io.dss import DSSFile, DSSPathname
>>>
>>> # Build a pathname
>>> pathname = DSSPathname.build(
... project="IWFM_MODEL",
... location="STREAM_NODE_1",
... parameter="flow",
... interval="daily",
... )
>>>
>>> # Write time series
>>> with DSSFile("output.dss", mode="w") as dss:
... dss.write_regular_timeseries(str(pathname), values, start_date)
- class pyiwfm.io.dss.DSSPathname(a_part='', b_part='', c_part='', d_part='', e_part='', f_part='')[source]#
Bases:
objectHEC-DSS pathname with structured parts.
DSS pathnames identify data records using six parts: /A/B/C/D/E/F/
- Variables:
- classmethod from_string(pathname)[source]#
Parse a pathname from string.
- Parameters:
pathname (str) – DSS pathname string (e.g., “/PROJECT/LOC/FLOW//1DAY/V1/”)
- Returns:
DSSPathname object
- Raises:
ValueError – If pathname format is invalid
- Return type:
- classmethod build(project='', location='', parameter='', date_range='', interval='1DAY', version='')[source]#
Build a pathname with more descriptive parameter names.
- Parameters:
project (str) – Project or basin name (A part)
location (str) – Location identifier (B part)
parameter (str) – Parameter name (C part) - will be converted to DSS code
date_range (str) – Date range (D part)
interval (str) – Time interval (E part) - will be converted to DSS code
version (str) – Version or scenario (F part)
- Returns:
DSSPathname object
- Return type:
- matches(pattern)[source]#
Check if this pathname matches a pattern.
Pattern parts can be empty to match any value.
- Parameters:
pattern (DSSPathname | str) – DSSPathname pattern or string
- Returns:
True if pathname matches pattern
- Return type:
- __init__(a_part='', b_part='', c_part='', d_part='', e_part='', f_part='')#
- class pyiwfm.io.dss.DSSPathnameTemplate(a_part='', b_part='', c_part='', d_part='', e_part='1DAY', f_part='')[source]#
Bases:
objectTemplate for generating multiple DSS pathnames.
Allows creating pathnames with variable parts.
Example
>>> template = DSSPathnameTemplate( ... a_part="PROJECT", ... c_part="FLOW", ... e_part="1DAY", ... f_part="OBS", ... ) >>> pathname = template.make_pathname(location="STREAM_01")
- make_pathname(location=None, date_range=None, **kwargs)[source]#
Create a pathname from the template.
- Parameters:
- Returns:
DSSPathname object
- Return type:
- __init__(a_part='', b_part='', c_part='', d_part='', e_part='1DAY', f_part='')#
- class pyiwfm.io.dss.DSSFile(filepath, mode='r')[source]#
Bases:
objectContext manager for HEC-DSS file operations.
Provides methods for reading and writing time series data to DSS files.
Example
>>> with DSSFile("data.dss", mode="rw") as dss: ... times, values = dss.read_regular_timeseries("/A/B/C/D/E/F/") ... dss.write_regular_timeseries("/A/B/C2/D/E/F/", values * 2, times[0])
- write_regular_timeseries(pathname, values, start_date, units='', data_type='INST-VAL')[source]#
Write a regular-interval time series to the DSS file.
Uses the HEC-DSS 7 constructor pattern:
zstructTsNewRegFloats()->ztsStore()->zstructFree()
- read_regular_timeseries(pathname, start_date=None, end_date=None)[source]#
Read a regular-interval time series from the DSS file.
Uses the HEC-DSS 7 constructor pattern:
zstructTsNewTimes()->ztsRetrieve()-> extract fields ->zstructFree()
- class pyiwfm.io.dss.DSSFileMock(filepath, mode='r')[source]#
Bases:
objectMock DSS file for when the library is not available.
Allows code to run without the DSS library, but operations will raise informative errors.
- pyiwfm.io.dss.DSSFileClass#
alias of
DSSFileMock
- exception pyiwfm.io.dss.DSSLibraryError[source]#
Bases:
ExceptionError loading or using the HEC-DSS library.
- class pyiwfm.io.dss.DSSTimeSeriesInfo(pathname, start_date=None, end_date=None, n_values=0, units='', data_type='')[source]#
Bases:
objectInformation about a DSS time series record.
- Variables:
pathname (str) – Full DSS pathname
start_date (datetime.datetime | None) – Start datetime
end_date (datetime.datetime | None) – End datetime
n_values (int) – Number of values
units (str) – Units string
data_type (str) – Data type string
- __init__(pathname, start_date=None, end_date=None, n_values=0, units='', data_type='')#
- pyiwfm.io.dss.check_dss_available()[source]#
Check if the DSS library is available.
- Raises:
DSSLibraryError – If the library is not available
- class pyiwfm.io.dss.DSSTimeSeriesWriter(filepath)[source]#
Bases:
objectHigh-level writer for time series data to HEC-DSS files.
Example
>>> writer = DSSTimeSeriesWriter(Path("output.dss")) >>> template = DSSPathnameTemplate( ... a_part="PROJECT", ... c_part="FLOW", ... e_part="1DAY", ... ) >>> writer.write_timeseries(ts, template.make_pathname(location="STREAM_01")) >>> writer.close()
- close()[source]#
Close the DSS file and return write result.
- Returns:
DSSWriteResult with summary of written data
- Return type:
- write_timeseries(ts, pathname, units=None, data_type='INST-VAL')[source]#
Write a TimeSeries to the DSS file.
- Parameters:
ts (TimeSeries) – TimeSeries object to write
pathname (DSSPathname | str) – DSS pathname for the record
units (str | None) – Units string (defaults to ts.units)
data_type (str) – Data type (e.g., “INST-VAL”, “PER-AVER”)
- Returns:
True if successful, False otherwise
- Return type:
- write_collection(collection, pathname_factory, units=None, data_type='INST-VAL')[source]#
Write a TimeSeriesCollection to the DSS file.
- Parameters:
collection (TimeSeriesCollection) – TimeSeriesCollection to write
pathname_factory (Callable[[str], DSSPathname]) – Function that takes location and returns pathname
units (str | None) – Units string
data_type (str) – Data type
- Returns:
Number of time series successfully written
- Return type:
- write_multiple_timeseries(times, values_dict, template, units='', data_type='INST-VAL')[source]#
Write multiple time series with a common time axis.
- Parameters:
times (Sequence[datetime] | ndarray[tuple[Any, ...], dtype[datetime64]]) – Common time array
values_dict (dict[str, ndarray[tuple[Any, ...], dtype[float64]]]) – Dictionary mapping location to values array
template (DSSPathnameTemplate) – Pathname template
units (str) – Units string
data_type (str) – Data type
- Returns:
Number of time series successfully written
- Return type:
- class pyiwfm.io.dss.DSSTimeSeriesReader(filepath)[source]#
Bases:
objectHigh-level reader for time series data from HEC-DSS files.
Example
>>> reader = DSSTimeSeriesReader(Path("input.dss")) >>> ts = reader.read_timeseries("/A/B/C/D/E/F/") >>> reader.close()
- read_timeseries(pathname, start_date=None, end_date=None, name='')[source]#
Read a time series from the DSS file.
- Parameters:
pathname (DSSPathname | str) – DSS pathname
start_date (datetime | None) – Optional start datetime
end_date (datetime | None) – Optional end datetime
name (str) – Name for the TimeSeries
- Returns:
TimeSeries object
- Return type:
- class pyiwfm.io.dss.DSSWriteResult(filepath, pathnames_written, n_records, errors)[source]#
Bases:
objectResult of a DSS write operation.
- Variables:
- __init__(filepath, pathnames_written, n_records, errors)#
- pyiwfm.io.dss.write_timeseries_to_dss(filepath, ts, pathname, units=None)[source]#
Write a single TimeSeries to a DSS file.
- Parameters:
ts (TimeSeries) – TimeSeries to write
pathname (DSSPathname | str) – DSS pathname
units (str | None) – Optional units string
- Returns:
DSSWriteResult
- Return type:
- pyiwfm.io.dss.read_timeseries_from_dss(filepath, pathname, start_date=None, end_date=None)[source]#
Read a single TimeSeries from a DSS file.
- Parameters:
- Returns:
TimeSeries object
- Return type:
- pyiwfm.io.dss.write_collection_to_dss(filepath, collection, template, units='')[source]#
Write a TimeSeriesCollection to a DSS file.
- Parameters:
collection (TimeSeriesCollection) – TimeSeriesCollection to write
template (DSSPathnameTemplate) – Pathname template
units (str) – Units string
- Returns:
DSSWriteResult
- Return type:
DSS Pathname Utilities#
HEC-DSS pathname utilities.
This module provides classes and functions for working with HEC-DSS pathnames which are used to identify data records in DSS files.
DSS Pathname Format: /A/B/C/D/E/F/ - A: Project or Basin name - B: Location (e.g., stream gage, well ID) - C: Parameter (e.g., FLOW, STAGE, HEAD) - D: Date range (e.g., 01JAN2000) - E: Time interval (e.g., 1DAY, 1HOUR) - F: Version or scenario
- class pyiwfm.io.dss.pathname.DSSPathname(a_part='', b_part='', c_part='', d_part='', e_part='', f_part='')[source]#
Bases:
objectHEC-DSS pathname with structured parts.
DSS pathnames identify data records using six parts: /A/B/C/D/E/F/
- Variables:
- classmethod from_string(pathname)[source]#
Parse a pathname from string.
- Parameters:
pathname (str) – DSS pathname string (e.g., “/PROJECT/LOC/FLOW//1DAY/V1/”)
- Returns:
DSSPathname object
- Raises:
ValueError – If pathname format is invalid
- Return type:
- classmethod build(project='', location='', parameter='', date_range='', interval='1DAY', version='')[source]#
Build a pathname with more descriptive parameter names.
- Parameters:
project (str) – Project or basin name (A part)
location (str) – Location identifier (B part)
parameter (str) – Parameter name (C part) - will be converted to DSS code
date_range (str) – Date range (D part)
interval (str) – Time interval (E part) - will be converted to DSS code
version (str) – Version or scenario (F part)
- Returns:
DSSPathname object
- Return type:
- matches(pattern)[source]#
Check if this pathname matches a pattern.
Pattern parts can be empty to match any value.
- Parameters:
pattern (DSSPathname | str) – DSSPathname pattern or string
- Returns:
True if pathname matches pattern
- Return type:
- __init__(a_part='', b_part='', c_part='', d_part='', e_part='', f_part='')#
- class pyiwfm.io.dss.pathname.DSSPathnameTemplate(a_part='', b_part='', c_part='', d_part='', e_part='1DAY', f_part='')[source]#
Bases:
objectTemplate for generating multiple DSS pathnames.
Allows creating pathnames with variable parts.
Example
>>> template = DSSPathnameTemplate( ... a_part="PROJECT", ... c_part="FLOW", ... e_part="1DAY", ... f_part="OBS", ... ) >>> pathname = template.make_pathname(location="STREAM_01")
- make_pathname(location=None, date_range=None, **kwargs)[source]#
Create a pathname from the template.
- Parameters:
- Returns:
DSSPathname object
- Return type:
- __init__(a_part='', b_part='', c_part='', d_part='', e_part='1DAY', f_part='')#
- pyiwfm.io.dss.pathname.format_dss_date_range(start, end)[source]#
Format a date range for DSS D-part.
DSS Wrapper#
HEC-DSS 7 C library wrapper using ctypes.
This module provides a Python interface to the HEC-DSS 7 C library for reading and writing DSS files. The HEC-DSS library must be installed separately and the path specified via the HECDSS_LIB environment variable.
Note: HEC-DSS 7 uses 64-bit integers for IFLTAB (250 elements), not the legacy 32-bit version (600 elements).
Example
>>> from pyiwfm.io.dss import DSSFile
>>> with DSSFile("output.dss", mode="w") as dss:
... dss.write_regular_timeseries(pathname, values, start_date)
- exception pyiwfm.io.dss.wrapper.DSSLibraryError[source]#
Bases:
ExceptionError loading or using the HEC-DSS library.
- exception pyiwfm.io.dss.wrapper.DSSFileError[source]#
Bases:
ExceptionError with DSS file operations.
- pyiwfm.io.dss.wrapper.check_dss_available()[source]#
Check if the DSS library is available.
- Raises:
DSSLibraryError – If the library is not available
- class pyiwfm.io.dss.wrapper.DSSTimeSeriesInfo(pathname, start_date=None, end_date=None, n_values=0, units='', data_type='')[source]#
Bases:
objectInformation about a DSS time series record.
- Variables:
pathname (str) – Full DSS pathname
start_date (datetime.datetime | None) – Start datetime
end_date (datetime.datetime | None) – End datetime
n_values (int) – Number of values
units (str) – Units string
data_type (str) – Data type string
- __init__(pathname, start_date=None, end_date=None, n_values=0, units='', data_type='')#
- class pyiwfm.io.dss.wrapper.DSSFile(filepath, mode='r')[source]#
Bases:
objectContext manager for HEC-DSS file operations.
Provides methods for reading and writing time series data to DSS files.
Example
>>> with DSSFile("data.dss", mode="rw") as dss: ... times, values = dss.read_regular_timeseries("/A/B/C/D/E/F/") ... dss.write_regular_timeseries("/A/B/C2/D/E/F/", values * 2, times[0])
- write_regular_timeseries(pathname, values, start_date, units='', data_type='INST-VAL')[source]#
Write a regular-interval time series to the DSS file.
Uses the HEC-DSS 7 constructor pattern:
zstructTsNewRegFloats()->ztsStore()->zstructFree()
- read_regular_timeseries(pathname, start_date=None, end_date=None)[source]#
Read a regular-interval time series from the DSS file.
Uses the HEC-DSS 7 constructor pattern:
zstructTsNewTimes()->ztsRetrieve()-> extract fields ->zstructFree()
- class pyiwfm.io.dss.wrapper.DSSFileMock(filepath, mode='r')[source]#
Bases:
objectMock DSS file for when the library is not available.
Allows code to run without the DSS library, but operations will raise informative errors.
- pyiwfm.io.dss.wrapper.get_dss_file_class()[source]#
Get the appropriate DSS file class.
Returns DSSFile if library is available, DSSFileMock otherwise.
- pyiwfm.io.dss.wrapper.DSSFileClass#
alias of
DSSFileMock
DSS Time Series#
HEC-DSS time series read/write utilities.
This module provides high-level functions for reading and writing time series data to HEC-DSS files, with integration to pyiwfm’s TimeSeries class.
- class pyiwfm.io.dss.timeseries.DSSWriteResult(filepath, pathnames_written, n_records, errors)[source]#
Bases:
objectResult of a DSS write operation.
- Variables:
- __init__(filepath, pathnames_written, n_records, errors)#
- class pyiwfm.io.dss.timeseries.DSSTimeSeriesWriter(filepath)[source]#
Bases:
objectHigh-level writer for time series data to HEC-DSS files.
Example
>>> writer = DSSTimeSeriesWriter(Path("output.dss")) >>> template = DSSPathnameTemplate( ... a_part="PROJECT", ... c_part="FLOW", ... e_part="1DAY", ... ) >>> writer.write_timeseries(ts, template.make_pathname(location="STREAM_01")) >>> writer.close()
- close()[source]#
Close the DSS file and return write result.
- Returns:
DSSWriteResult with summary of written data
- Return type:
- write_timeseries(ts, pathname, units=None, data_type='INST-VAL')[source]#
Write a TimeSeries to the DSS file.
- Parameters:
ts (TimeSeries) – TimeSeries object to write
pathname (DSSPathname | str) – DSS pathname for the record
units (str | None) – Units string (defaults to ts.units)
data_type (str) – Data type (e.g., “INST-VAL”, “PER-AVER”)
- Returns:
True if successful, False otherwise
- Return type:
- write_collection(collection, pathname_factory, units=None, data_type='INST-VAL')[source]#
Write a TimeSeriesCollection to the DSS file.
- Parameters:
collection (TimeSeriesCollection) – TimeSeriesCollection to write
pathname_factory (Callable[[str], DSSPathname]) – Function that takes location and returns pathname
units (str | None) – Units string
data_type (str) – Data type
- Returns:
Number of time series successfully written
- Return type:
- write_multiple_timeseries(times, values_dict, template, units='', data_type='INST-VAL')[source]#
Write multiple time series with a common time axis.
- Parameters:
times (Sequence[datetime] | ndarray[tuple[Any, ...], dtype[datetime64]]) – Common time array
values_dict (dict[str, ndarray[tuple[Any, ...], dtype[float64]]]) – Dictionary mapping location to values array
template (DSSPathnameTemplate) – Pathname template
units (str) – Units string
data_type (str) – Data type
- Returns:
Number of time series successfully written
- Return type:
- class pyiwfm.io.dss.timeseries.DSSTimeSeriesReader(filepath)[source]#
Bases:
objectHigh-level reader for time series data from HEC-DSS files.
Example
>>> reader = DSSTimeSeriesReader(Path("input.dss")) >>> ts = reader.read_timeseries("/A/B/C/D/E/F/") >>> reader.close()
- read_timeseries(pathname, start_date=None, end_date=None, name='')[source]#
Read a time series from the DSS file.
- Parameters:
pathname (DSSPathname | str) – DSS pathname
start_date (datetime | None) – Optional start datetime
end_date (datetime | None) – Optional end datetime
name (str) – Name for the TimeSeries
- Returns:
TimeSeries object
- Return type:
- pyiwfm.io.dss.timeseries.write_timeseries_to_dss(filepath, ts, pathname, units=None)[source]#
Write a single TimeSeries to a DSS file.
- Parameters:
ts (TimeSeries) – TimeSeries to write
pathname (DSSPathname | str) – DSS pathname
units (str | None) – Optional units string
- Returns:
DSSWriteResult
- Return type:
- pyiwfm.io.dss.timeseries.read_timeseries_from_dss(filepath, pathname, start_date=None, end_date=None)[source]#
Read a single TimeSeries from a DSS file.
- Parameters:
- Returns:
TimeSeries object
- Return type:
- pyiwfm.io.dss.timeseries.write_collection_to_dss(filepath, collection, template, units='')[source]#
Write a TimeSeriesCollection to a DSS file.
- Parameters:
collection (TimeSeriesCollection) – TimeSeriesCollection to write
template (DSSPathnameTemplate) – Pathname template
units (str) – Units string
- Returns:
DSSWriteResult
- Return type:
Data Loaders#
These modules provide lazy, cached access to IWFM output data (heads,
hydrographs, land-use areas). They were moved from visualization.webapi
so that CLI tools, notebooks, and scripts can use them without importing the
web viewer.
Head Data Loader#
Lazy HDF5 reader for time-varying groundwater head data.
Lazy nodal data loader for IWFM HDF5 output.
This module provides the LazyHeadDataLoader class for loading time-varying nodal data (heads or subsidence) from HDF5 files without reading all timesteps into memory at once.
Supports three IWFM native HDF5 dataset formats:
GWHeadAtAllNodes— groundwater head at all nodesSubsidenceAtAllNodes— subsidence at all nodes (v4.1/v5.1)pyiwfm format (dataset
headwith shape(n_timesteps, n_nodes, n_layers))
All native formats store data as (n_timesteps, n_nodes * n_layers)
with layer-major ordering.
- class pyiwfm.io.head_loader.LazyHeadDataLoader(file_path, dataset_name='head', cache_size=50, n_layers=None)[source]#
Bases:
objectLazy loader for time-varying nodal data backed by HDF5 files.
Uses an LRU cache to keep a bounded number of timesteps in memory. Supports dict-like access via
loader[datetime].Auto-detects the dataset type (head vs subsidence) from the HDF5 contents. The
data_typeproperty reports what was found.- Parameters:
Examples
>>> loader = LazyHeadDataLoader("GW_HeadAll.hdf5") >>> print(loader.times[:3]) >>> head_at_t0 = loader[loader.times[0]] >>> print(head_at_t0.shape) # (n_nodes, n_layers)
- __init__(file_path, dataset_name='head', cache_size=50, n_layers=None)[source]#
Initialize the lazy loader.
- Parameters:
file_path (
Pathorstr) – Path to the HDF5 file containing nodal data.dataset_name (
str, optional) – Name of the HDF5 dataset for pyiwfm-format files.cache_size (
int, optional) – Maximum number of timesteps to cache. Default is 50.n_layers (
intorNone, optional) – Number of model layers. When provided, takes precedence over anyNLayersattribute in the HDF5 file. Required for IWFM native HDF5 files that lack the attribute (which is the common case — the Fortran writer does not store it).
- get_frame(frame_idx)[source]#
Get nodal data for a specific frame index.
- Parameters:
frame_idx (
int) – Frame index (0-based).- Returns:
Nodal values, shape (n_nodes, n_layers).
- Return type:
NDArray[np.float64]
- get_head(frame_idx, layer, node_ids=None)[source]#
Get nodal values for a single layer at a specific timestep.
This method is used by
ResultsExtractorto access per-layer data for FE interpolation.- Parameters:
- Returns:
Values at the requested nodes for the given layer, or None if the frame is out of range.
- Return type:
NDArray[np.float64]orNone
- get_composite_subsidence(frame_idx)[source]#
Get total subsidence at each node by summing across all layers.
Subsidence is additive across layers (unlike head which uses T-weighted averaging). This matches the Fortran behavior in
Class_IWFM2OBS.f90:ApplyMultiLayerSubsidence.
- __getitem__(key)[source]#
Get data by datetime or frame index.
- Parameters:
key (
datetimeorint) – Time step or frame index.- Returns:
Nodal values.
- Return type:
NDArray[np.float64]
- to_dict()[source]#
Load all frames into a dict (for use with TimeAnimationController).
This loads all data into memory. For large datasets, prefer using the lazy access via
__getitem__.- Returns:
All data keyed by datetime.
- Return type:
dict[datetime,NDArray[np.float64]]
- get_layer_range(layer, percentile_lo=2.0, percentile_hi=98.0, max_frames=0)[source]#
Compute robust min/max values across all (or sampled) timesteps.
- Parameters:
layer (
int) – 1-based layer number. Use 0 for composite subsidence (sum across all layers).percentile_lo (
float) – Percentiles for robust range (default 2nd-98th).percentile_hi (
float) – Percentiles for robust range (default 2nd-98th).max_frames (
int) – If > 0, sample at most this many evenly-spaced frames instead of scanning all timesteps.
- Returns:
(min_value, max_value, n_frames_scanned)
- Return type:
tuple[float,float,int]
Hydrograph Reader#
Parser for IWFM .out text hydrograph files.
Reader for IWFM hydrograph output text files (.out).
Parses both GW and stream hydrograph output files which share the same IWFM text format with header metadata and whitespace-delimited time series.
- class pyiwfm.io.hydrograph_reader.IWFMHydrographReader(filepath)[source]#
Bases:
objectReader for IWFM hydrograph output text files.
Parses the header for column metadata (hydrograph IDs, layers, node/element IDs) and reads the full time series data into a NumPy array for efficient column extraction.
- Parameters:
filepath (
Pathorstr) – Path to the IWFM hydrograph output file (.out).
- get_time_series(column_index)[source]#
Get time series for a specific column.
- Parameters:
column_index (
int) – 0-based column index.- Returns:
(times, values) where times are ISO 8601 strings.
- Return type:
tuple[list[str],list[float]]
- get_columns_as_smp_dict(bore_ids, filter_ids=None)[source]#
Extract specified columns as
SMPTimeSerieskeyed by bore ID.Bridges the
.outfile reader to the interpolation pipeline.- Parameters:
bore_ids (
dict[int,str]) – Mapping of 0-based column index to bore ID string.filter_ids (
set[int] | None) – Optional set of column indices to process. When provided, only columns whose index is infilter_idsare included; all others are skipped. This avoids loading every column from large.outfiles when only a subset is needed.
- Returns:
Time series keyed by bore ID, suitable for
interpolate_batch().- Return type:
dict[str,SMPTimeSeries]
Hydrograph Loader#
Lazy HDF5-backed hydrograph loader (same interface as IWFMHydrographReader).
Lazy hydrograph data loader backed by HDF5.
Provides the same interface as IWFMHydrographReader but reads from
HDF5 cache files produced by hydrograph_converter.py. This avoids
loading the full text file into memory and enables LRU-cached access.
- class pyiwfm.io.hydrograph_loader.LazyHydrographDataLoader(file_path, cache_size=100)[source]#
Bases:
objectLazy loader for hydrograph time series backed by HDF5.
Exposes the same public interface as
IWFMHydrographReaderso the web viewer route code can use either interchangeably.- Parameters:
Area Data Loader#
Lazy HDF5 reader for land-use area data and multi-type area manager.
Lazy area data loader for IWFM web visualization.
Provides LazyAreaDataLoader for loading time-varying land-use area data
from HDF5 files without reading all timesteps into memory, and
AreaDataManager which manages all four land-use area file types.
- class pyiwfm.io.area_loader.LazyAreaDataLoader(file_path, dataset='area', cache_size=50)[source]#
Bases:
objectLazy HDF5 reader for land-use area data with LRU cache.
- Parameters:
- get_frame(frame_idx)[source]#
Get area data for one timestep.
Returns array of shape
(n_elements, n_cols).
- get_element_timeseries(element_idx)[source]#
Get all timesteps for one element using HDF5 hyperslab slicing.
Returns array of shape
(n_timesteps, n_cols).
- class pyiwfm.io.area_loader.AreaDataManager[source]#
Bases:
objectManages lazy loaders for all 4 land-use area file types.
- load_from_rootzone(rz, cache_dir)[source]#
Convert area files to HDF5 if needed and create lazy loaders.
- get_snapshot(timestep)[source]#
Get aggregated land-use data for all elements at one timestep.
Returns a dict mapping element_id to a dict with keys:
agricultural,urban,native_riparian,water,total_area,dominant.
- get_element_breakdown(element_id, timestep=0)[source]#
Get per-column area breakdown for one element at one timestep.
Returns a dict mapping land-use label (e.g.
"nonponded") to a list of per-column areas. Each entry corresponds to a column in the HDF5 dataset for that land-use type.
- get_element_timeseries(element_id)[source]#
Get all-timestep timeseries for one element across all land-use types.
Returns a dict with keys per land-use type, each containing
areas(list of per-timestep values) and column count info.
SQLite Cache Builder#
Pre-computes aggregates from HDF5/text loaders into a single SQLite database.
SQLite cache builder for the IWFM web viewer.
Reads from existing HDF5/text loaders and pre-computes aggregates into a single SQLite database for fast serving. The cache provides:
Pre-computed element-averaged head values (by-element)
Pre-computed head ranges per layer (2nd/98th percentile)
Pre-computed budget summaries (total/average per column)
Pre-aggregated zone budget totals
Unified hydrograph timeseries (GW/stream/subsidence from output files)
Stream rating tables
Land-use area snapshots with dominant-type classification
- class pyiwfm.io.cache_builder.SqliteCacheBuilder(cache_path)[source]#
Bases:
objectBuilds the SQLite viewer cache from model data and loaders.
Usage:
builder = SqliteCacheBuilder(cache_path) builder.build(model, head_loader, budget_readers, ...)
- build(model, head_loader=None, budget_readers=None, area_manager=None, gw_hydrograph_reader=None, stream_hydrograph_reader=None, subsidence_reader=None, tile_drain_reader=None, subsidence_loader=None, progress_callback=None)[source]#
Build the complete cache.
- Parameters:
model (
IWFMModel) – The loaded model.head_loader (
LazyHeadDataLoader, optional) – Head data loader (HDF5-backed).budget_readers (
dict, optional) – Mapping of budget_type -> BudgetReader.area_manager (
AreaDataManager, optional) – Land-use area data manager.gw_hydrograph_reader (
IWFMHydrographReader, optional)stream_hydrograph_reader (
IWFMHydrographReader, optional)subsidence_reader (
IWFMHydrographReader, optional)tile_drain_reader (
IWFMHydrographReader, optional)subsidence_loader (
LazyHeadDataLoader, optional) – Subsidence surface data loader (SubsidenceAtAllNodes HDF5).progress_callback (
callable, optional) – Called with (step_name, pct) for progress reporting.
SQLite Cache Loader#
Read-only access to the viewer SQLite cache.
SQLite cache loader for the IWFM web viewer.
Provides fast read access to pre-computed data stored by
SqliteCacheBuilder. Uses WAL mode for
concurrent reads and connection pooling for thread safety.
- class pyiwfm.io.cache_loader.SqliteCacheLoader(cache_path)[source]#
Bases:
objectRead-only access to the viewer SQLite cache.
Thread-safe via per-thread connections with WAL mode.
- Parameters:
cache_path (
Path) – Path to the SQLite cache file.
- get_head_frame(frame_idx)[source]#
Get a raw head frame (n_nodes, n_layers).
Returns None if frame not cached.
- get_head_by_element(frame_idx, layer)[source]#
Get pre-computed element-averaged heads.
Returns (values_array, min_val, max_val) or None.
- get_head_range(layer)[source]#
Get the pre-computed head range for a layer.
Returns dict with percentile_02, percentile_98, abs_min, abs_max.
- get_subsidence_range(layer)[source]#
Get the pre-computed subsidence range for a layer.
Returns dict with percentile_02, percentile_98, abs_min, abs_max.
- get_budget_locations(budget_type)[source]#
Get locations for a budget type as (idx, name, area) tuples.
- get_budget_columns(budget_type)[source]#
Get columns for a budget type as (idx, name, units) tuples.
- get_budget_data(budget_type, location_idx)[source]#
Get budget data for a location as (n_timesteps, n_cols) array.
- get_budget_summary(budget_type, location_idx)[source]#
Get budget summaries as (col_idx, total, average) tuples.
- get_hydrograph(hydro_type, column_idx)[source]#
Get a hydrograph timeseries.
Returns (times_list, values_array) or None.
- get_hydrograph_columns(hydro_type)[source]#
Get hydrograph column metadata as (col_idx, node_id, layer) tuples.
- get_gw_hydrograph_all_layers(node_id)[source]#
Get all GW hydrograph layers for a node.
Returns list of (layer, times, values) tuples, or None.
- get_gw_hydrograph_by_columns(base_col, n_layers)[source]#
Get GW hydrograph layers by consecutive column range.
IWFM GW hydrograph output files store n_layers consecutive columns per location: [loc_lay1, loc_lay2, …, loc_layN].
Returns list of (layer, times, values) tuples, or None.
- get_stream_rating(stream_node_id)[source]#
Get a stream node’s rating table.
Returns (bottom_elev, stages, flows) or None.
Observation File I/O#
SMP Module#
Reader and writer for IWFM SMP (Sample/Bore) observation files, the standard format for observed and simulated time series at well locations.
SMP (Sample/Bore) file reader and writer for IWFM observation data.
The SMP format is IWFM’s standard observation file format used by IWFM2OBS and other calibration utilities. It uses fixed-width columns:
Columns 1-25: Bore ID (left-justified)
Columns 26-37: Date (MM/DD/YYYY)
Columns 38-49: Time (HH:MM:SS)
Columns 50-60: Value (numeric)
Column 61+: Optional ‘X’ for excluded records
Sentinel values (-1.1E38, -9.1E37, etc.) are treated as NaN.
Example
>>> from pyiwfm.io.smp import SMPReader, SMPWriter
>>> reader = SMPReader("observations.smp")
>>> data = reader.read()
>>> for bore_id, ts in data.items():
... print(f"{bore_id}: {len(ts.values)} records")
- class pyiwfm.io.smp.SMPRecord(bore_id, datetime, value, excluded=False)[source]#
Bases:
objectA single SMP observation record.
- Variables:
- __init__(bore_id, datetime, value, excluded=False)#
- class pyiwfm.io.smp.SMPTimeSeries(bore_id, times, values, excluded)[source]#
Bases:
objectTime series for a single bore from an SMP file.
- Variables:
bore_id (
str) – Observation well / bore identifier.times (
NDArray[np.datetime64]) – Array of observation timestamps.values (
NDArray[np.float64]) – Array of observed values.excluded (
NDArray[np.bool_]) – Boolean mask; True where records are excluded.
- __init__(bore_id, times, values, excluded)#
- class pyiwfm.io.smp.SMPReader(filepath)[source]#
Bases:
BaseReaderReader for IWFM SMP (Sample/Bore) observation files.
- Parameters:
filepath (
Path | str) – Path to the SMP file.
Example
>>> reader = SMPReader("obs_wells.smp") >>> data = reader.read() >>> ts = data["WELL_01"] >>> print(ts.n_records)
- class pyiwfm.io.smp.SMPWriter(filepath, fixed_format=False)[source]#
Bases:
BaseWriterWriter for IWFM SMP (Sample/Bore) observation files.
- Parameters:
filepath (
Path | str) – Path to the output SMP file.fixed_format (
bool) – If True, enforce CalcTypeHyd Fortran format(A25,A12,A12,A11)with left-justified date/time fields. Default False.
Example
>>> writer = SMPWriter("output.smp") >>> writer.write(data) >>> # CalcTypeHyd-compatible output >>> writer = SMPWriter("output.smp", fixed_format=True) >>> writer.write(data)
- write(data)[source]#
Write all bore time series to the SMP file.
- Parameters:
data (
dict[str,SMPTimeSeries]) – Mapping of bore ID to time series.
- write_bore(ts)[source]#
Append a single bore’s time series to the file.
- Parameters:
ts (
SMPTimeSeries) – Time series to write.
- pyiwfm.io.smp.smp_transform(input_path, output_path, func)[source]#
Apply a value transform to all records in an SMP file.
Reads the input SMP file, applies
functo each value, and writes the result to the output file. Preserves bore IDs, dates, and formatting.- Parameters:
input_path (
Path | str) – Input SMP file.output_path (
Path | str) – Output SMP file.func (
callable) – Transform function applied to each value. Receives a float, returns a float. Example:lambda v: math.copysign(math.sqrt(abs(v)), v)for signed sqrt.
- Returns:
Number of records transformed.
- Return type:
Example
>>> import math >>> smp_transform("stream.smp", "stream_sqrt.smp", ... lambda v: math.copysign(math.sqrt(abs(v)), v))
Simulation Messages#
Parser for IWFM SimulationMessages.out files, extracting messages by
severity (INFO, WARN, FATAL) and spatial IDs (node, element, reach,
layer) via regex patterns.
Parser for IWFM SimulationMessages.out files.
SimulationMessages.out is produced by IWFM during simulation and contains warnings, errors, and informational messages with spatial context (node IDs, element IDs, reach IDs, layer IDs). Additionally parses convergence iteration counts, mass balance errors, and timestep cut / damping factor events.
Example
>>> from pyiwfm.io.simulation_messages import SimulationMessagesReader
>>> reader = SimulationMessagesReader("SimulationMessages.out")
>>> result = reader.read()
>>> print(f"Warnings: {result.warning_count}, Errors: {result.error_count}")
>>> for msg in result.filter_by_severity(MessageSeverity.WARN):
... print(msg.text[:80])
>>> summary = result.get_convergence_summary()
>>> print(f"Max iterations: {summary['max_iterations']}")
- class pyiwfm.io.simulation_messages.MessageSeverity(*values)[source]#
Bases:
EnumSeverity levels for simulation messages.
- MESSAGE = 0#
- INFO = 1#
- WARN = 2#
- FATAL = 3#
- class pyiwfm.io.simulation_messages.SimulationMessage(severity, text, procedure, line_number, node_ids=<factory>, element_ids=<factory>, reach_ids=<factory>, layer_ids=<factory>)[source]#
Bases:
objectA single parsed simulation message.
- Variables:
severity (
MessageSeverity) – Message severity level.text (
str) – Full message text (joined from continuation lines).procedure (
str) – Name of the Fortran procedure that generated the message.line_number (
int) – Line number in the file where the message starts.node_ids (
list[int]) – Node IDs extracted from the message text.element_ids (
list[int]) – Element IDs extracted from the message text.reach_ids (
list[int]) – Reach IDs extracted from the message text.layer_ids (
list[int]) – Layer IDs extracted from the message text.
- severity: MessageSeverity#
- __init__(severity, text, procedure, line_number, node_ids=<factory>, element_ids=<factory>, reach_ids=<factory>, layer_ids=<factory>)#
- class pyiwfm.io.simulation_messages.ConvergenceRecord(timestep_index, date, iteration_count, max_residual, convergence_achieved, bottleneck_variable='', supply_adj_count=0)[source]#
Bases:
objectRecord of convergence iteration data for a single timestep.
- Variables:
timestep_index (
int) – 1-based timestep number.date (
str) – IWFM date string (MM/DD/YYYY_HH:MM) for the timestep.iteration_count (
int) – Number of solver iterations for this timestep.max_residual (
float | None) – Maximum residual at final iteration, if reported.convergence_achieved (
bool) – Whether the solver converged within the allowed iterations.
- __init__(timestep_index, date, iteration_count, max_residual, convergence_achieved, bottleneck_variable='', supply_adj_count=0)#
- class pyiwfm.io.simulation_messages.ConvergenceHotspot(variable, entity_type, entity_id, layer, occurrence_count, total_iterations, worst_timestep_index, worst_timestep_date)[source]#
Bases:
objectAggregated convergence bottleneck information for a single variable.
- Variables:
variable (
str) – Variable identifier (e.g."GW_25393_(L1)").entity_type (
str) – Entity type:"groundwater","stream", or"lake".entity_id (
int) – Numeric ID of the entity.layer (
int | None) – Layer number for groundwater nodes.occurrence_count (
int) – Number of timesteps where this was the bottleneck variable.total_iterations (
int) – Sum of iteration counts across all timesteps where this was bottleneck.worst_timestep_index (
int) – Timestep with the most iterations for this variable.worst_timestep_date (
str) – Date of the worst timestep.
- __init__(variable, entity_type, entity_id, layer, occurrence_count, total_iterations, worst_timestep_index, worst_timestep_date)#
- class pyiwfm.io.simulation_messages.MassBalanceRecord(timestep_index, date, component, error_value, error_percent)[source]#
Bases:
objectMass balance error record for a single timestep and component.
- Variables:
timestep_index (
int) – 1-based timestep number.date (
str) – IWFM date string for the timestep.component (
str) – Hydrologic component (e.g."groundwater","stream","rootzone").error_value (
float) – Absolute mass balance error value.error_percent (
float | None) – Mass balance error as a percentage, if reported.
- __init__(timestep_index, date, component, error_value, error_percent)#
- class pyiwfm.io.simulation_messages.TimestepCutRecord(timestep_index, date, reason, new_dt)[source]#
Bases:
objectRecord of a timestep cut or damping factor adjustment.
- Variables:
- __init__(timestep_index, date, reason, new_dt)#
- class pyiwfm.io.simulation_messages.SimulationMessagesResult(messages, total_runtime, warning_count, error_count, convergence_records=<factory>, mass_balance_records=<factory>, timestep_cuts=<factory>, max_iterations=0, avg_iterations=0.0)[source]#
Bases:
objectResult of parsing a SimulationMessages.out file.
- Variables:
messages (
list[SimulationMessage]) – All parsed messages.total_runtime (
timedelta | None) – Total simulation runtime if found in the summary.warning_count (
int) – Number of warning messages.error_count (
int) – Number of fatal/error messages.convergence_records (
list[ConvergenceRecord]) – Per-timestep convergence iteration data.mass_balance_records (
list[MassBalanceRecord]) – Per-timestep mass balance error data.timestep_cuts (
list[TimestepCutRecord]) – Timestep cut / damping adjustment events.max_iterations (
int) – Highest iteration count across all timesteps (0 if none parsed).avg_iterations (
float) – Average iteration count across all timesteps (0.0 if none parsed).
- messages: list[SimulationMessage]#
- convergence_records: list[ConvergenceRecord]#
- mass_balance_records: list[MassBalanceRecord]#
- timestep_cuts: list[TimestepCutRecord]#
- get_convergence_summary()[source]#
Return summary statistics for convergence and mass balance.
- Returns:
Dictionary with keys:
max_iterations— highest iteration count across all timestepsavg_iterations— mean iteration counttotal_timesteps— number of timesteps with convergence dataconverged_count— number of timesteps that convergedfailed_count— number of timesteps that did NOT convergeconvergence_rate— fraction of timesteps that convergedtimestep_cuts— total number of timestep cut eventsmass_balance_records— total number of mass balance recordsmax_mass_balance_error— largest absolute mass balance errorcomponents_with_errors— sorted list of unique component names
- Return type:
dict[str,Any]
- get_hotspots()[source]#
Return convergence hotspot variables sorted by occurrence count.
Groups convergence records by
bottleneck_variableand aggregates occurrence counts, total iterations, and worst timestep.- Returns:
Hotspots sorted by occurrence count (descending).
- Return type:
list[ConvergenceHotspot]
- filter_by_severity(severity)[source]#
Return messages matching the given severity.
- Parameters:
severity (
MessageSeverity) – Severity level to filter by.- Returns:
Filtered messages.
- Return type:
list[SimulationMessage]
- get_spatial_summary()[source]#
Summarize message counts by spatial entity.
- Returns:
Mapping from entity type (
"nodes","elements","reaches","layers") to a dict of ID → message count.- Return type:
dict[str,dict[int,int]]
- to_geodataframe(grid)[source]#
Convert spatial message summary to a GeoDataFrame.
- Parameters:
grid (
AppGrid) – The model grid for looking up node/element coordinates.- Returns:
Point geometries at node locations or element centroids with message count attributes.
- Return type:
GeoDataFrame
- __init__(messages, total_runtime, warning_count, error_count, convergence_records=<factory>, mass_balance_records=<factory>, timestep_cuts=<factory>, max_iterations=0, avg_iterations=0.0)#
- class pyiwfm.io.simulation_messages.SimulationMessagesReader(filepath)[source]#
Bases:
BaseReaderReader for IWFM SimulationMessages.out files.
- Parameters:
filepath (
Path | str) – Path to the SimulationMessages.out file.
Drawdown#
Compute drawdown (head change) relative to a reference timestep, with support for per-node, per-element, robust range, and maximum drawdown map computations.
Drawdown computation from IWFM head data.
This module provides the DrawdownComputer class for computing
drawdown (head change) relative to a reference timestep. Drawdown is
defined as head(t_ref) - head(t) so that positive values indicate
water level decline.
Sentinel values (< -9000) used by IWFM to represent dry cells are treated as NaN.
- class pyiwfm.io.drawdown.DrawdownComputer(head_loader)[source]#
Bases:
objectCompute drawdown (head change) relative to a reference timestep.
Drawdown = head(t_ref) - head(t) (positive = water level decline)
- Parameters:
head_loader (
LazyHeadDataLoader) – Loader providing lazy access to per-timestep head arrays.
- compute_drawdown(timestep, reference_timestep=0, layer=1)[source]#
Compute per-node drawdown for a single timestep vs reference.
- Parameters:
- Returns:
Array of shape
(n_nodes,). Positive values mean water level decline. NaN where either timestep has a dry-cell sentinel.- Return type:
NDArray[np.float64]
- compute_drawdown_by_element(timestep, reference_timestep=0, layer=1, grid=None)[source]#
Compute per-element drawdown (average of element node values).
Each element’s drawdown is the arithmetic mean of its vertex node drawdown values.
- Parameters:
- Returns:
Array of shape
(n_elements,)ordered by element ID. NaN where any contributing node is NaN.- Return type:
NDArray[np.float64]- Raises:
ValueError – If grid is
None.
- compute_drawdown_range(reference_timestep=0, layer=1, max_frames=0)[source]#
Compute robust min/max drawdown across all timesteps.
Uses the 2nd and 98th percentile to exclude outliers.
- Parameters:
- Returns:
(min_drawdown, max_drawdown)across all (sampled) timesteps. Falls back to(0.0, 1.0)if no valid data exists.- Return type:
tuple[float,float]
Stream Depletion#
Compare baseline and pumping-scenario model runs to quantify stream flow depletion at individual reaches.
Stream depletion analysis — compare streamflow between baseline and pumping scenarios.
- class pyiwfm.io.stream_depletion.StreamDepletionResult(reach_id, reach_name, times, baseline_flow, scenario_flow, depletion, cumulative_depletion, max_depletion, max_depletion_timestep, total_depletion)[source]#
Bases:
objectResult of stream depletion analysis at a single reach/node.
- baseline_flow: NDArray[np.float64]#
- scenario_flow: NDArray[np.float64]#
- depletion: NDArray[np.float64]#
- cumulative_depletion: NDArray[np.float64]#
- __init__(reach_id, reach_name, times, baseline_flow, scenario_flow, depletion, cumulative_depletion, max_depletion, max_depletion_timestep, total_depletion)#
- class pyiwfm.io.stream_depletion.StreamDepletionReport(results, n_reaches, n_timesteps, total_max_depletion, total_cumulative_depletion)[source]#
Bases:
objectAggregate depletion results across multiple reaches.
- results: list[StreamDepletionResult]#
- __init__(results, n_reaches, n_timesteps, total_max_depletion, total_cumulative_depletion)#
- pyiwfm.io.stream_depletion.compute_stream_depletion(baseline_dir, scenario_dir, reach_ids=None, budget_type='Stream Reach Budgets')[source]#
Compute stream depletion by comparing two model runs.
- Parameters:
baseline_dir (
strorPath) – Path to the baseline (no-pumping) model results directory.scenario_dir (
strorPath) – Path to the pumping scenario model results directory.reach_ids (
list[int]orNone) – Specific reach IDs to analyze. If None, analyze all reaches.budget_type (
str) – Budget type name to look for in the HDF5 files.
- Returns:
Depletion analysis results.
- Return type:
Budget Checks#
Mass balance sanity checks for IWFM budget data — detect timesteps where inflows, outflows, and storage change are out of balance.
Water budget mass balance sanity checks.
This module provides utilities for verifying mass balance closure in IWFM
budget output. Given a BudgetReader, it classifies columns as
inflows, outflows, or storage changes and computes per-timestep discrepancies.
Example
>>> from pyiwfm.io.budget import BudgetReader
>>> from pyiwfm.io.budget_checks import check_budget_balance
>>> reader = BudgetReader("GW_Budget.hdf")
>>> report = check_budget_balance(reader, location_index=0)
>>> print(report.max_percent_error)
- class pyiwfm.io.budget_checks.BalanceCheckResult(timestep_index, date, total_inflow, total_outflow, storage_change, discrepancy, percent_error, within_tolerance)[source]#
Bases:
objectResult of a mass balance check for one timestep.
- __init__(timestep_index, date, total_inflow, total_outflow, storage_change, discrepancy, percent_error, within_tolerance)#
- class pyiwfm.io.budget_checks.BudgetSanityReport(budget_type, location, n_timesteps, n_violations, max_percent_error, mean_percent_error, records=<factory>)[source]#
Bases:
objectFull sanity check report for a budget.
- records: list[BalanceCheckResult]#
- __init__(budget_type, location, n_timesteps, n_violations, max_percent_error, mean_percent_error, records=<factory>)#
- pyiwfm.io.budget_checks.check_budget_balance(reader, location_index=0, tolerance_percent=1.0, inflow_columns=None, outflow_columns=None, storage_column=None)[source]#
Check mass balance for a budget location.
If column names are not specified, auto-detect by looking for columns containing
'inflow'/'recharge'/'gain'for inflows,'outflow'/'discharge'/'loss'for outflows, and'storage'/'change'for storage.- Parameters:
reader (
BudgetReader) – An already-opened budget reader.location_index (
int) – Zero-based location index.tolerance_percent (
float) – Maximum acceptable percent error.inflow_columns (
list[str]orNone) – Explicit column names for inflows/outflows.outflow_columns (
list[str]orNone) – Explicit column names for inflows/outflows.storage_column (
strorNone) – Explicit storage column name.
- Return type:
- pyiwfm.io.budget_checks.check_all_budgets(budget_readers, tolerance_percent=1.0)[source]#
Check mass balance across all available budgets.
- Parameters:
budget_readers (
dict[str,BudgetReader]) – Mapping of budget type name to reader instance.tolerance_percent (
float) – Maximum acceptable percent error per timestep.
- Returns:
Mapping of budget type name to its sanity report (first location only).
- Return type:
dict[str,BudgetSanityReport]
Zone File I/O#
The zones module provides readers and writers for IWFM zone definition files (used by ZBudget) and GeoJSON zone files.
Zone file I/O for IWFM and GeoJSON formats.
This module handles reading and writing zone definition files:
IWFM ZBudget format (text-based element-zone assignments)
GeoJSON format (geospatial zone boundaries)
IWFM Zone File Format#
The IWFM zone file format is used by ZBudget for water budget analysis:
`
C Comment lines start with C
1 # ZExtent: 1=horizontal, 0=vertical
1 Sacramento Valley # Zone ID and name
2 San Joaquin Valley
/ # Separator
1 1 # Element 1 -> Zone 1
2 1 # Element 2 -> Zone 1
3 2 # Element 3 -> Zone 2
`
Example
Read zone file:
>>> from pyiwfm.io.zones import read_iwfm_zone_file, write_iwfm_zone_file
>>> zone_def = read_iwfm_zone_file("ZBudget_Zones.dat")
>>> print(f"Loaded {zone_def.n_zones} zones")
Write zone file:
>>> write_iwfm_zone_file(zone_def, "output_zones.dat")
- pyiwfm.io.zones.read_iwfm_zone_file(filepath, element_areas=None)[source]#
Read an IWFM-format zone definition file.
- Parameters:
filepath (
Pathorstr) – Path to the zone file.element_areas (
dict[int,float], optional) – Element areas for zone area calculation.
- Returns:
The loaded zone definition.
- Return type:
ZoneDefinition
Notes
The IWFM zone file format: - Lines starting with ‘C’ or ‘*’ are comments - First data line: ZExtent (1=horizontal, 0=vertical) - Zone definitions: ID and optional name - Separator: ‘/’ - Element assignments: element_id zone_id
Examples
>>> zone_def = read_iwfm_zone_file("zones.dat") >>> print(f"Loaded {zone_def.n_zones} zones with {zone_def.n_elements} elements")
- pyiwfm.io.zones.write_iwfm_zone_file(zone_def, filepath, header_comment='')[source]#
Write a zone definition to IWFM format file.
- Parameters:
Examples
>>> write_iwfm_zone_file(zone_def, "output_zones.dat", header_comment="Custom zones")
- pyiwfm.io.zones.read_geojson_zones(filepath, zone_id_field='id', zone_name_field='name', element_id_field='element_id')[source]#
Read zone definitions from a GeoJSON file.
- Parameters:
filepath (
Pathorstr) – Path to the GeoJSON file.zone_id_field (
str, optional) – Property field for zone ID. Default is “id”.zone_name_field (
str, optional) – Property field for zone name. Default is “name”.element_id_field (
str, optional) – Property field for element IDs (array). Default is “element_id”.
- Returns:
The loaded zone definition.
- Return type:
ZoneDefinition
Notes
Expected GeoJSON structure:
{ "type": "FeatureCollection", "features": [ { "type": "Feature", "properties": { "id": 1, "name": "Zone A", "element_id": [1, 2, 3, 4] }, "geometry": { ... } } ] }
- pyiwfm.io.zones.write_geojson_zones(zone_def, filepath, grid=None, include_geometry=True)[source]#
Write zone definitions to a GeoJSON file.
- Parameters:
Notes
If grid is provided and include_geometry is True, zone boundaries are computed as the convex hull of element centroids.
- pyiwfm.io.zones.read_zone_file(filepath, element_areas=None)[source]#
Read a zone file, auto-detecting the format.
- Parameters:
filepath (
Pathorstr) – Path to the zone file.element_areas (
dict[int,float], optional) – Element areas for zone area calculation (IWFM format only).
- Returns:
The loaded zone definition.
- Return type:
ZoneDefinition- Raises:
ValueError – If file format cannot be determined.
Examples
>>> zone_def = read_zone_file("zones.dat") # IWFM format >>> zone_def = read_zone_file("zones.geojson") # GeoJSON format
- pyiwfm.io.zones.write_zone_file(zone_def, filepath, grid=None)[source]#
Write a zone file, choosing format based on extension.
- Parameters:
zone_def (
ZoneDefinition) – The zone definition to write.filepath (
Pathorstr) – Output file path.grid (
AppGrid, optional) – Model grid for GeoJSON geometry computation.
Examples
>>> write_zone_file(zone_def, "zones.dat") # IWFM format >>> write_zone_file(zone_def, "zones.geojson", grid) # GeoJSON format
Supported formats:
IWFM ZBudget format: Text-based element-to-zone assignments with zone names and extents (horizontal/vertical)
GeoJSON: Standard geospatial format with geometry and properties for interoperability with GIS tools
Comment Extractor#
Extracts comments from IWFM files for preservation during roundtrip I/O.
Comment extraction from IWFM input files.
This module provides tools for extracting comments from IWFM input files, preserving them for later restoration during file writing.
IWFM supports several comment styles: - Full-line comments starting with ‘C’, ‘c’, or ‘*’ in column 1 - Inline comments starting with ‘/’ preceded by whitespace - Header blocks using banner patterns (C***…*)
LineType: Enum for classifying input lines. CommentExtractor: Main class for extracting comments from files.
Bases:
EnumClassification of IWFM input file lines.
Bases:
objectA parsed line from an IWFM input file.
line_number (int) – 1-based line number in the file.
raw (str) – Original line text including newline.
stripped (str) – Line with trailing whitespace removed.
line_type (pyiwfm.io.comment_extractor.LineType) – Classification of the line.
data_part (str) – Data portion of the line (for DATA and INLINE_COMMENT).
comment_part (str) – Comment portion of the line (for INLINE_COMMENT).
keyword (str) – Keyword from / KEYWORD suffix (e.g., “NNODES”).
Bases:
objectExtract comments from IWFM input files.
This class parses IWFM input files and extracts all comment information, organizing it into a CommentMetadata structure that can be used to preserve comments during round-trip file operations.
IWFM comment conventions (from IWFM source code): - Full-line comment indicators: ‘C’, ‘c’, ‘*’ in column 1 - Inline comment indicator: ‘/’ preceded by whitespace - Banner patterns: Lines of C***** or C—– used as section dividers
Example
FULL_LINE_CHARS – Characters that indicate a full-line comment.
INLINE_CHAR – Character that indicates an inline comment.
BANNER_PATTERN – Regex pattern for banner lines.
KEYWORD_PATTERN – Regex pattern for / KEYWORD suffixes.
Initialize the comment extractor.
preserve_mode (PreserveMode) – Level of comment preservation.
Extract comments from an IWFM input file.
filepath (Path | str) – Path to the IWFM input file.
CommentMetadata containing all extracted comments.
FileNotFoundError – If the file does not exist.
IOError – If the file cannot be read.
CommentMetadata
Convenience function to extract comments from an IWFM file.
filepath (Path | str) – Path to the IWFM input file.
CommentMetadata containing all extracted comments.
CommentMetadata
Example
Extract comments and save to a sidecar file.
filepath (Path | str) – Path to the IWFM input file.
Path to the saved sidecar file.
Path
Example