Tutorial 61: nx-Graph
This example demonstrates how to use the SIR_3S_to_nx_graph() of the SIR 3S Toolkit to generate a nx-Graph based on a SIR 3S model.
SIR 3S Installation
[1]:
SIR3S_SIRGRAF_DIR = r"C:\3S\SIR 3S\SirGraf-90-15-00-20x64_Quebec-Upd1" #change to local path
Imports
Note: The SIR 3S Toolkit requires the Sir3S_Toolkit.dll included in SIR 3S installations (version Quebec and higher).
[2]:
import sir3stoolkit
The core of sir3stoolkit is a Python wrapper around basic functionality of SIR 3S, offering a low-level access to the creation, modification and simulation of SIR 3S models. In the future pure python subpackages may be added.
[3]:
from sir3stoolkit.core import wrapper
[4]:
from sir3stoolkit.mantle.alternative_models import SIR3S_Model_Alternative_Models
[5]:
sir3stoolkit
[5]:
<module 'sir3stoolkit' from 'C:\\Users\\aUsername\\3S\\sir3stoolkit\\src\\sir3stoolkit\\__init__.py'>
The wrapper package has to be initialized with reference to a SIR 3S (SirGraf) installation.
[6]:
wrapper.Initialize_Toolkit(SIR3S_SIRGRAF_DIR)
Additional imports
[7]:
import os
import pandas as pd
import networkx as nx
import matplotlib.pyplot as plt
import logging
Initialization
[8]:
s3s = SIR3S_Model_Alternative_Models()
Initialization complete
Open Model
[9]:
dbFilePath=r"C:\Users\aUsername\3S\PT3S\PT3S\Examples\Example5.db3"
[10]:
s3s.OpenModel(dbName=dbFilePath,
providerType=s3s.ProviderTypes.SQLite,
Mid="M-1-0-1",
saveCurrentlyOpenModel=False,
namedInstance="",
userID="",
password="")
Model is open for further operation
Generate nx Graph
We can use the SIR_3S_to_nx_graph() method to create a nx graph representing a SIR 3S model.
[11]:
logging.disable(logging.INFO)
[12]:
G=s3s.SIR_3S_to_nx_graph()
[2025-12-05 16:03:05,771] WARNING in sir3stoolkit.mantle.dataframes: [metadata] Spatial Reference Identifier (SRID) not defined in model. DataFrame cannot be transformed to GeoDataFrame but geometry column can be created independently of SRID. Returning regular DataFrame with a geometry column.
[2025-12-05 16:03:06,289] WARNING in sir3stoolkit.mantle.dataframes: [metadata] Spatial Reference Identifier (SRID) not defined in model. DataFrame cannot be transformed to GeoDataFrame but geometry column can be created independently of SRID. Returning regular DataFrame with a geometry column.
[2025-12-05 16:03:06,613] WARNING in sir3stoolkit.mantle.dataframes: [metadata] Spatial Reference Identifier (SRID) not defined in model. DataFrame cannot be transformed to GeoDataFrame but geometry column can be created independently of SRID. Returning regular DataFrame with a geometry column.
[2025-12-05 16:03:06,621] WARNING in sir3stoolkit.mantle.dataframes: [metadata] Spatial Reference Identifier (SRID) not defined in model. DataFrame cannot be transformed to GeoDataFrame but geometry column can be created independently of SRID. Returning regular DataFrame with a geometry column.
[2025-12-05 16:03:06,637] WARNING in sir3stoolkit.mantle.dataframes: [metadata] Spatial Reference Identifier (SRID) not defined in model. DataFrame cannot be transformed to GeoDataFrame but geometry column can be created independently of SRID. Returning regular DataFrame with a geometry column.
[2025-12-05 16:03:06,761] WARNING in sir3stoolkit.mantle.dataframes: [metadata] Spatial Reference Identifier (SRID) not defined in model. DataFrame cannot be transformed to GeoDataFrame but geometry column can be created independently of SRID. Returning regular DataFrame with a geometry column.
[2025-12-05 16:03:06,871] WARNING in sir3stoolkit.mantle.dataframes: [metadata] Spatial Reference Identifier (SRID) not defined in model. DataFrame cannot be transformed to GeoDataFrame but geometry column can be created independently of SRID. Returning regular DataFrame with a geometry column.
[2025-12-05 16:03:06,886] WARNING in sir3stoolkit.mantle.dataframes: [metadata] Spatial Reference Identifier (SRID) not defined in model. DataFrame cannot be transformed to GeoDataFrame but geometry column can be created independently of SRID. Returning regular DataFrame with a geometry column.
[13]:
logging.disable(logging.NOTSET)
View generated Graph
As you can see below the graph does not contain any additional properties or result values.
[14]:
node_attrs = {n: data for n, data in G.nodes(data=True)}
[15]:
node_attrs['4680103632661687203']
[15]:
{'tk': '4680103632661687203',
'Fkcont': '5478326535335532120',
'geometry': <POINT (55176.324 98780.495)>}
[16]:
edge_attrs = {(u, v): data for u, v, data in G.edges(data=True)}
[17]:
edge_attrs['4680103632661687203', '5432609004919372061']
[17]:
{'tk': '5460759352148475007',
'Fkcont': '5478326535335532120',
'geometry': <LINESTRING (55176.324 98780.495, 55231.478 98824.335)>,
'fkKI': '4680103632661687203',
'fkKK': '5432609004919372061',
'element type': 'Pipe'}
[18]:
nx.is_weakly_connected(G) # Is connected as an undirected graph
[18]:
True
[19]:
def plot_nx_graph(G, main_container):
# Extract node positions from geometry and filter by Fkcont
pos = {
node_id: (data['geometry'].x, data['geometry'].y)
for node_id, data in G.nodes(data=True)
if 'geometry' in data and hasattr(data['geometry'], 'x') and hasattr(data['geometry'], 'y')
and data.get('Fkcont') == main_container
}
# Extract edges with valid geometry and both nodes in pos
edges = [
(u, v, data) for u, v, data in G.edges(data=True)
if u in pos and v in pos and 'geometry' in data and data['geometry'].geom_type != 'Point'
]
# Plot
plt.figure(figsize=(20, 14))
for _, _, data in edges:
geom = data['geometry']
x, y = geom.xy
plt.plot(x, y, color='black', linewidth=1)
# Only draw nodes that have positions
nx.draw_networkx_nodes(G, pos=pos, nodelist=list(pos.keys()), node_color='black', node_size=10)
plt.title(f"nx-Graph'{main_container}'")
plt.axis('equal')
plt.show()
[20]:
plot_nx_graph(G, s3s.GetMainContainer()[0])
Add properities to graph
Now, we can metadata properties and result properties to the nodes and edges.
[21]:
props_to_add = ["Kvr", "T", "BCIND"]
G = s3s.add_properties_to_graph(
G=G,
element_type="Node",
properties=props_to_add,
)
[2025-12-05 16:03:08,673] INFO in sir3stoolkit.mantle.alternative_models: [graph] Enriching graph with properties for element_type='Node'
[2025-12-05 16:03:08,675] INFO in sir3stoolkit.mantle.alternative_models: [graph] Using 1 metadata props and 2 result props.
[2025-12-05 16:03:08,680] INFO in sir3stoolkit.mantle.dataframes: [metadata] Generating metadata dataframe for element type: ObjectTypes.Node
[2025-12-05 16:03:08,681] INFO in sir3stoolkit.mantle.dataframes: [metadata] Retrieved 1559 element(s) of element type ObjectTypes.Node.
[2025-12-05 16:03:08,684] INFO in sir3stoolkit.mantle.dataframes: [Resolving tks] Retrieved 1559 element(s) of element type ObjectTypes.Node.
[2025-12-05 16:03:08,686] INFO in sir3stoolkit.mantle.dataframes: [Resolving Metadata Properties] Using 1 metadata properties.
[2025-12-05 16:03:08,687] INFO in sir3stoolkit.mantle.dataframes: [metadata] Retrieving metadata properties ['Kvr']...
[2025-12-05 16:03:08,790] INFO in sir3stoolkit.mantle.dataframes: [metadata] Done. Shape: (1559, 2)
[2025-12-05 16:03:09,029] INFO in sir3stoolkit.mantle.dataframes: [results] Generating results dataframe for element type: ObjectTypes.Node
[2025-12-05 16:03:09,281] INFO in sir3stoolkit.mantle.dataframes: [Resolving Timestamps] Only static timestamp 2025-09-24 00:00:00.000 +02:00 is used
[2025-12-05 16:03:09,284] INFO in sir3stoolkit.mantle.dataframes: [Resolving Timestamps] 1 valid timestamp(s) will be used.
[2025-12-05 16:03:09,286] INFO in sir3stoolkit.mantle.dataframes: [Resolving tks] Retrieved 1559 element(s) of element type ObjectTypes.Node.
[2025-12-05 16:03:09,288] INFO in sir3stoolkit.mantle.dataframes: [results] Using 2 result properties.
[2025-12-05 16:03:09,341] INFO in sir3stoolkit.mantle.dataframes: [results] Retrieving result properties...
[2025-12-05 16:03:09,919] INFO in sir3stoolkit.mantle.dataframes: [results] Done. Shape: (1, 3118)
[2025-12-05 16:03:09,935] DEBUG in sir3stoolkit.mantle.alternative_models: Index(['tk', 'Kvr', 'BCIND', 'T'], dtype='object')
[2025-12-05 16:03:09,945] INFO in sir3stoolkit.mantle.alternative_models: [graph] Enrichment summary for element_type='Node': nodes_updated=1559; edges_updated=0; cols_added=['Kvr', 'T', 'BCIND']
[22]:
node_attrs = {n: data for n, data in G.nodes(data=True)}
[23]:
node_attrs['4680103632661687203']
[23]:
{'tk': '4680103632661687203',
'Fkcont': '5478326535335532120',
'geometry': <POINT (55176.324 98780.495)>,
'Kvr': '1',
'T': 125.03,
'BCIND': 17.0}
[24]:
props_to_add = ["DN", "L", "JV", "PHR"]
G = s3s.add_properties_to_graph(
G=G,
element_type="Pipe",
properties=props_to_add,
)
[2025-12-05 16:03:09,994] INFO in sir3stoolkit.mantle.alternative_models: [graph] Enriching graph with properties for element_type='Pipe'
[2025-12-05 16:03:09,996] INFO in sir3stoolkit.mantle.alternative_models: [graph] Using 2 metadata props and 2 result props.
[2025-12-05 16:03:10,000] INFO in sir3stoolkit.mantle.dataframes: [metadata] Generating metadata dataframe for element type: ObjectTypes.Pipe
[2025-12-05 16:03:10,005] INFO in sir3stoolkit.mantle.dataframes: [metadata] Retrieved 1672 element(s) of element type ObjectTypes.Pipe.
[2025-12-05 16:03:10,007] INFO in sir3stoolkit.mantle.dataframes: [Resolving tks] Retrieved 1672 element(s) of element type ObjectTypes.Pipe.
[2025-12-05 16:03:10,011] INFO in sir3stoolkit.mantle.dataframes: [Resolving Metadata Properties] Using 2 metadata properties.
[2025-12-05 16:03:10,011] INFO in sir3stoolkit.mantle.dataframes: [metadata] Retrieving metadata properties ['DN', 'L']...
[2025-12-05 16:03:10,215] INFO in sir3stoolkit.mantle.dataframes: [metadata] Done. Shape: (1672, 3)
[2025-12-05 16:03:10,428] INFO in sir3stoolkit.mantle.dataframes: [results] Generating results dataframe for element type: ObjectTypes.Pipe
[2025-12-05 16:03:10,696] INFO in sir3stoolkit.mantle.dataframes: [Resolving Timestamps] Only static timestamp 2025-09-24 00:00:00.000 +02:00 is used
[2025-12-05 16:03:10,696] INFO in sir3stoolkit.mantle.dataframes: [Resolving Timestamps] 1 valid timestamp(s) will be used.
[2025-12-05 16:03:10,704] INFO in sir3stoolkit.mantle.dataframes: [Resolving tks] Retrieved 1672 element(s) of element type ObjectTypes.Pipe.
[2025-12-05 16:03:10,706] INFO in sir3stoolkit.mantle.dataframes: [results] Using 2 result properties.
[2025-12-05 16:03:10,757] INFO in sir3stoolkit.mantle.dataframes: [results] Retrieving result properties...
[2025-12-05 16:03:11,535] INFO in sir3stoolkit.mantle.dataframes: [results] Done. Shape: (1, 3344)
[2025-12-05 16:03:11,538] DEBUG in sir3stoolkit.mantle.alternative_models: Index(['tk', 'DN', 'L', 'JV', 'PHR'], dtype='object')
[2025-12-05 16:03:11,552] INFO in sir3stoolkit.mantle.alternative_models: [graph] Enrichment summary for element_type='Pipe': nodes_updated=0; edges_updated=1672; cols_added=['DN', 'L', 'JV', 'PHR']
[25]:
edge_attrs = {(u, v): data for u, v, data in G.edges(data=True)}
[26]:
edge_attrs['4680103632661687203', '5432609004919372061']
[26]:
{'tk': '5460759352148475007',
'Fkcont': '5478326535335532120',
'geometry': <LINESTRING (55176.324 98780.495, 55231.478 98824.335)>,
'fkKI': '4680103632661687203',
'fkKK': '5432609004919372061',
'element type': 'Pipe',
'DN': '125',
'L': '75',
'JV': 0.04940455,
'PHR': 0.003705341}