# Created by Lech Wiktor Piotrowski at 14/03/2025
from dataclasses import dataclass, field
import numpy as np
from grand import CartesianRepresentation
from grand.basis import validate as _validate
from grand.basis.fielddoc import document_fields
[docs]
@document_fields
@dataclass
class Shower(_validate.CheckedFields):
"""A class for holding a shower"""
# As the TShower setters check them (#267)
_field_checks = {
"primary_type": _validate.field_check("str"),
"energy_em": _validate.field_check("real", minimum=0, unit="GeV"),
"energy_primary": _validate.field_check("real", minimum=0, unit="GeV"),
"Xmax": _validate.field_check("real", minimum=0, unit="g/cm2"),
"azimuth": _validate.field_check("real", minimum=0, maximum=360, unit="degrees"),
"zenith": _validate.field_check("real", minimum=0, maximum=180, unit="degrees"),
"magnetic_field": _validate.field_check("vector3"),
}
primary_type: str = ""
"""Shower primary particle type, such as proton, Fe, etc."""
energy_em: float = 0
"""Shower from e+- (ie related to radio emission) (GeV)"""
energy_primary: float = 0
"""Total energy of the primary (including muons, neutrinos, ...) (GeV)"""
Xmax: float = 0
"""Shower Xmax [g/cm2]"""
_Xmaxpos: CartesianRepresentation = field(default_factory=lambda: CartesianRepresentation(x=np.zeros(1, np.float64), y=np.zeros(1, np.float64), z=np.zeros(1, np.float64)))
"""Shower position in the site's reference frame"""
azimuth: float = 0
"""Shower azimuth, in degrees, from north toward west (NWU frame, origin at the core); the direction the shower *comes from*, as in ``TShower``"""
zenith: float = 0
"""Shower zenith, in degrees (NWU frame, origin at the core); the direction the shower *comes from*, as in ``TShower``"""
magnetic_field: np.ndarray = field(default_factory=lambda: np.zeros(3))
"""Magnetic field parameters: Inclination, Declination, modulus"""
## Direction of origin (ToDo: is it the same as origin of the coordinate system?)
_origin_geoid: CartesianRepresentation = field(default_factory=lambda: CartesianRepresentation(x=np.zeros(1, np.float64), y=np.zeros(1, np.float64), z=np.zeros(1, np.float64)))
## Position of the core on the ground in the site's reference frame
_core_ground_pos: CartesianRepresentation = field(default_factory=lambda: CartesianRepresentation(x=np.zeros(1, np.float64), y=np.zeros(1, np.float64), z=np.zeros(1, np.float64)))
@property
def Xmaxpos(self):
"""Shower position in the site's reference frame
Returns
-------
CartesianRepresentation, shape (3, 1)
Position of shower maximum, in meters (x north, y west, z up).
"""
return self._Xmaxpos
@Xmaxpos.setter
def Xmaxpos(self, v):
r"""Sets the position of shower maximum.
Parameters
----------
v : array_like
Position of Xmax, in the frame the event uses.
"""
self._Xmaxpos = CartesianRepresentation(x=v[0], y=v[1], z=v[2])
@property
def origin_geoid(self):
"""Origin of the array frame the shower's positions are in
Returns
-------
CartesianRepresentation, shape (3, 1)
Latitude and longitude in degrees and height in meters, as x, y
and z.
"""
return self._origin_geoid
@origin_geoid.setter
def origin_geoid(self, v):
r"""Sets the geodetic origin of the local frame.
Parameters
----------
v : array_like
Latitude, longitude and height.
"""
self._origin_geoid = CartesianRepresentation(x=v[0], y=v[1], z=v[2])
@property
def core_ground_pos(self):
"""Position of the core on the ground in the site's reference frame
Returns
-------
CartesianRepresentation, shape (3, 1)
Shower core position at ground, in meters (x north, y west, z up).
"""
return self._core_ground_pos
@core_ground_pos.setter
def core_ground_pos(self, v):
r"""Sets the shower core position at ground.
Parameters
----------
v : array_like
Core position, in the array frame.
"""
self._core_ground_pos = CartesianRepresentation(x=v[0], y=v[1], z=v[2])