Process reference: camera_geometry

Generated from the docstrings of vaft.process.camera_geometry: 4 public functions. Each entry is what vaft.process.describe("camera_geometry.<name>") prints. All process categories

Overview

Pure array-in/array-out functions (no ODS, no file I/O) mirroring the style of vaft.process.equilibrium. Reproduces the forward/virtual-camera projection used by the VEST_Fast Camera_Diagnostics repository’s camera_geometry.ipynb (see that repo’s CALIBRATION.md): a standard OpenCV pinhole model with Brown-Conrady radial/tangential distortion, cv2.projectPoints, applied directly with a shot’s calibrated (rvec, tvec) pose onto the ORIGINAL (distorted) camera frame. Per that notebook’s own documented finding (cell 50), the recovered pose is the true physical camera attitude regardless of which click-point convention was used to solve for it, so no undistortion or newOrigin handling is needed at projection time – one formula for every calibrated shot.

World points are in centimeters throughout, matching the packaged calibration convention: (X, Y, Z)_cm = (R_m * cos(theta), R_m * sin(theta), Z_m) * 100.

Functions

project_pointsProject world points into camera pixels, flagging the ones the model cannot be trusted for. Convention
sweep_toroidalSweep poloidal points through toroidal angles into world points. Convention
toroidal_ringSweep one poloidal point into a full toroidal ring. Convention
trajectory_world_pointsConvert a matched trajectory of cylindrical coordinates into world points. Convention

project_points

Machine-independentConvention-sensitive source
project_points(world_xyz_cm, rvec, tvec, camera_matrix, dist_coeffs, *, max_normalized_radius=1.3)

Project world points into camera pixels, flagging the ones the model cannot be trusted for.

NameTypeUnitDescription
world_xyz_cmarray_likecm

World points as (N, 3), in the machine frame.

rvecarray_likerad

Rotation vector of the calibrated camera pose, Rodrigues form.

tvecarray_likecm

Translation vector of that pose.

camera_matrixarray_like-

Intrinsic matrix, 3x3.

dist_coeffsarray_like-

Brown-Conrady radial and tangential distortion coefficients.

max_normalized_radiusfloat, optional-

Largest normalized image-plane radius still considered inside the model’s fitted range.

Returns
pixel_uvnp.ndarray-

Pixel positions as (N, 2) in column-then-row order.

valid_masknp.ndarray-

True where the projection can be trusted.

Convention

Pixels are returned column first, then row, which is the opposite of the row-then-column order an image array is indexed with. World points are in centimetres, matching the packaged calibration, while every other geometry argument in this package is in metres; the sweep helpers here do that conversion.

The pose is applied directly to the original distorted frame. Per the source notebook’s own finding, the recovered pose is the true physical camera attitude whichever click-point convention solved for it, so no undistortion step is needed and one formula serves every calibrated shot.

Defaults · Applicability · Limitations · Provenance

Defaults

max_normalized_radius = 1.3 is a validated-workflow default, the same guard the source notebook applies in its own projection routine.

Applicability

Machine-independent. Standard OpenCV pinhole geometry; the calibration that makes it a VEST camera is supplied by the caller.

Limitations

Two kinds of point are excluded rather than projected. A point behind the camera has non-positive depth and no meaningful pixel. A point far off the optical axis lies outside the angular range the distortion polynomial was fitted over, where that polynomial can turn non-monotonic and place the point at a wildly wrong pixel rather than smoothly off-frame; the mask catches that case, which is why it is a validity test and not a crop.

Requires OpenCV, imported at call time.

Provenance

  1. The VEST FAST camera diagnostics repository’s camera_geometry.ipynb and its CALIBRATION.md; this reproduces that notebook’s projection, including the depth and field-of-view guard from its own routine.

sweep_toroidal

Machine-independentConvention-sensitive source
sweep_toroidal(r_m, z_m, theta_rad)
Show source vaft/process/camera_geometry.py, lines 172–227
def sweep_toroidal(r_m: np.ndarray, z_m: np.ndarray, theta_rad: np.ndarray) -> np.ndarray:
    """Sweep poloidal points through toroidal angles into world points.

    Parameters
    ----------
    r_m : array_like
        Major radius of each poloidal point [m].
    z_m : array_like
        Height of each poloidal point, same shape as *r_m* [m].
    theta_rad : array_like
        Toroidal angles to sweep through [rad].

    Returns
    -------
    np.ndarray
        World points as ``(len(theta) * len(r), 3)``, one row per angle and point
        combination [cm].

    Raises
    ------
    ValueError
        The two poloidal arrays do not have the same shape.

    Convention
    ----------
    ``X = R cos(theta)``, ``Y = R sin(theta)``, ``Z = Z``, then converted from
    metres to centimetres because the packaged calibration is in centimetres.
    Rows vary fastest over the poloidal points and slowest over the angles.

    This is an **outer product**: every point is swept through every angle, giving
    a surface. :func:`trajectory_world_points` pairs them element-wise instead,
    for a single ordered path. Confusing the two produces an array of the wrong
    length rather than an error.

    Applicability
    -------------
    Machine-independent.

    Provenance
    ----------
    .. [1] Reproduces the source notebook's torus sweep; see
       :func:`project_points` for the repository and calibration reference.
    """
    r = np.asarray(r_m, dtype=np.float64).reshape(-1)
    z = np.asarray(z_m, dtype=np.float64).reshape(-1)
    theta = np.asarray(theta_rad, dtype=np.float64).reshape(-1)
    if r.shape != z.shape:
        raise ValueError("r_m and z_m must have the same shape.")

    cos_theta = np.cos(theta)
    sin_theta = np.sin(theta)
    x = np.outer(cos_theta, r).reshape(-1)
    y = np.outer(sin_theta, r).reshape(-1)
    z_tiled = np.tile(z, theta.size)

    return np.stack([x, y, z_tiled], axis=1) * 100.0

Sweep poloidal points through toroidal angles into world points.

NameTypeUnitDescription
r_marray_likem

Major radius of each poloidal point.

z_marray_likem

Height of each poloidal point, same shape as r_m.

theta_radarray_likerad

Toroidal angles to sweep through.

Returns
—np.ndarraycm

World points as (len(theta) * len(r), 3), one row per angle and point combination.

Convention

X = R cos(theta), Y = R sin(theta), Z = Z, then converted from metres to centimetres because the packaged calibration is in centimetres. Rows vary fastest over the poloidal points and slowest over the angles.

This is an outer product: every point is swept through every angle, giving a surface. trajectory_world_points pairs them element-wise instead, for a single ordered path. Confusing the two produces an array of the wrong length rather than an error.

Raises

  • ValueError The two poloidal arrays do not have the same shape.
Applicability · Provenance

Applicability

Machine-independent.

Provenance

  1. Reproduces the source notebook’s torus sweep; see project_points for the repository and calibration reference.

toroidal_ring

Machine-independentConvention-sensitive source
toroidal_ring(r_m, z_m, theta_rad)
Show source vaft/process/camera_geometry.py, lines 230–260
def toroidal_ring(r_m: float, z_m: float, theta_rad: np.ndarray) -> np.ndarray:
    """Sweep one poloidal point into a full toroidal ring.

    Parameters
    ----------
    r_m : float
        Major radius of the point [m].
    z_m : float
        Height of the point [m].
    theta_rad : array_like
        Toroidal angles making up the ring [rad].

    Returns
    -------
    np.ndarray
        World points as ``(len(theta), 3)`` [cm].

    Convention
    ----------
    The single-point case of :func:`sweep_toroidal`, with the same axis
    definitions and the same conversion from metres to centimetres.

    Applicability
    -------------
    Machine-independent.

    Provenance
    ----------
    .. [1] :func:`sweep_toroidal`, which this delegates to.
    """
    return sweep_toroidal(np.array([float(r_m)]), np.array([float(z_m)]), theta_rad)

Sweep one poloidal point into a full toroidal ring.

NameTypeUnitDescription
r_mfloatm

Major radius of the point.

z_mfloatm

Height of the point.

theta_radarray_likerad

Toroidal angles making up the ring.

Returns
—np.ndarraycm

World points as (len(theta), 3).

Convention

The single-point case of sweep_toroidal, with the same axis definitions and the same conversion from metres to centimetres.

Applicability · Provenance

Applicability

Machine-independent.

Provenance

  1. sweep_toroidal, which this delegates to.

trajectory_world_points

Machine-independentConvention-sensitive source
trajectory_world_points(r_m, z_m, phi_rad)
Show source vaft/process/camera_geometry.py, lines 263–308
def trajectory_world_points(r_m: np.ndarray, z_m: np.ndarray, phi_rad: np.ndarray) -> np.ndarray:
    """Convert a matched trajectory of cylindrical coordinates into world points.

    Parameters
    ----------
    r_m : array_like
        Major radius along the trajectory [m].
    z_m : array_like
        Height along the trajectory, same shape [m].
    phi_rad : array_like
        Toroidal angle at each point, same shape [rad].

    Returns
    -------
    np.ndarray
        World points as ``(N, 3)``, one row per trajectory point [cm].

    Raises
    ------
    ValueError
        The three arrays do not all have the same shape.

    Convention
    ----------
    **Element-wise pairing**, one angle per point, for an ordered path such as a
    traced field line. :func:`sweep_toroidal` takes the outer product instead and
    gives a surface. Same axis definitions and the same conversion to centimetres.

    Applicability
    -------------
    Machine-independent.

    Provenance
    ----------
    .. [1] The world-frame convention of the source notebook; see
       :func:`project_points`.
    """
    r = np.asarray(r_m, dtype=np.float64).reshape(-1)
    z = np.asarray(z_m, dtype=np.float64).reshape(-1)
    phi = np.asarray(phi_rad, dtype=np.float64).reshape(-1)
    if not (r.shape == z.shape == phi.shape):
        raise ValueError("r_m, z_m, and phi_rad must have the same shape.")

    x = r * np.cos(phi)
    y = r * np.sin(phi)
    return np.stack([x, y, z], axis=1) * 100.0

Convert a matched trajectory of cylindrical coordinates into world points.

NameTypeUnitDescription
r_marray_likem

Major radius along the trajectory.

z_marray_likem

Height along the trajectory, same shape.

phi_radarray_likerad

Toroidal angle at each point, same shape.

Returns
—np.ndarraycm

World points as (N, 3), one row per trajectory point.

Convention

Element-wise pairing, one angle per point, for an ordered path such as a traced field line. sweep_toroidal takes the outer product instead and gives a surface. Same axis definitions and the same conversion to centimetres.

Raises

  • ValueError The three arrays do not all have the same shape.
Applicability · Provenance

Applicability

Machine-independent.

Provenance

  1. The world-frame convention of the source notebook; see project_points.

results matching ""

    No results matching ""