Custom names for links, nodes, subareas¶
This is a sample notebook demonstrating how to use the ShapefileToSwiftConverter
class from the geosdhydro
package to convert a shapefile with custom names for links, nodes, and subareas into a JSON format compatible with the swift2
hydrological modeling framework.
In [1]:
Copied!
from pathlib import Path
import geopandas as gpd
from shapely.geometry import LineString
from geosdhydro import ShapefileToSwiftConverter
from pathlib import Path
import geopandas as gpd
from shapely.geometry import LineString
from geosdhydro import ShapefileToSwiftConverter
Create synthetic test data¶
Side note that even if string columns for IDS are preferable, the converter will convert them to string if they are not, as will be the case for ToNodeID below.
We use the default column names for the required fields:
In [2]:
Copied!
data = {
"LinkID": ["1", "2", "3", "4", "5"], # As strings
"FromNodeID": ["2", "3", "4", "5", "6"], # As strings
"ToNodeID": [1, 2, 2, 2, 5],
"SPathLen": [1000.0, 1500.0, 2000.0, 800.0, 1200.0],
"DArea2": [3000000.0, 4000000.0, 2500000.0, -1.0, 3500000.0], # Link 4 has negative area
"geometry": [
LineString([(2.1, 2.2), (1.1, 1.2)]), # Link 1: node 2 -> node 1
LineString([(3.1, 3.2), (2.1, 2.2)]), # Link 2: node 3 -> node 2
LineString([(4.1, 4.2), (2.1, 2.2)]), # Link 3: node 4 -> node 2
LineString([(5.1, 5.2), (2.1, 2.2)]), # Link 4: node 5 -> node 2
LineString([(6.1, 6.2), (5.1, 5.2)]), # Link 5: node 6 -> node 5
],
}
data = {
"LinkID": ["1", "2", "3", "4", "5"], # As strings
"FromNodeID": ["2", "3", "4", "5", "6"], # As strings
"ToNodeID": [1, 2, 2, 2, 5],
"SPathLen": [1000.0, 1500.0, 2000.0, 800.0, 1200.0],
"DArea2": [3000000.0, 4000000.0, 2500000.0, -1.0, 3500000.0], # Link 4 has negative area
"geometry": [
LineString([(2.1, 2.2), (1.1, 1.2)]), # Link 1: node 2 -> node 1
LineString([(3.1, 3.2), (2.1, 2.2)]), # Link 2: node 3 -> node 2
LineString([(4.1, 4.2), (2.1, 2.2)]), # Link 3: node 4 -> node 2
LineString([(5.1, 5.2), (2.1, 2.2)]), # Link 4: node 5 -> node 2
LineString([(6.1, 6.2), (5.1, 5.2)]), # Link 5: node 6 -> node 5
],
}
That was the minimally required columns. We can add a few more to illustrate custom names:
In [3]:
Copied!
custom_linkname_fieldname = "LinkName"
data[custom_linkname_fieldname] = [f"CustomLinkName_{i}" for i in range(5)]
# Custom names for subareas
custom_subarea_name_fieldname = "SubAreaName"
data[custom_subarea_name_fieldname] = [f"CustomSubAreaName_{i}" for i in range(5)]
gdf = gpd.GeoDataFrame(data)
gdf
custom_linkname_fieldname = "LinkName"
data[custom_linkname_fieldname] = [f"CustomLinkName_{i}" for i in range(5)]
# Custom names for subareas
custom_subarea_name_fieldname = "SubAreaName"
data[custom_subarea_name_fieldname] = [f"CustomSubAreaName_{i}" for i in range(5)]
gdf = gpd.GeoDataFrame(data)
gdf
Out[3]:
LinkID | FromNodeID | ToNodeID | SPathLen | DArea2 | geometry | LinkName | SubAreaName | |
---|---|---|---|---|---|---|---|---|
0 | 1 | 2 | 1 | 1000.0 | 3000000.0 | LINESTRING (2.1 2.2, 1.1 1.2) | CustomLinkName_0 | CustomSubAreaName_0 |
1 | 2 | 3 | 2 | 1500.0 | 4000000.0 | LINESTRING (3.1 3.2, 2.1 2.2) | CustomLinkName_1 | CustomSubAreaName_1 |
2 | 3 | 4 | 2 | 2000.0 | 2500000.0 | LINESTRING (4.1 4.2, 2.1 2.2) | CustomLinkName_2 | CustomSubAreaName_2 |
3 | 4 | 5 | 2 | 800.0 | -1.0 | LINESTRING (5.1 5.2, 2.1 2.2) | CustomLinkName_3 | CustomSubAreaName_3 |
4 | 5 | 6 | 5 | 1200.0 | 3500000.0 | LINESTRING (6.1 6.2, 5.1 5.2) | CustomLinkName_4 | CustomSubAreaName_4 |
In [4]:
Copied!
# Custom node names
custom_nodenames = {str(i): f"CustomNodeName_{i}" for i in range(1, 7)}
# Custom node names
custom_nodenames = {str(i): f"CustomNodeName_{i}" for i in range(1, 7)}
In [5]:
Copied!
converter = ShapefileToSwiftConverter(
gdf,
linkname_field=custom_linkname_fieldname,
subarea_name_field=custom_subarea_name_fieldname,
node_names=custom_nodenames,
)
result = converter.convert()
converter = ShapefileToSwiftConverter(
gdf,
linkname_field=custom_linkname_fieldname,
subarea_name_field=custom_subarea_name_fieldname,
node_names=custom_nodenames,
)
result = converter.convert()
In [6]:
Copied!
result.keys()
result.keys()
Out[6]:
dict_keys(['Links', 'Nodes', 'SubAreas'])
In [7]:
Copied!
result["Nodes"][0]
result["Nodes"][0]
Out[7]:
{'ErrorCorrection': {'ErrorCorrectionType': 'NoErrorCorrection'}, 'ID': '1', 'Name': 'CustomNodeName_1', 'Reservoir': {'ReservoirType': 'NoReservoir'}}
In [8]:
Copied!
result["Links"][0]
result["Links"][0]
Out[8]:
{'ChannelRouting': {'ChannelRoutingType': 'NoRouting'}, 'DownstreamNodeID': '1', 'ID': '1', 'Length': 1000.0, 'ManningsN': 1.0, 'Name': 'CustomLinkName_0', 'Slope': 1.0, 'UpstreamNodeID': '2', 'f': 1.0}
We check that one of the subarea is not present (area negative), even if a mapped name was specified:
In [9]:
Copied!
[s['Name'] for s in result["SubAreas"]]
[s['Name'] for s in result["SubAreas"]]
Out[9]:
['CustomSubAreaName_0', 'CustomSubAreaName_1', 'CustomSubAreaName_2', 'CustomSubAreaName_4']
In [ ]:
Copied!