Source code for zapmenot.ray

'''
ZapMeNot - a point kernel photon shielding library
Copyright (C) 2019-2025  C. Alan Ford

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <https://www.gnu.org/licenses/>.
'''

import numpy as np
import numbers
from collections.abc import Iterable


[docs] class FiniteLengthRay: """Represents a ray in three-space. The FiniteLengthRay object has a defined starting point, a defined end, and a resulting direction. Parameters ---------- start : :class:`list` or :class:`tuple` Defines the starting point of the ray in cartesian coordinates. end : :class:`list` or :class:`tuple` Defines the ending point of the ray in cartesian coordinates. """ ''' Attributes ---------- _start _end _origin : :class:`numpy.ndarray` A vector implemenation of the starting point. _length : float The length of the ray. _dir : :class:`numpy.ndarray` A numpy vector holding the vector normal of the ray. _invdir : :class:`numpy.ndarray` A numpy vector holding the inverse of the vector _dir. _sign : :class:`numpy.ndarray` Indicates the signs of the components of :py:obj:`dir`. ''' def __init__(self, start, end): if not FiniteLengthRay._is_validate_vector(start): raise ValueError("Invalid ray start") if not FiniteLengthRay._is_validate_vector(end): raise ValueError("Invalid ray end") self._start = start self._end = end self._regularize() @property def start(self): """:class:`list` : A list defining the starting point of the ray in cartesian coordinates.""" return self._start @start.setter def start(self, value): if not FiniteLengthRay._is_validate_vector(value): raise ValueError("Invalid ray start") self._start = value self._regularize() @property def end(self): """:class:`list` : A list defining the ending point of the ray in cartesian coordinates.""" return self._end @end.setter def end(self, value): if not FiniteLengthRay._is_validate_vector(value): raise ValueError("Invalid ray end") self._end = value self._regularize() def _regularize(self): """Calculates the mean free path for a given distance and photon energy Parameters ---------- energy : float The photon energy in MeV distance : float The distance through the material in cm """ self._origin = np.array(self._start) v = np.array(self._end) - self._origin self._length = np.linalg.norm(v) # direction doesn't matter if the length is zero if self._length == 0: self._dir = np.zeros(3) else: self._dir = v / self._length with np.errstate(divide='ignore'): self._invdir = 1/self._dir # vector is opposite of vector dir self._sign = [0, 0, 0] self._sign[0] = int((self._invdir[0] < 0)) self._sign[1] = int((self._invdir[1] < 0)) self._sign[2] = int((self._invdir[2] < 0)) @staticmethod def _is_validate_vector(vector): # vector should be a list if not (isinstance(vector, Iterable)): return False # vector should have a length of 3 if not (len(vector) == 3): return False # each element should be a number if not all([isinstance(item, numbers.Number) for item in vector]): return False return True