Latest release 1.0.11 now available on PyPi and Conda-forge

[[ visible ? '▲ HIDE' : '▼ SHOW BANNER' ]]

|||

tfv 1.0.11 documentation

Quick search

  • API Reference
  • Examples Gallery
    • Tutorial 1. TUFLOW FV Post-Processing Using Xarray
    • Tutorial 2. Introductory Matplotlib Plot Composition
    • Tutorial 3: Working With Gridded Boundary Condition Data
    • Tutorial 4. Introduction to the Particle Tracking Module Tools
    • Gallery 1: Timeseries Plots
    • Gallery 2: Profile Plots
    • Gallery 3: Sheet Plots
    • Gallery 4: Curtain Plots
    • Gallery 5: Combined Plots
    • Gallery 6: Particle Tracking Plots
    • Gallery 7: Miscellaneous

Gallery 3: Sheet Plots¶

This page provides examples on:

  • 2D and 3D plotting in plan view

  • Extracting and plotting maximum statistics

  • Plotting the difference between existing and developed conditions

  • Exporting of ASCII Arc Grids

  • Saving plots to disk

This notebook is used in combination with the TUFLOW FV Python Toolbox (tfv) package.

import numpy as np
import xarray as xr  # We utilise xarray to do all the heavy lifting 
import tfv.xarray
from pathlib import Path # We'll also make use of the `pathlib` module to assist with managing file-paths, although this is entirely optional! 
import matplotlib.pyplot as plt

Open TUFLOW FV Model Result¶

model_folder = Path('../../data')
model_file = 'HYD_002.nc'

fv = xr.open_dataset(model_folder / model_file, decode_times=False).tfv
# fv  # Uncomment this if you want to review the contents of the Dataframe

Single Sheet Plot¶

Quick plot - first time step of first variable

fv.plot()
<tfv.visual.SheetPatch at 0x28f1eef63c0>
Ignoring fixed x limits to fulfill fixed data aspect with adjustable data limits.
../../../_images/3b37fc177ca3b468a53310a6dc50d700ce7c9d972f6a1dcf17b4175b87ddb8a3.png

We can also plot any specific time in the model

ts = '2011-05-02 00:00'
fv.plot('H', ts)
<tfv.visual.SheetPatch at 0x28f2092ac10>
Ignoring fixed x limits to fulfill fixed data aspect with adjustable data limits.
../../../_images/905cce0c88382193e33b4b020d38fb5f7ade2ef8c7f987ca6a60e1f728a4d591.png

Sheet Plot With Vectors and Save to Disk¶

# Plot a variable at a particular time with vectors
ts = '2011-05-02 00:00'

# Add figure and axes
fig, ax = plt.subplots()

# Common settings
ax.set_aspect('equal')

fv.plot('H',ts, ax=ax)
fv.plot_vector('V', ts, ax=ax, color='k')   # We can plot a vector overlay using the `plot_vector` method here. This plot uses depth averaged vectors however you can use the datum and limits variable to change this.

# Save to disk
output_folder = Path('./outputs')
output_folder.mkdir(exist_ok=True) # Make the folder, if it doesn't exist

plt.savefig(output_folder / 'Example_Sheet.jpg', dpi=300)
../../../_images/bf25bdd0080679452c7a74363366543a475204a6b48828d46e0f2b59a55414fd.png

Sheet Plot at Different Depths¶

ts = '2011-05-02 00:00'
fig, axes = plt.subplots(ncols=3, figsize=(12, 6), constrained_layout=True)

sal_spec = dict(cmap='ocean', clim=(0, 36), shading='interp', colorbar=False)

ax = axes[0]
p1 = fv.plot('SAL', ts, ax=ax,  datum='depth', limits=(0,1), **sal_spec)  # By setting datum to depth, this is now the "surface 1m")
ax.set_title('Surface 1m')

ax = axes[1]
p2 = fv.plot('SAL', ts, ax=ax, datum='sigma', limits=(0,0.2), **sal_spec)
ax.set_title('Bottom 20% of Water Column')

ax = axes[2]
p3 = fv.plot('SAL', ts, ax=ax, **sal_spec)
plt.colorbar(p3.patch, ax=ax, orientation='vertical',label='Salinity (PSU)')
ax.set_title('Depth Averaged')

fig.suptitle('Example TUFLOW FV Stratified Result', fontweight='bold', x=0.55)
titles = {0: 'Velocity', 1: 'Salinity', 2: 'Temperature'}
../../../_images/f9a847df55a3ae7d78047da7b202c47edd929ba263f834e4bd7eb24e981597d4.png

Save Sheet To ASCII Arc Grid¶

ts = '2011-05-02 00:00'
cell_size =  5*10**-5
data = fv.xtr.get_sheet_cell('V', ts, datum='depth', limits=(0,1))

# Output the ASCII to disk
output_folder = Path('./outputs')
output_folder.mkdir(exist_ok=True) # Make the folder, if it doesn't exist

fv.xtr.write_data_to_ascii(output_folder / 'Surface_V_2011-05-02.asc', data, cell_size)

Extract Grid From Sheet And Output To GeoTiff¶

This example shows how to write a sheet to a custom grid resolution and extent using the get_sheet_grid method. A raster is then output to geotiff using the rioxarray package.

The get_sheet_method can be used to convert your TUFLOW FV mesh results to a regular grid. This may be useful if you need to compare TUFLOW FV results from different computational meshes, or if you need to compare a TUFLOW FV result with a data raster. For example, a DEM of surveyed bathmetry verses TUFLOW FV bed elevation outputs.

RioXarray is a wrapper around the rasterio package that allows for easy rasterio integration with xarray. It is a very powerful package that allows for the easy export of xarray data to a variety of formats.

Caution: The example below is based on a spherical model that uses latitude and longitude, thus the dx/dy parameters are very small representing degrees. If your model is in meters they should be changed to something more appropriate (e.g., 20m dx=20, dy=20, 200m dx=200,dy=200 and so on).

import rioxarray

# Define bounding box [xmin, ymin, xmax, ymax]
bbox = [159.08597, -31.39684, 159.09753, -31.3877]

# Extract the TUFLOW FV results to a regular grid. This example extracts a single timestep, however the default it for all timesteps. 
grd = fv.get_sheet_grid(time='2011-05-02 00:00',dx=0.00005, dy=0.00005, bbox=bbox)

# Ouptut salinity to geotiff
output_folder = Path('./outputs')
output_folder.mkdir(exist_ok=True) # Make the folder, if it doesn't exist

grd['SAL'].rio.to_raster(output_folder / 'raster_geotiff.tif')

Multiple Sheet Plots¶

%matplotlib inline
# With datum='depth', this is the surface 1m. 
# Experiment with datum='height' to see how the results change. 
datum = 'depth'
limits = (0,1)

fig, axes = plt.subplots(ncols=3, figsize=(12, 6), constrained_layout=True)

ts = '2011-05-02 00:00'

ax = axes[0]
p1 = fv.plot('V', ts, ax=ax,  shading='interp', cmap='turbo', clim=(0, 0.25), datum=datum, limits=limits, colorbar=False)  # By setting datum to depth, this is now the "surface 1m")
v1 = fv.plot_vector('V', ts, ax=ax, color='k')   # We can plot a vector overlay using the `plot_vector` method here
ax.set_title('Velocity')
plt.colorbar(p1.patch, ax=ax, orientation='horizontal', label='Speed (m/s)')

ax = axes[1]
p2 = fv.plot('SAL', ts, ax=ax,  shading='interp', cmap='ocean', clim=(0, 36), datum=datum, limits=limits, colorbar=False)
ax.set_title('Salinity')
plt.colorbar(p2.patch, ax=ax, orientation='horizontal', label='Salinity (PSU)')

ax = axes[2]
p3 = fv.plot('TEMP', ts, ax=ax, shading='interp', cmap='plasma', clim=(5, 25), datum=datum, limits=limits, colorbar=False)
ax.set_title('Temperature')
plt.colorbar(p3.patch, ax=ax, orientation='horizontal', label='Temp (°C)')

plt.show()
../../../_images/ebe3e40460ec0be488febb92ed2f937f8ed7b84ecd7fad01535e662969cd46bc.png

Impact Sheet Multiple Models¶

# Open second set of results. This model has a 40 degree celcius thermal discharge in the surface 1m. 
model_file = 'HYD_002'
model_file_therm = 'HYD_002_Thermal_Discharge.nc'  

# Open file
fv_therm = xr.open_dataset(model_folder / model_file_therm, decode_times=False).tfv

# Subtracting based on the 3D RAW DATA
fv_therm['IMPACT'] = fv_therm['TEMP'] - fv['TEMP']

ts = '2011-05-02 00:00'
fig, axes = plt.subplots(ncols=3, figsize=(12, 6), constrained_layout=True)

temp_spec = dict(cmap='jet', clim=(15, 25), shading='interp', colorbar=False)
diff_spec = dict(cmap='jet', clim=(-2, 2), shading='interp', colorbar=False)

ax = axes[0]
p1 = fv.plot('TEMP', ts, ax=ax,  datum='depth', limits=(0,1), **temp_spec)  # By setting datum to depth, this is now the "surface 1m")
ax.set_title('Existing Conditions')

ax = axes[1]
p2 = fv_therm.plot('TEMP', ts, ax=ax, datum='depth', limits=(0,1.0), **temp_spec)
ax.set_title('Developed Conditions')

ax = axes[2]
p3 = fv_therm.plot('IMPACT', ts, ax=ax, datum='depth', limits=(0,1.0), **diff_spec)
plt.colorbar(p3.patch, ax=ax, orientation='vertical',label='Temperature Difference (°C)')
ax.set_title('Difference - Developed minus Existing')

fig.suptitle('Impact of Thermal Discharge at ' + ts, fontweight='bold', x=0.45)
titles = {0: 'Existing Conditions', 1: 'Developed Conditions', 2: 'Impact'}

plt.show()
../../../_images/8defd8377b288f5527f526a5687df3f21eb5cfae3d7f7c055600e201f4f01861.png

Extract Contours From Sheet¶

This example shows how you can extract contours from a TUFLOW FV result as an array or a vector dataset. This is can be useful for highlighting thresholds in your model, or finding the area of a plume size, and so on.

The default way of using this function will return a dictionary containing keys corresponding to the requested levels, and values that are a list of numpy arrays containing the contour coordinates (Nx2 with X and Y columns).

We’ll follow on from the impact plot sample shown above. We will extract contours of the temperature difference above 0.5, 0.75 and 1.0°C.

levels = [0.5, 0.75, 1.0]  # temperature difference in degrees

gdf = fv_therm.get_contours(levels, 'IMPACT', ts, datum='depth', limits=(0, 1.0))

# contours is the default output - a dictionary 
# gdf is the optional output, a geodataframe. 
gdf
level geometry
0 0.50 POLYGON ((159.08624 -31.37594, 159.08642 -31.3...
1 0.75 POLYGON ((159.08819 -31.38019, 159.08831 -31.3...
2 1.00 POLYGON ((159.09403 -31.39216, 159.09396 -31.3...
fig, axes = plt.subplots(ncols=2, figsize=(10, 6), constrained_layout=True, sharey=True)
for ax in axes:
    ax.set_aspect('equal')

# Plot 1: The impacts from TUFLOW FV
fv_therm.plot('IMPACT', time=ts, ax=axes[0], datum='depth', limits=(0, 1), boundary=True, **diff_spec)
axes[0].set_title('Impacts From TUFLOW FV')

# Plot 2: The contoured up impact zones above our arbitary thresholds
fv_therm.plot('IMPACT', ax=axes[1],alpha=0.0, boundary=True, **diff_spec) # We're using this for the boundary line only :) 
gdf.plot(ax=axes[1], column='level', cmap='Reds', lw=1)
axes[1].set_title('Contoured Impacts Above Our Thresholds')

plt.show()
../../../_images/a1fe6bded17dfb238b20a98ca665d9fc1379762487cf3d67968d1126c21f4d14.png

We can also export a GeoDataFrame to shapefile, which can be useful for further analysis, or for plotting in external programs like QGIS.

By default, the geodataframe we’ve made doesn’t know what coordinate system it is in. You can add on a coordinate system (to make it load in QGIS/ArcGIS easier) by using gdf = gdf.set_crs(<epsg_code>) as below.

gdf = gdf.set_crs(4326)
gdf.to_file(output_folder / 'Impact_Contours.shp')

Plot Sheet Max¶

fv.get_statistics('max', 'SAL', datum='sigma').plot()
plt.title('Maximum Salinity from Map Output')
Text(0.5, 1.0, 'Maximum Salinity from Map Output')
Ignoring fixed x limits to fulfill fixed data aspect with adjustable data limits.
../../../_images/320bb4aa538df5760ee7651a91879e0b57c2142b3b43db043e736271891372a5.png

Save Max to asc¶

import numpy as np

stat_max = fv.get_statistics('max', 'SAL', datum='sigma')
cell_size =  5*10**-5

# Output the ASCII to disk
output_folder = Path('./outputs')
output_folder.mkdir(exist_ok=True) # Make the folder, if it doesn't exist

fv.xtr.write_data_to_ascii(output_folder / 'Max_Depth_Ave_Salinity.asc', np.squeeze(stat_max['SAL_max']), cell_size)

Save Sheet Plot Animation¶

To save an animation it is required to have the FFmpeg program on your computer’s Path environment variable.

# Output the ASCII to disk
output_folder = Path('./outputs')
output_folder.mkdir(exist_ok=True) # Make the folder, if it doesn't exist

out_file = output_folder / 'Salinty_Animation.mp4'
from matplotlib import animation

time_start = '2011-05-02 00:00'
time_end = '2011-05-02 12:00'

fvx = fv.sel(Time=slice(time_start, time_end))

# Colour settings
col_spec = dict(cmap='ocean', clim=(10, 36), shading='interp', edgecolor='face')

# Vector settings
vec_spec = dict(angles='uv', scale_units='dots', scale=1/200, width=0.002,
                headwidth=2.5, headlength=4, pivot='middle', minlength=2)

variable = 'SAL'
vector_variable = 'V'

fig, ax = plt.subplots()
ax.set_aspect('equal', adjustable='datalim')

sheet = fvx.plot(variable, 1, ax=ax, **col_spec) 
vec = fvx.plot_vector(vector_variable, 1, ax=ax, **vec_spec) 

def animate(i):
    sheet.set_time_current(i)
    vec.set_time_current(i)
    date = sheet.get_time_current()
    ax.set_title(date.strftime('%Y-%m-%d %H:%M'))

nframes = fvx.sizes['Time']
anim = animation.FuncAnimation(fig, animate, frames=nframes, repeat=False)
anim.save(
    out_file, 
    writer=animation.FFMpegWriter(),
    dpi=300)
Ignoring fixed x limits to fulfill fixed data aspect with adjustable data limits.
../../../_images/e29582b19bac46cae293f75361ffb1a0cbc8609fb69fcc703c12525b0a961dc9.png

Interactive Sheet Plot¶

It is a common task to view your results interactively so that you can get a feel for how a model is responding and behaving.

While this can be handled very well in QGIS with the TUFLOW Viewer plugin, it can also be done directly through this notebook interface.

The syntax for the interactive viewer is generally same as using fv.plot. Any keyword arguments that can be used on fv.plot(..) can also be used here, such as datum, cmap, and so on.

Vectors can also be added onto this figure. The vectors keyword argument will enable velocity if True is passed through (and V_x and V_y are present), however other variables can be plotted by specifying them directly as a list (e.g., vectors=['SEDLOAD_TOTAL_x', 'SEDLOAD_TOTAL_y']). Keyword arguments for the plot_vector command can also be used here, passed through as a dictionary to vector_kwargs - for example, vector_kwargs=dict(scale=10, color='red')

%matplotlib widget

Note that interactive plots don’t work well in the documentation so we’ve copied in a screenshot instead

fv.plot_interactive('V', shading='interp', cmap='turbo', clim=(0,0.5), datum='depth', vectors=True)

interactive_screenshot_1

To turn off interactive plotting (which can often make your sessions run faster, a good idea when you don’t need it), use %matplotlib inline

plt.close('all')
%matplotlib inline

This concludes the examples on sheet plotting.

<Page contents

>Page contents:

  • Gallery 3: Sheet Plots
    • Open TUFLOW FV Model Result
    • Single Sheet Plot
    • Sheet Plot With Vectors and Save to Disk
    • Sheet Plot at Different Depths
    • Save Sheet To ASCII Arc Grid
    • Extract Grid From Sheet And Output To GeoTiff
    • Multiple Sheet Plots
    • Impact Sheet Multiple Models
    • Extract Contours From Sheet
    • Plot Sheet Max
    • Save Max to asc
    • Save Sheet Plot Animation
    • Interactive Sheet Plot
<Gallery 2: Profile Plots
Gallery 4: Curtain Plots>
© Copyright 2024 BMT. Created using Sphinx 8.2.3.

Styled using the Piccolo Theme