Gallery 6: Particle Tracking Plots¶
Plot particle tracking outputs from TUFLOW FV’s Particle Tracking Module.
This notebook is used in combination with the TUFLOW FV Python Toolbox (tfv) package. To follow along on your own computer, please download the demonstration notebooks from the TUFLOW Downloads Page. Look for the TUFLOW FV Python Toolbox download. Installation instructions are provided on our TUFLOW FV Python Toolbox Wiki Page.
To view particle figures you need to have additionally PyQT5 installed in your working Python environment.
If using conda: conda install -c conda-forge pyqt. You will need to close this notebook, install with your environment activated (for example tfv-workspace) and then restart jupyter-lab.
In pip: pip install PyQT5.
Please note that the plots will be displayed in a separate window, not inline in the notebook.
import xarray as xr # We utilise xarray to do all the heavy lifting
import tfv.xarray
from tfv.particles import FvParticles
from tfv.visual import *
from tfv.viewer import Viewer, ColourBar
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
%gui qt5
Plot Basic¶
model_folder = Path(r'..\..\data')
model_file = 'PTM_002.nc'
model_ptm = 'PTM_002_ptm.nc'
fv = xr.open_dataset(model_folder / model_file, decode_times=False).tfv
# fv # Uncomment to review the dataset
fv_pxtr = FvParticles(model_folder / model_ptm)
# Prepare viewer object, figure & axes
viewer = Viewer(size=(200, 200), units='mm')
axes = viewer.figure.subplots(1, 1)
viewer.figure.subplots_adjust(bottom=0.15, top=0.95)
# Plot mesh
xy = np.dstack((fv.xtr.node_x[fv.xtr.cell_node], fv.xtr.node_y[fv.xtr.cell_node]))
patch = PolyCollection(xy, edgecolor='black', facecolor='None')
axes.add_collection(patch)
# Plot the particles in bottom 1m as black circles
ParticlesScatter(axes, fv_pxtr, viewer=viewer, datum='height', limits=[0, 1], shape='o', scale=0.00025, color='black', label='Bed (0m - 1m)')
# Plot the particles in top 1m as pink triangles
ParticlesScatter(axes, fv_pxtr, viewer=viewer, datum='depth', limits=[0, 1], shape='tri', scale=0.00025, color='pink', label='Water column (0m - 1m)')
axes.legend()
# Finish formatting plot
axes.set_aspect('equal')
for tick in axes.get_xticklabels():
tick.set_rotation(20)
axes.set_xlim([159.07, 159.14])
axes.set_ylim([-31.45, -31.35])
plt.show(block=True)
# The plot will open in a seperate PyQT5 Window.
# Once you've reviwed the results please close the figure window.
# You will then need interrupt the notebook kernel by clicking the stop button prior to moving on and running the next example.
Plot Groups¶
model_folder = Path(r'..\..\data')
model_file = 'PTM_005.nc'
model_ptm = 'PTM_005_ptm.nc'
sheet_variable = 'H'
variable_name = 'Water Level [mAHD]'
vector_variables = ['V_x', 'V_y']
# Depth averaging setup
datum = 'sigma'
limits = [0, 1]
# Vector settings
vec_spec = dict(units='dots', scale_units='dots', scale=1/200, width=0.5,
headwidth=10, headlength=10, angles='uv', pivot='middle')
# Colour settings
col_spec = dict(cmap=cm.jet, clim=[0.0, 0.5], norm=Normalize(0.0, 0.5))
fv = xr.open_dataset(model_folder / model_file, decode_times=False).tfv
# fv # Uncomment to review the dataset
fv_pxtr = FvParticles(model_folder / model_ptm)
# Prepare viewer object, figure & axes
viewer = Viewer(size=(200, 200), units='mm')
axes = viewer.figure.subplots(1, 1)
viewer.figure.subplots_adjust(bottom=0.15, top=0.95)
# Plot Sheet Results
sheet = SheetPatch(axes, fv.xtr, sheet_variable, datum, limits, viewer=viewer, shading='flat', edgecolor='face', **col_spec)
vector = SheetVector(axes, fv.xtr, vector_variables, datum, limits, viewer=viewer, zorder=1, **vec_spec)
# Plot the particles in group 1 as green circles
ParticlesScatter(axes, fv_pxtr, viewer=viewer, shape='o', scale=0.0001, color='green', show=dict(groupID=1), label='Clay')
# Plot the particles in group 2 as black circles
ParticlesScatter(axes, fv_pxtr, viewer=viewer, shape='o', scale=0.0001, color='black', show=dict(groupID=2), label='Silt')
# Plot the particles in group 3 as yellow circles
ParticlesScatter(axes, fv_pxtr, viewer=viewer, shape='o', scale=0.0001, color='yellow', show=dict(groupID=3), label='Fine Sand')
# Plot the particles in group 4 as brown circles
ParticlesScatter(axes, fv_pxtr, viewer=viewer, shape='o', scale=0.0001, color='brown', show=dict(groupID=4), label='Coarse Sand')
axes.legend()
# Finish formatting plot
axes.set_aspect('equal')
for tick in axes.get_xticklabels():
tick.set_rotation(20)
axes.set_xlim([159.07, 159.14])
axes.set_ylim([-31.45, -31.35])
plt.show(block=True)
# The plot will open in a seperate PyQT5 Window.
# Once you've reviwed the results please close the figure window.
# You will then need interrupt the notebook kernel by clicking the stop button prior to moving on and running the next example.
Plot Groups State¶
model_folder = Path(r'..\..\data')
model_file = 'PTM_002.nc'
model_ptm = 'PTM_002_ptm.nc'
fv = xr.open_dataset(model_folder / model_file, decode_times=False).tfv
# fv # Uncomment to review the dataset
fv_pxtr = FvParticles(model_folder / model_ptm)
# Prepare viewer object, figure & axes
viewer = Viewer(size=(200, 200), units='mm')
axes = viewer.figure.subplots(1, 1)
viewer.figure.subplots_adjust(bottom=0.15, top=0.95)
# Plot mesh
xy = np.dstack((fv.xtr.node_x[fv.xtr.cell_node], fv.xtr.node_y[fv.xtr.cell_node]))
patch = PolyCollection(xy, edgecolor='grey', facecolor='None')
axes.add_collection(patch)
# Plot the particles in suspension as blue circles
ParticlesScatter(axes, fv_pxtr, viewer=viewer, shape='o', scale=0.00025, color='blue', show=dict(stat=1), label='Suspended')
# Plot the particles that have washed up on the bank as yellow circles
ParticlesScatter(axes, fv_pxtr, viewer=viewer, shape='o', scale=0.00025, color='yellow', show=dict(stat=2), label='Dry')
# Plot the particles on the bed as brown circles
ParticlesScatter(axes, fv_pxtr, viewer=viewer, shape='o', scale=0.00025, color='brown', show=dict(stat=3), label='Bed')
axes.legend()
# Finish formatting plot
axes.set_aspect('equal')
for tick in axes.get_xticklabels():
tick.set_rotation(20)
axes.set_xlim([159.07, 159.14])
axes.set_ylim([-31.45, -31.35])
plt.show(block=True)
# The plot will open in a seperate PyQT5 Window.
# Once you've reviwed the results please close the figure window.
# You will then need interrupt the notebook kernel by clicking the stop button prior to moving on and running the next example.
Plot Coloured¶
model_folder = Path(r'..\..\data')
model_file = 'PTM_002.nc'
model_ptm = 'PTM_002_ptm.nc'
fv = xr.open_dataset(model_folder / model_file, decode_times=False).tfv
# fv # Uncomment to review the dataset
fv_pxtr = FvParticles(model_folder / model_ptm)
# Prepare viewer object, figure & axes
viewer = Viewer(size=(200, 200), units='mm')
axes = viewer.figure.subplots(1, 1)
viewer.figure.subplots_adjust(bottom=0.15, top=0.95)
# Plot mesh
xy = np.dstack((fv.xtr.node_x[fv.xtr.cell_node], fv.xtr.node_y[fv.xtr.cell_node]))
patch = PolyCollection(xy, edgecolor='grey', facecolor='None')
axes.add_collection(patch)
# Plot the particles all particles as black circles, highlighting group 2
col_spec = dict(cmap='jet', clim=[-6, 0], norm=Normalize(-6, 0))
scat = ParticlesScatter(axes, fv_pxtr, viewer=viewer, shape='o', scale=0.00025, expression='z', **col_spec)
# Add colour bar
col_bar = ColourBar(scat.patch, offset=0.08)
col_bar.ax.set_xlabel('Elevation (m MSL)')
# Finish formatting plot
axes.set_aspect('equal')
for tick in axes.get_xticklabels():
tick.set_rotation(20)
axes.set_xlim([159.07, 159.14])
axes.set_ylim([-31.45, -31.35])
plt.show(block=True)
# The plot will open in a seperate PyQT5 Window.
# Once you've reviwed the results please close the figure window.
# You will then need interrupt the notebook kernel by clicking the stop button prior to moving on and running the next example.
Plot Highlight¶
model_folder = Path(r'..\..\data')
model_file = 'PTM_002.nc'
model_ptm = 'PTM_002_ptm.nc'
fv = xr.open_dataset(model_folder / model_file, decode_times=False).tfv
# fv # Uncomment to review the dataset
fv_pxtr = FvParticles(model_folder / model_ptm)
# Prepare viewer object, figure & axes
viewer = Viewer(size=(200, 200), units='mm')
axes = viewer.figure.subplots(1, 1)
viewer.figure.subplots_adjust(bottom=0.15, top=0.95)
# Plot mesh
xy = np.dstack((fv.xtr.node_x[fv.xtr.cell_node], fv.xtr.node_y[fv.xtr.cell_node]))
patch = PolyCollection(xy, edgecolor='grey', facecolor='None')
axes.add_collection(patch)
# Plot the particles all particles as black circles, highlighting group 2
highlight = dict(groupID=2)
ParticlesScatter(axes, fv_pxtr, viewer=viewer, shape='o', scale=0.00025, color='black',
highlight=highlight)
# Finish formatting plot
axes.set_aspect('equal')
for tick in axes.get_xticklabels():
tick.set_rotation(20)
axes.set_xlim([159.07, 159.14])
axes.set_ylim([-31.45, -31.35])
plt.show(block=True)
# The plot will open in a seperate PyQT5 Window.
# Once you've reviwed the results please close the figure window.
# You will then need interrupt the notebook kernel by clicking the stop button prior to moving on and running the next example.
Plot Highlight Boolean AND¶
model_folder = Path(r'..\..\data')
model_file = 'PTM_002.nc'
model_ptm = 'PTM_002_ptm.nc'
fv = xr.open_dataset(model_folder / model_file, decode_times=False).tfv
# fv # Uncomment to review the dataset
fv_pxtr = FvParticles(model_folder / model_ptm)
# Prepare viewer object, figure & axes
viewer = Viewer(size=(200, 200), units='mm')
axes = viewer.figure.subplots(1, 1)
viewer.figure.subplots_adjust(bottom=0.15, top=0.95)
# Plot mesh
xy = np.dstack((fv.xtr.node_x[fv.xtr.cell_node], fv.xtr.node_y[fv.xtr.cell_node]))
patch = PolyCollection(xy, edgecolor='grey', facecolor='None')
axes.add_collection(patch)
# Plot the particles all particles as black circles, highlighting (group ID 4 OR particles on the bed stat=3) via
# Highlight_method='any' the default highlight_method
highlight = dict(groupID=4, stat=3)
ParticlesScatter(axes, fv_pxtr, viewer=viewer, shape='o', scale=0.00025, color='black',
highlight=highlight, highlight_method='any')
# Finish formatting plot
axes.set_aspect('equal')
for tick in axes.get_xticklabels():
tick.set_rotation(20)
axes.set_xlim([159.07, 159.14])
axes.set_ylim([-31.45, -31.35])
plt.show(block=True)
# The plot will open in a seperate PyQT5 Window.
# Once you've reviwed the results please close the figure window.
# You will then need interrupt the notebook kernel by clicking the stop button prior to moving on and running the next example.
Plot Highlight Boolean OR¶
model_folder = Path(r'..\..\data')
model_file = 'PTM_002.nc'
model_ptm = 'PTM_002_ptm.nc'
fv = xr.open_dataset(model_folder / model_file, decode_times=False).tfv
# fv # Uncomment to review the dataset
fv_pxtr = FvParticles(model_folder / model_ptm)
# Prepare viewer object, figure & axes
viewer = Viewer(size=(200, 200), units='mm')
axes = viewer.figure.subplots(1, 1)
viewer.figure.subplots_adjust(bottom=0.15, top=0.95)
# Plot mesh
xy = np.dstack((fv.xtr.node_x[fv.xtr.cell_node], fv.xtr.node_y[fv.xtr.cell_node]))
patch = PolyCollection(xy, edgecolor='grey', facecolor='None')
axes.add_collection(patch)
# Plot the particles all particles as black circles, highlighting (group ID 4 OR particles on the bed stat=3) via
# Highlight_method='any' the default highlight_method
highlight = dict(groupID=4, stat=3)
ParticlesScatter(axes, fv_pxtr, viewer=viewer, shape='o', scale=0.00025, color='black',
highlight=highlight, highlight_method='any')
# Finish formatting plot
axes.set_aspect('equal')
for tick in axes.get_xticklabels():
tick.set_rotation(20)
axes.set_xlim([159.07, 159.14])
axes.set_ylim([-31.45, -31.35])
plt.show(block=True)
# The plot will open in a seperate PyQT5 Window.
# Once you've reviwed the results please close the figure window.
# You will then need interrupt the notebook kernel by clicking the stop button prior to moving on and running the next example.
This concludes the examples on particle plotting.