Repository: PlasmaPy/PlasmaPy
Pull request #221 (2017-12-29 05:12:37)

Storing particle information and resolving particle aliases
This pull request creates `Particles` which is a dictionary in `atomic/particles.py` that contains information on particles such as electrons, muons, taus, neutrinos, protons, neutrons, and their antiparticles.

This pull request is preparation work for eventually providing a resolution to #174, and is related to #179.


Patch:
diff --git a/plasmapy/atomic/__init__.py b/plasmapy/atomic/__init__.py
index 692f5618..77227206 100644
--- a/plasmapy/atomic/__init__.py
+++ b/plasmapy/atomic/__init__.py
@@ -3,3 +3,4 @@
 from .nuclear import *
 from .elements import *
 from .isotopes import *
+from .particles import *
diff --git a/plasmapy/atomic/atomic.py b/plasmapy/atomic/atomic.py
index fdf32325..5e196b09 100644
--- a/plasmapy/atomic/atomic.py
+++ b/plasmapy/atomic/atomic.py
@@ -3,20 +3,25 @@
 import numpy as np
 import re
 from astropy import units as u, constants as const
-from astropy.units import Quantity
 import warnings
 from .elements import atomic_symbols, atomic_symbols_dict, Elements
 from .isotopes import Isotopes
-
-from typing import (Union, Optional, Any, List, Tuple)
+from .particles import _Particles, _get_standard_symbol
 
 # The code contained within atomic_symbol(), isotope_symbol(), and
 # _extract_charge_state() is designed to catch all of the special
 # cases for different inputs.  Complexity is concentrated in these
 # functions so that the rest of the functions can be simpler.
 
+# TODO: Implement subpackage specific exceptions/warnings (e.g., AtomicError)
+# TODO: Create an ion_symbol function
+# TODO: Create a particle_symbol function
+# TODO: Create a particle_mass function
+# TODO: Create lepton_number and baryon_number functions
+# TODO: Maybe create is_antimatter, is_lepton, is_baryon, is_boson, is_fermion
+
 
-def atomic_symbol(argument: Union[str, int]) -> str:
+def atomic_symbol(argument):
     r"""Returns the atomic symbol.
 
     Parameters
@@ -144,7 +149,7 @@ def atomic_symbol(argument: Union[str, int]) -> str:
     return element
 
 
-def isotope_symbol(argument: Union[str, int], mass_numb: int = None) -> str:
+def isotope_symbol(argument, mass_numb=None):
     r"""Returns the symbol representing an isotope.
 
     Parameters
@@ -297,7 +302,7 @@ def isotope_symbol(argument: Union[str, int], mass_numb: int = None) -> str:
     return isotope
 
 
-def atomic_number(argument: str) -> str:
+def atomic_number(argument):
     r"""Returns the number of protons in an atom, isotope, or ion.
 
     Parameters
@@ -340,8 +345,7 @@ def atomic_number(argument: str) -> str:
     return atomic_numb
 
 
-def is_isotope_stable(argument: Union[str, int],
-                      mass_numb: int = None) -> bool:
+def is_isotope_stable(argument, mass_numb=None):
     r"""Returns true for stable isotopes and false otherwise.
 
     Parameters
@@ -387,7 +391,7 @@ def is_isotope_stable(argument: Union[str, int],
     return is_stable
 
 
-def half_life(argument: Union[int, str], mass_numb: int = None) -> Quantity:
+def half_life(argument, mass_numb=None):
     r"""Returns the half-life in seconds for unstable isotopes, and
     numpy.inf for stable isotopes.
 
@@ -452,7 +456,7 @@ def half_life(argument: Union[int, str], mass_numb: int = None) -> Quantity:
     return half_life_sec
 
 
-def mass_number(isotope: str) -> int:
+def mass_number(isotope):
     r"""Get the mass number (the number of protons and neutrons) of an
     isotope.
 
@@ -510,7 +514,7 @@ def mass_number(isotope: str) -> int:
     return mass_numb
 
 
-def element_name(argument: Union[str, int]) -> str:
+def element_name(argument):
     r"""Returns the name of an element.
 
     Parameters
@@ -556,7 +560,7 @@ def element_name(argument: Union[str, int]) -> str:
     return name
 
 
-def standard_atomic_weight(argument: Union[str, int]) -> Quantity:
+def standard_atomic_weight(argument):
     r"""Returns the standard (conventional) atomic weight of an element
     based on the relative abundances of isotopes in terrestrial
     environments.
@@ -654,8 +658,7 @@ def standard_atomic_weight(argument: Union[str, int]) -> Quantity:
     return atomic_weight
 
 
-def isotope_mass(argument: Union[str, int],
-                 mass_numb: int = None) -> Quantity:
+def isotope_mass(argument, mass_numb=None):
     r"""Return the mass of an isotope.
 
     Parameters
@@ -720,8 +723,7 @@ def isotope_mass(argument: Union[str, int],
     return atomic_mass
 
 
-def ion_mass(argument: Union[str, int, Quantity], Z: int = None,
-             mass_numb: int = None) -> Quantity:
+def ion_mass(argument, Z=None, mass_numb=None):
     r"""Returns the mass of an ion by finding the standard atomic
     weight of an element or the atomic mass of an isotope, and then
     accounting for the change in mass due to loss of electrons from
@@ -822,7 +824,7 @@ def ion_mass(argument: Union[str, int, Quantity], Z: int = None,
 
     """
 
-    if isinstance(argument, Quantity) and Z is None and mass_numb is None:
+    if isinstance(argument, u.Quantity) and Z is None and mass_numb is None:
 
         try:
             m_i = argument.to(u.kg)
@@ -914,7 +916,7 @@ def ion_mass(argument: Union[str, int, Quantity], Z: int = None,
     return m_i
 
 
-def known_isotopes(argument: Union[str, int] = None) -> List[str]:
+def known_isotopes(argument=None):
     r"""Returns a list of all known isotopes of an element, or a list
     of all known isotopes of every element if no input is provided.
 
@@ -993,8 +995,7 @@ def known_isotopes_for_element(argument):
     return isotopes_list
 
 
-def common_isotopes(argument: Union[str, int] = None,
-                    most_common_only: bool = False) -> List[str]:
+def common_isotopes(argument=None, most_common_only=False):
     r"""Returns a list of isotopes of an element with an isotopic
     abundances greater than zero, or if no input is provided, a list
     of all such isotopes for every element.
@@ -1058,10 +1059,7 @@ def common_isotopes(argument: Union[str, int] = None,
 
     """
 
-    def common_isotopes_for_element(argument: Union[str, int],
-                                    most_common_only: Optional[bool])\
-            -> List[str]:
-
+    def common_isotopes_for_element(argument, most_common_only):
         isotopes = known_isotopes(argument)
         CommonIsotopes = [isotope for isotope in isotopes if
                           'isotopic_abundance' in Isotopes[isotope].keys()]
@@ -1096,8 +1094,7 @@ def common_isotopes_for_element(argument: Union[str, int],
     return isotopes_list
 
 
-def stable_isotopes(argument: Union[str, int] = None,
-                    unstable: bool = False) -> List[str]:
+def stable_isotopes(argument=None, unstable=False):
     r"""Returns a list of all stable isotopes of an element, or if no
     input is provided, a list of all such isotopes for every element.
 
@@ -1155,8 +1152,7 @@ def stable_isotopes(argument: Union[str, int] = None,
 
     """
 
-    def stable_isotopes_for_element(argument: Union[str, int],
-                                    stable_only: Optional[bool]) -> List[str]:
+    def stable_isotopes_for_element(argument, stable_only):
         KnownIsotopes = known_isotopes(argument)
         StableIsotopes = [isotope for isotope in KnownIsotopes if
                           Isotopes[isotope]['is_stable'] == stable_only]
@@ -1179,8 +1175,7 @@ def stable_isotopes_for_element(argument: Union[str, int],
     return isotopes_list
 
 
-def isotopic_abundance(argument: Union[str, int],
-                       mass_numb: int = None) -> Quantity:
+def isotopic_abundance(argument, mass_numb=None):
     r"""Returns the isotopic abundances if known, and otherwise zero.
 
     Parameters
@@ -1239,7 +1234,7 @@ def isotopic_abundance(argument: Union[str, int],
     return iso_comp
 
 
-def charge_state(particle: str) -> int:
+def charge_state(particle):
     r"""Returns the charge state of an ion or other particle.
 
     Parameters
@@ -1320,7 +1315,7 @@ def charge_state(particle: str) -> int:
     return Z
 
 
-def electric_charge(particle: str) -> Quantity:
+def electric_charge(particle):
     r"""Returns the electric charge (in coulombs) of an ion or other
     particle
 
@@ -1377,7 +1372,7 @@ def electric_charge(particle: str) -> Quantity:
         raise ValueError(f"{particle} is an invalid input to electric_charge")
 
 
-def _extract_charge_state(argument: str) -> Tuple[str, int]:
+def _extract_charge_state(argument):
     r"""Splits strings containing element or isotope and charge state
     information into a string without the charge state information and
     the charge state as an integer (or None if no charge state
@@ -1486,7 +1481,7 @@ def _extract_charge_state(argument: str) -> Tuple[str, int]:
     return argument, charge_state
 
 
-def _is_neutron(argument: Any, mass_numb: int = None) -> bool:
+def _is_neutron(argument, mass_numb=None):
     r"""Returns True if the argument corresponds to a neutron, and
     False otherwise."""
 
@@ -1501,8 +1496,7 @@ def _is_neutron(argument: Any, mass_numb: int = None) -> bool:
         return False
 
 
-def _is_hydrogen(argument: Any,
-                 can_be_atomic_number: Optional[bool] = False) -> bool:
+def _is_hydrogen(argument, can_be_atomic_number=False):
     r"""Returns True if the argument corresponds to hydrogen, and False
     otherwise."""
 
@@ -1535,7 +1529,7 @@ def _is_hydrogen(argument: Any,
     return is_hydrogen
 
 
-def _is_electron(arg: Any) -> bool:
+def _is_electron(arg):
     r"""Returns True if the argument corresponds to an electron, and False
     otherwise."""
 
@@ -1545,7 +1539,7 @@ def _is_electron(arg: Any) -> bool:
     return arg in ['e', 'e-'] or arg.lower() == 'electron'
 
 
-def _is_positron(arg: Any) -> bool:
+def _is_positron(arg):
     r"""Returns True if the argument corresponds to a positron, and False
     otherwise."""
 
@@ -1555,7 +1549,7 @@ def _is_positron(arg: Any) -> bool:
     return arg == 'e+' or arg.lower() == 'positron'
 
 
-def _is_antiproton(arg: Any) -> bool:
+def _is_antiproton(arg):
     r"""Returns True if the argument corresponds to an antiproton, and
     False otherwise."""
 
@@ -1565,7 +1559,7 @@ def _is_antiproton(arg: Any) -> bool:
     return arg == 'p-' or arg.lower() == 'antiproton'
 
 
-def _is_antineutron(arg: Any) -> bool:
+def _is_antineutron(arg):
     r"""Returns True if the argument corresponds to an antineutron, and
     False otherwise."""
 
@@ -1575,7 +1569,7 @@ def _is_antineutron(arg: Any) -> bool:
     return arg.lower() == 'antineutron'
 
 
-def _is_proton(arg: Any, Z: int = None, mass_numb: int = None) -> bool:
+def _is_proton(arg, Z=None, mass_numb=None):
     r"""Returns True if the argument corresponds to a proton, and
     False otherwise.  This function returns False for 'H-1' if no
     charge state is given."""
@@ -1594,7 +1588,7 @@ def _is_proton(arg: Any, Z: int = None, mass_numb: int = None) -> bool:
         return False
 
 
-def _is_alpha(arg: Any) -> bool:
+def _is_alpha(arg):
     r"""Returns True if the argument corresponds to an alpha particle,
     and False otherwise."""
 
diff --git a/plasmapy/atomic/particles.py b/plasmapy/atomic/particles.py
new file mode 100644
index 00000000..b9ff11f9
--- /dev/null
+++ b/plasmapy/atomic/particles.py
@@ -0,0 +1,233 @@
+import typing
+from astropy import units as u, constants as const
+import numpy as np
+
+
+def _create_Particles_dict() -> typing.Dict[str, dict]:
+    """Create a dictionary of dictionaries that contains physical
+    information for particles and antiparticles that are not
+    elements or ions.
+
+    The keys of the top-level dictionary are the standard
+    particle symbols. The values of the top-level dictionary
+    are dictionaries for each particle or antiparticle with
+    strings such as 'name', 'mass', and 'spin' as the keys
+    and the corresponding atomic properties as symbols."""
+
+    leptons = ['e-', 'mu-', 'tau-', 'nu_e', 'nu_mu', 'nu_tau']
+    antileptons = ['e+', 'mu+', 'tau+', 'anti_nu_e',
+                   'anti_nu_mu', 'anti_nu_tau']
+
+    baryons = ['p', 'n']
+    antibaryons = ['p-', 'antineutron']
+
+    everything = leptons + antileptons + baryons + antibaryons
+
+    particles = leptons + baryons
+    antiparticles = antileptons + antibaryons
+
+    fermions = leptons + antileptons + baryons + antibaryons
+    bosons = []
+
+    neutrinos = [lepton for lepton in leptons if 'nu' in lepton]
+    antineutrinos = [antilepton for antilepton in antileptons
+                     if 'nu' in antilepton]
+
+    symbols_and_names = [
+        ('e-', 'electron'),
+        ('e+', 'positron'),
+        ('mu-', 'muon'),
+        ('mu+', 'antimuon'),
+        ('tau-', 'tau'),
+        ('tau+', 'antitau'),
+        ('nu_e', 'electron neutrino'),
+        ('anti_nu_e', 'electron antineutrino'),
+        ('nu_mu', 'muon neutrino'),
+        ('anti_nu_mu', 'muon antineutrino'),
+        ('nu_tau', 'tau neutrino'),
+        ('anti_nu_tau', 'tau antineutrino'),
+        ('p', 'proton'),
+        ('p-', 'antiproton'),
+        ('n', 'neutron'),
+        ('antineutron', 'antineutron'),
+    ]
+
+    Particles = dict()
+
+    for thing in everything:
+        Particles[thing] = dict()
+
+    for symbol, name in symbols_and_names:
+        Particles[symbol]['name'] = name
+
+    for fermion in fermions:
+        Particles[fermion]['spin'] = 0.5
+
+    for boson in bosons:
+        Particles[boson]['spin'] = 0
+
+    for lepton in leptons:
+        Particles[lepton]['class'] = 'lepton'
+        Particles[lepton]['lepton number'] = 1
+        Particles[lepton]['baryon number'] = 0
+        if lepton not in neutrinos:
+            Particles[lepton]['charge'] = -1
+        else:
+            Particles[lepton]['charge'] = 0
+
+    for antilepton in antileptons:
+        Particles[antilepton]['class'] = 'antilepton'
+        Particles[antilepton]['lepton number'] = -1
+        Particles[antilepton]['baryon number'] = 0
+        if antilepton not in antineutrinos:
+            Particles[antilepton]['charge'] = 1
+        else:
+            Particles[antilepton]['charge'] = 0
+
+    for baryon in baryons:
+        Particles[baryon]['class'] = 'baryon'
+        Particles[baryon]['lepton number'] = 0
+        Particles[baryon]['baryon number'] = 1
+
+    for antibaryon in antibaryons:
+        Particles[antibaryon]['class'] = 'antibaryon'
+        Particles[antibaryon]['lepton number'] = 0
+        Particles[antibaryon]['baryon number'] = -1
+
+    for thing in leptons + antileptons:
+        if 'e' in thing:
+            Particles[thing]['generation'] = 1
+        elif 'mu' in thing:
+            Particles[thing]['generation'] = 2
+        elif 'tau' in thing:
+            Particles[thing]['generation'] = 3
+
+    for thing in leptons + antileptons:
+        if 'nu' not in thing:
+            if 'e' in thing:
+                Particles[thing]['mass'] = const.m_e
+            elif 'mu' in thing:
+                Particles[thing]['mass'] = 1.883_531_594e-28 * u.kg
+                Particles[thing]['half-life'] = 2.1969811e-6 * u.s
+            elif 'tau' in thing:
+                Particles[thing]['mass'] = 3.167_47e-27 * u.kg
+                Particles[thing]['half-life'] = 2.906e-13 * u.s
+
+    for thing in ['p', 'p-']:
+        Particles[thing]['mass'] = const.m_p
+
+    Particles['p']['charge'] = 1
+    Particles['p-']['charge'] = -1
+
+    for thing in ['n', 'antineutron']:
+        Particles[thing]['mass'] = const.m_n
+        Particles[thing]['half-life'] = 881.5 * u.s
+        Particles[thing]['charge'] = 0
+
+    for thing in everything:
+        if 'half-life' not in Particles[thing].keys():
+            Particles[thing]['half-life'] = np.inf * u.s
+
+    for particle in particles:
+        Particles[particle]['antimatter'] = False
+
+    for antiparticle in antiparticles:
+        Particles[antiparticle]['antimatter'] = True
+
+    return Particles
+
+
+def _create_alias_dicts(Particles: dict) -> (typing.Dict[str, str],
+                                             typing.Dict[str, str]):
+    """Create dictionaries for case sensitive aliases and case
+    insensitive aliases of special particles and antiparticles.
+
+    The keys of these dictionaries are the aliases, and the values
+    are the corresponding standardized symbol for the particle or
+    antiparticle."""
+
+    case_sensitive_aliases = {}
+    case_insensitive_aliases = {}
+
+    for symbol in Particles.keys():
+        name = Particles[symbol]['name']
+        case_insensitive_aliases[name.lower()] = symbol
+
+    case_sensitive_aliases_for_a_symbol = [
+        (['beta-'], 'e-'),
+        (['beta+'], 'e+'),
+        (['p+'], 'p'),
+        (['n-1'], 'n'),
+        (['H-2'], 'D'),
+        (['H-2+', 'H-2 1+', 'H-2 +1'], 'D 1+'),
+        (['H-3+', 'H-3 1+', 'H-3 +1'], 'T 1+'),
+    ]
+
+    case_insensitive_aliases_for_a_symbol = [
+        (['antielectron'], 'e+'),
+        (['muon-'], 'mu-'),
+        (['muon+'], 'mu+'),
+        (['tau particle'], 'tau-'),
+        (['protium'], 'H-1'),
+        (['protium+', 'protium 1+', 'protium +1'], 'p'),
+        (['deuterium', 'hydrogen-2'], 'D'),
+        (['deuteron', 'deuterium+', 'deuterium 1+', 'deuterium +1', 'D+'],
+         'D 1+'),
+        (['tritium', 'hydrogen-3'], 'T'),
+        (['triton', 'tritium+', 'tritium 1+', 'tritium +1'], 'T 1+'),
+        (['alpha'], 'He-4 2+'),
+    ]
+
+    for aliases, symbol in case_sensitive_aliases_for_a_symbol:
+        for alias in aliases:
+            case_sensitive_aliases[alias] = symbol
+
+    for aliases, symbol in case_insensitive_aliases_for_a_symbol:
+        for alias in aliases:
+            case_insensitive_aliases[alias.lower()] = symbol
+
+    alias_keys = list(case_insensitive_aliases.keys())
+
+    for alias in alias_keys:
+        if 'anti' in alias and 'anti-' not in alias:
+            symbol = case_insensitive_aliases[alias].lower()
+            new_alias = alias.replace('anti', 'anti-')
+            case_insensitive_aliases[new_alias] = symbol
+
+    return case_sensitive_aliases, case_insensitive_aliases
+
+
+_Particles = _create_Particles_dict()
+
+_case_sensitive_aliases, _case_insensitive_aliases = \
+    _create_alias_dicts(_Particles)
+
+
+def _get_standard_symbol(alias: typing.Union[str, int]) -> str:
+    """Returns the standard symbol for a particle or antiparticle
+    when the argument is a valid alias.  If the argument is not a
+    valid alias, then this function returns the original argument
+    (which will usually be a string but may be an int representing
+    atomic number)."""
+
+    if not isinstance(alias, str):
+        return alias
+
+    if alias in _case_sensitive_aliases.keys():
+        return _case_sensitive_aliases[alias]
+    elif alias.lower() in _case_insensitive_aliases.keys():
+        return _case_insensitive_aliases[alias.lower()]
+    else:
+        return alias
+
+
+if __name__ == "__main__":  # coveralls: ignore
+    from pprint import pprint
+    print("Case insensitive aliases:")
+    pprint(_case_insensitive_aliases)
+    print(20*"=")
+    print("Case sensitive aliases:")
+    pprint(_case_sensitive_aliases)
+    print(20*"=")
+    print("Particles:")
+    pprint(_Particles)
diff --git a/plasmapy/utils/checks.py b/plasmapy/utils/checks.py
index 322bc30b..44ea008d 100644
--- a/plasmapy/utils/checks.py
+++ b/plasmapy/utils/checks.py
@@ -151,7 +151,6 @@ def check_relativistic(func=None, betafrac=0.1):
     ...     return 1*u.m/u.s
 
     Passing in a custom `betafrac`
-
     >>> @check_relativistic(betafrac=0.01)
     ... def speed():
     ...     return 1*u.m/u.s


Test patch:
diff --git a/plasmapy/atomic/tests/__init__.py b/plasmapy/atomic/tests/__init__.py
index e69de29b..b8efa29f 100644
--- a/plasmapy/atomic/tests/__init__.py
+++ b/plasmapy/atomic/tests/__init__.py
@@ -0,0 +1,19 @@
+from .test_atomic import (test_atomic_symbol,
+                          test_isotope_symbol,
+                          test_atomic_number,
+                          test_mass_number,
+                          test_element_name,
+                          test_standard_atomic_weight,
+                          test_isotope_mass,
+                          test_ion_mass,
+                          test_is_isotope_stable,
+                          test_isotope_calls,
+                          test_half_life,
+                          test_atomic_TypeErrors,
+                          test_atomic_ValueErrors,
+                          test_known_common_stable_isotopes,
+                          test_isotopic_abundance,
+                          test_charge_state)
+
+from .test_nuclear import (test_nuclear_binding_energy,
+                           test_nuclear_reaction_energy)
diff --git a/plasmapy/atomic/tests/test_atomic.py b/plasmapy/atomic/tests/test_atomic.py
index 86b16cbc..ebbf39f1 100644
--- a/plasmapy/atomic/tests/test_atomic.py
+++ b/plasmapy/atomic/tests/test_atomic.py
@@ -1,35 +1,22 @@
-import pytest
-import numpy as np
 from itertools import product
 from astropy import units as u, constants as const
+import numpy as np
+import warnings
+
+from ..atomic import (atomic_symbol, isotope_symbol, atomic_number,
+                      mass_number, element_name, standard_atomic_weight,
+                      isotope_mass, ion_mass, is_isotope_stable,
+                      half_life, known_isotopes, common_isotopes,
+                      stable_isotopes, isotopic_abundance, charge_state,
+                      electric_charge, Elements, Isotopes,
+                      _is_neutron, _is_hydrogen, _is_electron,
+                      _is_positron, _is_antiproton, _is_alpha,
+                      _extract_charge_state, _is_proton)
 
-from ..atomic import (atomic_symbol,
-                      isotope_symbol,
-                      atomic_number,
-                      mass_number,
-                      element_name,
-                      standard_atomic_weight,
-                      isotope_mass,
-                      ion_mass,
-                      is_isotope_stable,
-                      half_life,
-                      known_isotopes,
-                      common_isotopes,
-                      stable_isotopes,
-                      isotopic_abundance,
-                      charge_state,
-                      electric_charge,
-                      Isotopes,
-                      _is_neutron,
-                      _is_hydrogen,
-                      _is_electron,
-                      _is_positron,
-                      _is_antiproton,
-                      _is_alpha,
-                      _extract_charge_state,
-                      _is_proton)
 from ..nuclear import (nuclear_binding_energy, nuclear_reaction_energy)
 
+import pytest
+
 # (argument, expected)
 atomic_symbol_table = [
     (1, 'H'),
@@ -73,16 +60,13 @@
 @pytest.mark.parametrize(
     'argument, expected', atomic_symbol_table)
 def test_atomic_symbol(argument, expected):
-    """Test that atomic_symbol returns the expected result."""
-    assert atomic_symbol(argument) == expected, \
-        (f"atomic_symbol({argument}) is returning {atomic_symbol(argument)} "
-         f"which differs from the expected value of {expected}.")
+    assert atomic_symbol(argument) == expected
 
 
 # (argument, expected_error)
 atomic_symbol_error_table = [
     ('H-0', ValueError),
-    (3.14159, TypeError),
+    (3.141592653589793238462643383279502884, TypeError),
     ('Og-294b', ValueError),
     ('H-934361079326356530741942970523610389', ValueError),
     ('Fe 2+4', ValueError),
@@ -98,15 +82,14 @@ def test_atomic_symbol(argument, expected):
     ('he', ValueError),
     ('au', ValueError),
     ('p-', ValueError),
-    ('antiproton', ValueError)]
+    ('antiproton', ValueError),
+]
 
 
 @pytest.mark.parametrize(
     'argument, expected_error', atomic_symbol_error_table)
 def test_atomic_symbol_error(argument, expected_error):
-    """Test that atomic_symbol raises the expected exceptions."""
-    with pytest.raises(expected_error, message=(
-            f"atomic_symbol({argument}) is not raising {expected_error}.")):
+    with pytest.raises(expected_error):
         atomic_symbol(argument)
 
 
@@ -147,13 +130,9 @@ def test_atomic_symbol_error(argument, expected_error):
 
 
 @pytest.mark.parametrize(
-    "arguments, expected", isotope_symbol_table)
-def test_isotope_symbol(arguments, expected):
-    """Test that isotope_symbol returns the expected results."""
-    assert isotope_symbol(*arguments) == expected, \
-        (f"isotope_symbol is returning {isotope_symbol(*arguments)} "
-         f"for arguments of {arguments}, which differs from the "
-         f"expected value of {expected}.")
+    "argument, expected", isotope_symbol_table)
+def test_isotope_symbol(argument, expected):
+    assert isotope_symbol(*argument) == expected
 
 
 # (argument, kwargs, expected_error)
@@ -188,10 +167,7 @@ def test_isotope_symbol(arguments, expected):
 @pytest.mark.parametrize(
     "argument, kwargs, expected_error", isotope_symbol_error_table)
 def test_isotope_symbol_error(argument, kwargs, expected_error):
-    """Test that isotope_symbol raises the expected exceptions."""
-    with pytest.raises(expected_error, message=(
-            f"isotope_symbol({argument}, **{kwargs}) is not raising a "
-            f"{expected_error}.")):
+    with pytest.raises(expected_error):
         isotope_symbol(argument, **kwargs)
 
 
@@ -208,11 +184,8 @@ def test_isotope_symbol_error(argument, kwargs, expected_error):
 
 @pytest.mark.parametrize(
     "argument, kwargs, expected_warning", isotope_symbol_warning_table)
-def test_isotope_symbol_warnings(argument, kwargs, expected_warning):
-    """Test that isotope_symbol issues the expected warnings."""
-    with pytest.warns(expected_warning, message=(
-            f"isotope_symbol({argument}, **{kwargs}) is not issuing a "
-            f"{expected_warning}.")):
+def test_isotope_symbol_error(argument, kwargs, expected_warning):
+    with pytest.warns(expected_warning):
         isotope_symbol(argument, **kwargs)
 
 
@@ -240,10 +213,7 @@ def test_isotope_symbol_warnings(argument, kwargs, expected_warning):
 
 @pytest.mark.parametrize("argument, expected", atomic_number_table)
 def test_atomic_number(argument, expected):
-    """Test that atomic_number returns the expected results."""
-    assert atomic_number(argument) == expected, \
-        (f"atomic_number({argument}) is expecting a result of {expected} but "
-         f"is getting a result of {atomic_number(argument)}.")
+    assert atomic_number(argument) == expected
 
 
 # (argument, expected_error)
@@ -263,9 +233,7 @@ def test_atomic_number(argument, expected):
 @pytest.mark.parametrize(
     "argument, expected_error", atomic_number_error_table)
 def test_atomic_number_error(argument, expected_error):
-    """Test that atomic_number raises the expected exceptions."""
-    with pytest.raises(expected_error, warning=(
-            f"atomic_number({argument}) is not raising a {expected_error}")):
+    with pytest.raises(expected_error):
         atomic_number(argument)
 
 
@@ -292,11 +260,7 @@ def test_atomic_number_error(argument, expected_error):
 
 @pytest.mark.parametrize("isotope, expected", mass_number_table)
 def test_mass_number(isotope, expected):
-    """Test that mass_number returns the expected results."""
-    assert mass_number(isotope) == expected, \
-        (f"mass_number({isotope}) is returning a value of "
-         f"{mass_number(isotope)}, which differs from the expected "
-         f"value of {expected}.")
+    assert mass_number(isotope) == expected
 
 
 # (argument, expected_error)
@@ -311,7 +275,6 @@ def test_mass_number(isotope, expected):
 @pytest.mark.parametrize(
     "argument, expected_error", mass_number_error_table)
 def test_mass_number_error(argument, expected_error):
-    """Test that mass_number raises the expected exceptions."""
     with pytest.raises(expected_error):
         mass_number(argument)
 
@@ -345,11 +308,7 @@ def test_mass_number_error(argument, expected_error):
 
 @pytest.mark.parametrize("argument, expected", element_name_table)
 def test_element_name(argument, expected):
-    """Test that element_name returns the expected results."""
-    assert element_name(argument) == expected, \
-        (f"element_name({argument}) is returning a value of "
-         f"{element_name(argument)}, which differs from the expected "
-         f"value of {expected}.")
+    assert element_name(argument) == expected
 
 
 # (argument, expected_error)
@@ -369,23 +328,21 @@ def test_element_name(argument, expected):
 
 @pytest.mark.parametrize("argument, expected_error", element_name_error_table)
 def test_element_name_error(argument, expected_error):
-    """Test that element_name raises the expected exceptions."""
+
     with pytest.raises(expected_error):
         element_name(argument)
 
 
+def test_standard_atomic_weight_not_none():
+    assert standard_atomic_weight('N') is not None
+
+
 def test_standard_atomic_weight_value_between():
-    """Test that standard_atomic_weight returns approximately the correct
-    value for phosphorus."""
-    assert 30.973 < standard_atomic_weight('P').value < 30.974, \
-        "Incorrect standard atomic weight for phosphorus."
+    assert 30.973 < standard_atomic_weight('P').value < 30.974
 
 
 def test_standard_atomic_weight_unit():
-    """Test that standard_atomic_weight returns a Quantity with the
-    expected units."""
-    assert standard_atomic_weight('Au').unit == u.u, \
-        "Incorrect units from standard_atomic_weight for gold."
+    assert standard_atomic_weight('Au').unit == u.u
 
 
 # (argument, expected)
@@ -397,10 +354,7 @@ def test_standard_atomic_weight_unit():
 
 @pytest.mark.parametrize("argument, expected", standard_atomic_weight_table)
 def test_standard_atomic_weight(argument, expected):
-    """Test that standard_atomic_weight returns the expected values for
-    hydrogen."""
-    assert standard_atomic_weight(argument).value == expected, \
-        f"Incorrect standard_atomic_weight for {argument}."
+    assert standard_atomic_weight(argument).value == expected
 
 
 # (argument, expected_error)
@@ -423,30 +377,20 @@ def test_standard_atomic_weight(argument, expected):
 @pytest.mark.parametrize("argument, expected_error",
                          standard_atomic_weight_error_table)
 def test_standard_atomic_weight_error(argument, expected_error):
-    """Test that standard_atomic_weight raises the expected exceptions."""
-    with pytest.raises(expected_error, message=(
-            f"standard_atomic_weight({argument}) is not raising a "
-            "{expected_error}.")):
+    with pytest.raises(expected_error):
         standard_atomic_weight(argument)
 
 
 def test_isotope_mass_berkelium_249():
-    """Test that isotope_mass returns the correct value for Bk-249."""
-    assert np.isclose(isotope_mass('berkelium-249').value, 249.0749877), \
-        "Incorrect isotope mass for berkelium."
+    assert np.isclose(isotope_mass('berkelium-249').value, 249.0749877)
 
 
 def test_isotope_mass_n():
-    """Test that isotope_mass returns the correct value for neutrons."""
-    assert np.isclose(isotope_mass('n') / (1.008664 * u.u), 1, atol=1e-6), \
-        "Incorrect isotope mass for neutrons."
+    assert np.isclose(isotope_mass('n') / (1.008664 * u.u), 1, atol=1e-6)
 
 
 def test_isotope_mass_si_30_units():
-    """Test that isotope_mass returns a Quantity with the correct unit
-    for Si-30."""
-    assert isotope_mass('Si-30').unit == u.u, \
-        "Incorrect unit for isotope mass for Si-30."
+    assert isotope_mass('Si-30').unit == u.u
 
 
 # (arg1, arg2)
@@ -463,10 +407,7 @@ def test_isotope_mass_si_30_units():
 
 @pytest.mark.parametrize("arg1, arg2", isotope_mass_table)
 def test_isotope_mass(arg1, arg2):
-    """Test that isotope_mass returns equivalent results for equivalent
-    arguments."""
-    assert isotope_mass(*arg1) == isotope_mass(*arg2), \
-        f"isotope_mass(*{arg1}) is not equivalent to isotope_mass(*{arg2})"
+    assert isotope_mass(*arg1) == isotope_mass(*arg2)
 
 
 # (argument, expected_error)
@@ -486,96 +427,52 @@ def test_isotope_mass(arg1, arg2):
 
 @pytest.mark.parametrize("argument, expected_error", isotope_mass_error_table)
 def test_isotope_mass_error(argument, expected_error):
-    """Test that isotope_mass raises the expected exceptions."""
-    with pytest.raises(expected_error, warning=(
-            f"isotope_mass({argument}) is not raising a {expected_error}")):
+    with pytest.raises(expected_error):
         isotope_mass(argument)
 
 
-def test_ion_mass_for_hydrogen_with_no_mass_number():
-    """Test that ion_mass does not return the proton mass when no
-    mass number is specified for hydrogen.  In this case, the
-    standard atomic weight should be used to account for the small
-    fraction of deuterium."""
-    assert ion_mass('H', Z=1) > const.m_p
+def test_ion_mass_hydrogen():
+    assert ion_mass('H', Z=1) > const.m_p, "Use standard_atomic_weight of 'H'"
     assert ion_mass('hydrogen', Z=1) > const.m_p
 
 
 def test_ion_mass_unit():
-    """Test that ion_mass returns a Quantity with the correct units."""
     assert ion_mass('F-19', Z=3).unit == u.kg
-
-
-# (arg, kwargs)
-inputs_that_should_return_proton_mass = [
-    ('proton', {}),
-    ('H-1+', {}),
-    ('H-1 +1', {}),
-    ('H-1 1+', {}),
-    ('H-1', {'Z': 1}),
-    ('hydrogen-1', {'Z': 1}),
-    ('p+', {}),
-    ('antiproton', {}),
-    ('p-', {}),
-]
-
-
-@pytest.mark.parametrize("arg, kwargs", inputs_that_should_return_proton_mass)
-def test_ion_mass_proton_mass(arg, kwargs):
-    should_be_proton_mass = ion_mass(arg, **kwargs)
-    assert should_be_proton_mass == const.m_p, \
-        (f"ion_mass({arg}, **{kwargs}) should be returning the proton mass, "
-         f"but is instead returning {should_be_proton_mass}.")
-
-
-def test_ion_mass_miscellaneous_cases():
-    """Test miscellaneous cases for ion_mass."""
+    assert ion_mass('F-19', Z='3').unit == u.kg
+
+
+def test_ion_mass():
+    assert ion_mass('proton') == const.m_p
+    assert ion_mass('H-1+') == const.m_p
+    assert ion_mass('hydrogen-1+') == const.m_p
+    assert ion_mass('H-1', Z=1) == const.m_p
+    assert ion_mass('p') == const.m_p
+    assert ion_mass('p+') == const.m_p
+    assert ion_mass('p-') == const.m_p
+    assert ion_mass('e+') == ion_mass('positron') == const.m_e
+    assert np.isclose(ion_mass('alpha') / ion_mass('He-4', Z=2), 1.0)
+    assert ion_mass('Ne-22', Z=2) == 21.991385114 * u.u - 2 * const.m_e
+    assert ion_mass('H-1+') == const.m_p
+    assert ion_mass('He-4 2+') == ion_mass('alpha')
+    assert np.isclose(ion_mass('Fe 1-').value,
+                      (ion_mass('Fe 1+') + 2 * const.m_e).value, rtol=1e-14)
+    assert np.isclose(ion_mass('Fe-56 1-').value,
+                      (ion_mass('Fe-56 1+') + 2 * const.m_e).value, rtol=1e-14)
+    assert np.isclose((ion_mass('Fe-56 1+')).value,
+                      (ion_mass('Fe', Z=1, mass_numb=56)).value)
+    assert np.isclose((ion_mass('Fe-56 1+')).value,
+                      (ion_mass(26, Z=1, mass_numb=56)).value)
+    assert ion_mass(1, Z=1, mass_numb=1) == ion_mass('p')
+    assert ion_mass('deuteron') == ion_mass('D +1')
+    assert ion_mass('T', Z=1) == ion_mass('T +1')
+    assert ion_mass('Fe', mass_numb=56, Z=2) == \
+        ion_mass('Fe', mass_numb='56', Z=2)
     assert np.isclose(ion_mass(9.11e-31 * u.kg).value, 9.10938291e-31,
                       atol=1e-37)
     assert ion_mass(1.67e-27 * u.kg) == 1.67e-27 * u.kg
     assert np.isclose(ion_mass(1 * u.u).value, 1.660538921e-27, atol=1e-35)
     assert ion_mass('alpha') > ion_mass('He-3 2+')
-
-
-# (arg1, kwargs1, arg2, kwargs2, expected)
-equivalent_ion_mass_args = [
-    ('e+', {}, 'positron', {}, const.m_e),
-    ('alpha', {}, "He-4++", {}, None),
-    ('alpha', {}, "helium-4 2+", {}, None),
-    ('deuteron', {}, "H", {"Z": 1, "mass_numb": 2}, None),
-    ('D+', {}, "H-2+", {}, None),
-    ('D+', {}, "D 1+", {}, None),
-    ('Deuterium+', {}, "D", {"Z": 1}, None),
-    ('triton', {}, "H", {"Z": 1, "mass_numb": 3}, None),
-    ('T+', {}, "H-3+", {}, None),
-    ('T+', {}, "T 1+", {}, None),
-    ('Tritium+', {}, "T", {"Z": 1}, None),
-    ('Fe-56 1+', {}, 'Fe', {"mass_numb": 56, "Z": 1},
-     ion_mass('Fe-56 1-') - 2 * const.m_e),
-    ('Fe-56 +1', {}, 26, {"mass_numb": 56, "Z": 1}, None),
-    # The functionality for the following test parameters may be deprecated.
-    ('H', {'Z': 1, 'mass_numb': 2}, 1, {'Z': '1', 'mass_numb': '2'}, None)
-]
-
-
-@pytest.mark.parametrize(
-    "arg1, kwargs1, arg2, kwargs2, expected", equivalent_ion_mass_args)
-def test_ion_mass_equivalent_args(arg1, kwargs1, arg2, kwargs2, expected):
-    """Test that """
-
-    result1 = ion_mass(arg1, **kwargs1)
-    result2 = ion_mass(arg2, **kwargs2)
-
-    assert result1 == result2, \
-        (f"ion_mass({arg1}, **{kwargs1}) = {result1}, whereas "
-         f"ion_mass({arg2}, **{kwargs2}) = {result2}.  "
-         f"These results are not equivalent as expected.")
-
-    if expected is not None:
-        assert result1 == result2 == expected, \
-            (f"ion_mass({arg1}, **{kwargs1}) = {result1} and "
-             f"ion_mass({arg2}, **{kwargs2}) = {result2}, but  "
-             f"these results are not equivalent to {expected} as expected.")
+    assert ion_mass('antiproton') == ion_mass('p-') == ion_mass('p+')
 
 
 # (argument, kwargs, expected_error)
@@ -598,10 +495,7 @@ def test_ion_mass_equivalent_args(arg1, kwargs1, arg2, kwargs2, expected):
 @pytest.mark.parametrize("argument, kwargs, expected_error",
                          ion_mass_error_table)
 def test_ion_mass_error(argument, kwargs, expected_error):
-    """Test errors that should be raised by ion_mass."""
-    with pytest.raises(expected_error, message=(
-            f"ion_mass({argument}, **{kwargs}) is not raising a "
-            f"{expected_error}.")):
+    with pytest.raises(expected_error):
         ion_mass(argument, **kwargs)
 
 
@@ -614,10 +508,7 @@ def test_ion_mass_error(argument, kwargs, expected_error):
 @pytest.mark.parametrize("argument, kwargs, expected_warning",
                          ion_mass_warning_table)
 def test_ion_mass_warnings(argument, kwargs, expected_warning):
-    """Test that ion_mass issues the expected warnings."""
-    with pytest.warns(expected_warning, message=(
-            f"ion_mass({argument}, **{kwargs}) is not issuing a "
-            f"{expected_warning}.")):
+    with pytest.warns(expected_warning):
         ion_mass(argument, **kwargs)
 
 
@@ -639,14 +530,12 @@ def test_ion_mass_warnings(argument, kwargs, expected_warning):
     ('iron-56',),
     ('Iron-56',),
     (26, 56),
-]
+    ]
 
 
 @pytest.mark.parametrize("argument", is_isotope_stable_table)
 def test_is_isotope_stable(argument):
-    """Test that is_isotope_stable returns True for stable isotopes."""
-    assert is_isotope_stable(*argument), \
-        f"is_isotope_stable is not returning True for {argument}"
+    assert is_isotope_stable(*argument)
 
 
 # (argument)
@@ -671,9 +560,7 @@ def test_is_isotope_stable(argument):
 
 @pytest.mark.parametrize("argument", is_isotope_stable_false_table)
 def test_is_isotope_stable_false(argument):
-    """Test that is_isotope_stable returns False for unstable isotopes."""
-    assert not is_isotope_stable(*argument), \
-        f"is_isotope_stable is not returning False for {argument}"
+    assert not is_isotope_stable(*argument)
 
 
 # (argument, expected_error)
@@ -688,108 +575,56 @@ def test_is_isotope_stable_false(argument):
 @pytest.mark.parametrize("argument, expected_error",
                          is_isotope_stable_error_table)
 def test_is_isotope_stable_error(argument, expected_error):
-    """Test errors that should be raised by is_isotope_stable."""
-    with pytest.raises(expected_error, message=(
-            f"is_isotope_stable({argument}) is not raising a "
-            f"{expected_error}")):
+    with pytest.raises(expected_error):
         is_isotope_stable(*argument)
 
 
-def test_known_common_stable_isotopes():
-    """Test that known_isotopes, common_isotopes, and stable_isotopes return
-    the correct values for hydrogen."""
-
-    known_should_be = ['H-1', 'D', 'T', 'H-4', 'H-5', 'H-6', 'H-7']
-    common_should_be = ['H-1', 'D']
-    stable_should_be = ['He-3', 'He-4']
-
-    assert known_isotopes('H') == known_should_be, \
-        (f"known_isotopes('H') should return {known_should_be}, but is "
-         f"instead returning {known_isotopes('H')}")
-
-    assert common_isotopes('H') == common_should_be, \
-        (f"common_isotopes('H') should return {common_should_be}, but is "
-         f"instead returning {common_isotopes('H')}")
-
-    assert stable_isotopes('He') == stable_should_be, \
-        (f"stable_isotopes('He') should return {stable_should_be}, but is "
-         f"instead returning {stable_isotopes('He')}")
+def test_isotope_calls():
+    assert known_isotopes('H') == \
+        ['H-1', 'D', 'T', 'H-4', 'H-5', 'H-6', 'H-7']
+    assert common_isotopes('H') == ['H-1', 'D']
+    assert stable_isotopes('He') == ['He-3', 'He-4']
 
 
 def test_half_life():
-    """Test that half_life returns the correct values for various isotopes."""
-    assert half_life('H-1') == np.inf * u.s, "Incorrect half-life for H-1'."
-
+    assert half_life('H-1') == np.inf * u.s
     assert np.isclose(half_life('tritium').to(u.s).value,
-                      (12.32 * u.yr).to(u.s).value, rtol=2e-4), \
-        "Incorrect half-life for tritium."
-
-    assert half_life('H-1').unit == 's', "Incorrect unit for H-1."
-    assert half_life('tritium').unit == 's', "Incorrect unit for tritium."
+                      (12.32 * u.yr).to(u.s).value, rtol=2e-4)
+    assert half_life('H-1').unit == 's'
+    assert half_life('tritium').unit == 's'
 
 
 def test_half_life_unstable_isotopes():
-    """Test that half_life returns None and issues a warning for all isotopes
-    that do not yet have half-life data."""
-    for isotope in Isotopes.keys():
+    for isotope in Isotopes.keys():  # unstable isotopes w/o half-life data
         if 'half_life' not in Isotopes[isotope].keys() and \
                 not Isotopes[isotope].keys():
-            with pytest.warns(UserWarning, message=(
-                    f"No UserWarning issued for {isotope}")):
+            with pytest.warns(UserWarning):
                 assert half_life(isotope) is None
 
 
 def test_half_life_u_220():
-    """Test that half_life returns None and issues a warning for an isotope
-    without half-life data.
-
-    If half-life data is added for this isotope, then this test should fail
-    and a different isotope without half-life data should be chosen instead
-    until all isotopes have half-life data."""
-
-    isotope_without_half_life_data = "U-220"
-
     with pytest.warns(UserWarning):
-
-        try:
-            half_life_isotope = half_life(isotope_without_half_life_data)
-        except Exception:
-            raise ValueError(f"half_life is raising an exception instead of "
-                             f"issuing a UserWarning for an isotope without "
-                             f"half-life data")
-
-        assert half_life_isotope is None, \
-            (f"half_life should return None for an isotope without half-life "
-             f"data, but is returning {half_life_isotope}")
+        half_life('U-220')
+        assert half_life('U-220') is None, \
+            ("If half-life data is added for this isotope, then this test "
+             "*should* fail and a different isotope without half-life data "
+             "should be chosen instead")
 
 
 atomic_TypeError_funcs_table = [
-    atomic_symbol,
-    isotope_symbol,
-    atomic_number,
-    is_isotope_stable,
-    half_life,
-    mass_number,
-    element_name,
-    standard_atomic_weight,
-    isotope_mass,
-    ion_mass,
-    nuclear_binding_energy,
-    nuclear_reaction_energy
-]
-
+    atomic_symbol, isotope_symbol, atomic_number, is_isotope_stable, half_life,
+    mass_number, element_name, standard_atomic_weight, isotope_mass, ion_mass,
+    nuclear_binding_energy, nuclear_reaction_energy]
 atomic_TypeError_bad_arguments = [1.1, {'cats': 'bats'}, 1 + 1j]
 
 
 @pytest.mark.parametrize(
-    "func, argument",
+    "function, argument",
     product(atomic_TypeError_funcs_table,
             atomic_TypeError_bad_arguments))
-def test_atomic_TypeErrors(func, argument):
-    """Test that atomic functions raise TypeErrors when arguments of the
-    incorrect time are provided."""
+def test_atomic_TypeErrors(function, argument):
     with pytest.raises(TypeError):
-        func(argument)
+        function(argument)
 
 
 atomic_ValueErrors_funcs_table = [
@@ -800,19 +635,15 @@ def test_atomic_TypeErrors(func, argument):
 
 
 @pytest.mark.parametrize(
-    "func, argument",
+    "function, argument",
     product(atomic_ValueErrors_funcs_table,
             atomic_ValueError_bad_arguments))
-def test_atomic_ValueErrors(func, argument):
-    """Test that atomic functions raise ValueErrors when incorrect
-    arguments are provided."""
+def test_atomic_ValueErrors(function, argument):
     with pytest.raises(ValueError):
-        func(argument)
+        function(argument)
 
 
-def test_known_common_stable_isotopes_cases():
-    """Test that known_isotopes, common_isotopes, and stable_isotopes
-    return certain isotopes that fall into these categories."""
+def test_known_common_stable_isotopes():
     assert 'H-1' in known_isotopes('H')
     assert 'D' in known_isotopes('H')
     assert 'T' in known_isotopes('H')
@@ -823,56 +654,38 @@ def test_known_common_stable_isotopes_cases():
     assert 'H-1' in stable_isotopes('H')
     assert 'D' in stable_isotopes('H')
     assert 'T' not in stable_isotopes('H')
-    assert 'Fe-56' in common_isotopes('Fe', most_common_only=True)
-    assert 'He-4' in common_isotopes('He', most_common_only=True)
-
-
-def test_known_common_stable_isotopes_len():
-    """Test that known_isotopes, common_isotopes, and stable_isotopes return
-    lists of the expected lengths.
-
-    The number of common isotopes may change if isotopic composition data
-    has any significant changes.
-
-    The number of stable isotopes may decrease slightly if some isotopes are
-    discovered to be unstable but with extremely long half-lives.
-
-    The number of known isotopes will increase as new isotopes are discovered,
-    so a buffer is included in the test."""
 
     assert len(common_isotopes()) == 288, \
-        ("The length of the list returned by common_isotopes() is "
-         f"{len(common_isotopes())}, which is not the expected value.")
+        ("The number of common isotopes may change if isotopic composition "
+         "data has any significant changes.")
 
     assert len(stable_isotopes()) == 254, \
-        ("The length of the list returned by stable_isotopes() is "
-         f"{len(stable_isotopes())}, which is not the expected value.")
+        ("The number of stable isotopes may decrese slightly if some are "
+         "discovered to be unstable but with extremely long half-lives.")
 
-    assert 3352 <= len(known_isotopes()) <= 3400, \
-        ("The length of the list returned by known_isotopes() is "
-         f"{len(known_isotopes())}, which is not within the expected range.")
+    assert 3351 <= len(known_isotopes()) <= 3600, \
+        ("The number of known isotopes ")
+
+    assert 'Fe-56' in common_isotopes('Fe', most_common_only=True)
+    assert 'He-4' in common_isotopes('He', most_common_only=True)
 
 
 @pytest.mark.parametrize(
     "func", [common_isotopes, stable_isotopes, known_isotopes])
 def test_known_common_stable_isotopes_error(func):
-    """Test that known_isotopes, common_isotopes, and stable_isotopes
-    raise ValueErrors for neutrons."""
-    with pytest.raises(ValueError, message=(
-            f"{func} is not raising a ValueError for neutrons.")):
+    with pytest.raises(ValueError):
         func('n')
 
 
 def test_isotopic_abundance():
-    """Test that isotopic_abundance returns the appropriate values or
-    raises appropriate errors for various isotopes."""
+
     assert isotopic_abundance('H', 1) == isotopic_abundance('protium')
     assert np.isclose(isotopic_abundance('D'), 0.000115)
     assert isotopic_abundance('Be-8') == 0.0, 'Be-8'
     assert isotopic_abundance('Li-8') == 0.0, 'Li-8'
     assert isotopic_abundance('Og', 294) == 0.0
 
-    with pytest.raises(ValueError, message="No exception raised for neutrons"):
+    with pytest.raises(ValueError):
         isotopic_abundance('neutron')
 
     with pytest.raises(ValueError):
@@ -881,10 +694,8 @@ def test_isotopic_abundance():
 
 isotopic_abundance_elements = (
     atomic_number(atomic_numb) for atomic_numb in range(1, 119))
-
 isotopic_abundance_isotopes = (
     common_isotopes(element) for element in isotopic_abundance_elements)
-
 isotopic_abundance_sum_table = (
     (element, isotopes) for element, isotopes in
     zip(isotopic_abundance_elements, isotopic_abundance_isotopes)
@@ -893,11 +704,10 @@ def test_isotopic_abundance():
 
 @pytest.mark.parametrize("element, isotopes", isotopic_abundance_sum_table)
 def test_isotopic_abundances_sum(element, isotopes):
-    """Test that the sum of isotopic abundances for each element with
-    isotopic abundances is one."""
+    # Check that the sum of isotopic abundances for each element is one
     sum_of_iso_abund = sum(isotopic_abundance(isotope) for isotope in isotopes)
     assert np.isclose(sum_of_iso_abund, 1, atol=1e-6), \
-        f"The sum of the isotopic abundances for {element} does not equal 1."
+        "Problem with: " + element
 
 
 # (argument, expected)
@@ -927,10 +737,7 @@ def test_isotopic_abundances_sum(element, isotopes):
 
 @pytest.mark.parametrize("argument, expected", charge_state_table)
 def test_charge_state(argument, expected):
-    """Test that charge_state returns the expected results."""
-    assert charge_state(argument) == expected, \
-        (f"charge_state({argument}) is returning {charge_state(argument)} "
-         f"which differs from the expected result of {expected}.")
+    assert charge_state(argument) == expected
 
 
 # (argument, expected_error)
@@ -947,9 +754,7 @@ def test_charge_state(argument, expected):
 
 @pytest.mark.parametrize("argument, expected_error", charge_state_error_table)
 def test_charge_state_error(argument, expected_error):
-    """Test that charge_state raises the expected exceptions."""
-    with pytest.raises(expected_error, message=(
-            f"charge_state({argument} is not raising a {expected_error}.")):
+    with pytest.raises(expected_error):
         charge_state(argument)
 
 
@@ -963,15 +768,11 @@ def test_charge_state_error(argument, expected_error):
 @pytest.mark.parametrize("argument, expected_warning",
                          charge_state_warning_table)
 def test_charge_state_warnings(argument, expected_warning):
-    """Test that charge_state issues appropriate warnings."""
-    with pytest.warns(expected_warning, message=(
-            f"charge_state({argument}) is not issuing a {expected_warning}")):
+    with pytest.warns(expected_warning):
         charge_state(argument)
 
 
 def test_electric_charge():
-    """Test that the results from electric_charge provide the correct
-    values that have the correct characteristics."""
     assert electric_charge('p').value == 1.6021766208e-19
     assert electric_charge('p').unit == 'C'
     assert electric_charge('e').value == -1.6021766208e-19
@@ -990,10 +791,7 @@ def test_electric_charge():
 @pytest.mark.parametrize("argument, expected_error",
                          electric_charge_error_table)
 def test_electric_charge_error(argument, expected_error):
-    """Test that electric_charge raises the expected exceptions."""
-    with pytest.raises(expected_error, message=(
-            f"electric_charge({argument}) is not raising a "
-            f"{expected_error}.")):
+    with pytest.raises(expected_error):
         electric_charge(argument)
 
 
@@ -1005,11 +803,8 @@ def test_electric_charge_error(argument, expected_error):
 
 @pytest.mark.parametrize("argument, expected_warning",
                          electric_charge_warning_table)
-def test_electric_charge_warning(argument, expected_warning):
-    """Test that electric_charge issues the expected warnings."""
-    with pytest.warns(expected_warning, message=(
-            f"electric_charge({argument}) is not issuing a "
-            f"{expected_warning}.")):
+def test_electric_charge_error(argument, expected_warning):
+    with pytest.warns(expected_warning):
         electric_charge(argument)
 
 
@@ -1025,8 +820,6 @@ def test_electric_charge_warning(argument, expected_warning):
                           (0, {"mass_numb": 1}, True),
                           ('n0', {}, True)])
 def test_is_neutron(test_input, kwargs, expected):
-    """Test that _is_neutron returns True when the argument corresponds to a
-    neutron and False otherwise."""
     assert _is_neutron(test_input, **kwargs) == expected
 
 
@@ -1060,8 +853,6 @@ def test_is_neutron(test_input, kwargs, expected):
                           (1, False, False),
                           ('p-', False, False)])
 def test_is_hydrogen(test_input, can_be_atom_numb, expected):
-    """Test that _is_hydrogen returns True if the argument corresponds to
-    hydrogen and False otherwise."""
     assert _is_hydrogen(test_input,
                         can_be_atomic_number=can_be_atom_numb) == expected
 
@@ -1070,7 +861,6 @@ def test_is_hydrogen(test_input, can_be_atom_numb, expected):
                          [('H 2+', {}, ValueError),
                           ('D++', {}, ValueError)])
 def test_is_hydrogen_errors(test_input, kwargs, expected_error):
-    """Test that _is_hydrogen raises the expected exceptions."""
     with pytest.raises(expected_error):
         _is_hydrogen(test_input, **kwargs)
 
@@ -1087,8 +877,6 @@ def test_is_hydrogen_errors(test_input, kwargs, expected_error):
                           ('beta', False),
                           (-1, False)])
 def test_is_electron(test_input, expected):
-    """Test that _is_electron returns True if the argument corresponds to
-    an electron and False otherwise."""
     assert _is_electron(test_input) == expected
 
 
@@ -1104,8 +892,6 @@ def test_is_electron(test_input, expected):
                           ('beta', False),
                           (1, False)])
 def test_is_positron(test_input, expected):
-    """Test that _is_positron returns True if the argument corresponds to
-    positron and False otherwise."""
     assert _is_positron(test_input) == expected
 
 
@@ -1130,8 +916,6 @@ def test_is_positron(test_input, expected):
                           ('H', {"Z": 1}, False),
                           ('H-1', {"Z": 0}, False)])
 def test_is_proton(test_input, kwargs, expected):
-    """Test that _is_proton returns True if the argument corresponds to
-    a proton and False otherwise."""
     assert _is_proton(test_input, **kwargs) == expected
 
 
@@ -1153,8 +937,6 @@ def test_is_proton(test_input, kwargs, expected):
                           ('P-', False),
                           (57, False)])
 def test_is_antiproton(test_input, expected):
-    """Test that _is_antiproton returns True if the argument corresponds to
-    an antiproton and False otherwise."""
     assert _is_antiproton(test_input) == expected
 
 
@@ -1189,8 +971,6 @@ def test_is_antiproton(test_input, expected):
                           ('Fe', False),
                           ('he-4 2+', False)])
 def test_is_alpha(test_input, expected):
-    """Test that _is_alpha returns True if the argument corresponds to
-    an alpha particle and False otherwise."""
     assert _is_alpha(test_input) == expected
 
 
@@ -1205,22 +985,17 @@ def test_is_alpha(test_input, expected):
                           ('H-1-', 'H-1', -1),
                           ('He-4-', 'He-4', -1)])
 def test_extract_charge_state(test_input, expected_newarg, expected_Z):
-    """Test that _extract_charge_state returns the expected values."""
     new_symbol, new_Z = _extract_charge_state(test_input)
-    assert new_symbol == expected_newarg, \
-        (f"_extract_charge_state should return {expected_newarg} as "
-         f" its first argument, but is instead returning {new_symbol}")
-    assert new_Z == expected_Z, \
-        (f"_extract_charge_state should return {expected_Z} as its second"
-         f"argument, but is instead returning {new_Z}.")
+    assert new_symbol == expected_newarg, str(test_input)
+    assert new_Z == expected_Z
 
 
 @pytest.mark.parametrize("test_input,expected_error",
                          [('H-1-+-+', ValueError),
                           ('H ++', ValueError),
-                          ('Fe +21+', ValueError)])
+                          ('Fe +21+', ValueError),
+                          ('lead-12345', ValueError)])
 def test_extract_charge_state_errors(test_input, expected_error):
-    """Test that _extract_charge_state raises the expected exceptions."""
     with pytest.raises(expected_error):
         _extract_charge_state(test_input)
 
@@ -1229,7 +1004,6 @@ def test_extract_charge_state_errors(test_input, expected_error):
                          [('H-1----', UserWarning),
                           ('Fe -4', UserWarning),
                           ('lead 4-', UserWarning)])
-def test_extract_charge_state_warnings(test_input, expected_warning):
-    """Test that _extract_charge_state issues the expected warnings."""
+def test_extract_charge_state_errors(test_input, expected_warning):
     with pytest.warns(expected_warning):
         _extract_charge_state(test_input)
diff --git a/plasmapy/atomic/tests/test_particles.py b/plasmapy/atomic/tests/test_particles.py
new file mode 100644
index 00000000..2ef407da
--- /dev/null
+++ b/plasmapy/atomic/tests/test_particles.py
@@ -0,0 +1,110 @@
+import pytest
+
+from ..particles import (
+    _get_standard_symbol,
+    _Particles,
+    _case_sensitive_aliases,
+    _case_insensitive_aliases)
+
+
+particle_antiparticle_pairs = [
+    ('e-', 'e+'),
+    ('mu-', 'mu+'),
+    ('tau-', 'tau+'),
+    ('p', 'p-'),
+    ('n', 'antineutron'),
+    ('nu_e', 'anti_nu_e'),
+    ('nu_mu', 'anti_nu_mu'),
+    ('nu_tau', 'anti_nu_tau'),
+]
+
+
+@pytest.mark.parametrize("particle,antiparticle", particle_antiparticle_pairs)
+def test_particle_antiparticle_pairs(particle, antiparticle):
+    """Test that particles and antiparticles have the same or exact
+    opposite properties in the _Particles dictionary."""
+
+    assert not _Particles[particle]['antimatter'], \
+        f"{particle} is incorrectly marked as antimatter."
+
+    assert _Particles[antiparticle]['antimatter'], \
+        f"{antiparticle} is incorrectly marked as matter."
+
+    identical_keys = ['half-life', 'spin']
+
+    if 'nu' not in particle:
+        identical_keys.append('mass')
+
+    if particle in ['e-', 'mu-', 'tau-'] or 'nu' in particle:
+        identical_keys.append('generation')
+
+    opposite_keys = ['charge', 'lepton number', 'baryon number']
+
+    for key in identical_keys:
+        assert _Particles[particle][key] == _Particles[antiparticle][key], \
+            f"{particle} and {antiparticle} do not have identical {key}."
+
+    for key in opposite_keys:
+        assert _Particles[particle][key] == -_Particles[antiparticle][key], \
+            f"{particle} and {antiparticle} do not have exact opposite {key}."
+
+    if particle not in ['e-', 'n']:
+        assert _Particles[particle]['name'] == \
+            _Particles[antiparticle]['name'].replace('anti', ''), \
+            (f"{particle} and {antiparticle} do not have same name except "
+             "for 'anti'.")
+
+
+aliases_and_symbols = [
+    ('electron', 'e-'),
+    ('beta-', 'e-'),
+    ('beta+', 'e+'),
+    ('positron', 'e+'),
+    ('proton', 'p'),
+    ('', ''),
+    (5, 5),
+    ('deuterium+', 'D 1+'),
+    ('deuterium 1+', 'D 1+'),
+    ('tritium +1', 'T 1+'),
+    ('alpha', 'He-4 2+'),
+    ('D+', 'D 1+'),
+    ('Deuterium', 'D'),
+    ('deuteron', 'D 1+'),
+    ('triton', 'T 1+'),
+    ('muon', 'mu-'),
+    ('antimuon', 'mu+'),
+    ('tau particle', 'tau-'),
+    ('antitau', 'tau+'),
+    ('p+', 'p'),
+]
+
+
+@pytest.mark.parametrize("alias,symbol", aliases_and_symbols)
+def test_get_standard_symbol(alias, symbol):
+    """Test that _get_standard_symbol correctly takes in aliases and
+    returns the corresponding symbols, and returns the original argument
+    if the argument does not correspond to an alias."""
+    result = _get_standard_symbol(alias)
+    assert result == symbol, \
+        (f"_get_standard_symbol({alias}) returns {result}, which differs "
+         f"from the expected symbol of {symbol}.\n\n"
+         f"_case_insensitive_aliases:\n{_case_insensitive_aliases}\n\n"
+         f"_case_sensitive_aliases:\n{_case_sensitive_aliases}")
+
+
+alias_dictionaries = [_case_sensitive_aliases, _case_insensitive_aliases]
+
+
+@pytest.mark.parametrize("alias_dict", alias_dictionaries)
+def test_alias_dict_properties(alias_dict):
+    """Test properties of the alias dictionaries."""
+
+    for key in alias_dict.keys():
+        assert isinstance(key, str), \
+            (f"The following key should be a string, but isn't: {key}\n\n"
+             f"The entire dictionary is:\n\n{alias_dict}")
+
+    for value in alias_dict.values():
+        assert isinstance(value, str), \
+            (f"The following value should be a string, but isn't: {value}\n\n"
+             f"The entire dictionary is:\n\n{alias_dict}")