Plotting Water Surface Elevation from a 2D HEC-RAS Model using Python - Tutorial

This tutorial demonstrates how to accurately and efficiently extract the water surface elevation at a specific point from a HEC-RAS 2D unsteady flow model using Python in Jupyter Lab. Since water levels vary across the mesh and native software tools can limit automation, the author teaches how to open HDF5 output files (.hdf), load a point shapefile using GeoPandas, and apply a geospatial index K-d tree to locate the nearest computational cell. Finally, the time series data is processed to generate a water level hydrograph, which is essential for hydrogeological model calibration.


Tutorial


Code

#!pip install h5py geopandas
import h5py
import numpy as np
import pandas as pd
import geopandas as gpd
from scipy.spatial import KDTree
import matplotlib.pyplot as plt
hdfPath = '../HecUnsteady/theisNashUnsteady.p01.hdf'
AreaName = '2D Flow Area'
sw1Df = gpd.read_file('../Shp/SW1.shp')
sw1Coords = list(sw1Df.iloc[0].geometry.coords)[0]
sw1Coords
(697308.6910000006, 4345781.995000001)
hdf = h5py.File(hdfPath,'r')
cellCentroidsArray = np.asarray(hdf['Geometry']['2D Flow Areas']['Cell Points'])
cellCentroidsArray[:5]
array([[ 697293.70114532, 4345868.42012913],
       [ 697295.70114532, 4345868.42012913],
       [ 697289.70114532, 4345866.42012913],
       [ 697291.70114532, 4345866.42012913],
       [ 697293.70114532, 4345866.42012913]])
spatialIndex = KDTree(cellCentroidsArray)
timeBlocks = hdf['Results']['Unsteady']['Output']['Output Blocks']['Base Output']['Unsteady Time Series']['Time Date Stamp']
timeBlocksList = []
for timeBlock in timeBlocks:
    timeString = timeBlock.decode('utf-8').strip()
    timeDf = pd.to_datetime(timeString, format='%d%b%Y %H:%M:%S')
    timeBlocksList.append(timeDf)
timeBlocksList[:5]
[Timestamp('2023-01-15 00:00:00'),
 Timestamp('2023-01-15 04:00:00'),
 Timestamp('2023-01-15 08:00:00'),
 Timestamp('2023-01-15 12:00:00'),
 Timestamp('2023-01-15 16:00:00')]
surfaceDataset = hdf['Results']['Unsteady']['Output']['Output Blocks']['Base Output']['Unsteady Time Series']['2D Flow Areas']['Perimeter 1']['Water Surface']
surfaceDatasetArray = np.asarray(surfaceDataset)
surfaceDatasetArray[:2]
array([[149.05461, 149.05457, 149.05469, ..., 148.81921, 149.04991,
        148.80786],
       [149.561  , 149.56096, 149.56113, ..., 149.44379, 149.55418,
        149.4338 ]], shape=(2, 7908), dtype=float32)
surfaceDatasetArray.shape
(187, 7908)
distance, cellIndex = spatialIndex.query(sw1Coords)
print(distance)
1.077286895311947
print(cellIndex)
3978
#check position 
print(sw1Coords)
print(cellCentroidsArray[cellIndex])
(697308.6910000006, 4345781.995000001)
[ 697307.70114532 4345782.42012913]
#create modeled SW1 dataframe
sw1SimDf = pd.DataFrame()
sw1SimDf['Date'] = timeBlocksList
sw1SimDf['WSE'] = surfaceDatasetArray[:,cellIndex]
sw1SimDf = sw1SimDf.set_index(['Date'])
sw1SimDf.head()

WSE
Date
2023-01-15 00:00:00 149.053177
2023-01-15 04:00:00 149.558655
2023-01-15 08:00:00 149.503647
2023-01-15 12:00:00 149.476654
2023-01-15 16:00:00 149.445267
fig, ax = plt.subplots()
sw1SimDf.plot(ax=ax)
ax.legend()
ax.grid()
ax.set_xlim(sw1SimDf.index[0], sw1SimDf.index[-1])
(464928.0, 465672.0)

Input data

You can download the input data from this link:

owncloud.hatarilabs.com/s/LHpEe67q0kbYFCq

Password: Hatarilabs

Comment

Saul Montoya

Saul Montoya es Ingeniero Civil graduado de la Pontificia Universidad Católica del Perú en Lima con estudios de postgrado en Manejo e Ingeniería de Recursos Hídricos (Programa WAREM) de la Universidad de Stuttgart con mención en Ingeniería de Aguas Subterráneas y Hidroinformática.

 

Suscribe to our online newsletter

Subscribe for free newsletter, receive news, interesting facts and dates of our courses in water resources.