Source code for toor.DetectionLayout.Collimators.collimatorGeneric

import numpy as np


[docs] class CollimatorGeneric(object): def __init__(self): """ Collimator geometry Bore size: 1.28 x 1.28 mm Septa length: 2.3 cm """ self._boreSize = [1.28, 1.28] self._septaWidth = 0.32 self._septaLength = 23 self._distanceToDetector = 0 #1.9 self._yShiftCenterOfDetectorToCollimatorCenter = 0 self._zShiftCenterOfDetectorToCollimatorCenter = 0 self._collimatorDensity = None self._collimatorShape = "Square parallel-hole" self._collimatorMaterial = "Tungsten-alloy" if self._collimatorShape == "Square parallel-hole": self._areaSepta = self._boreSize[0] * self._boreSize[1] self._vertex1 = None self._vertex2 = None self._vertex3 = None self._vertex4 = None self._focalPoint = None self._centerOutsideFace = None self._initialMatrix = None
[docs] def joinPyramidPointsIntoArray(self): """ Join the points of the pyramid into a numpy array :return: """ return np.array([self._focalPoint[0], self._focalPoint[1], self._focalPoint[2], self._vertex1[0], self._vertex1[1], self._vertex1[2], self._vertex2[0], self._vertex2[1], self._vertex2[2], self._vertex3[0], self._vertex3[1], self._vertex3[2], self._vertex4[0], self._vertex4[1], self._vertex4[2]], dtype=np.float32).T
[docs] def calculateInitialPyramidalVertex(self, CztModule, alpha=0, beta=0, sigma=0, x=0, y=0, z=0, angunit="deg"): """ Calculate the initial farest vertices of the collimator :param CztModule object :return: """ distanceFromPoint = [-self._septaLength, self._boreSize[0] / 2, self._boreSize[1] / 2] shifts = [self._distanceToDetector, -self._yShiftCenterOfDetectorToCollimatorCenter, -self._zShiftCenterOfDetectorToCollimatorCenter] self._vertex1 = CollimatorGeneric.vectorVertex(CztModule.initialMatrix, distanceFromPoint, shifts) distanceFromPoint = [-self._septaLength, -self._boreSize[0] / 2, self._boreSize[1] / 2] self._vertex2 = CollimatorGeneric.vectorVertex(CztModule.initialMatrix, distanceFromPoint, shifts) distanceFromPoint = [-self._septaLength, -self._boreSize[0] / 2, -self._boreSize[1] / 2] self._vertex3 = CollimatorGeneric.vectorVertex(CztModule.initialMatrix, distanceFromPoint, shifts) distanceFromPoint = [-self._septaLength, self._boreSize[0] / 2, -self._boreSize[1] / 2] self._vertex4 = CollimatorGeneric.vectorVertex(CztModule.initialMatrix, distanceFromPoint, shifts) self._focalPoint = CztModule.initialMatrix # self._focalPoint[0] -= 23/2 self._vertex1 = self.rotateAndTranslate(self._vertex1, alpha=alpha, beta=beta, sigma=sigma, x=x, y=y, z=z, angunit=angunit) self._vertex2 = self.rotateAndTranslate(self._vertex2, alpha=alpha, beta=beta, sigma=sigma, x=x, y=y, z=z, angunit=angunit) self._vertex3 = self.rotateAndTranslate(self._vertex3, alpha=alpha, beta=beta, sigma=sigma, x=x, y=y, z=z, angunit=angunit) self._vertex4 = self.rotateAndTranslate(self._vertex4, alpha=alpha, beta=beta, sigma=sigma, x=x, y=y, z=z, angunit=angunit) self._focalPoint = self.rotateAndTranslate(self._focalPoint, alpha=alpha, beta=beta, sigma=sigma, x=x, y=y, z=z, angunit=angunit)
# generate a function to calculate the intersection of two vectors
[docs] def rotateAndTranslate(self, point, alpha=0, beta=0, sigma=0, x=0, y=0, z=0, angunit="deg"): """ Rotates and translates the initial matrix according to the given angles and translations. Args: alpha (float): The angle of rotation around the x axis. beta (float): The angle of rotation around the y axis. sigma (float): The angle of rotation around the z axis. x (float): The translation in the x axis. y (float): The translation in the y axis. z (float): The translation in the z axis. angunit (str): The unit of the angles. Default is "deg" for degrees. """ # self.alphaRotation += alpha # self.betaRotation += beta # self.sigmaRotation += sigma # self.xTranslation += x # self.yTranslation += y # self.zTranslation += z if angunit == "deg": alpha = np.deg2rad(alpha) beta = np.deg2rad(beta) sigma = np.deg2rad(sigma) A = np.array([[np.cos(sigma) * np.cos(beta), -np.sin(sigma) * np.cos(alpha) + np.cos(sigma) * np.sin(beta) * np.sin(alpha), np.sin(sigma) * np.sin(alpha) + np.cos(sigma) * np.sin(beta) * np.cos(alpha), x], [np.sin(sigma) * np.cos(beta), np.cos(sigma) * np.cos(alpha) + np.sin(sigma) * np.sin(beta) * np.sin(alpha), -np.cos(sigma) * np.sin(alpha) + np.sin(sigma) * np.sin(beta) * np.cos(alpha), y], [-np.sin(beta), np.cos(beta) * np.sin(alpha), np.cos(beta) * np.cos(alpha), z], [0, 0, 0, 1]], dtype=np.float32) B = np.ones((4, point.shape[1])) B[0:3] = point return np.array([A[0, 0] * B[0] + A[0, 1] * B[1] + A[0, 2] * B[2] + A[0, 3] * B[3], A[1, 0] * B[0] + A[1, 1] * B[1] + A[1, 2] * B[2] + A[1, 3] * B[3], A[2, 0] * B[0] + A[2, 1] * B[1] + A[2, 2] * B[2] + A[2, 3] * B[3]], dtype=np.float32)
[docs] def calculateFocalPoint(self, CztModule): """ Calculate the focal point of the collimator :param CztModule object :return: """ # calculate the focal point # calculate the center of the outside face pass
[docs] @staticmethod def vectorVertex(centerpoint, distanceFromPoint, shift): """ Calculate the vector of the vertice :param centerpoint: :param distanceFromPoint: :param shift: :return: """ point = np.zeros(centerpoint.shape) for i in range(3): point[i] = centerpoint[i] + distanceFromPoint[i] + shift[i] return point
@property def focalPoint(self): """ Return the focal point of the collimator :return: """ return self._focalPoint @property def vertex1(self): """ Return the vertice 1 :return: """ return self._vertex1 @property def vertex2(self): """ Return the vertice 2 :return: """ return self._vertex2 @property def vertex3(self): """ Return the vertice 3 :return: """ return self._vertex3 @property def vertex4(self): """ Return the vertice 4 :return: """ return self._vertex4