Example #1
0
    def mass_energy(self) -> u.Quantity:
        """
        Return the mass energy of the particle in joules.

        If the particle is an isotope or nuclide, return the mass energy
        of the nucleus only.

        If the mass of the particle is not known, then raise a
        `~plasmapy.utils.MissingAtomicDataError`.

        Examples
        --------
        >>> proton = Particle('p+')
        >>> proton.mass_energy
        <Quantity 1.50327759e-10 J>

        >>> protium = Particle('H-1 0+')
        >>> protium.mass_energy
        <Quantity 1.50327759e-10 J>

        >>> electron = Particle('electron')
        >>> electron.mass_energy.to('MeV')
        <Quantity 0.51099895 MeV>

        """
        try:
            mass = self.nuclide_mass if self.isotope else self.mass
            energy = mass * const.c ** 2
            return energy.to(u.J)
        except MissingAtomicDataError:
            raise MissingAtomicDataError(
                f"The mass energy of {self.particle} is not available "
                f"because the mass is unknown.") from None
Example #2
0
    def half_life(self) -> Union[u.Quantity, str]:
        """
        Return the particle's half-life in seconds, or a `str`
        with half-life information.

        Particles that do not have sufficiently well-constrained
        half-lives will return a `str` containing the information
        that is available about the half-life and issue a
        `~plasmapy.utils.MissingAtomicDataWarning`.

        Examples
        --------
        >>> neutron = Particle('n')
        >>> neutron.half_life
        <Quantity 881.5 s>

        """
        if self.element and not self.isotope:
            raise InvalidIsotopeError(_category_errmsg(self.particle, 'isotope'))

        if isinstance(self._attributes['half-life'], str):
            warnings.warn(
                f"The half-life for {self.particle} is not known precisely; "
                "returning string with estimated value.", MissingAtomicDataWarning)

        if self._attributes['half-life'] is None:
            raise MissingAtomicDataError(f"The half-life of '{self.particle}' is not available.")
        return self._attributes['half-life']
Example #3
0
    def lepton_number(self) -> Integral:
        """
        Return ``1`` for leptons, ``-1`` for antileptons, and ``0``
        otherwise.

        This attribute returns the number of leptons minus the number of
        antileptons, excluding bound electrons in an atom or ion.

        If the lepton number is unavailable, then this attribute will
        raise a `~plasmapy.utils.MissingAtomicDataError`.

        Examples
        --------
        >>> Particle('e-').lepton_number
        1
        >>> Particle('mu+').lepton_number
        -1
        >>> Particle('He-4 0+').lepton_number
        0

        """
        if self._attributes['lepton number'] is None:  # coverage: ignore
            raise MissingAtomicDataError(
                f"The lepton number for {self.particle} is not available.")
        return self._attributes['lepton number']
Example #4
0
    def spin(self) -> Real:
        """
        Return the spin of the particle.

        If the spin is unavailable, then a
        `~plasmapy.utils.MissingAtomicDataError` will be raised.

        Examples
        --------
        >>> positron = Particle('e+')
        >>> positron.spin
        0.5

        """
        if self._attributes['spin'] is None:
            raise MissingAtomicDataError(f"The spin of particle '{self.particle}' is unavailable.")

        return self._attributes['spin']
Example #5
0
    def get_particle_mass(particle) -> u.Quantity:
        """Return the mass of a particle.

        Take a representation of a particle and returns the mass in
        kg.  If the input is a `~astropy.units.Quantity` or
        `~astropy.constants.Constant` with units of mass already, then
        this returns that mass converted to kg.
        """
        try:
            if isinstance(particle, (u.Quantity, const.Constant)):
                return particle.to(u.kg)
            if not isinstance(particle, Particle):
                particle = Particle(particle)
            return particle.mass.to(u.kg)
        except u.UnitConversionError as exc1:
            raise u.UnitConversionError(f"Incorrect units in reduced_mass.") from exc1
        except MissingAtomicDataError:
            raise MissingAtomicDataError(
                f"Unable to find the reduced mass because the mass of "
                f"{particle} is not available.") from None
Example #6
0
    def baryon_number(self) -> Integral:
        """
        Return the number of baryons in a particle.

        This attribute will return the number of protons and neutrons
        minus the number of antiprotons and antineutrons. The baryon
        number is equivalent to the mass number for isotopes.

        If the baryon number is unavailable, then this attribute will
        raise a `~plasmapy.utils.MissingAtomicDataError`.

        Examples
        --------
        >>> alpha = Particle('alpha')
        >>> alpha.baryon_number
        4

        """
        if self._attributes['baryon number'] is None:  # coverage: ignore
            raise MissingAtomicDataError(
                f"The baryon number for '{self.particle}' is not available.")
        return self._attributes['baryon number']
Example #7
0
    def nuclide_mass(self) -> u.Quantity:
        """
        Return the mass of the bare nucleus of an isotope or a neutron.

        This attribute will raise a
        `~plasmapy.utils.InvalidIsotopeError` if the particle is not an
        isotope or neutron, or a
        `~plasmapy.utils.MissingAtomicDataError` if the isotope mass is
        not available.

        Examples
        --------
        >>> deuterium = Particle('D')
        >>> deuterium.nuclide_mass
        <Quantity 3.34358372e-27 kg>

        """

        if self.isotope == 'H-1':
            return const.m_p
        elif self.isotope == 'D':
            return _special_ion_masses['D 1+']
        elif self.isotope == 'T':
            return _special_ion_masses['T 1+']
        elif self.particle == 'n':
            return const.m_n

        if not self.isotope:
            raise InvalidIsotopeError(_category_errmsg(self, 'isotope'))

        base_mass = self._attributes['isotope mass']

        if base_mass is None:  # coverage: ignore
            raise MissingAtomicDataError(f"The mass of a {self.isotope} nuclide is not available.")

        _nuclide_mass = self._attributes['isotope mass'] - self.atomic_number * const.m_e

        return _nuclide_mass.to(u.kg)
Example #8
0
    def standard_atomic_weight(self) -> u.Quantity:
        """
        Return an element's standard atomic weight in kg.

        If the particle is isotope or ion or not an element, this
        attribute will raise an `~plasmapy.utils.InvalidElementError`.

        If the element does not have a defined stsandard atomic weight,
        this attribute will raise a
        `~plasmapy.utils.MissingAtomicDataError`.

        Examples
        --------
        >>> oxygen = Particle('O')
        >>> oxygen.standard_atomic_weight
        <Quantity 2.65669641e-26 kg>

        """
        if self.isotope or self.is_ion or not self.element:
            raise InvalidElementError(_category_errmsg(self, 'element'))
        if self._attributes['standard atomic weight'] is None:  # coverage: ignore
            raise MissingAtomicDataError(
                f"The standard atomic weight of {self} is unavailable.")
        return self._attributes['standard atomic weight'].to(u.kg)
Example #9
0
    def mass(self) -> u.Quantity:
        """
        Return the mass of the particle in kilograms.

        If the particle is an element and not an isotope or ion, then
        this attribute will return the standard atomic weight, if
        available.

        If the particle is an isotope but not an ion, then this
        attribute will return the isotopic mass, including bound
        electrons.

        If the particle is an ion, then this attribute will return the
        mass of the element or isotope (as just described) minus the
        product of the integer charge and the electron mass.

        For special particles, this attribute will return the standard
        value for the particle's mass.

        If the mass is unavailable (e.g., for neutrinos or elements with
        no standard atomic weight), then this attribute will raise a
        `~plasmapy.utils.MissingAtomicDataError`.

        Examples
        --------
        >>> Particle('He').mass
        <Quantity 6.64647688e-27 kg>
        >>> Particle('He+').mass
        <Quantity 6.64556594e-27 kg>
        >>> Particle('He-4 +1').mass
        <Quantity 6.64556803e-27 kg>
        >>> Particle('alpha').mass
        <Quantity 6.64465709e-27 kg>

        """

        if self._attributes['mass'] is not None:
            return self._attributes['mass'].to(u.kg)

        if self.is_ion:

            if self.isotope:
                base_mass = self._attributes['isotope mass']
            else:
                base_mass = self._attributes['standard atomic weight']

            if base_mass is None:
                raise MissingAtomicDataError(
                    f"The mass of ion '{self.ionic_symbol}' is not available."
                )

            mass = base_mass - self.integer_charge * const.m_e

            return mass.to(u.kg)

        if self.element:

            if self.isotope:
                mass = self._attributes['isotope mass']
            else:
                mass = self._attributes['standard atomic weight']

            if mass is not None:
                return mass.to(u.kg)

        raise MissingAtomicDataError(f"The mass of {self} is not available.")