Source code for stam.nurbs

import numpy as np
from geomdl import BSpline, knotvector


[docs]def tracks2surf(tracks, param, delta=0.01, xparam="color", yparam="absmag", xstep=0.1, ystep=0.1): """ tracks2surf(tracks, param, delta=0.01, xparam="color", yparam="absmag", xstep=0.1, ystep=0.1) Compute a NURBS surface from a set of stellar evolution tracks, using the `geomdl` package. Parameters ---------- tracks : Table Stellar-track grid, as retrieved by `stam.gentracks.get_isomasses` or `stam.gentracks.get_combined_isomasses`. param : str The parameter to evaluate (options: "mass", "age", "mh"). delta : float, optional `geomdl` surface evaluation step size. xparam : str, optional x-axis parameter (default: "color"). yparam : str, optional y-axis parameter (default: "absmag"). xstep : float, optional x-axis grid step (default: 0.1). ystep : float, optional y-axis grid step (default: 0.1). Returns ------- surf : `geomdl.NURBS.Surface` object 2D NURBS surface based on `tracks`. """ xmin = np.min(np.around(tracks[xparam], -int(np.round(np.log10(xstep))))) xmax = np.max(np.around(tracks[xparam], -int(np.round(np.log10(xstep))))) ymin = np.min(np.around(tracks[yparam], -int(np.round(np.log10(ystep))))) ymax = np.max(np.around(tracks[yparam], -int(np.round(np.log10(ystep))))) x, y = np.meshgrid(np.arange(xmin, xmax, xstep), np.arange(ymin, ymax, ystep)) z = np.zeros_like(x)*np.nan for i in range(x.shape[0]): for j in range(x.shape[1]): dist = np.sqrt((x[i, j] - tracks[xparam])**2 + (y[i, j] - tracks[yparam])**2) min_idx = np.argmin(dist) z[i, j] = tracks[param][min_idx] ctrlpts = np.array([x.flatten(), y.flatten(), z.flatten()]).T ctrlpts = ctrlpts.reshape((x.shape[0], x.shape[1], 3)) ctrlpts = ctrlpts.tolist() surf = BSpline.Surface() surf.degree_u = 3 surf.degree_v = 3 surf.ctrlpts2d = ctrlpts surf.knotvector_u = knotvector.generate(surf.degree_u, surf.ctrlpts_size_u) surf.knotvector_v = knotvector.generate(surf.degree_v, surf.ctrlpts_size_v) surf.delta = delta return surf
[docs]def evaluate(surf, x, y): """ evaluate(surf, x, y) Evaluate NURBS surface at a specific set of coordinates. Parameters ---------- surf : `geomdl.NURBS.Surface` object 2D NURBS surface based on `tracks`. x : array_like x-axis evaluation points. y : array_like y-axis evaluation points (same size as `x`). Returns ------- z: array_like Array of evaluated values (same size as `x`). """ z = np.nan*np.zeros_like(x) # initialize # calculate (u, v) coordinates on surface v = (x - surf.bbox[0][0]) / (surf.bbox[1][0] - surf.bbox[0][0]) u = (y - surf.bbox[0][1]) / (surf.bbox[1][1] - surf.bbox[0][1]) uv = np.array([u, v]).T # evaluate only points inside surface (points outside surface can't be evaluated) idx = ((0 <= v) & (v <= 1)) & ((0 <= u) & (u <= 1)) if np.any(idx): z[idx] = np.array(surf.evaluate_list(uv[idx, :].tolist()))[:, -1] return z