Source code for pyRadPlan.geometry.lps
"""Geometry functions for LPS system."""
import numpy as np
import array_api_compat
from ..core.xp_utils.typing import Array
[docs]
def get_gantry_rotation_matrix(gantry_angle: Array) -> Array:
"""
Calculate the rotation matrix for gantry.
Represents an active, counter-clockwise rotation Matrix for Gantry around z
with pre-multiplication of the matrix (R*x).
Parameters
----------
gantry_angle : Array
The angle of gantry rotation in degrees.
Returns
-------
Array
The rotation matrix.
Notes
-----
Gantry rotation is physically an active rotation of a beam
vector around the target / isocenterin the patient coordinate
system
The LPS system is right-handed, where the gantry rotates counter-clockwise around the z-axis
and the couch rotates counter-clockwise around the y-axis.
The gantry rotation is an active rotation of a beam vector around the target/isocenter
in the patient coordinate system.
"""
xp = array_api_compat.array_namespace(gantry_angle)
gantry_angle = gantry_angle / 180 * xp.pi
c = xp.cos(gantry_angle)
s = xp.sin(gantry_angle)
dev = array_api_compat.device(gantry_angle)
zero = xp.zeros((), dtype=c.dtype, device=dev)
one = xp.ones((), dtype=c.dtype, device=dev)
r_gantry = xp.stack(
[
xp.stack([c, -s, zero]),
xp.stack([s, c, zero]),
xp.stack([zero, zero, one]),
]
)
return r_gantry
[docs]
def get_couch_rotation_matrix(couch_angle: Array) -> Array:
"""
Calculate the rotation matrix for the couch.
Parameters
----------
couch_angle : Array
The angle of couch rotation in degrees.
Returns
-------
Array
The rotation matrix.
Notes
-----
The LPS system is right-handed, where the gantry rotates counter-clockwise around the z-axis
and the couch rotates counter-clockwise around the y-axis.
The gantry rotation is an active rotation of a beam vector around the target/isocenter
in the patient coordinate system.
"""
xp = array_api_compat.array_namespace(couch_angle)
couch_angle = couch_angle / 180 * xp.pi
c = xp.cos(couch_angle)
s = xp.sin(couch_angle)
dev = array_api_compat.device(couch_angle)
zero = xp.zeros((), dtype=c.dtype, device=dev)
one = xp.ones((), dtype=c.dtype, device=dev)
r_gantry = xp.stack(
[
xp.stack([c, zero, s]),
xp.stack([zero, one, zero]),
xp.stack([-s, zero, c]),
]
)
return r_gantry
[docs]
def get_beam_rotation_matrix(gantry_angle: Array, couch_angle: Array) -> Array:
"""
Calculate the rotation matrix for gantry and couch angles.
Represents active, counter-clockwise rotation for couch around y
with pre-multiplication of the matrix (R*x)
Parameters
----------
gantry_angle : Array
The angle of gantry rotation in degrees.
couch_angle : Array
The angle of couch rotation in degrees.
Returns
-------
Array
The 3x3 rotation matrix.
Notes
-----
Couch rotation is physically a passive rotation of the
patient system around the beam target point / isocenter
The LPS system is right-handed, where the gantry rotates counter-clockwise around the z-axis
and the couch rotates counter-clockwise around the y-axis.
The gantry rotation is an active rotation of a beam vector around the target/isocenter
in the patient coordinate system.
Examples
--------
>>> get_beam_rotation_matrix(90, 45)
array([[ 0. , -0.70710678, 0.70710678],
[ 1. , 0. , 0. ],
[ 0. , 0.70710678, 0.70710678]])
"""
# Array API compatibility requires angles to be arrays.
# Force to numpy arrays. Legacy code would have done so either way.
if isinstance(gantry_angle, (int, float)):
gantry_angle = np.asarray(gantry_angle)
if isinstance(couch_angle, (int, float)):
couch_angle = np.asarray(couch_angle)
r_gantry = get_gantry_rotation_matrix(gantry_angle)
r_couch = get_couch_rotation_matrix(couch_angle)
rot_mat = r_couch @ r_gantry
return rot_mat