def test_call_of_check_sweep(self): """ Test `find_floating_potential` appropriately calls `plasmapy.analysis.swept_langmuir.helpers.check_sweep` so we can relay on the `check_sweep` tests. """ varr = np.linspace(-20.0, 20.0, 100) carr = np.linspace(-20.0, 20.0, 100) assert _sl.helpers.check_sweep is _sl.floating_potential.check_sweep with mock.patch(_sl.floating_potential.__name__ + ".check_sweep") as mock_cs: mock_cs.return_value = varr, carr find_floating_potential(voltage=varr, current=carr, fit_type="linear") assert mock_cs.call_count == 1 # passed args assert len(mock_cs.call_args[0]) == 2 assert np.array_equal(mock_cs.call_args[0][0], varr) assert np.array_equal(mock_cs.call_args[0][1], carr) # passed kwargs assert mock_cs.call_args[1] == {"strip_units": True}
def test_kwarg_min_points(self, min_points, fit_type, islands, indices): """ Test functionality of keyword `min_points` and how it affects the size of the crossing-point island. """ voltage = self._voltage current = self._linear_current if fit_type == "linear" else self._exp_current results = find_floating_potential( voltage, current, min_points=min_points, fit_type=fit_type, ) assert isinstance(results, FloatingPotentialResults) assert results.islands == islands assert results.indices == indices
def test_perfect_exponential(self, a, alpha, b): """Test calculated fit parameters on a few perfectly exponential cases.""" voltage = self._voltage current = a * np.exp(alpha * voltage) + b results = find_floating_potential( voltage=voltage, current=current, fit_type="exponential", min_points=0.8, ) assert isinstance(results, FloatingPotentialResults) assert np.isclose(results.vf, np.log(-b / a) / alpha) assert np.isclose(results.vf_err, 0.0, 1e-7) assert np.isclose(results.rsq, 1.0) assert isinstance(results.func, ffuncs.ExponentialPlusOffset) assert np.allclose(results.func.params, (a, alpha, b)) assert np.allclose(results.func.param_errors, (0.0, 0.0, 0.0), atol=2e-8)
def test_perfect_linear(self, m, b): """Test calculated fit parameters on a few perfectly linear cases.""" voltage = self._voltage current = m * voltage + b results = find_floating_potential( voltage=voltage, current=current, fit_type="linear", min_points=0.8, ) assert isinstance(results, FloatingPotentialResults) assert np.isclose(results.vf, -b / m) assert np.isclose(results.vf_err, 0.0) assert np.isclose(results.rsq, 1.0) assert isinstance(results.func, ffuncs.Linear) assert np.allclose(results.func.params, (m, b)) assert np.allclose(results.func.param_errors, (0.0, 0.0), atol=2e-8)
def test_warnings(self, kwargs, expected, _warning): """Test scenarios that issue warnings.""" with pytest.warns(_warning): results = find_floating_potential(**kwargs) assert isinstance(results, FloatingPotentialResults) for key, val in expected.items(): rtn_val = getattr(results, key) if val is None: assert rtn_val is None elif key == "func": assert isinstance(rtn_val, val.__class__) elif np.isscalar(val): if np.isnan(val): assert np.isnan(rtn_val) else: assert np.isclose(rtn_val, val) else: assert rtn_val == val
def test_island_finding(self, kwargs, expected): """ Test scenarios related to the identification of crossing-point islands. """ results = find_floating_potential(**kwargs) assert isinstance(results, FloatingPotentialResults) for key, val in expected.items(): rtn_val = getattr(results, key) if val is None: assert rtn_val is None elif key == "func": assert isinstance(rtn_val, val.__class__) elif np.isscalar(val): if np.isnan(val): assert np.isnan(rtn_val) else: assert np.isclose(rtn_val, val, atol=1e-7) else: assert rtn_val == val
def test_raises(self, kwargs, _error): """Test scenarios that raise `Exception`s.""" with pytest.raises(_error): find_floating_potential(**kwargs)