The purpose of this tutorial is to provide explanation on how to use the classes defined in xmsextractor to extract data at given locations on an unstructured grid (xmsgrid) with scalar values.
The motivation for this library is a tool to interrogate results from numerical models. Numerical models use either structured or unstructured grids to perform calculations. The locations where the numerical model performs calculations do not usually coincide with points of interest. This library extracts data values from arbitrary locations in an unstructured grid (or structured grid); also, the library includes functionality to extract values along a line.
import numpy as np
import geoviews as gv
import holoviews as hv
import pandas as pd
import xarray as xr
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
import panel as pn
from shapely.geometry import Polygon
from holoviews.streams import Params
import xmsextractor
import xmsgrid
import ugrid_tools
hv.extension('bokeh')
This first example shows how to extract data from a simple XmUGrid. A picture of the example is shown below. Notice that the XmUGrid is a simple square from (0,0) to (1,1) split into two triangle cells. The scalar data is mapped to the cells (this usually means that the numerical model has computed a value at the cell center).
If the scalar data were mapped to the points then that would mean that the numerical model computed values at the point locations.
# create a simple xmsgrid
pts = [(0, 0, 0), (1, 0, 0), (1, 1, 0), (0, 1, 0)]
cells = [
xmsgrid.ugrid.UGrid.TRIANGLE, 3, 0, 1, 2,
xmsgrid.ugrid.UGrid.TRIANGLE, 3, 2, 3, 0,
]
ugrid = xmsgrid.ugrid.UGrid(pts, cells)
# draw the grid
polygons, lines, points = ugrid_tools.create_hv_objects_for_image(ugrid)
%opts Polygons Points [width=700, height=700]
polygons.options(color="red", alpha=0.25) * lines * points.options(size=3)
The basic steps to extract interpolated locations from an XmUGrid and scalar values is as follows:
extractor = xmsextractor.extractor.UGrid2dDataExtractor(ugrid)
Usually these values would come from a numerical model. Activity values refers to output from a numerical model where certain areas in the grid do not have computed values. For a 2D simulation of the flow of water the "inactive" areas could be areas that are dry.
cellScalars = (1, 2)
extractor.set_grid_cell_scalars(cellScalars, (), xmsextractor.extractor.data_location_enum.LOC_CELLS)
These are the locations where we want to know the value computed by the numerical model. The value will be interpolated based on the surrounding values computed by the numerical model.
extractor_locations = [
(0.0, 0.0, 0.0),
(0.25, 0.75, 100.0),
(0.5, 0.5, 0.0),
(0.75, 0.25, -100.0),
(-0.1, -0.1, 0.0),
(0, 1, 0),
(1, 1, 0),
(1, 0, 0),
(0.25, 0.4, 0),
(0.75, 0.6, 0),
]
# draw the locations
extractor_location_points = hv.Points(extractor_locations).options(color='red', size=10)
%opts Polygons Points [width=700, height=700]
polygons * lines * points * extractor_location_points
extractor.set_extract_locations(extractor_locations)
extraction_values = extractor.extract_data()
for i in range(0, len(extractor_locations)):
print(f"Extraction value at {extractor_locations[i]}: {extraction_values[i]}")
extract_scatter_vals = np.array([
(extractor_locations[i][0],
extractor_locations[i][1],
extraction_values[i])
for i in range(0, len(extraction_values))
])
hv_extract_values = hv.Scatter(extract_scatter_vals, vdims=['y', 'z'])
polygons, lines, points = ugrid_tools.create_hv_objects_for_image(ugrid)
%opts Polygons Points [width=700, height=700 tools=['hover']]
%opts Scatter [color_index=2 colorbar=True tools=['hover']] (size=10 cmap="cool")
polygons * lines * points.options(size=3) * hv_extract_values
This example shows how to use a location extractor on transient data.
This example shows how to extract data from a XmUGrid that has transient scalar data. A picture of the example is shown below. Notice that the UGrid is a 2x3 structured grid with quadrillateral cells. There are two time steps with scalar data mapped to the points.
transient_example_points = [(288050, 3907770, 0), (294050, 3907770, 0), (300050, 3907770, 0),
(306050, 3907770, 0), (288050, 3901770, 0), (294050, 3901770, 0),
(300050, 3901770, 0), (306050, 3901770, 0), (288050, 3895770, 0),
(294050, 3895770, 0), (300050, 3895770, 0), (306050, 3895770, 0)
]
transient_example_cells = [xmsgrid.ugrid.UGrid.ugrid_celltype_enum.QUAD, 4, 0, 4, 5, 1,
xmsgrid.ugrid.UGrid.ugrid_celltype_enum.QUAD, 4, 1, 5, 6, 2,
xmsgrid.ugrid.UGrid.ugrid_celltype_enum.QUAD, 4, 2, 6, 7, 3,
xmsgrid.ugrid.UGrid.ugrid_celltype_enum.QUAD, 4, 4, 8, 9, 5,
xmsgrid.ugrid.UGrid.ugrid_celltype_enum.QUAD, 4, 5, 9, 10, 6,
xmsgrid.ugrid.UGrid.ugrid_celltype_enum.QUAD, 4, 6, 10, 11, 7
]
transient_example_ugrid = xmsgrid.ugrid.UGrid(transient_example_points, transient_example_cells)
polygons, lines, points = ugrid_tools.create_hv_objects_for_image(transient_example_ugrid)
%opts Polygons Points [width=700, height=700]
polygons * lines * points.options(size=3)
transient_example_extractor = xmsextractor.extractor.UGrid2dDataExtractor(transient_example_ugrid)
transient_example_extract_locations = [(289780, 3906220, 0),
(293780, 3899460, 0),
(298900, 3900780, 0),
(301170, 3904960, 0),
(296330, 3906180, 0),
(307395, 3901463, 0)
]
transient_example_extractor.set_extract_locations(transient_example_extract_locations)
transient_example_extractor_location_points = hv.Points(transient_example_extract_locations).options(color='red', size=10)
%opts Polygons Points [width=700, height=700]
polygons * lines * points * transient_example_extractor_location_points
transient_example_point_scalars = [730.787, 1214.54, 1057.145, 629.2069, 351.1153, 631.6649, 1244.366,
449.9133, 64.04247, 240.9716, 680.0491, 294.9547]
transient_example_extractor.set_grid_point_scalars(
transient_example_point_scalars, [], xmsextractor.extractor.data_location_enum.LOC_CELLS
)
transient_example_extraction_values = transient_example_extractor.extract_data()
for i in range(0, len(transient_example_extract_locations)):
print(f"Extraction value at {transient_example_extract_locations[i]}: {transient_example_extraction_values[i]}")
transient_example_point_scalars = [float('nan'), 1220.5, 1057.1, 613.2, 380.1, 625.6, 722.2, 449.9, 51.0, 240.9, 609.0, 294.9]
transient_example_cell_activity = [True] * transient_example_ugrid.get_cell_count()
transient_example_cell_activity[0] = False
transient_example_extractor.set_grid_point_scalars(
transient_example_point_scalars,
transient_example_cell_activity,
xmsextractor.extractor.data_location_enum.LOC_CELLS
)
transient_example_extraction_values = transient_example_extractor.extract_data()
for i in range(0, len(transient_example_extract_locations)):
print(f"Extraction value at {transient_example_extract_locations[i]}: {transient_example_extraction_values[i]}")
transient_extract_scatter_vals = np.array([
(transient_example_extract_locations[i][0],
transient_example_extract_locations[i][1],
transient_example_extraction_values[i])
for i in range(0, len(transient_example_extraction_values))
])
hv_transient_extract_values = hv.Scatter(transient_extract_scatter_vals, vdims=['y', 'z'])
polygons, lines, points = ugrid_tools.create_hv_objects_for_image(transient_example_ugrid)
%opts Polygons Points [width=700, height=700 tools=['hover']]
%opts Scatter [color_index=2 colorbar=True tools=['hover']] (size=10)
polygons * lines * points.options(size=3) * hv_transient_extract_values
This example shows how to use a polyline extractor on transient data.
This example shows how to extract data along a polyline from a XmUGrid that has transient scalar data. A picture of the example is shown below. Notice that the UGrid is a 2x3 structured grid with quadrillateral cells. There are two time steps with scalar data mapped to the points.
The steps to extract interpolated values along a polyline for transient scalar values include:
polyline_example_points = [(288050, 3907770, 0), (294050, 3907770, 0), (300050, 3907770, 0),
(306050, 3907770, 0), (288050, 3901770, 0), (294050, 3901770, 0),
(300050, 3901770, 0), (306050, 3901770, 0), (288050, 3895770, 0),
(294050, 3895770, 0), (300050, 3895770, 0), (306050, 3895770, 0)
]
polyline_example_cells = [xmsgrid.ugrid.UGrid.ugrid_celltype_enum.QUAD, 4, 0, 4, 5, 1,
xmsgrid.ugrid.UGrid.ugrid_celltype_enum.QUAD, 4, 1, 5, 6, 2,
xmsgrid.ugrid.UGrid.ugrid_celltype_enum.QUAD, 4, 2, 6, 7, 3,
xmsgrid.ugrid.UGrid.ugrid_celltype_enum.QUAD, 4, 4, 8, 9, 5,
xmsgrid.ugrid.UGrid.ugrid_celltype_enum.QUAD, 4, 5, 9, 10, 6,
xmsgrid.ugrid.UGrid.ugrid_celltype_enum.QUAD, 4, 6, 10, 11, 7
]
polyline_example_ugrid = xmsgrid.ugrid.UGrid(polyline_example_points, polyline_example_cells)
# Step 1. Create an extractor for an XmUGrid giving the mapped location of the scalar values
polyline_example_extractor = xmsextractor.extractor.UGrid2dPolylineDataExtractor(
polyline_example_ugrid, xmsextractor.extractor.data_location_enum.LOC_POINTS
)
polygons, lines, points = ugrid_tools.create_hv_objects_for_image(polyline_example_ugrid)
%opts Polygons Points [width=700, height=700]
polygons * lines * points.options(size=3)
# Step 3. Set the polyline to be extracted along.
polyline = [(290764, 3895106, 0), (291122, 3909108, 0),
(302772, 3909130, 0), (302794, 3895775, 0)
]
polyline_example_extractor.set_polyline(polyline)
hv_polyline = hv.Path([polyline,]).options(line_color='red')
hv_polyline_points = hv.Points(polyline).options(size=6)
polygons, lines, points = ugrid_tools.create_hv_objects_for_image(polyline_example_ugrid)
%opts Polygons Points [width=700, height=700]
polygons * lines * points.options(size=3) * hv_polyline * hv_polyline_points
polyline_example_extracted_locations = polyline_example_extractor.get_extract_locations()
hv_polyline = hv.Path([polyline,]).options(line_color='red')
hv_polyline_points = hv.Points(polyline_example_extracted_locations).options(size=10)
polygons, lines, points = ugrid_tools.create_hv_objects_for_image(polyline_example_ugrid)
%opts Polygons Points [width=700, height=700]
polygons * lines * points.options(size=3) * hv_polyline * hv_polyline_points
point_scalars = [730.787, 1214.54, 1057.145, 629.2069, 351.1153, 631.6649,
1244.366, 449.9133, 64.04247, 240.9716, 680.0491, 294.9547
]
polyline_example_extractor.set_grid_scalars(point_scalars, [], xmsextractor.extractor.data_location_enum.LOC_CELLS)
polyline_example_extraction_values = polyline_example_extractor.extract_data()
for i in range(0, len(polyline_example_extracted_locations)):
print(f"Extraction value at {polyline_example_extracted_locations[i]}: {polyline_example_extraction_values[i]}")
point_scalars = [float('nan'), 1220.5, 1057.1, 613.2, 380.1, 625.6, 722.2, 449.9, 51.0, 240.9,
609.0, 294.9]
polyline_example_extractor.set_grid_scalars(point_scalars, [], xmsextractor.extractor.data_location_enum.LOC_CELLS)
extract_vals = polyline_example_extractor.extract_data()
extract_scatter_vals = np.array([
(polyline_example_extracted_locations[i][0], polyline_example_extracted_locations[i][1], extract_vals[i])
for i in range(0, len(extract_vals))
])
hv_extract_values = hv.Scatter(extract_scatter_vals, vdims=['y', 'z'])
polygons, lines, points = ugrid_tools.create_hv_objects_for_image(polyline_example_ugrid)
%opts Polygons Points [width=700, height=700 tools=['hover']]
%opts Scatter [color_index=2 colorbar=True tools=['hover']] (size=10)
polygons * lines * points.options(size=3) * hv_polyline * hv_extract_values