utils#
Optiland Utilities Module
This module provides utility functions for optical system analysis, including the calculation of the working F-number (F/#) of an optical system.
Kramer Harrison, 2025
Functions
|
Return only FieldPoints with weight > 0. |
|
Return only WavelengthPoints with weight > 0. |
|
Retrieve an attribute of an object using a dot-separated path. |
|
Calculates the working F-number of the optical system for the single defined field point and given wavelength. |
|
Transform local surface coordinates to global coordinates. |
|
Classify per-element |
|
Machine epsilon of |
|
Resolve field input into a list of FieldPoints (coord + weight). |
|
Resolves a single wavelength input into a float value. |
|
Resolve wavelength input into a list of WavelengthPoints (value + weight). |
|
Set an attribute of an object using a dot-separated path. |
|
Solve per-element |
|
Compute a weighted normalized average: Σ(w_i × x_i) / Σ(w_i). |
Classes
|
A resolved field coordinate with its associated weight. |
|
Scale-invariant conditioning state of per-element |
|
Outcome of a batched, conditioning-aware 2x2 linear solve. |
|
A resolved wavelength value with its associated weight. |
- class FieldPoint(coord: tuple[float, float], weight: float)[source]#
A resolved field coordinate with its associated weight.
- Variables:
- class Jacobian2x2Condition(a: Any, b: Any, c: Any, d: Any, scale: Any, det: Any, rcond: Any, singular: Any)[source]#
Scale-invariant conditioning state of per-element
2x2matrices.- Variables:
d (a, b, c,) – Entries of the normalized matrix
A = J / s.scale (Any) – Per-element normalization
s = max(|J11|,|J12|,|J21|,|J22|), replaced by 1 wheres == 0(those elements are singular).det (Any) – Determinant of the normalized matrix
A(sign preserved).rcond (Any) – Reciprocal Frobenius-condition estimate
|det(A)| / ||A||_F^2.singular (Any) – Per-element mask – non-finite entries, zero scale, or reciprocal condition at round-off level.
- class LinearSolve2x2Result(x1: Any, x2: Any, rcond: Any, valid: Any)[source]#
Outcome of a batched, conditioning-aware 2x2 linear solve.
- Variables:
x2 (x1,) – Per-element solution of
J @ [x1, x2] = [r1, r2]; exact zeros wherevalidis False (never a clipped step).rcond (Any) – Scale-invariant reciprocal Frobenius-condition estimate of each element’s matrix.
valid (Any) – Per-element mask; False where the matrix is singular or ill-conditioned at round-off level and no solution was formed.
- class WavelengthPoint(value: float, weight: float)[source]#
A resolved wavelength value with its associated weight.
- Variables:
- active_fields(resolved: list[FieldPoint]) list[FieldPoint][source]#
Return only FieldPoints with weight > 0. Use in weighted contexts.
- Parameters:
resolved – A list of FieldPoint named tuples.
- Returns:
Filtered list containing only items with positive weight.
- active_wavelengths(resolved: list[WavelengthPoint]) list[WavelengthPoint][source]#
Return only WavelengthPoints with weight > 0. Use in weighted contexts.
- Parameters:
resolved – A list of WavelengthPoint named tuples.
- Returns:
Filtered list containing only items with positive weight.
- get_attr_by_path(obj: Any, path: str) Any[source]#
Retrieve an attribute of an object using a dot-separated path. Supports list indexing, e.g., ‘surfaces[1].geometry.radius’.
- Parameters:
obj – The object to retrieve the attribute from.
path – The dot-separated path to the attribute.
- Returns:
The value of the attribute.
- get_working_FNO(optic, field, wavelength)[source]#
Calculates the working F-number of the optical system for the single defined field point and given wavelength.
- Parameters:
- Algorithm:
Retrieve the defined given wavelength and field coordinates.
Determine the image-space refractive index ‘n’ at the given wavelength.
Trace four marginal rays (top, bottom, left, right) at the pupil edges, as well as the chief ray.
Compute the angle between each marginal ray and the chief ray.
Calculate the average of the squared numerical apertures from all traced marginal rays.
Compute the working F-number as 1 / (2 * be.sqrt(average_NA_squared)).
Cap the calculated F/# at 10,000 if it exceeds this value.
- Returns:
The working F-number.
- Return type:
- globalize_coordinates(surface, x_local, y_local, z_local)[source]#
Transform local surface coordinates to global coordinates.
- Parameters:
surface – The surface whose coordinate system is used for the transformation.
x_local (BEArray) – The local x-coordinates.
y_local (BEArray) – The local y-coordinates.
z_local (BEArray) – The local z-coordinates.
- Returns:
(x_global, y_global, z_global) as flattened backend arrays.
- Return type:
- jacobian_2x2_condition(J11, J12, J21, J22) Jacobian2x2Condition[source]#
Classify per-element
2x2matrices with a scale-invariant test.Normalizes each element’s matrix by its largest-magnitude entry and computes the reciprocal Frobenius-condition estimate
rho_F = |det(A)| / (a^2 + b^2 + c^2 + d^2),which for a
2x2matrix bounds1 / cond_F(J). The classification is invariant under a global scaling of the matrix, so a well-conditioned but small-magnitude matrix (e.g.1e-3 * Iin float32) is never misclassified as singular. This is the single authority for 2x2 conditioning across Optiland (field solves and ray aiming); do not duplicate determinant logic elsewhere.
- machine_eps(value) float[source]#
Machine epsilon of
value’s floating dtype.Backend-agnostic: uses
torch.finfofor torch tensors and numpy’sfinfootherwise. Numerical thresholds built from this scale correctly in float32, where a hardcoded float64-sized constant is below round-off and therefore never triggers.- Parameters:
value – A backend array/tensor, or anything without a
dtypeattribute (treated as the default Python float precision).- Returns:
The machine epsilon for the corresponding dtype.
- Return type:
- resolve_fields(optic, fields) list[FieldPoint][source]#
Resolve field input into a list of FieldPoints (coord + weight).
When fields=’all’, field weights come from optic.fields. For any user-supplied raw coordinates (list of tuples, a single tuple, or an integer index), weight defaults to 1.0 because there is no associated Field object to look up the weight from.
- Parameters:
optic (Optic) – The optical system.
fields – ‘all’, a list of (x, y) tuples, a single (x, y) tuple, or an integer index into optic.fields.
- Returns:
List of FieldPoint named tuples. Each has .coord (x, y) and .weight.
- Raises:
ValueError – If fields is an invalid string.
TypeError – If fields is not one of the supported types.
- resolve_wavelength(optic, wavelength)[source]#
Resolves a single wavelength input into a float value.
- resolve_wavelengths(optic, wavelengths) list[WavelengthPoint][source]#
Resolve wavelength input into a list of WavelengthPoints (value + weight).
When wavelengths=’all’, weights come from optic.wavelengths. For ‘primary’, the primary wavelength’s weight is used. For user-supplied raw float values (list of floats), weight defaults to 1.0.
- Parameters:
optic (Optic) – The optical system.
wavelengths – ‘all’, ‘primary’, or a list of float wavelength values in µm.
- Returns:
List of WavelengthPoint named tuples. Each has .value (float, µm) and .weight.
- Raises:
ValueError – If wavelengths is an invalid string.
TypeError – If wavelengths is not a string or list.
- set_attr_by_path(obj: Any, path: str, value: Any) None[source]#
Set an attribute of an object using a dot-separated path. Supports list indexing, e.g., ‘surfaces[1].geometry.radius’.
- Parameters:
obj – The object to set the attribute on.
path – The dot-separated path to the attribute.
value – The value to set.
- solve_2x2(J11, J12, J21, J22, r1, r2) LinearSolve2x2Result[source]#
Solve per-element
J @ x = rvia the normalized system.Each element’s matrix is normalized by its largest-magnitude entry (see
jacobian_2x2_condition()), which makes both the singularity classification and the solve invariant under global scaling and avoids raw-determinant overflow/underflow. The determinant’s sign is preserved for every valid element – it is never clamped to an arbitrary positive value, so a Newton step formed from the solution can never be silently reversed. Singular elements receive an exact zero solution andvalid = False, leaving the caller to refresh, substitute or hold.- Parameters:
J11 – Per-element matrix entries.
J12 – Per-element matrix entries.
J21 – Per-element matrix entries.
J22 – Per-element matrix entries.
r1 – Per-element right-hand sides.
r2 – Per-element right-hand sides.
- Returns:
The
LinearSolve2x2Resultwith solutions, reciprocal condition estimates and the validity mask.
- weighted_average(values: list[float], weights: list[float]) float[source]#
Compute a weighted normalized average: Σ(w_i × x_i) / Σ(w_i).
- Parameters:
values – Scalar values to average.
weights – Non-negative weights (must have same length as values). Zero-weight items contribute nothing; Σ(w_i) must be > 0.
- Returns:
Weighted normalized average.
- Raises:
ValueError – If all weights are zero.