def test_simplify_mpeaks(self): # 1D: Four attributes. peaks = swprocess.Peaks(self.frq, self.vel, identifier=self._id, azimuth=self.azi, power=self.pwr, ellipticity=self.ell, noise=self.noi) for attr in [ "frequency", "velocity", "azimuth", "power", "ellipticity", "noise" ]: simplified_attr = peaks.simplify_mpeaks(attr) self.assertArrayEqual(getattr(peaks, f"{attr}"), simplified_attr) # 2D: No attributes with nan. peaks = swprocess.Peaks(self.frq2n, self.vel2n, identifier=self._id2n) row, col = np.array([1, 0, 0]), np.array([0, 1, 2]) for attr in ["frequency", "velocity"]: simplified_attr = peaks.simplify_mpeaks(attr) self.assertArrayEqual( getattr(peaks, f"_{attr}")[row, col], simplified_attr) # 2D: Four attributes with nan. peaks = swprocess.Peaks(self.frq2n, self.vel2n, identifier=self._id2n, azimuth=self.azi2n, power=self.pwr2n, ellipticity=self.ell2n, noise=self.noi2n) row, col = np.array([1, 0, 0]), np.array([0, 1, 2]) for attr in [ "frequency", "velocity", "azimuth", "power", "ellipticity", "noise" ]: simplified_attr = peaks.simplify_mpeaks(attr) self.assertArrayEqual( getattr(peaks, f"_{attr}")[row, col], simplified_attr) # 2D: Power attribute with nan. frequency = np.array([[1, 3, 5, 7, 9, np.nan], [1, 3, np.nan, np.nan, 9, 2], [np.nan, np.nan, np.nan, 7, 9, 2]]) velocity = np.array([[1, 3, 5, 7, 9, np.nan], [3, 9, np.nan, np.nan, 9, 2], [np.nan, np.nan, np.nan, 7, 9, 2]]) power = np.array([[2, 6, 1, 8, 2, np.nan], [5, 1, np.nan, np.nan, 9, 1], [np.nan, np.nan, np.nan, 1, 1, 9]]) peaks = swprocess.Peaks(frequency, velocity, identifier=self._id2n, power=power) row, col = np.array([1, 0, 0, 0, 1, 2]), np.array([0, 1, 2, 3, 4, 5]) for attr in ["frequency", "velocity", "power"]: simplified_attr = peaks.simplify_mpeaks(attr) self.assertArrayEqual( getattr(peaks, f"_{attr}")[row, col], simplified_attr)
def test_reject_limits_outside(self): fs = np.array([1, 5, 9, np.nan, 3, 5, 7, 4, 6, 2, 8]) vs = np.array([1, 9, 4, np.nan, 5, 6, 8, 5, 2, 1, 4]) # None peaks = swprocess.Peaks(fs, vs) limits = None, None with warnings.catch_warnings(): warnings.simplefilter("ignore") peaks.reject_limits_outside("frequency", limits) self.assertArrayEqual(fs[np.isfinite(fs)], peaks.frequency) self.assertArrayEqual(vs[np.isfinite(vs)], peaks.velocity) # Remove all above 4.5 peaks = swprocess.Peaks(fs, vs) limits = None, 4.5 peaks.reject_limits_outside("frequency", limits) self.assertArrayEqual(np.array([1., 3, 4, 2]), peaks.frequency) self.assertArrayEqual(np.array([1., 5, 5, 1]), peaks.velocity) # Remove all below 4.5 peaks = swprocess.Peaks(fs, vs) limits = 4.5, None peaks.reject_limits_outside("frequency", limits) self.assertArrayEqual(np.array([5., 9, 5, 7, 6, 8]), peaks.frequency) self.assertArrayEqual(np.array([9., 4, 6, 8, 2, 4]), peaks.velocity) # Remove all below 1.5 and above 6.5 peaks = swprocess.Peaks(fs, vs) limits = 1.5, 6.5 peaks.reject_limits_outside("frequency", limits) self.assertArrayEqual(np.array([5., 3, 5, 4, 6, 2]), peaks.frequency) self.assertArrayEqual(np.array([9., 5, 6, 5, 2, 1]), peaks.velocity)
def test_init(self): # 1D: No keyword arguments peaks = swprocess.Peaks(self.frq, self.vel, identifier=self._id) self.assertArrayEqual(np.array(self.frq), peaks.frequency) self.assertArrayEqual(np.array(self.vel), peaks.velocity) self.assertEqual(self._id, peaks.identifier) # 1D: Four keyword arguments peaks = swprocess.Peaks(self.frq, self.vel, identifier=self._id, azimuth=self.azi, ellipticity=self.ell, noise=self.noi, power=self.pwr) self.assertArrayEqual(np.array(self.frq), peaks.frequency) self.assertArrayEqual(np.array(self.vel), peaks.velocity) self.assertEqual(self._id, peaks.identifier) self.assertArrayEqual(np.array(self.azi), peaks.azimuth) self.assertArrayEqual(np.array(self.ell), peaks.ellipticity) self.assertArrayEqual(np.array(self.noi), peaks.noise) self.assertArrayEqual(np.array(self.pwr), peaks.power) # 2D: Four keyword arguments peaks = swprocess.Peaks(self.frq2, self.vel2, identifier=self._id2, azimuth=self.azi2, ellipticity=self.ell2, noise=self.noi2, power=self.pwr2) self.assertArrayEqual(np.array(self.frq2).flatten(), peaks.frequency) self.assertArrayEqual(np.array(self.vel2).flatten(), peaks.velocity) self.assertEqual(self._id2, peaks.identifier) self.assertArrayEqual(np.array(self.azi2).flatten(), peaks.azimuth) self.assertArrayEqual(np.array(self.ell2).flatten(), peaks.ellipticity) self.assertArrayEqual(np.array(self.noi2).flatten(), peaks.noise) self.assertArrayEqual(np.array(self.pwr2).flatten(), peaks.power) # 2D: Four keyword arguments with nans peaks = swprocess.Peaks(self.frq2n, self.vel2n, identifier=self._id2n, azimuth=self.azi2n, ellipticity=self.ell2n, noise=self.noi2n, power=self.pwr2n) self.assertArrayEqual( np.array(self.frq2n)[self.valid], peaks.frequency) self.assertArrayEqual(np.array(self.vel2n)[self.valid], peaks.velocity) self.assertEqual(self._id2n, peaks.identifier) self.assertArrayEqual(np.array(self.azi2n)[self.valid], peaks.azimuth) self.assertArrayEqual( np.array(self.ell2n)[self.valid], peaks.ellipticity) self.assertArrayEqual(np.array(self.noi2n)[self.valid], peaks.noise) self.assertArrayEqual(np.array(self.pwr2n)[self.valid], peaks.power)
def test_append(self): # Simple append operation. p0 = swprocess.Peaks([1, 2, 3], [4, 5, 6], "p0") p1 = swprocess.Peaks([[7, np.nan, 9], [4, 5, 6]], [[1, np.nan, 2], [7, 8, 9]], "p1") suite = swprocess.PeaksSuite(p0) suite.append(p1) for returned, expected in zip(suite, [p0, p1]): self.assertEqual(expected, returned) # Bad: replicated identifier self.assertRaises(KeyError, suite.append, p1) # Bad: append non-Peaks object self.assertRaises(TypeError, suite.append, "not a Peaks object")
def test_configure_axes(self): peaks = swprocess.Peaks(self.frq, self.vel, self._id) defaults = { "frequency": { "label": "frq", "scale": "linear" }, "velocity": { "label": "vel", "scale": "log" } } # Standard calls. ax = MagicMock() peaks._configure_axes(ax, xtype="frequency", ytype="velocity", defaults=defaults) ax.set_xlabel.assert_called_with("frq") ax.set_xscale.assert_called_with("linear") ax.set_ylabel.assert_called_with("vel") ax.set_yscale.assert_called_with("log") # Non-standard calls to unknown attribute. ax = MagicMock() peaks._configure_axes(ax, xtype="frequency", ytype="azimuth", defaults=defaults) ax.set_xlabel.assert_called_with("frq") ax.set_xscale.assert_called_with("linear") ax.set_ylabel.assert_not_called() ax.set_yscale.assert_not_called()
def test_reject_box_inside(self): xs = np.array([1, 2, 4, np.nan, 5, 1, 2, 6, 4, 9, 4]) ys = np.array([1, 5, 8, np.nan, 6, 4, 7, 7, 1, 3, 5]) power = np.array([0, 1, 2, np.nan, 4, 5, 6, 7, 8, 9, 10]) # Reject on frequency and velocity. peaks = swprocess.Peaks(xs, ys, power=power) peaks.reject_box_inside(xtype="frequency", xlims=(4.5, 7.5), ytype="velocity", ylims=(3.5, 8.5)) keep_ids = [0, 1, 2, 5, 6, 8, 9, 10] attrs = dict(frequency=xs, velocity=ys, power=power) for attr, value in attrs.items(): self.assertArrayEqual(value[keep_ids], getattr(peaks, attr)) # Reject on frequency and power. peaks = swprocess.Peaks(xs, ys, power=power) peaks.reject_box_inside(xtype="frequency", xlims=(4.5, 7.5), ytype="power", ylims=(3.5, 8.5)) keep_ids = [0, 1, 2, 5, 6, 8, 9, 10] attrs = dict(frequency=xs, velocity=ys, power=power) for attr, value in attrs.items(): self.assertArrayEqual(value[keep_ids], getattr(peaks, attr)) # Reject on wavelength and slowness. ws = np.array([1, 5, 8, np.nan, 6, 4, 7, 7, 1, 3, 5]) ps = np.array([1, 5, 9, np.nan, 4, 5, 6, 7, 8, 1, 7]) power = np.array([0, 1, 2, np.nan, 4, 5, 6, 7, 8, 9, 10]) xs = 1 / (ws * ps) ys = 1 / ps peaks = swprocess.Peaks(xs, ys, power=power) peaks.reject_box_inside(xtype="wavelength", xlims=(3.2, 8.5), ytype="slowness", ylims=(4.5, 7.5)) keep_ids = [0, 2, 4, 8, 9] attrs = dict(frequency=xs, velocity=ys, power=power) for attr, value in attrs.items(): self.assertArrayEqual(value[keep_ids], getattr(peaks, attr))
def test_to_and_from_json(self): # Standard to_json and from_json. fname = "test_0.json" expected = swprocess.Peaks(self.frq, self.vel, self._id, azimuth=self.azi, power=self.pwr) expected.to_json(fname) returned = swprocess.Peaks.from_json(fname) self.assertEqual(expected, returned) os.remove(fname) # Create and append with to_json, read the original with from_json. fname = "test_1.json" expected = swprocess.Peaks(self.frq, self.vel, "org") expected.to_json(fname) append = swprocess.Peaks(self.frq2, self.vel2, "app") append.to_json(fname, append=True) with warnings.catch_warnings(): warnings.simplefilter("ignore") returned = swprocess.Peaks.from_json(fname) self.assertEqual(expected, returned) os.remove(fname) # Append using to_json but data already exists. fname = "test_2.json" peaks = swprocess.Peaks(self.frq, self.vel, "org") peaks.to_json(fname) self.assertRaises(KeyError, peaks.to_json, fname, append=True) os.remove(fname) # Write and overwrite using to_json, read overwrite with from_json. fname = "test_3.json" expected = swprocess.Peaks(self.frq, self.vel, "org") expected.to_json(fname) expected.identifier = "app" expected.to_json(fname, append=False) returned = swprocess.Peaks.from_json(fname) self.assertEqual(expected, returned) os.remove(fname)
def test__plot(self): peaks = swprocess.Peaks(self.frq, self.vel, self._id) # Standard fig, ax = plt.subplots() peaks._plot(ax=ax, xtype="frequency", ytype="velocity") # Bad Attribute fig, ax = plt.subplots() self.assertRaises(AttributeError, peaks._plot, ax=ax, xtype="magic", ytype="size_of_unicorn") plt.show(block=False) plt.close("all")
def test_properties(self): peaks = swprocess.Peaks(self.frq, self.vel, self._id, azimuth=self.azi) # Wavelength self.assertArrayEqual( np.array(self.vel) / np.array(self.frq), peaks.wavelength) # Extended Attrs expected = [ "frequency", "velocity", "azimuth", "wavelength", "slowness", "wavenumber" ] returned = peaks.extended_attrs self.assertListEqual(expected, returned) # Wavenumber self.assertArrayAlmostEqual(2 * np.pi / peaks.wavelength, peaks.wavenumber)
def test__eq__(self): peaks_a = swprocess.Peaks(self.frq, self.vel, self._id, azimuth=self.azi) peaks_b = "I am not even a Peaks object" peaks_c = swprocess.Peaks(self.frq, self.vel, "diff", azimuth=self.azi) peaks_d = swprocess.Peaks(self.frq[:-2], self.vel[:-2], self._id, azimuth=self.azi[:-2]) peaks_e = swprocess.Peaks(np.zeros_like(self.frq), self.vel, self._id, azimuth=self.azi) peaks_f = swprocess.Peaks(np.zeros_like(self.frq), self.vel, self._id) peaks_g = swprocess.Peaks(self.frq, self.vel, self._id, azimuth=self.azi) del peaks_g.identifier peaks_h = swprocess.Peaks(self.frq, self.vel, self._id, noise=self.noi) peaks_i = swprocess.Peaks(self.frq, self.vel, self._id, azimuth=self.azi) self.assertTrue(peaks_a == peaks_a) self.assertFalse(peaks_a == peaks_b) self.assertFalse(peaks_a == peaks_c) self.assertFalse(peaks_a == peaks_d) self.assertFalse(peaks_a == peaks_e) self.assertFalse(peaks_a == peaks_f) self.assertFalse(peaks_a == peaks_g) self.assertFalse(peaks_a == peaks_h) self.assertTrue(peaks_a == peaks_i)
def test_plot_statistics(self): # Mock ax ax = MagicMock(spec=plt.Axes) suite = swprocess.PeaksSuite(swprocess.Peaks([1, 2, 3], [0, 1, 2])) suite.plot_statistics(ax, [1, 2, 3], [0, 1, 2], [4, 5, 6]) ax.errorbar.assert_called_once()
def test_statistics(self): # 1D: no missing data. values = np.array([[1, 2, 3, 4, 5], [4, 5, 7, 8, 9], [4, 3, 6, 4, 2]]) frq = [1, 2, 3, 4, 5] peaks = [swprocess.Peaks(frq, values[k], str(k)) for k in range(3)] suite = swprocess.PeaksSuite.from_peaks(peaks) rfrq, rmean, rstd, rcorr = suite.statistics(xtype="frequency", ytype="velocity", xx=frq, ignore_corr=False) self.assertArrayEqual(np.array(frq), rfrq) self.assertArrayEqual(np.mean(values, axis=0), rmean) self.assertArrayEqual(np.std(values, axis=0, ddof=1), rstd) self.assertArrayEqual(np.corrcoef(values.T), rcorr) # 1D: fewer than three Peaks in PeaksSuite -> ValueError. peaks = [swprocess.Peaks(frq, values[k], str(k)) for k in range(2)] suite = swprocess.PeaksSuite.from_peaks(peaks) self.assertRaises(ValueError, suite.statistics, xtype="frequency", ytype="velocity", xx=frq) # 1D: drop_sample_if_fewer_count = 3. values = np.array([[np.nan] * 6, [np.nan, 1, 2, 3, 4, 5], [0, 4, 5, 7, 8, 9], [0, 4, 3, 6, 4, 2]]) frq = [0.2, 1, 2, 3, 4, 5] valid = np.array([[1, 2, 3, 4, 5], [4, 5, 7, 8, 9], [4, 3, 6, 4, 2]]) valid_frq = frq[1:] peaks = [swprocess.Peaks(frq, values[k], str(k)) for k in range(4)] suite = swprocess.PeaksSuite.from_peaks(peaks) rfrq, rmean, rstd, rcorr = suite.statistics(xtype="frequency", ytype="velocity", xx=frq, ignore_corr=False) self.assertArrayEqual(np.array(valid_frq), rfrq) self.assertArrayEqual(np.mean(valid, axis=0), rmean) self.assertArrayEqual(np.std(valid, axis=0, ddof=1), rstd) self.assertArrayEqual(np.corrcoef(valid.T), rcorr) # 2D: with missing data. f0 = [[1, 3, 5, 7, np.nan], [np.nan, 3, 5, 7, 9], [1, 3, 5, 7, 9]] v0 = [[4, 6, 7, 1, np.nan], [np.nan, 3, 2, 5, 4], [1, 3, 5, 1, 2]] p0 = [[4, 3, 5, 1, np.nan], [np.nan, 3, 7, 5, 4], [1, 6, 7, 1, 2]] # --> 4, 3, 2, 5, 4 peaks0 = swprocess.Peaks(f0, v0, identifier="0", power=p0) f1 = [[1, 3, 5, 7, np.nan], [np.nan, 3, 5, 7, 9], [1, 3, 5, 7, 9]] v1 = [[8, 8, 7, 7, np.nan], [np.nan, 2, 1, 3, 8], [4, 1, 4, 1, 4]] p1 = [[4, 6, 7, 1, np.nan], [np.nan, 3, 7, 5, 4], [1, 3, 5, 1, 2]] # --> 8, 8, 7, 3, 8 peaks1 = swprocess.Peaks(f1, v1, identifier="1", power=p1) f2 = [[1, 3, 5, 7, np.nan], [np.nan, 3, 5, 7, 9], [1, 3, 5, 7, 9]] v2 = [[2, 4, 1, 1, np.nan], [np.nan, 8, 1, 3, 2], [5, 2, 9, 4, 8]] p2 = [[4, 6, 7, 1, np.nan], [np.nan, 3, 7, 5, 4], [1, 3, 5, 1, 2]] # --> 2, 4, 1, 3, 2 peaks2 = swprocess.Peaks(f2, v2, identifier="2", power=p2) suite = swprocess.PeaksSuite.from_peaks([peaks0, peaks1, peaks2]) valid = np.array([[4, 3, 2, 5, 4], [8, 8, 7, 3, 8], [2, 4, 1, 3, 2]], dtype=float) frq = [1, 3, 5, 7, 9] rfrq, rmean, rstd, rcorr = suite.statistics(xtype="frequency", ytype="velocity", xx=frq, ignore_corr=False) self.assertArrayEqual(np.array(frq), rfrq) self.assertArrayEqual(np.mean(valid, axis=0), rmean) self.assertArrayEqual(np.std(valid, axis=0, ddof=1), rstd) self.assertArrayEqual(np.corrcoef(valid.T), rcorr)
def test_init(self): p0 = swprocess.Peaks([1, np.nan, 3], [4, np.nan, 6], "p0") suite = swprocess.PeaksSuite(p0) self.assertEqual(suite[0], p0) self.assertEqual(suite.ids[0], p0.identifier)
def test_interactive_trimming(self): # Create simple suite, composed of two Peaks. peaks_a = swprocess.Peaks(frequency=[0.5, 0.5], velocity=[0.5, 1.5], identifier="a") peaks_b = swprocess.Peaks(frequency=[1.5, 1.5], velocity=[0.5, 1.5], identifier="b") suite = swprocess.PeaksSuite(peaks_a) suite.append(peaks_b) # Create a response generator. def response_generator(responses): index = 0 while index < len(responses): yield responses[index] index += 1 # Use a closure to wrap generator. def wrap_generator(generator): def wrapper(*args, **kwargs): return next(generator) return wrapper # Define generator to replace _draw_box() xlims, ylims, axclicked = (1., 2.), (0., 1.), 0 response_0 = (xlims, ylims, axclicked) xlims, ylims, axclicked = (1., 1.), (1., 1.), 0 response_1 = (xlims, ylims, axclicked) pick_generator = response_generator([response_0, response_1]) _draw_box_responses = wrap_generator(generator=pick_generator) with patch("swprocess.peakssuite.PeaksSuite._draw_box", side_effect=_draw_box_responses): with patch('builtins.input', return_value="0"): suite.interactive_trimming(xtype="frequency", ytype="velocity") self.assertArrayEqual(np.array([0.5, 0.5]), peaks_a.frequency) self.assertArrayEqual(np.array([0.5, 1.5]), peaks_a.velocity) self.assertArrayEqual(np.array([1.5]), peaks_b.frequency) self.assertArrayEqual(np.array([1.5]), peaks_b.velocity) # Redefine generator for _draw_box() pick_generator = response_generator([response_0, response_1]) _draw_box_responses = wrap_generator(generator=pick_generator) # Define generator to replace input() input_generator = response_generator(["5", "0"]) _input_responses = wrap_generator(generator=input_generator) # Check with bad user entry at input(). with patch("swprocess.peakssuite.PeaksSuite._draw_box", side_effect=_draw_box_responses): with patch("builtins.input", side_effect=_input_responses): with warnings.catch_warnings(): warnings.simplefilter("ignore") suite.interactive_trimming(xtype="frequency", ytype="velocity") # Redefine generator for _draw_box() pick_generator = response_generator([response_1]) _draw_box_responses = wrap_generator(generator=pick_generator) mock = MagicMock() # Check with bad user entry at input(). with patch("swprocess.peakssuite.PeaksSuite._draw_box", side_effect=_draw_box_responses): with patch("builtins.input", return_value="0"): with patch( "swprocess.peakssuite.PeaksSuite.plot_resolution_limits", side_effect=mock): suite.interactive_trimming( xtype="frequency", ytype="velocity", resolution_limits=["wavelength", (1, 10)]) mock.assert_called()