I am wanting to generate a heatmap of the gradients between the Z-Values and display using Plotly.
The issue I have is being able to effectively mask the unwanted data that forms from interpolation in 'concave' areas which don't have datapoints.
One solution (maybe not the most elegant) would be to find the boundary of the points (concave hull) and then set anything outside of this boundary to nan
.
To find the boundary you can use alphashape and to determine if the grid_z
points are inside (or on) the boundary you can use shapely.
Here is an example that picks up right before the first plotly plots:
from shapely.geometry import Polygon, Point
import alphashape
mpoints = [Point(X, Y) for X, Y in zip(x, y)]
alpha=.125
hull = alphashape.alphashape(mpoints, alpha)
poly = Polygon(hull)
grid_gz = grid_z
gx = np.arange(min(x), max(x),1)
gy = np.arange(min(y), max(y),1)
for i, gxi in enumerate(gx):
for j, gyi in enumerate(gy):
if not np.isnan(grid_gz[j,i]): #UPDATE: no need to test pts that are already NaN
p1 = Point(gxi, gyi)
test = poly.contains(p1) | poly.touches(p1)
if test==False:
grid_gz[j,i]=np.nan
fig = go.Figure()
fig.add_trace(
go.Heatmap(z=grid_gz,x0=min(x),y0=min(y),showscale=True, zsmooth='best',
connectgaps=False, colorscale='Hot'
))
fig.add_trace(
go.Scatter(
x=x,
y=y,mode="markers",marker_size=2,marker_color="black",
))
fig.update_layout(
width = 1200,
height = 1200,
title = "Gradient Heatmap Plot",
yaxis = dict(
scaleanchor = "x",
scaleratio = 1,
))
fig.show()
Further Comments:
optimizealpha
to find the alpha value, BUT this value ended up being a little too course and the one edge had steps in the heatmap. See here as well.alphashape
.contains
and here on touches