Math utils¶
- class surfalize.mathutils.Cylinder(point, direction, radius)¶
Bases:
objectRepresentation of a cylinder in 3d space, defined by its rotation axis (a point on the axis and a unit direction vector) and its radius.
The cylinder is the set of points at perpendicular distance
radiusfrom the axis line. This class provides the geometry needed for cylinder form removal: computing the distance of points to the axis, fitting a cylinder to a point cloud and intersecting vertical lines (along z) with the cylinder surface.- Parameters:
- pointarray-like[float, float, float]
A point lying on the rotation axis.
- directionarray-like[float, float, float]
Direction vector of the rotation axis. It is normalized internally and does not need to be a unit vector.
- radiusfloat
Radius of the cylinder.
Methods
distance_to_axis(points)Computes the perpendicular distance of one or more points to the rotation axis.
from_fit(points, guess[, radius])Fits a cylinder to a point cloud by minimizing the sum of squared radial deviations from the cylinder surface using scipy.optimize.least_squares.
intersect_vertical(x, y, z_reference)Intersects vertical lines (parallel to the z-axis) at positions (x, y) with the cylinder surface and returns the z-coordinate of the intersection.
residuals(points)Computes the signed radial deviation of points from the cylinder surface, i.e. the distance to the axis minus the radius.
- distance_to_axis(points)¶
Computes the perpendicular distance of one or more points to the rotation axis.
- Parameters:
- pointsndarray
Array of shape (N, 3) containing the (x, y, z) coordinates of N points.
- Returns:
- ndarray
Array of shape (N,) containing the distance of each point to the axis.
- classmethod from_fit(points, guess, radius=None)¶
Fits a cylinder to a point cloud by minimizing the sum of squared radial deviations from the cylinder surface using scipy.optimize.least_squares.
The axis is parametrized minimally with respect to the dominant component of the initial guess direction to avoid gauge freedom: the dominant direction component is fixed to one while the remaining two components are free, and the axis point is constrained to the plane where the dominant coordinate is zero. This leaves four free parameters for the axis (two for orientation, two for position), plus the radius if it is not fixed.
- Parameters:
- pointsndarray
Array of shape (N, 3) containing the (x, y, z) coordinates of the point cloud.
- guessCylinder
Initial guess for the cylinder. A good guess for the axis orientation, position and radius is required for reliable convergence.
- radiusfloat | None, default None
If provided, the radius is held fixed at this value and only the axis is optimized. If None, the radius is optimized as well, starting from
guess.radius.
- Returns:
- Cylinder
The fitted cylinder.
- intersect_vertical(x, y, z_reference)¶
Intersects vertical lines (parallel to the z-axis) at positions (x, y) with the cylinder surface and returns the z-coordinate of the intersection. For each (x, y) position there are generally two intersections (the upper and lower side of the cylinder); the one closest to
z_referenceis returned. Positions whose vertical line does not intersect the cylinder yield NaN.- Parameters:
- x, yndarray
Coordinates at which to intersect.
- z_referencendarray
Reference z-values used to select between the two intersection points (typically the measured heights).
- Returns:
- ndarray
z-coordinate of the cylinder surface at each (x, y) position.
- residuals(points)¶
Computes the signed radial deviation of points from the cylinder surface, i.e. the distance to the axis minus the radius.
- Parameters:
- pointsndarray
Array of shape (N, 3) containing the (x, y, z) coordinates of N points.
- Returns:
- ndarray
Array of shape (N,) containing the radial deviation of each point.
- class surfalize.mathutils.Sinusoid(amplitude, period, x0, y0)¶
Bases:
objectGeneric sinusoid representation.
- Parameters:
- amplitudefloat
amplitude.
- periodfloat
period.
- x0float
offset in x.
- y0float
offset in y.
Methods
__call__(x)Computes the value of a generic sinusoid at position x.
Compute the position of the first extremum (peak or valley) for x >= 0.
Compute the position of the first peak for x >= 0.
from_fit(xdata, ydata[, p0, infer_p0])Fit a general sinusoid to x and y data using scipy.optimize.curve_fit.
- first_extremum()¶
Compute the position of the first extremum (peak or valley) for x >= 0.
- Returns:
- xfefloat
- first_peak()¶
Compute the position of the first peak for x >= 0.
- Returns:
- xfpfloat
- classmethod from_fit(xdata, ydata, p0=None, infer_p0=False)¶
Fit a general sinusoid to x and y data using scipy.optimize.curve_fit. Optionally, an initial guess for the sinusoid parameters a, p, x0, y0 can be specified using the p0 keyword argument, where a is the amplitude, p is the period, x0 is the lateral and y0 the vertical offset.
This function uses unbounded fitting, which can result in negative amplitude, because bounded fitting using scipy.optimize.curve_fit invokes a different algorithm which seems to perform worse on this specific fitting problem. Instead, a result with negative amplitude is converted into the positive amplitude equivalent by phase shifting.
- Parameters:
- xdatalist-like
array of x-data
- ydatalist-like
array of y-data
- p0list-like[float, float, float, float] | None, defaults to None
Optional initial guess for the parameters a, p, x0, y0.
- infer_p0bool, defaults to False
If True, automatically infers starting guesses of the parameters. Any values provided to the p0 keyword argument will be overwritten with the automatically inferred values.
- Returns:
- Sinusoid
- surfalize.mathutils.argclosest(x, xdata)¶
Returns the index of the value in an array that is closest to the value x.
- Parameters:
- xfloat
value to which closest array value index should be computed
- xdataarray_like
array of x-values
- Returns:
- indexint
Index of the value in xdata that is closest to x.
- surfalize.mathutils.argmax_all(arr)¶
Returns all indices where the array reaches its maximum value.
- Parameters:
- arrarray-like
Input array
- Returns:
- numpy.ndarray
Array of indices where the maximum value occurs
- surfalize.mathutils.argmin_all(arr)¶
Returns all indices where the array reaches its minimum value.
- Parameters:
- arrarray-like
Input array
- Returns:
- numpy.ndarray
Array of indices where the minimum value occurs
- surfalize.mathutils.closest(x, data)¶
Returns the value in an array that is closest to the value x.
- Parameters:
- xfloat
value to which closest array value index should be computed
- xdataarray_like
array of x-values
- Returns:
- value
Value in xdata that is closest to x.
- surfalize.mathutils.get_period_fft_1d(xdata, ydata)¶
Estimates the dominant period from a 1d periodic profile with uniformly spaced points.
- Parameters:
- xdatalist-like
array of uniformly spaced xdata.
- ydatalist-like
array of ydata with the same size as xdata.
- Returns:
- periodfloat
- surfalize.mathutils.interp1d(xdata, ydata, assume_sorted=False)¶
Creates a function that linearly interpolates the given x- and y-data at any value of x.
Mimics scipy.interpolate.interp1d, since the scipy version is no longer supported and might be removed in future versions. Contrary to the scipy implementation, assume_sorted is False by default, since a default True value would lead to more errors. If the xdata is sorted in ascending order, then assume_sorted can be set to True to gain a performance increase.
- Parameters:
- xdataarray_like
array of x-values
- ydataarray_like
array of y-values
- assume_sortedbool, default False
If True, they xdata array must be supplied with ascendingly ordered values and sorting is skipped. If False, the array xdata will be sorted in ascending order and the array ydata will be sorted accordingly.
- Returns:
- function
Linear interpolation function y(x).
- surfalize.mathutils.interpolate_line_on_2d_array(array, start, end, order=3, num_points=100)¶
Interpolates a line between two points on a 2d array using spline interpolation.
- Parameters:
- array2d array-like
- starttuple[int, int]
Index of the start point.
- endtuple[int, int]
Index of the end point.
- orderint
Order of spline interpolation. Defaults to 3.
- num_pointsint
Number of points of the interpolated line. Defaults to 100.
- Returns:
- np.ndarray
- surfalize.mathutils.otsu_threshold(values, nbins=256)¶
Computes the optimal threshold that separates the values into two classes using Otsu’s method, which maximizes the between-class variance. For one-dimensional two-class segmentation this yields the global optimum and is a fast, deterministic alternative to a two-cluster k-means.
- Parameters:
- valuesarray_like
Input values. Non-finite values (NaN, inf) are ignored.
- nbinsint, default 256
Number of histogram bins used to evaluate the threshold.
- Returns:
- thresholdfloat
Value separating the two classes. Values greater than the threshold belong to the upper class.
- surfalize.mathutils.resolve_box(box, border, x_max, y_max)¶
Resolves a rectangle specification from either an explicit box or a border inset.
Exactly one of box or border must be given. box is returned unchanged as an (x0, x1, y0, y1) tuple. border specifies the distance from each edge inwards to the rectangle, in the same units and axis order as box: a scalar insets all four edges equally, while an (x0, x1, y0, y1) tuple insets each edge individually. x_max and y_max are the coordinates of the far edges (width_um/height_um in physical units, or size.x - 1/size.y - 1 in pixels).
- Parameters:
- boxtuple[float, float, float, float] | None
Explicit rectangle as (x0, x1, y0, y1), or None if border is used instead.
- borderfloat | tuple[float, float, float, float] | None
Distance from each edge inwards, as a scalar or (x0, x1, y0, y1) tuple, or None if box is used instead.
- x_max, y_maxfloat
Coordinates of the far edges along x and y.
- Returns:
- boxtuple[float, float, float, float]
The resolved (x0, x1, y0, y1) rectangle.