def graph_surface_interactive(f, x_range, y_range, **options):
x, xmin, xmax = x_range
y, ymin, ymax = y_range
zmin = options.get("zmin", 0)
zmax = options.get("zmax", 12)
f = fast_float(f, x, y)
x = np.random.uniform(xmin, xmax, 2001)
x[0] = xmin - 1
y = np.random.uniform(ymin, ymax, 2001)
z = np.array([f(X, Y) for X,Y in zip(x, y)])
fig = plotly.graph_objects.FigureWidget()
fig.layout.margin = dict(t=10, b=10, r=10, l=10)
fig.layout.showlegend = True
fig.layout.legend.y = 0.9
fig.layout.legend.font.size = 16
fig.layout.scene.xaxis.title.text = "X"
fig.layout.scene.yaxis.title.text = "Y"
fig.layout.scene.zaxis.title.text = "Z"
fig.layout.scene.xaxis.range = (xmin, xmax)
fig.layout.scene.yaxis.range = (ymin, ymax)
fig.layout.scene.zaxis.range = (zmin, zmax)
fig.layout.scene.aspectmode = "cube"
fig.add_scatter3d(name="Points on XY-plane", mode="markers",
marker_color="red", marker_size=2)
on_plane = fig.data[-1]
fig.add_scatter3d(name="Points on graph", mode="markers",
marker_color="blue", marker_size=2)
on_graph = fig.data[-1]
options = list(range(17)) + [50, 100, 200, 400, 800, 2000, 4000]
options = [(f"{(n + 1) // 2}{' '*(n % 2)}", n) for n in options]
@interact(numpoints=SelectionSlider(options=options, continuous_update=false,
description="Points:"))
def update(numpoints):
n1 = (numpoints + 1) // 2 + 1
n2 = numpoints // 2 + 1
with fig.batch_update():
on_plane.x = x[:n1]
on_plane.y = y[:n1]
on_plane.z = np.zeros(n1)
on_graph.x = x[:n2]
on_graph.y = y[:n2]
on_graph.z = z[:n2]
return fig