IEF Class#

Summary#

The IEF class is used to read, write and update Flood Modeller’s ief file format. The class can be initiated with the full filepath of an ief file to load an existing ief, or with no path to create a new ief file in memory.

In [1]: from floodmodeller_api import IEF;

In [2]: ief = IEF("network.ief") # Loads existing IEF into memory

In [3]: new_ief = IEF(); # Used to create new 'blank' IEF

In [4]: new_ief
Out[4]: <floodmodeller_api Class: IEF(filepath=None)>

All standard IEF settings can be changed by the user by simply updating the class property with the same name. For example to set the model title, simply type:

In [5]: ief.title = "My New Title";

In [6]: ief.title
Out[6]: 'My New Title'

Warning

Any changes made to the IEF class object are only made to the object itself and do not change the source IEF file until the update() method is called. Alternatively if the save() method is called then the changes are saved to a new file (based on the given path) and the original source IEF remains unchanged

Class properties can be updated in this fashion for existing IEF settings as well as to add new settings. To remove a particular setting from the IEF simply delete the property object, for example to remove ‘LINKFLOW’ simple type:

del ief.linkflow

Note

IEF properties can be accessed using any casing (e.g. ief.results is equivalent to ief.Results) therefore any scripts using the IEF class can be implemented using typical python style with lowercase properties, whilst retaining the casing in the original file.

Class properties can also be managed using python’s built-in getattr(), setattr() and delattr() functions, using these methods is recommended for more complex updates such as updating settings from a dictionary of values, but is required for certain IEF settings which are prefixed with a number such as ‘2DFLOW’ since these are not valid python variables. An example of updating the ‘2DFLOW’ setting in this way is:

setattr(ief, '2DFLOW', 1) # Sets the IEF's '2DFLOW' setting to 1

IEF files can also be simulated directly by calling the simulate() method on an active IEF class object. This method assumes that Flood Modeller is installedat the default location (‘C:\Program Files\Flood Modeller\bin’). An optional argument 'method' is used to control whether the python code should pause until the simulation has completed, or to return the simulation as a subprocess.Popen() instance and continue code execution. By default, the ‘WAIT’ method is used to providea simple way to know when the simulation has completed. Using the option to return the process as an object would mostly be used for more complex scripts where you are wanting to have more control over checking simulation progress and performing any tasks whilst the simulation is running. Subprocess is a package included in the Python Standard Library which allows for spawning new processes and handling their input and output pipes. More information on working with subprocess.Popen() can be found here.

Working with Event Data attributes#

An IEF file can have any number of ‘EventData’ attributes which point to the location of IED files. In the IEF class these are all contained within the .eventdata attribute as a dictionary. This allows for each event data to have an associated title which is defined in the IEF file as a comment before the event data attribute. The dictionary keys represent the titles, and the values represent the event data paths. An example would look like this:

In [7]: ief = IEF();

In [8]: ief.eventdata = {
   ...:     'MainInflow' : 'Q100.IED',
   ...:     'TribInflow' : 'Q100_trib.IED',
   ...:     'TidalBoundary' : 'T100_DSBDY.IED'
   ...: };
   ...: 

This would then write out the following lines in the IEF file:

In [9]: print(ief._write())
[ISIS Event Header]
Title=
Datafile=
Results=
[ISIS Event Details]
RunType=Steady
Start=0
ICsFrom=1
;MainInflow
EventData=Q100.IED
;TribInflow
EventData=Q100_trib.IED
;TidalBoundary
EventData=T100_DSBDY.IED

When editing event data attibutes, they can simply be edited in the same way as a dictionary. For example, deleting keys using del, adding new keys and editing existing ones.

Warning

The .eventdata attribute has been changed to use a dictionary as of version 0.4.1 of the API. Previously in v0.4.0 .eventdata would return a list instead, without support for reading/editing the event data titles. This introduces a change which is incompatible with previous versions of the API in how event data in IEF files is handled. Any existing code that treats eventdata as a list will need to be updated in order to run this version.

Flow Time Profile data#

Added in version 0.5.0.

In addition to using the ‘EventData’ attributes to define boundary conditions for a simulation, inflows can also be defined using any number of ‘flowtimeprofile’ attributes in an IEF file. These typically look something like this in an IEF file:

[Flow Time Profiles]
NoOfFlowTimeProfiles = 2
NoOfFlowTimeSeries = 2
FlowTimeProfile0 = SEV19005,19,23,..\..\associated_data\Baseline unchecked.csv,hplus,100 - 11 - 2020 Upper,
FlowTimeProfile1 = randomInflow,9,23,..\..\associated_data\Baseline unchecked.csv,hplus,100 - 11 - Reconciled Baseline,

These flow time profiles are typically generating via the Flood Modeller UI, and have a range of different formats that can be used. For more information on how these are set up and used in Flood Modeller, go to how-to-use-flow-time-series-datafiles.

With the Flood Modeller API we can also access this data in a helpful way by using the .flowtimeprofiles attribute on an IEF instance, which returns a list of FlowTimeProfile objects.

In [10]: ief = IEF("7082.ief"); # IEF file containing flow time profile data

In [11]: ief.flowtimeprofiles
Out[11]: 
[<floodmodeller_api FlowTimeProfile(
 	labels=['SEV19005'],
 	columns=[19],
 	start_row=23,
 	csv_filepath=..\..\associated_data\Baseline unchecked.csv,
 	file_type=hplus,
 	profile=100 - 11 - 2020 Upper,
 	comment=
 )>,
 <floodmodeller_api FlowTimeProfile(
 	labels=['randomInflow'],
 	columns=[9],
 	start_row=23,
 	csv_filepath=..\..\associated_data\Baseline unchecked.csv,
 	file_type=hplus,
 	profile=100 - 11 - Reconciled Baseline,
 	comment=
 )>]

Each FlowTimeProfile can be used to access the various components that make up a flow time profile:

In [12]: profile = ief.flowtimeprofiles[0];  # Access the first flow time profile

In [13]: profile.labels
Out[13]: ['SEV19005']

In [14]: profile.csv_filepath
Out[14]: '..\\..\\associated_data\\Baseline unchecked.csv'

As with any other attribute these can all be modified and saved to the ief:

In [15]: profile.labels.append("new_lbl");  # Adding a new label to include to the first flowtimeprofile

In [16]: profile.columns.append(10);  # Adding the relevant additional column

In [17]: profile.csv_filepath = "../some_new_flow_data.csv";  # Changing the csv filepath

# Take a look at the resultant IEF
In [18]: print(ief._write())
[ISIS Event Header]
Title = 7082
Datafile = ..\..\networks\BridgeSpill1.dat
Results = Output\7082

[ISIS Event Details]
RunType = Unsteady
TimeZero = 0000hrs; 23/05/2024
Start = 0500hrs; 23/05/2024
Finish = 80
Timestep = 300
SaveInterval = 300
ICsFrom = 1
RefineBridgeSecProps = 0
SolveDHEqualsZeroAtStart = 1
RulesAtTimeZero = 1
RulesOnFirstIteration = 0
ResetTimesAfterPos = 1
UseFPSModularLimit = 1
OutputUnitSummary = 1
UseRemoteQ = 1
2DFLOW = 1

[Flow Time Profiles]
NoOfFlowTimeProfiles = 2
NoOfFlowTimeSeries = 3
FlowTimeProfile0 = SEV19005 new_lbl,19 10,23,../some_new_flow_data.csv,hplus,100 - 11 - 2020 Upper,
FlowTimeProfile1 = randomInflow,9,23,..\..\associated_data\Baseline unchecked.csv,hplus,100 - 11 - Reconciled Baseline,

We can also create new flow time profiles to add to an ief:

In [19]: from floodmodeller_api.ief import FlowTimeProfile;

In [20]: new_profile = FlowTimeProfile(
   ....:     labels=["label1", "label2"],
   ....:     columns=[5, 6],
   ....:     start_row=4,
   ....:     csv_filepath="fmfile.csv",
   ....:     file_type="fm2",
   ....:     profile="T=100",
   ....:     comment="MultiEvent&Nodes",
   ....:     ief_filepath="../projects",
   ....: );
   ....: 

In [21]: ief.flowtimeprofiles.append(new_profile);

In [22]: print(ief._write())
[ISIS Event Header]
Title = 7082
Datafile = ..\..\networks\BridgeSpill1.dat
Results = Output\7082

[ISIS Event Details]
RunType = Unsteady
TimeZero = 0000hrs; 23/05/2024
Start = 0500hrs; 23/05/2024
Finish = 80
Timestep = 300
SaveInterval = 300
ICsFrom = 1
RefineBridgeSecProps = 0
SolveDHEqualsZeroAtStart = 1
RulesAtTimeZero = 1
RulesOnFirstIteration = 0
ResetTimesAfterPos = 1
UseFPSModularLimit = 1
OutputUnitSummary = 1
UseRemoteQ = 1
2DFLOW = 1

[Flow Time Profiles]
NoOfFlowTimeProfiles = 3
NoOfFlowTimeSeries = 5
FlowTimeProfile0 = SEV19005 new_lbl,19 10,23,../some_new_flow_data.csv,hplus,100 - 11 - 2020 Upper,
FlowTimeProfile1 = randomInflow,9,23,..\..\associated_data\Baseline unchecked.csv,hplus,100 - 11 - Reconciled Baseline,
FlowTimeProfile2 = label1 label2,5 6,4,fmfile.csv,fm2,T=100,MultiEvent&Nodes

Reference#

class floodmodeller_api.IEF(ief_filepath: str | Path | None = None, from_json: bool = False)#

Reads and write Flood Modeller event file format ‘.ief’

Parameters:

ief_filepath (str, optional) – Full filepath to ief file. If not specified, a new IEF class will be created.. Defaults to None.

Raises:
  • TypeError – Raised if ief_filepath not pointing to valide IEF file

  • FileNotFoundError – Raised if ief_filepath points to a non-existent location

Output:

Initiates ‘IEF’ class object

update() None#

Updates the existing IEF based on any altered attributes

save(filepath: str | Path) None#

Saves the IEF to the given location, if pointing to an existing file it will be overwritten. Once saved, the IEF() class will continue working from the saved location, therefore any further calls to IEF.update() will update in the latest saved location rather than the original source IEF used to construct the class

Parameters:

filepath (string) – Full filepath to new location for ief file (including ‘.ief’ extension)

simulate(method: str = 'WAIT', raise_on_failure: bool = True, precision: str = 'DEFAULT', enginespath: str = '', range_function: ~typing.Callable = <function trange>, range_settings: dict | None = None) Popen | None#

Simulate the IEF file directly as a subprocess

Parameters:
  • method (str, optional) – {‘WAIT’} | ‘RETURN_PROCESS’ ‘WAIT’ - The function waits for the simulation to complete before continuing (This is default) ‘RETURN_PROCESS’ - The function sets the simulation running in background and immediately continues, whilst returning the process object. Defaults to ‘WAIT’.

  • raise_on_failure (bool, optional) – If True, an exception will be raised if the simulation fails to complete without errors. If set to False, then the script will continue to run even if the simulation fails. If ‘method’ is set to ‘RETURN_PROCESS’ then this argument is ignored. Defaults to True.

  • precision (str, optional) – {‘DEFAULT’} | ‘SINGLE’ | ‘DOUBLE’ Define which engine to use for simulation, if set to ‘DEFAULT’ it will use the precision specified in the IEF. Alternatively, this can be overwritten using ‘SINGLE’ or ‘DOUBLE’.

  • enginespath (str, optional) – {‘’} | ‘/absolute/path/to/engine/executables’ Define where the engine executables are located. This replaces the default location (usual installation folder) if set to anything other than ‘’.

Raises:

UserWarning – Raised if ief filepath not already specified

Returns:

If method == ‘RETURN_PROCESS’, the Popen() instance of the process is returned.

Return type:

subprocess.Popen()

get_results() ZZN#

If results for the simulation exist, this function returns them as a ZZN class object

Returns:

floodmodeller_api.ZZN class object

get_log()#

If log files for the simulation exist, this function returns them as a LF1 class object

Returns:

floodmodeller_api.LF1 class object

diff(other: IEF, force_print: bool = False) None#

Compares the IEF class against another IEF class to check whether they are equivalent, or if not, what the differences are. Two instances of an IEF class are deemed equivalent if all of their attributes are equal except for the filepath and raw data.

The result is printed to the console. If you need to access the returned data, use the method IEF._get_diff()

Parameters:
  • other (floodmodeller_api.IEF) – Other instance of an IEF class

  • force_print (bool) – Forces the API to print every difference found, rather than just the first 25 differences. Defaults to False.

to_json() str#

Converts the object instance into a JSON string representation.

Returns:

A JSON string representing the object instance.

Return type:

str

classmethod from_json(json_string: str)#

Creates an object instance from a JSON string.

Parameters:

json_string (str) – A JSON string representation of the object.

Returns:

An object instance of the class.

class floodmodeller_api.ief.FlowTimeProfile(raw_string: str | None = None, **kwargs)#

Handles defining and formatting flow time profiles in IEF files

Parameters:

raw_string (Optional[str]) – A raw CSV-formatted string to initialize the profile attributes.

Keyword Arguments:
  • labels (list[str]) – A list of string labels for the profile headers.

  • columns (list[int]) – A list of integers (1-indexed) for the column indices of the profile.

  • start_row (int) – The starting row index (1-indexed) for reading data from the CSV.

  • csv_filepath (str) – The file path to the CSV file containing flow data.

  • file_type (str) – The type of the file format, e.g. fm1, fm2, hplus, refh2.

  • profile (str) – A description or identifier for the profile.

  • comment (str) – An optional comment or note related to the profile.

  • ief_filepath (str) – The base directory path for resolving the CSV file.

Raises:

ValueError – If neither a raw_string nor keyword arguments are provided.

Examples#

Example 1 - Update all IEFs in a folder to point to a new DAT file

The following example shows how the IEF class could be used to iteratively update all IEF files in a folder to point to a new DAT file.

# Import modules
from glob import glob
from floodmodeller_api import IEF

# Point to folder of interest
folder = r'C:\FloodModeller_ExampleData\Examples\1D\Flow'

# Get list of IEF files using glob function
ief_files = glob(folder + '\*.ief')

for ief_path in ief_files:
    ief = IEF(ief_path) # Initiate IEF Class Object
    ief.datafile = r'..\NEW_RIVER_001.DAT' # Set 'Datafile' setting to new DAT file location
    ief.update() # Update the IEF file

Example 2 - Create new set of IEFs versions based on previous IEF files

The following example shows how the IEF class could be used to create a new set of IEF files with the title, results and filepath updated to ‘v2’

# Import modules
import od
from glob import glob
from floodmodeller_api import IEF

# Point to folder of interest
folder = r'C:\FloodModeller_ExampleData\Examples\1D\Flow'

# Get list of IEF files using glob function
ief_files = glob(folder + '\*.ief')

for ief_path in ief_files:
    ief_name = os.path.basename(ief_path) # get existing filename
    new_ief_name = ief_name.replace('.ief', '_v2.ief') # update filename with 'v2' appended
    new_ief_path = Path(folder, new_ief_name) # get updated filepath

    ief = IEF(ief_path) # Initiate IEF Class Object
    ief.title += '_v2' # Update title
    try:
        ief.results += '_v2' # If Results setting already exists, append v2
    except AttributeError:
        ief.results = 'v2' # If no results yet specified, set results to v2

    ief.save(new_ief_path) # Save updated IEF files to the new filepath

Example 3 - Simulate an IEF and read the results directly

The following example shows how the IEF class could be used to set a simulation going and then access the 1D results directly once it has completed.

# Import modules
from floodmodeller_api import IEF

ief_file = r'path\to\simualtion.ief'

# Instantiate IEF Class object
ief = IEF(ief_file)

# Simulate IEF (the default is for python to wait until simulation is complete)
ief.simulate()

# Access results directly into ZZN class object
zzn = ief.get_results()

# Get dataframe from results
my_results = zzn.to_dataframe()

Example 4 - Simulate an IEF and read the log directly

The following example shows how the IEF class could be used to set a simulation going and then access the log file directly once it has completed.

# Import modules
from floodmodeller_api import IEF

ief_file = r'path\to\simualtion.ief'

# Instantiate IEF Class object
ief = IEF(ief_file)

# Simulate IEF (the default is for python to wait until simulation is complete)
ief.simulate()

# Access results directly into LF1 class object
lf1 = ief.get_log()

# Get dataframe from log file
my_log = lf1.to_dataframe()