Ejemplo n.º 1
0
def various_particles():
    """A sample `ParticleList` with several different valid particles."""
    return ParticleList([
        "H",
        "He",
        "e-",
        "alpha",
        "tau neutrino",
        CustomParticle(mass=3 * u.kg, charge=5 * u.C),
        CustomParticle(),
        CustomParticle(mass=7 * u.kg),
        CustomParticle(charge=11 * u.C),
    ])
Ejemplo n.º 2
0
class TestPickling:
    """
    Test that different objects in `plasmapy.particles` can be pickled.
    """

    xfail = pytest.mark.xfail(reason="see issue #1011")

    @pytest.mark.parametrize(
        "instance",
        [
            CustomParticle(mass=1 * u.kg, charge=1 * u.C),
            DimensionlessParticle(mass=5, charge=5),
            pytest.param(Particle("p+"), marks=xfail),
            pytest.param(IonicFraction("p+", 0.1, 1e9 * u.m**-3), marks=xfail),
            pytest.param(IonizationState("H", [0.5, 0.5]), marks=xfail),
            pytest.param(IonizationStateCollection({"H": [0.5, 0.5]}),
                         marks=xfail),
        ],
    )
    def test_pickling(self, instance, tmp_path):
        """
        Test that different objects contained within `plasmapy.particles`
        can be pickled and unpickled.
        """
        filename = tmp_path / "pickled_particles.p"
        with open(filename, "wb") as pickle_file:
            pickle.dump(instance, pickle_file)

        with open(filename, "rb") as pickle_file:
            loaded_particle = pickle.load(pickle_file)

        assert str(instance) == str(loaded_particle)
Ejemplo n.º 3
0
def test_particle_list_extend(various_particles):
    """
    Test that a `ParticleList` can be extended when provided with an
    iterable that yields particle-like objects.
    """
    new_particles = ["Fe", Particle("e-"), CustomParticle()]
    various_particles.extend(new_particles)
    assert _everything_is_particle_or_custom_particle(various_particles)
    assert various_particles[-3:] == new_particles
Ejemplo n.º 4
0
def test_mean_particle():
    """
    Test that ``ParticleList.average_particle()`` returns a particle with
    the mean mass and mean charge of a |ParticleList|.
    """
    massless_uncharged_particle = CustomParticle(mass=0 * u.kg, charge=0 * u.C)
    particle_list = ParticleList([proton, electron, alpha, massless_uncharged_particle])
    expected_mass = (proton.mass + electron.mass + alpha.mass) / 4
    expected_charge = (proton.charge + electron.charge + alpha.charge) / 4
    average_particle = particle_list.average_particle()
    assert u.isclose(average_particle.mass, expected_mass, rtol=1e-14)
    assert u.isclose(average_particle.charge, expected_charge, rtol=1e-14)
Ejemplo n.º 5
0
def test_weighted_mean_particle():
    """
    Test that ``ParticleList.average_particle()`` returns a particle with
    the weighted mean.
    """
    custom_proton = CustomParticle(mass=proton.mass, charge=proton.charge)
    particle_list = ParticleList([proton, electron, alpha, custom_proton])
    abundances = [1, 2, 0, 1]
    expected_mass = (proton.mass + electron.mass) / 2
    expected_charge = 0 * u.C
    average_particle = particle_list.average_particle(abundances=abundances)
    assert u.isclose(average_particle.mass, expected_mass, rtol=1e-14)
    assert u.isclose(average_particle.charge, expected_charge, rtol=1e-14)
Ejemplo n.º 6
0
def test_particle_list_extended_with_particle_list(various_particles):
    """Test that a `ParticleList` can be extended with another `ParticleList`."""
    particle_list = ParticleList(["D", "T", CustomParticle()])
    various_particles.extend(particle_list)
    assert various_particles[-3:] == particle_list
Ejemplo n.º 7
0
from typing import Dict

from plasmapy.particles import alpha, electron, neutron, proton
from plasmapy.particles.atomic import atomic_number
from plasmapy.particles.exceptions import ChargeError, InvalidParticleError
from plasmapy.particles.nuclear import nuclear_reaction_energy
from plasmapy.particles.particle_class import (
    CustomParticle,
    DimensionlessParticle,
    Particle,
    ParticleLike,
)
from plasmapy.particles.particle_collections import ionic_levels, ParticleList

custom_particle = CustomParticle(mass=1e-25 * u.kg, charge=1e-18 * u.C)
dimensionless_particle = DimensionlessParticle(mass=1.25, charge=1.58)

attributes = [
    "charge",
    "half_life",
    "charge_number",
    "mass",
    "mass_energy",
]


@pytest.fixture
def various_particles():
    """A sample `ParticleList` with several different valid particles."""
    return ParticleList([
Ejemplo n.º 8
0
import astropy.units as u
import pytest

from plasmapy.particles import deuteron, electron, proton
from plasmapy.particles._factory import _physical_particle_factory
from plasmapy.particles.exceptions import InvalidParticleError
from plasmapy.particles.particle_class import CustomParticle, Particle
from plasmapy.particles.particle_collections import ParticleList

mass = 1e-26 * u.kg
charge = 1e-29 * u.C
custom_particle = CustomParticle(mass, charge)

test_cases = [
    ([[]], {}, ParticleList()),
    ([proton], {}, proton),
    (["p+"], {}, proton),
    (["H"], {
        "Z": 1,
        "mass_numb": 2
    }, deuteron),
    (["muon"], {}, Particle("muon")),
    pytest.param([charge, mass], {},
                 custom_particle,
                 marks=[pytest.mark.xfail]),
    ([mass, charge], {}, custom_particle),
    ([], {
        "symbol": "ξ"
    }, CustomParticle(symbol="ξ")),
    ([[proton, electron]], {}, ParticleList([proton, electron])),
    ([], {
Ejemplo n.º 9
0
    def average_particle(
        self,
        abundances=None,
        *,
        use_rms_charge: bool = False,
        use_rms_mass: bool = False,
    ) -> Union[CustomParticle, Particle]:
        """
        Return a particle with the average mass and charge.

        By default, the mean will be used as the average. If the ``abundances``
        are provided, then this method will return the weighted mean. If
        ``use_rms_charge`` or ``use_rms_mass`` is `True`, then this method will
        return the root mean square of the charge or mass, respectively. If all
        items in the |ParticleList| are the same, then this method will return
        that item.

        Parameters
        ----------
        abundances : array_like, optional
            Real numbers representing relative abundances of the particles in
            the |ParticleList|. Must have the same number of elements as the
            |ParticleList|. This parameter gets passed to `numpy.average` via
            that function's ``weights`` parameter. If not provided, the
            particles contained in the |ParticleList| are assumed to be
            equally abundant.

        use_rms_charge : `bool`, optional, keyword-only
            If `True`, use the root mean square charge instead of the mean
            charge. Defaults to `False`.

        use_rms_mass : `bool`, optional, keyword-only
            If `True`, use the root mean square mass instead of the mean mass.
            Defaults to `False`.

        Examples
        --------
        >>> reactants = ParticleList(["electron", "positron"])
        >>> reactants.average_particle()
        CustomParticle(mass=9.109383...e-31 kg, charge=0.0 C)
        >>> reactants.average_particle(abundances=[1, 0.5])
        CustomParticle(mass=9.109383...e-31 kg, charge=-5.34058...e-20 C)
        >>> reactants.average_particle(use_rms_charge=True)
        CustomParticle(mass=9.109383...e-31 kg, charge=1.6021766...-19 C)
        >>> protons = ParticleList(["p+", "p+", "p+"])
        >>> protons.average_particle()
        Particle("p+")
        """
        # If all items in the ParticleList are the same, return that item.
        if len(set(self)) == 1:
            return self[0]

        def _average(array, weights, use_rms):
            if use_rms:
                return np.sqrt(np.average(array**2, weights=weights))
            else:
                return np.average(array, weights=weights)

        new_mass = _average(self.mass,
                            weights=abundances,
                            use_rms=use_rms_mass)
        new_charge = _average(self.charge,
                              weights=abundances,
                              use_rms=use_rms_charge)

        return CustomParticle(mass=new_mass, charge=new_charge)