Xns11

Xns11 is the main interface for accessing cross section data.

Opening files

from mikeio1d import Xns11
xns = Xns11('../data/mikep_cs_demo.xns11')
xns
<mikeio1d.Xns11>

Cross section collections

Each Xns11 object contains a collection of cross sections via the xsections attribute.

xns.xsections
<CrossSectionCollection 103>

Overview

An overview of a cross section collection can be obtained by calling the ‘to_dataframe’ method.

xns.xsections.to_dataframe()
cross_section
location_id chainage topo_id
basin_left1 2.004 1 <CrossSection: basin_left1, 2.004, 1>
33.774 1 <CrossSection: basin_left1, 33.774, 1>
80.945 1 <CrossSection: basin_left1, 80.945, 1>
122.042 1 <CrossSection: basin_left1, 122.042, 1>
166.107 1 <CrossSection: basin_left1, 166.107, 1>
... ... ... ...
tributary 250.000 tributary <CrossSection: tributary, 250.000, tributary>
300.000 tributary <CrossSection: tributary, 300.000, tributary>
400.000 tributary <CrossSection: tributary, 400.000, tributary>
450.000 tributary <CrossSection: tributary, 450.000, tributary>
500.000 tributary <CrossSection: tributary, 500.000, tributary>

103 rows × 1 columns

Indexing

Cross section collections are dict-like and can be indexed by a tuple of location ID, chainage, and topo ID.

xns.xsections['basin_left1', '122.042', '1']
<CrossSection: basin_left1, 122.042, 1>

Alternatively, the location ID, chainage, and topo ID can be explicitly expressed with the sel method.

xns.xsections.sel(location_id='basin_left1', chainage='122.042', topo_id='1')
<CrossSection: basin_left1, 122.042, 1>

Slicing

Cross section collections can be sliced by location ID, chainage, or topo ID.

xns.xsections['basin_left1'] # all cross sections at location 'basin_left1'
<CrossSectionCollection 12>
xns.xsections[:, '122.042'] # all cross sections at chainage '122.042'
<CrossSectionCollection 1>
xns.xsections[:,:,'1'] # all cross sections with topo ID '1'
<CrossSectionCollection 44>

Combining

Cross section collections can be combined into a new collection.

new_collection = xns.xsections['basin_left1', '2.004'] | xns.xsections['basin_left1', '210.212']
new_collection.to_dataframe()
cross_section
location_id chainage topo_id
basin_left1 2.004 1 <CrossSection: basin_left1, 2.004, 1>
210.212 1 <CrossSection: basin_left1, 210.212, 1>

Adding a cross section

A new cross section can be added to a collection with the add_xsection method.

xs_to_add = xns.xsections.sel(location_id='basin_left1', chainage='33.774', topo_id='1')
new_collection.add_xsection(xs_to_add)
new_collection.to_dataframe()
cross_section
location_id chainage topo_id
basin_left1 2.004 1 <CrossSection: basin_left1, 2.004, 1>
210.212 1 <CrossSection: basin_left1, 210.212, 1>
33.774 1 <CrossSection: basin_left1, 33.774, 1>

Cross sections

A cross section is uniquely identified by its location ID, chainage, and topo ID.

xs = xns.xsections['basin_left1', '122.042', '1']
xs
<CrossSection: basin_left1, 122.042, 1>

Plotting

Cross sections can be plotted directly with the plot method.

xs.plot()

Raw data

The raw data of a cross section can be accessed via the raw attribute.

df = xs.raw
df.head()
markers marker_labels x z resistance
0 0.000 59.508 25.0
1 2.062 59.624 25.0
2 1 Left Levee Bank (1) 4.124 59.754 25.0
3 6.186 59.607 25.0
4 14.435 58.882 25.0

Raw data is modifiable by setting the ‘raw’ attribute with a new DataFrame of the same column names.

df_modified = xs.raw
df_modified['z'] = df_modified['z'] + 1000
xs.raw = df_modified
xs.plot()

Markers

Markers can be viewed with the markers attribute.

xs.markers
marker marker_label x z
0 1 Left Levee Bank (1) 4.124 1059.754
1 2 Lowest Point (2) 72.914 1052.803
2 3 Right Levee Bank (3) 195.897 1057.989

Set and unset markers with the set_marker and unset_marker methods. Alternatively, reassign a modified marker DataFrame like is done for raw data.

xs.set_marker(42, 50) # set a user-defined marker '42' at the closest point to x=50
xs.plot()

xs.unset_marker(42) # unset the user-defined marker '42'
xs.plot()

Processed data

Processed data is accessible via the processed attribute.

df = xs.processed
df.head()
level flow_area radius storage_width additional_storage_area resistance conveyance_factor
0 1052.803000 0.000000 0.000000 0.000000 0.0 25.0 0.000000
1 1052.944857 0.160191 0.075849 2.743476 0.0 25.0 0.717592
2 1053.086714 0.790062 0.165260 6.136873 0.0 25.0 5.948131
3 1053.228571 3.633195 0.171565 29.866016 0.0 25.0 28.044487
4 1053.370429 9.264321 0.249458 50.128968 0.0 25.0 91.780854

Processed data is modifiable by setting the ‘processed’ attribute with a new DataFrame of the same column names.

df_modified = xs.processed
df_modified['level'] = df_modified['level'] -500
xs.processed = df_modified
xs.processed.head()
level flow_area radius storage_width additional_storage_area resistance conveyance_factor
0 552.803000 0.000000 0.000000 0.000000 0.0 25.0 0.000000
1 552.944857 0.160191 0.075849 2.743476 0.0 25.0 0.717592
2 553.086714 0.790062 0.165260 6.136873 0.0 25.0 5.948131
3 553.228571 3.633195 0.171565 29.866016 0.0 25.0 28.044487
4 553.370429 9.264321 0.249458 50.128968 0.0 25.0 91.780854

To recalculate processed datd based on the raw data, call the recompute_processed method.

xs.processed_allow_recompute = True
xs.recompute_processed()
xs.processed.head()
level flow_area radius storage_width additional_storage_area resistance conveyance_factor
0 1052.803000 0.000000 0.000000 0.000000 0.0 25.0 0.000000
1 1052.944857 0.160191 0.075849 2.743476 0.0 25.0 0.717592
2 1053.086714 0.790062 0.165260 6.136873 0.0 25.0 5.948131
3 1053.228571 3.633195 0.171565 29.866016 0.0 25.0 28.044487
4 1053.370429 9.264321 0.249458 50.128968 0.0 25.0 91.780854

GeoDataFrames

Cross section collections can be extracted into a GeoDataFrame.

gdf = xns.xsections.to_geopandas()
gdf.head()
location_id chainage topo_id geometry
0 basin_left1 2.004 1 LINESTRING (385926.349 5715923.327, 385967.914...
1 basin_left1 33.774 1 LINESTRING (385918.718 5715879.808, 386007.086...
2 basin_left1 80.945 1 LINESTRING (385947.01 5715843.133, 386074.498 ...
3 basin_left1 122.042 1 LINESTRING (385970.062 5715808.903, 386134.575...
4 basin_left1 166.107 1 LINESTRING (385997.773 5715775.281, 386176.257...
gdf.plot(column='location_id', cmap='tab20', legend=True)

It is also possible to extract cross section markers as GeoDataFrames.

gdf = xns.xsections.to_geopandas_markers()
gdf.head()
location_id chainage topo_id marker marker_label geometry
0 basin_left1 2.004 1 1 Left Levee Bank (1) POINT (385926.349 5715923.327)
1 basin_left1 2.004 1 2 Lowest Point (2) POINT (385955.309 5715945.473)
2 basin_left1 2.004 1 3 Right Levee Bank (3) POINT (385967.914 5715955.112)
3 basin_left1 33.774 1 1 Left Levee Bank (1) POINT (385924.812 5715884.216)
4 basin_left1 33.774 1 2 Lowest Point (2) POINT (385973.567 5715919.482)
ax = xns.xsections.to_geopandas().plot()
xns.xsections.to_geopandas_markers().plot(ax=ax, column='marker', markersize=9, legend=True)

Examples

Tip

There are also several notebook examples available on our GitHub repositoryhttps://github.com/DHI/mikeio1d/tree/main/notebooks.