Source code for at.lattice.particle_object

"""Description of particles."""

import numpy as np

from ..constants import e_mass, p_mass, mu_mass


[docs] class Particle: """ Particle object: it defines the properties of the particles circulating in a ring. """ _known = { "relativistic": {"rest_energy": 0.0, "charge": -1.0}, "electron": {"rest_energy": e_mass, "charge": -1.0}, "positron": {"rest_energy": e_mass, "charge": 1.0}, "proton": {"rest_energy": p_mass, "charge": 1.0}, "antiproton": {"rest_energy": mu_mass, "charge": -1.0}, "posmuon": {"rest_energy": mu_mass, "charge": 1.0}, "negmuon": {"rest_energy": mu_mass, "charge": -1.0}, } def __init__(self, name: str | None = "relativistic", **kwargs): """ Parameters: name: Particle name. 'electron', 'positron', 'proton', 'posmuon', 'negmuon' are predefined. For other particles, the rest energy and charge must be provided as keywords. If *name* is blank or None, an attempt to identify the particle is done. Keyword Arguments: rest_energy: Particle rest energy [ev] charge: Particle charge [elementary charge] *: Other keywords will be set as attributes of the particle """ def scan(dct): """Try to identify an unknown particle.""" energy = dct["rest_energy"] charge = int(dct["charge"]) for nm, val in self._known.items(): de = abs(energy - val["rest_energy"]) / energy if de < 1.0e-8 and charge == int(val["charge"]): return nm return "unknown" if name in self._known: kwargs.update(self._known[name]) elif not name: # If name is blank, try to identify the particle name = scan(kwargs) self.name = name # Use a numpy scalar to allow division by zero self._rest_energy = np.array(kwargs.pop("rest_energy"), dtype=float) self._charge = kwargs.pop("charge") for key, value in kwargs.items(): setattr(self, key, value)
[docs] def to_dict(self) -> dict: attrs = vars(self).copy() attrs["rest_energy"] = attrs.pop("_rest_energy") attrs["charge"] = attrs.pop("_charge") return attrs
def __repr__(self): if self.name in self._known: return f"Particle('{self.name}')" else: attrs = self.to_dict() name = attrs.pop("name") args = ", ".join(f"{k}={v!r}" for k, v in attrs.items()) return f"Particle('{name}', {args})" def __str__(self): if self.name in self._known: return self.name else: return self.__repr__() # Use properties so that they are read-only @property def rest_energy(self) -> np.ndarray: """Particle rest energy [eV].""" return self._rest_energy @property def charge(self) -> float: """Particle charge [elementary charge].""" return self._charge