We can use pygfx Geometry.texcoords and Material.map to handle cmaps and transforms more elegantly:
Function to create [0, 1] normalized values for the transform that we feed to pygfx. This takes into account vmin, vmax, and gamma.
def normalize_min_max(a, vmin: float = None, vmax: float = None, gamma: float = 1.0):
"""normalize an array between 0 - 1, clipped to (vmin, vmax)"""
vmin = np.min(a) if vmin is None else vmin
vmax = np.max(a) if vmax is None else vmax
if vmax <= vmin:
return np.zeros(a.size)
transform = np.clip((a - vmin) / (vmax - vmin), 0, 1)
if gamma == 1.0:
return transform
return transform ** gamma
This is basically everything we need to implement in the refactored graphic features:
xs = np.linspace(0, 4 * np.pi, 100)
ys = np.sin(xs)
data = np.column_stack([xs, ys])
ys_scaled = normalize_min_max(ys)
geometry.texcoords = pygfx.Buffer(ys_scaled.astype(np.float32))
material.color_mode = "vertex_map"
material.map = cmap_lib.Colormap("seismic").to_pygfx()
We then have vmin, vmax, gamma graphic features on positional graphics as well and the imgui colorbar can keep them in sync.
We can use pygfx
Geometry.texcoordsandMaterial.mapto handle cmaps and transforms more elegantly:Function to create [0, 1] normalized values for the transform that we feed to pygfx. This takes into account vmin, vmax, and gamma.
This is basically everything we need to implement in the refactored graphic features:
We then have
vmin,vmax,gammagraphic features on positional graphics as well and the imgui colorbar can keep them in sync.