Repository: PlasmaPy/PlasmaPy

Issue:
Integrate Particle into arguments in langmuir.py
Currently, the `langmuir.py` module uses the `gas` argument in a number of functions to define the mass of the plasma species. This should be refactored to use the Particle class instead.

EDIT: and of course rename the argument variable to something more descriptive and consistent with the rest of PlasmaPy!


Discussion:
Hi! Wondering if this is still open and if I could take a crack at it. Thanks!
I don't recall any work being done towards this. Go right ahead! :)


Resolving patch:
diff --git a/plasmapy/diagnostics/langmuir.py b/plasmapy/diagnostics/langmuir.py
--- a/plasmapy/diagnostics/langmuir.py
+++ b/plasmapy/diagnostics/langmuir.py
@@ -8,6 +8,7 @@
 from astropy.visualization import quantity_support
 import matplotlib.pyplot as plt
 from scipy.optimize import curve_fit
+from plasmapy.atomic import Particle
 
 __all__ = [
     "Characteristic",
@@ -204,13 +205,8 @@ def plot(self):  # coverage: ignore
                                   'can_be_negative': False,
                                   'can_be_complex': False,
                                   'can_be_inf': False,
-                                  'can_be_nan': False},
-                      gas={'units': u.u,
-                           'can_be_negative': False,
-                           'can_be_complex': False,
-                           'can_be_inf': False,
-                           'can_be_nan': False})
-def swept_probe_analysis(probe_characteristic, probe_area, gas,
+                                  'can_be_nan': False})
+def swept_probe_analysis(probe_characteristic, probe_area, gas_argument,
                          bimaxwellian=False, visualize=False,
                          plot_electron_fit=False, plot_EEDF=False):
     r"""Attempt to perform a basic swept probe analysis based on the provided
@@ -225,8 +221,11 @@ def swept_probe_analysis(probe_characteristic, probe_area, gas,
     probe_area : ~astropy.units.Quantity
         The area of the probe exposed to plasma in units convertible to m^2.
 
-    gas : ~astropy.units.Quantity
-        The (mean) mass of the background gas in atomic mass units.
+    gas_argument : argument to instantiate the `Particle` class.
+        `str`, `int`, or `~plasmapy.atomic.Particle`
+        A string representing a particle, element, isotope, or ion; an
+        integer representing the atomic number of an element; or a
+        `Particle` instance.
 
     visualize : bool, optional
         Can be used to plot the characteristic and the obtained parameters.
@@ -287,6 +286,8 @@ def swept_probe_analysis(probe_characteristic, probe_area, gas,
     for OML theory hold.
 
     """
+    # Instantiate gas using the Particle class
+    gas = Particle(argument=gas_argument)
 
     # Check (unit) validity of the probe characteristic
     probe_characteristic.check_validity()
@@ -336,7 +337,7 @@ def swept_probe_analysis(probe_characteristic, probe_area, gas,
     # Using a good estimate of electron temperature, obtain the ion and
     # electron densities from the saturation currents.
     n_i = get_ion_density_LM(I_is, reduce_bimaxwellian_temperature(T_e,
-                             hot_fraction), probe_area, gas)
+                             hot_fraction), probe_area, gas.mass)
     n_e = get_electron_density_LM(I_es, reduce_bimaxwellian_temperature(T_e,
                                   hot_fraction), probe_area)
 
@@ -548,12 +549,7 @@ def get_ion_saturation_current(probe_characteristic):
                                   'can_be_negative': False,
                                   'can_be_complex': False,
                                   'can_be_inf': False,
-                                  'can_be_nan': False},
-                      gas={'units': u.u,
-                           'can_be_negative': False,
-                           'can_be_complex': False,
-                           'can_be_inf': False,
-                           'can_be_nan': False})
+                                  'can_be_nan': False})
 def get_ion_density_LM(ion_saturation_current, T_e,
                        probe_area, gas):
     r"""Implement the Langmuir-Mottley (LM) method of obtaining the ion
@@ -1009,12 +1005,7 @@ def reduce_bimaxwellian_temperature(T_e, hot_fraction):
                                   'can_be_negative': False,
                                   'can_be_complex': False,
                                   'can_be_inf': False,
-                                  'can_be_nan': False},
-                      gas={'units': u.u,
-                           'can_be_negative': False,
-                           'can_be_complex': False,
-                           'can_be_inf': False,
-                           'can_be_nan': False})
+                                  'can_be_nan': False})
 def get_ion_density_OML(probe_characteristic, probe_area, gas,
                         visualize=False, return_fit=False):
     r"""Implement the Orbital Motion Limit (OML) method of obtaining an
@@ -1072,7 +1063,9 @@ def get_ion_density_OML(probe_characteristic, probe_area, gas,
 
     slope = fit[0]
 
-    n_i_OML = np.sqrt(-slope * u.mA ** 2 / u.V * np.pi ** 2 * gas /
+    ion = Particle(argument=gas)
+
+    n_i_OML = np.sqrt(-slope * u.mA ** 2 / u.V * np.pi ** 2 * ion.mass /
                       (probe_area ** 2 * const.e ** 3 * 2))
 
     if visualize:  # coverage: ignore
diff --git a/plasmapy/examples/plot_langmuir_analysis.py b/plasmapy/examples/plot_langmuir_analysis.py
--- a/plasmapy/examples/plot_langmuir_analysis.py
+++ b/plasmapy/examples/plot_langmuir_analysis.py
@@ -39,14 +39,14 @@
 # ion mass number of 4 is entered. The results are visualized and the obtained
 # EEDF is also shown.
 print(swept_probe_analysis(characteristic,
-                           probe_area, 4 * u.u,
+                           probe_area, 'He-4+',
                            visualize=True,
                            plot_EEDF=True))
 
 ######################################################
 # The cyan and yellow lines indicate the fitted electron and ion currents,
 # respectively. The green line is the sum of these and agrees nicely with the
-# data. This indicates a succesfull analysis.
+# data. This indicates a successful analysis.
 
 ######################################################
 # The next sample probe data is provided by David Pace. It is also obtained
@@ -63,7 +63,7 @@
 # of the electron growth region will be plotted.
 swept_probe_analysis(characteristic,
                      0.738 * u.cm**2,
-                     40 * u.u,
+                     'Ar-40 1+',
                      bimaxwellian=False,
                      plot_electron_fit=True)
 
@@ -73,7 +73,7 @@
 # with bimaxwellian set to True, which yields improved results.
 print(swept_probe_analysis(characteristic,
                            0.738 * u.cm**2,
-                           40 * u.u,
+                           'Ar-40 1+',
                            bimaxwellian=True,
                            visualize=True,
                            plot_electron_fit=True))
@@ -105,7 +105,7 @@
 # The fit converges nicely to the two slopes of the electron growth region.
 print(swept_probe_analysis(characteristic,
                            probe_area,
-                           4 * u.u,
+                           'He-4+',
                            bimaxwellian=True,
                            plot_electron_fit=True,
                            visualize=True))


Test patch:
diff --git a/plasmapy/diagnostics/tests/test_langmuir.py b/plasmapy/diagnostics/tests/test_langmuir.py
--- a/plasmapy/diagnostics/tests/test_langmuir.py
+++ b/plasmapy/diagnostics/tests/test_langmuir.py
@@ -259,38 +259,21 @@ def test_nan_area():
         r"""Test error upon NaN area"""
 
         with pytest.raises(ValueError):
-            langmuir.swept_probe_analysis(characteristic, np.nan * u.cm**2, 40 * u.u)
+            langmuir.swept_probe_analysis(characteristic, np.nan * u.cm**2, 'Ar-40 1+')
 
     @staticmethod
     def test_unit_conversion_error():
         r"""Test error upon incorrect probe area unit"""
 
         with pytest.raises(u.UnitConversionError):
-            langmuir.swept_probe_analysis(characteristic, 1 * u.cm, 40 * u.u)
+            langmuir.swept_probe_analysis(characteristic, 1 * u.cm, 'Ar-40 1+')
 
     @staticmethod
     def test_negative_area():
         r"""Test error upon negative probe area"""
 
         with pytest.raises(ValueError):
-            langmuir.swept_probe_analysis(characteristic, -1 * u.cm**2, 40 * u.u)
-
-    @staticmethod
-    def test_ion_mass_unit():
-        r"""Test equality of float and a.m.u. ion mass"""
-
-        sim = characteristic_simulated()
-
-        sim_result1 = langmuir.swept_probe_analysis(
-            sim, 1 * u.cm**2, 40)
-
-        sim_result2 = langmuir.swept_probe_analysis(
-            sim, 1 * u.cm**2, 40 * u.u)
-
-        errStr = (f"`swept_probe_analysis` should accept both floats and "
-                  f"a.m.u. Quantities as atomic gas mass input.")
-        for key in sim_result1:
-            assert (sim_result1[key] == sim_result2[key]).all(), errStr
+            langmuir.swept_probe_analysis(characteristic, -1 * u.cm**2, 'Ar-40 1+')
 
     @staticmethod
     @pytest.mark.parametrize("bimaxwellian", [True, False])
@@ -302,13 +285,13 @@ def test_ordering_invariance(bimaxwellian):
         sim_result = langmuir.swept_probe_analysis(
             sim,
             1 * u.cm**2,
-            40 * u.u,
+            'Ar-40 1+',
             bimaxwellian=bimaxwellian)
 
         sim_result_shuffled = langmuir.swept_probe_analysis(
             shuffle_characteristic(sim),
             1 * u.cm**2,
-            40 * u.u,
+            'Ar-40 1+',
             bimaxwellian=bimaxwellian)
 
         errStr = (f"Analysis should be invariant to the ordering of the "
@@ -330,8 +313,8 @@ def test_get_ion_density_OML_without_return_fit():
 
     char = characteristic()
     density = langmuir.get_ion_density_OML(char, 5000000*u.m**2,
-                                           1*u.u, return_fit=False)
-    assert np.isclose(density.value, 383949768.0764418)
+                                           'p+', return_fit=False)
+    assert np.isclose(density.value, 385344135.12064785)
 
 
 def test_get_EEDF():