xmsgridtrace

Introduction

xmsgridtrace provides functionality to trace a particle through a vector field on an unstructure grid (xmsgrid). This notebook demonstrates using this library to trace through the vector field computed by a numerical model (SRH2D).

In [1]:
from shapely.geometry import Polygon
import holoviews as hv
import pandas as pd

from cartopy import crs as ccrs

import numpy as np
import geoviews as gv
import xarray as xr
import cartopy.crs as ccrs

import hvplot.pandas
import hvplot.xarray

import math
import xmsgridtrace
import xmsgrid

import gridtrace_tools
import particle_trace_data

hv.extension("bokeh", "matplotlib")

Setup Projection and Basemap

In [2]:
srs = ccrs.UTM(zone=13)

basemap = gv.tile_sources.ESRI().options(width=500, height=500)

Create UGrid

In [3]:
points = particle_trace_data.points
cells = particle_trace_data.cells
ug = xmsgrid.ugrid.UGrid(points, cells)

Display UGrid

In [4]:
%opts Polygons [width=900 height=900]
ug_polygons, ug_lines, ug_points = gridtrace_tools.create_hv_objects_from_ugrid(ug, _projection=srs)
ug_polygons = ug_polygons.redim.range(x=(-0.5, 2.5), y=(-0.5, 2.5))
basemap * ug_polygons * ug_lines.options(line_width=0.1) * ug_points
Out[4]:

Create Tracer

In [5]:
tracer = xmsgridtrace.gridtrace.GridTrace(
    ugrid=ug,
    vector_multiplier=1,
    max_tracing_time=-1,
    max_tracing_distance=-1,
    min_delta_time=0.01,
    max_change_distance=-1,
    max_change_velocity=-1,
    max_change_direction_in_radians=(math.pi/4)
)

Scalars at Time Steps

In [6]:
activity = [True for _ in range(len(particle_trace_data.scalars1))]

# First Timestep
scalars1 = particle_trace_data.scalars1
tracer.add_grid_scalars_at_time(
    scalars=scalars1, 
    scalar_loc="points",
    cell_activity=activity, 
    activity_loc="points",
    time=0.0
)

# Second Timestep
scalars2 = particle_trace_data.scalars2
tracer.add_grid_scalars_at_time(
    scalars=scalars2, 
    scalar_loc="points",
    cell_activity=activity, 
    activity_loc="points",
    time=20.0
)

#Third Timestep
scalars3 = particle_trace_data.scalars3
tracer.add_grid_scalars_at_time(
    scalars=scalars3, 
    scalar_loc="points",
    cell_activity=activity, 
    activity_loc="points",
    time=40.0
)
In [7]:
traces, times = tracer.trace_point((196959.1, 3681068.6, 0.0), 0.0)
In [8]:
t_points = gv.Points(traces, crs=srs).options(color='blue', size=3)
t_path = gv.Path([traces,], crs=srs).options(color='red')
dx_dy = []
for i in range(len(traces) - 1):
    dx_dy.append((
        traces[i+1][0] - traces[i][0],
        traces[i+1][1] - traces[i][1],
        traces[i+1][2] - traces[i][2],
))
t_vec = gridtrace_tools.hv_vector_field_from_2_timesteps(
    dx_dy, traces[:-1], _projection=srs
).opts(
    hv.opts.VectorField(line_width=3, color='magenta', magnitude=hv.dim('Magnitude').norm()*4)
)
basemap * t_points * t_path * t_vec
Out[8]: