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()