Module sipmarray.unit
Expand source code
from importlib import import_module
from typing import Tuple
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.patches import Rectangle
class SiPMunit():
"""Class to represent a SiPM unit."""
def __init__(self, model):
self.get_model_file(model)
self.get_model_geometry()
self.set_dependant_properties()
def get_model_file(self, model):
from sipmarray.models import model_lib
if model in model_lib.keys():
self.model = model_lib[model]
else:
raise ValueError('Model not found. Please make a PR to add it.')
def get_model_geometry(self):
"""Loads model geometric properties from the model file.
Raises:
ModuleNotFoundError: raised if the model file is not found.
"""
try:
model_module = import_module(f'sipmarray.models.{self.model}')
model_class = getattr(model_module, self.model)
_model = model_class()
self.name = _model.name
self.width_package = _model.width_package
self.height_package = _model.height_package
self.width_tolerance = _model.width_tolerance
self.height_tolerance = _model.height_tolerance
self.width_active = _model.width_active
self.height_active = _model.height_active
self.active_area_correction = _model.active_area_correction
self.D_corner_x_active = _model.D_corner_x_active
self.D_corner_y_active = _model.D_corner_y_active
self.set_dependant_properties()
except ModuleNotFoundError:
raise ModuleNotFoundError(
'Model not found. Please make a PR to add it.')
def set_dependant_properties(self):
"""Defines dependant properties of the SiPM unit: total area, active
area and active area fraction.
"""
self.width_unit = self.width_package + 2*self.width_tolerance
self.height_unit = self.height_package + 2*self.height_tolerance
self.total_area = self.width_unit*self.height_unit
self.active_area = (self.width_active *
self.height_active *
self.active_area_correction)
def get_unit_centre(self)->Tuple[float, float]:
"""Get the centre of the SiPM unit
Returns:
tuple: (x,y) of the centre of the SiPM unit in SiPM unit
coordinates.
"""
return (self.width_unit/2, self.height_unit/2)
def get_unit_active_centre(self)->Tuple[float, float]:
"""Get the centre of the active area of the SiPM unit
Returns:
tuple: (x,y) of the centre of the active area of the SiPM unit
in SiPM unit coordinates.
"""
x = self.D_corner_x_active + self.width_active/2
y = self.D_corner_y_active + self.height_active/2
return (x,y)
def plot_model(self, xy = (0,0), figax = None):
"""Make a plot of the SiPM unit model
Args:
xy (tuple, optional): coordinates of the bottom left corner.
Defaults to (0,0).
figax (_type_, optional): figure and axis environment.
Defaults to None.
Returns:
_type_: updated figure and axis environment
"""
if figax == None:
fig, ax = plt.subplots(1,1,figsize = (5,5))
ax.add_patch(Rectangle((xy[0]+self.width_tolerance,
xy[1]+self.height_tolerance),
width=self.width_package,
height=self.height_package,
facecolor = 'gray',
alpha = 0.3, edgecolor = 'k',
label = 'Packaging area', zorder = 1))
ax.add_patch(Rectangle((xy[0]+self.D_corner_x_active,
xy[1]+self.D_corner_y_active),
width=self.width_active,
height=self.height_active,
facecolor = 'k', alpha = 0.8, edgecolor = 'k',
label = 'Active area', zorder = 2))
geometric_centre = self.get_unit_centre()
active_centre = self.get_unit_active_centre()
ax.plot(geometric_centre[0], geometric_centre[1], 'o',
c = 'g', label = 'Geometric centre')
ax.plot(active_centre[0], active_centre[1], 'x',
c = 'r', label = 'Active centre')
ax.set_xlim(xy[0]-0.1*self.width_unit, xy[0]+1.1*self.width_unit)
ax.set_ylim(xy[1]-0.1*self.height_unit, xy[1]+1.1*self.height_unit)
ax.set_aspect('equal')
ax.legend()
ax.set_xlabel('x [mm]')
ax.set_ylabel('y [mm]')
ax.set_aspect('equal')
ax.grid(zorder = -10)
if figax == None:
plt.show()
else:
return fig, ax
def get_unit_patches(self,xy:np.ndarray) -> list:
"""Get the patches of the SiPM unit for plotting.
Args:
xy (np.ndarray): the coordinates of the bottom left corner of
the SiPM unit.
Returns:
list: list of patches of the SiPM units
"""
p = [Rectangle((xy[0]+self.width_tolerance,
xy[1]+self.height_tolerance),
width=self.width_package,
height=self.height_package,
facecolor = 'gray',
alpha = 0.3, edgecolor = 'k', zorder = 3),
Rectangle((xy[0]+self.D_corner_x_active,
xy[1]+self.D_corner_y_active),
width=self.width_active,
height=self.height_active,
facecolor = 'k', alpha = 0.98,
edgecolor = 'k', zorder = 4)
]
return p
def print_properties(self) -> None:
"""Print the main properties of the SiPM model
"""
print(f'Model: {self.name}')
print(f'Total unit area: {self.total_area:.2f} mm^2')
print(f'Active area geometric correction: '
f'{self.active_area_correction:.2f}')
print(f'Active area: {self.active_area:.2f} mm^2')
print(f'Active area fraction: '
f'{self.active_area/self.total_area:.2f}')
print(f'Width tolerance: {self.width_tolerance} mm')
print(f'Height tolerance: {self.height_tolerance} mm')
Classes
class SiPMunit (model)
-
Class to represent a SiPM unit.
Expand source code
class SiPMunit(): """Class to represent a SiPM unit.""" def __init__(self, model): self.get_model_file(model) self.get_model_geometry() self.set_dependant_properties() def get_model_file(self, model): from sipmarray.models import model_lib if model in model_lib.keys(): self.model = model_lib[model] else: raise ValueError('Model not found. Please make a PR to add it.') def get_model_geometry(self): """Loads model geometric properties from the model file. Raises: ModuleNotFoundError: raised if the model file is not found. """ try: model_module = import_module(f'sipmarray.models.{self.model}') model_class = getattr(model_module, self.model) _model = model_class() self.name = _model.name self.width_package = _model.width_package self.height_package = _model.height_package self.width_tolerance = _model.width_tolerance self.height_tolerance = _model.height_tolerance self.width_active = _model.width_active self.height_active = _model.height_active self.active_area_correction = _model.active_area_correction self.D_corner_x_active = _model.D_corner_x_active self.D_corner_y_active = _model.D_corner_y_active self.set_dependant_properties() except ModuleNotFoundError: raise ModuleNotFoundError( 'Model not found. Please make a PR to add it.') def set_dependant_properties(self): """Defines dependant properties of the SiPM unit: total area, active area and active area fraction. """ self.width_unit = self.width_package + 2*self.width_tolerance self.height_unit = self.height_package + 2*self.height_tolerance self.total_area = self.width_unit*self.height_unit self.active_area = (self.width_active * self.height_active * self.active_area_correction) def get_unit_centre(self)->Tuple[float, float]: """Get the centre of the SiPM unit Returns: tuple: (x,y) of the centre of the SiPM unit in SiPM unit coordinates. """ return (self.width_unit/2, self.height_unit/2) def get_unit_active_centre(self)->Tuple[float, float]: """Get the centre of the active area of the SiPM unit Returns: tuple: (x,y) of the centre of the active area of the SiPM unit in SiPM unit coordinates. """ x = self.D_corner_x_active + self.width_active/2 y = self.D_corner_y_active + self.height_active/2 return (x,y) def plot_model(self, xy = (0,0), figax = None): """Make a plot of the SiPM unit model Args: xy (tuple, optional): coordinates of the bottom left corner. Defaults to (0,0). figax (_type_, optional): figure and axis environment. Defaults to None. Returns: _type_: updated figure and axis environment """ if figax == None: fig, ax = plt.subplots(1,1,figsize = (5,5)) ax.add_patch(Rectangle((xy[0]+self.width_tolerance, xy[1]+self.height_tolerance), width=self.width_package, height=self.height_package, facecolor = 'gray', alpha = 0.3, edgecolor = 'k', label = 'Packaging area', zorder = 1)) ax.add_patch(Rectangle((xy[0]+self.D_corner_x_active, xy[1]+self.D_corner_y_active), width=self.width_active, height=self.height_active, facecolor = 'k', alpha = 0.8, edgecolor = 'k', label = 'Active area', zorder = 2)) geometric_centre = self.get_unit_centre() active_centre = self.get_unit_active_centre() ax.plot(geometric_centre[0], geometric_centre[1], 'o', c = 'g', label = 'Geometric centre') ax.plot(active_centre[0], active_centre[1], 'x', c = 'r', label = 'Active centre') ax.set_xlim(xy[0]-0.1*self.width_unit, xy[0]+1.1*self.width_unit) ax.set_ylim(xy[1]-0.1*self.height_unit, xy[1]+1.1*self.height_unit) ax.set_aspect('equal') ax.legend() ax.set_xlabel('x [mm]') ax.set_ylabel('y [mm]') ax.set_aspect('equal') ax.grid(zorder = -10) if figax == None: plt.show() else: return fig, ax def get_unit_patches(self,xy:np.ndarray) -> list: """Get the patches of the SiPM unit for plotting. Args: xy (np.ndarray): the coordinates of the bottom left corner of the SiPM unit. Returns: list: list of patches of the SiPM units """ p = [Rectangle((xy[0]+self.width_tolerance, xy[1]+self.height_tolerance), width=self.width_package, height=self.height_package, facecolor = 'gray', alpha = 0.3, edgecolor = 'k', zorder = 3), Rectangle((xy[0]+self.D_corner_x_active, xy[1]+self.D_corner_y_active), width=self.width_active, height=self.height_active, facecolor = 'k', alpha = 0.98, edgecolor = 'k', zorder = 4) ] return p def print_properties(self) -> None: """Print the main properties of the SiPM model """ print(f'Model: {self.name}') print(f'Total unit area: {self.total_area:.2f} mm^2') print(f'Active area geometric correction: ' f'{self.active_area_correction:.2f}') print(f'Active area: {self.active_area:.2f} mm^2') print(f'Active area fraction: ' f'{self.active_area/self.total_area:.2f}') print(f'Width tolerance: {self.width_tolerance} mm') print(f'Height tolerance: {self.height_tolerance} mm')
Subclasses
Methods
def get_model_file(self, model)
-
Expand source code
def get_model_file(self, model): from sipmarray.models import model_lib if model in model_lib.keys(): self.model = model_lib[model] else: raise ValueError('Model not found. Please make a PR to add it.')
def get_model_geometry(self)
-
Loads model geometric properties from the model file.
Raises
ModuleNotFoundError
- raised if the model file is not found.
Expand source code
def get_model_geometry(self): """Loads model geometric properties from the model file. Raises: ModuleNotFoundError: raised if the model file is not found. """ try: model_module = import_module(f'sipmarray.models.{self.model}') model_class = getattr(model_module, self.model) _model = model_class() self.name = _model.name self.width_package = _model.width_package self.height_package = _model.height_package self.width_tolerance = _model.width_tolerance self.height_tolerance = _model.height_tolerance self.width_active = _model.width_active self.height_active = _model.height_active self.active_area_correction = _model.active_area_correction self.D_corner_x_active = _model.D_corner_x_active self.D_corner_y_active = _model.D_corner_y_active self.set_dependant_properties() except ModuleNotFoundError: raise ModuleNotFoundError( 'Model not found. Please make a PR to add it.')
def get_unit_active_centre(self) ‑> Tuple[float, float]
-
Get the centre of the active area of the SiPM unit
Returns
tuple
- (x,y) of the centre of the active area of the SiPM unit in SiPM unit coordinates.
Expand source code
def get_unit_active_centre(self)->Tuple[float, float]: """Get the centre of the active area of the SiPM unit Returns: tuple: (x,y) of the centre of the active area of the SiPM unit in SiPM unit coordinates. """ x = self.D_corner_x_active + self.width_active/2 y = self.D_corner_y_active + self.height_active/2 return (x,y)
def get_unit_centre(self) ‑> Tuple[float, float]
-
Get the centre of the SiPM unit
Returns
tuple
- (x,y) of the centre of the SiPM unit in SiPM unit coordinates.
Expand source code
def get_unit_centre(self)->Tuple[float, float]: """Get the centre of the SiPM unit Returns: tuple: (x,y) of the centre of the SiPM unit in SiPM unit coordinates. """ return (self.width_unit/2, self.height_unit/2)
def get_unit_patches(self, xy: numpy.ndarray) ‑> list
-
Get the patches of the SiPM unit for plotting.
Args
xy
:np.ndarray
- the coordinates of the bottom left corner of the SiPM unit.
Returns
list
- list of patches of the SiPM units
Expand source code
def get_unit_patches(self,xy:np.ndarray) -> list: """Get the patches of the SiPM unit for plotting. Args: xy (np.ndarray): the coordinates of the bottom left corner of the SiPM unit. Returns: list: list of patches of the SiPM units """ p = [Rectangle((xy[0]+self.width_tolerance, xy[1]+self.height_tolerance), width=self.width_package, height=self.height_package, facecolor = 'gray', alpha = 0.3, edgecolor = 'k', zorder = 3), Rectangle((xy[0]+self.D_corner_x_active, xy[1]+self.D_corner_y_active), width=self.width_active, height=self.height_active, facecolor = 'k', alpha = 0.98, edgecolor = 'k', zorder = 4) ] return p
def plot_model(self, xy=(0, 0), figax=None)
-
Make a plot of the SiPM unit model
Args
xy
:tuple
, optional- coordinates of the bottom left corner. Defaults to (0,0).
figax
:_type_
, optional- figure and axis environment. Defaults to None.
Returns
_type_
- updated figure and axis environment
Expand source code
def plot_model(self, xy = (0,0), figax = None): """Make a plot of the SiPM unit model Args: xy (tuple, optional): coordinates of the bottom left corner. Defaults to (0,0). figax (_type_, optional): figure and axis environment. Defaults to None. Returns: _type_: updated figure and axis environment """ if figax == None: fig, ax = plt.subplots(1,1,figsize = (5,5)) ax.add_patch(Rectangle((xy[0]+self.width_tolerance, xy[1]+self.height_tolerance), width=self.width_package, height=self.height_package, facecolor = 'gray', alpha = 0.3, edgecolor = 'k', label = 'Packaging area', zorder = 1)) ax.add_patch(Rectangle((xy[0]+self.D_corner_x_active, xy[1]+self.D_corner_y_active), width=self.width_active, height=self.height_active, facecolor = 'k', alpha = 0.8, edgecolor = 'k', label = 'Active area', zorder = 2)) geometric_centre = self.get_unit_centre() active_centre = self.get_unit_active_centre() ax.plot(geometric_centre[0], geometric_centre[1], 'o', c = 'g', label = 'Geometric centre') ax.plot(active_centre[0], active_centre[1], 'x', c = 'r', label = 'Active centre') ax.set_xlim(xy[0]-0.1*self.width_unit, xy[0]+1.1*self.width_unit) ax.set_ylim(xy[1]-0.1*self.height_unit, xy[1]+1.1*self.height_unit) ax.set_aspect('equal') ax.legend() ax.set_xlabel('x [mm]') ax.set_ylabel('y [mm]') ax.set_aspect('equal') ax.grid(zorder = -10) if figax == None: plt.show() else: return fig, ax
def print_properties(self) ‑> NoneType
-
Print the main properties of the SiPM model
Expand source code
def print_properties(self) -> None: """Print the main properties of the SiPM model """ print(f'Model: {self.name}') print(f'Total unit area: {self.total_area:.2f} mm^2') print(f'Active area geometric correction: ' f'{self.active_area_correction:.2f}') print(f'Active area: {self.active_area:.2f} mm^2') print(f'Active area fraction: ' f'{self.active_area/self.total_area:.2f}') print(f'Width tolerance: {self.width_tolerance} mm') print(f'Height tolerance: {self.height_tolerance} mm')
def set_dependant_properties(self)
-
Defines dependant properties of the SiPM unit: total area, active area and active area fraction.
Expand source code
def set_dependant_properties(self): """Defines dependant properties of the SiPM unit: total area, active area and active area fraction. """ self.width_unit = self.width_package + 2*self.width_tolerance self.height_unit = self.height_package + 2*self.height_tolerance self.total_area = self.width_unit*self.height_unit self.active_area = (self.width_active * self.height_active * self.active_area_correction)