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), ])
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)
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
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)
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)
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
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([
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])), ([], {
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)