def test_integrate(self): times_long = np.linspace(0, 2 * np.pi, 10000) values_long = np.sin(times_long) TS = ts.TimeSeries(times_long, values_long) TS_c = ts.TimeSeries(times_long, values_long + 1j * values_long) self.assertTrue( np.allclose(TS.integrated().y, 1 - np.cos(times_long), atol=1e-4)) self.assertTrue( np.allclose( TS_c.integrated().y, 1 - np.cos(times_long) + 1j * (1 - np.cos(times_long)), atol=1e-4, )) sins = TS.copy() sins.integrate() self.assertTrue(np.allclose(sins.y, 1 - np.cos(times_long), atol=1e-4)) # Masked data with self.assertRaises(RuntimeError): self.TS_cm.integrated()
def test_save(self): times = np.logspace(0, 1, 10) sins = ts.TimeSeries(times, np.sin(times)) compl = ts.TimeSeries(times, np.sin(times) + 1j * np.sin(times)) sins_file = "test_save_sins.dat" compl_file = "test_save_compl.dat" sins.save(sins_file) compl.save(compl_file) loaded_sins = np.loadtxt(sins_file).T os.remove(sins_file) loaded_compl = np.loadtxt(compl_file).T os.remove(compl_file) self.assertTrue(np.allclose(loaded_sins[0], times)) self.assertTrue(np.allclose(loaded_sins[1], np.sin(times))) self.assertTrue(np.allclose(loaded_compl[0], times)) self.assertTrue(np.allclose(loaded_compl[1], np.sin(times))) self.assertTrue(np.allclose(loaded_compl[2], np.sin(times))) with self.assertWarns(RuntimeWarning): path = "/tmp/tmp_kuibit_tmp.dat" self.TS_cm.save("/tmp/tmp_kuibit_tmp.dat") os.remove(path)
def test_time_unit_change(self): sins = ts.TimeSeries(self.times, self.values) new_times = np.linspace(0, np.pi, 100) new_times_inverse = np.linspace(0, 6 * np.pi, 100) self.assertTrue(np.allclose(sins.time_unit_changed(2).t, new_times)) self.assertTrue( np.allclose( sins.time_unit_changed(3, inverse=True).t, new_times_inverse ) ) sins.time_unit_change(2) self.assertTrue(np.allclose(sins.t, new_times)) sins.time_unit_change(6, inverse=True) self.assertTrue(np.allclose(sins.t, new_times_inverse)) two_times = np.linspace(0, 4 * np.pi, 100) sins = self.TS.copy() sins_half_frequency = ts.TimeSeries(two_times, np.sin(0.5 * two_times)) self.assertEqual(sins.redshifted(1), sins_half_frequency) sins.redshift(1) self.assertEqual(sins, sins_half_frequency)
def setUp(self): self.times = np.linspace(0, 2 * np.pi, 100) self.values = np.sin(self.times) self.TS = ts.TimeSeries(self.times, self.values) # Complex self.TS_c = ts.TimeSeries(self.times, self.values + 1j * self.values)
def test_init(self): # Check that errors are thrown if: # 1. There is a mismatch between t and y # 2. The timeseries is empty # 1 times = np.linspace(0, 2 * np.pi, 100) values = np.array([1, 2, 3]) with self.assertRaises(ValueError): ts.TimeSeries(times, values) # 2 times = np.array([]) values = np.array([]) with self.assertRaises(ValueError): ts.TimeSeries(times, values) # Test timeseries with one element scalar = ts.TimeSeries(0, 0) self.assertEqual(scalar.y, 0) # Test guarantee_x_is_monotonic # This should not throw an error even if it is wrong times = np.linspace(2 * np.pi, 0, 100) values = np.sin(times) wrong = ts.TimeSeries(times, values, guarantee_t_is_monotonic=True) self.assertCountEqual(wrong.t, times)
def test__apply_binary(self): # Check that errors are thrown if: # 1. Lists have different times # 2. The object is unknown # We as example of a function np.sum # 1a times = np.linspace(0, 2 * np.pi, 200) values = np.cos(times) cos = ts.TimeSeries(times, values) with self.assertRaises(ValueError): out = self.TS._apply_binary(cos, np.add) # 1b times = np.linspace(2, 3 * np.pi, 100) values = np.cos(times) cos = ts.TimeSeries(times, values) with self.assertRaises(ValueError): out = self.TS._apply_binary(cos, np.add) # 2 with self.assertRaises(TypeError): self.TS._apply_binary("str", np.add)
def test_differentiate(self): times = np.linspace(0, 2 * np.pi, 1000) values = np.sin(times) higher_res_TS = ts.TimeSeries(times, values) higher_res_TS_c = ts.TimeSeries(times, values + 1j * values) self.assertTrue( np.allclose(higher_res_TS.differentiated().y, np.cos(times), atol=1e-3)) self.assertTrue( np.allclose(higher_res_TS.differentiated(2).y, -np.sin(times), atol=5e-2)) self.assertTrue( np.allclose( higher_res_TS_c.differentiated().y, np.cos(times) + 1j * np.cos(times), atol=1e-3, )) sins = higher_res_TS.copy() sins.differentiate() self.assertTrue(np.allclose(sins.y, np.cos(times), atol=1e-3)) sins = higher_res_TS.copy() with self.assertRaises(ValueError): sins.spline_differentiated(8) # The boundaries are not accurate self.assertTrue( np.allclose( higher_res_TS.spline_differentiated().y, np.cos(times), atol=1e-3, )) self.assertTrue( np.allclose( higher_res_TS.spline_differentiated(2).y, -np.sin(times), atol=1e-3, )) self.assertTrue( np.allclose( higher_res_TS_c.spline_differentiated().y, np.cos(times) + 1j * np.cos(times), atol=1e-3, )) sins.spline_differentiate() self.assertTrue(np.allclose(sins.y, np.cos(times), atol=1e-3))
def setUp(self): self.num_times = 4000 self.times = np.linspace(0, 20 * 2 * np.pi, self.num_times) self.values1 = np.sin(30 * self.times) self.values2 = np.sin(60 * self.times) * np.cos(30 * self.times) self.ts1 = ts.TimeSeries(self.times, self.values1) self.ts2 = ts.TimeSeries(self.times, self.values2)
def setUp(self): # Prepare fake multipoles self.t1 = np.linspace(0, 1, 100) self.t2 = np.linspace(2, 3, 100) self.y1 = np.sin(self.t1) self.y2 = np.sin(self.t2) self.ts1 = ts.TimeSeries(self.t1, self.y1) self.ts2 = ts.TimeSeries(self.t2, self.y2)
def test_make_spline_call(self): # Cannot make a spline with 1 point with self.assertRaises(ValueError): sins = ts.TimeSeries([0], [0]) sins._make_spline() # Check that spline reproduce data # These are pulled from the data self.assertTrue(np.allclose(self.TS(self.times), self.values)) # These have some that computed with splines other_times = np.linspace(0, np.pi, 100) other_values = np.sin(other_times) self.assertTrue(np.allclose(self.TS(other_times), other_values)) self.assertTrue(np.allclose(self.TS(np.pi / 2), 1)) # Vector input in, vector input out self.assertTrue(isinstance(self.TS([np.pi / 2]), np.ndarray)) self.assertTrue(np.allclose(self.TS(self.TS.t[0]), self.TS.y[0])) # From data self.assertTrue( np.allclose(self.TS_c(self.times), self.values + 1j * self.values)) # From spline self.assertTrue( np.allclose(self.TS_c(other_times), other_values + 1j * other_values)) # Masked data with self.assertRaises(RuntimeError): self.TS_cm(other_times) # Does the spline update? # Let's test with a method that changes the timeseries sins = ts.TimeSeries(self.times, self.values + 1) self.assertTrue(np.allclose(sins(self.times), self.values + 1)) sins.mean_remove() self.assertTrue(np.allclose(sins(self.times), self.values)) with self.assertRaises(ValueError): sins(-1) # Test that setting directly the members invalidates the spline sins.y *= 2 self.assertTrue(sins.invalid_spline) sins.invalid_spline = False sins.t *= 2 self.assertTrue(sins.invalid_spline)
def setUp(self): self.times = np.linspace(0, 2 * np.pi, 100) self.values = np.sin(self.times) self.TS = ts.TimeSeries(self.times, self.values) # Complex self.TS_c = ts.TimeSeries(self.times, self.values + 1j * self.values) # Complex and masked self.vals_cm = np.ma.log10(self.values + 1j * self.values) self.TS_cm = ts.TimeSeries(self.times, self.vals_cm)
def test_MultipolesDir(self): sim = sd.SimDir("tests/tov") cacdir = mp.MultipolesDir(sim) # multipoles from textfile with self.assertRaises(RuntimeError): cacdir._multipole_from_textfile( "tests/tov/output-0000/static_tov/carpet-timing..asc") path = "tests/tov/output-0000/static_tov/mp_Phi2_l2_m-1_r110.69.asc" path_h5 = "tests/tov/output-0000/static_tov/mp_harmonic.h5" t, real, imag = np.loadtxt(path).T with h5py.File(path_h5, "r") as data: # Loop over the groups in the hdf5 a = data["l2_m2_r8.00"][()].T mpts = ts.TimeSeries(t, real + 1j * imag) ts_h5 = ts.TimeSeries(a[0], a[1] + 1j * a[2]) self.assertEqual(mpts, cacdir._multipole_from_textfile(path)) self.assertEqual( ts_h5, cacdir._multipoles_from_h5files([path_h5])[8.00](2, 2), ) mpfiles = [(2, 2, 100, path)] # Check one specific case self.assertEqual( mpts, cacdir._multipoles_from_textfiles(mpfiles)[100](2, 2), ) self.assertEqual(cacdir["phi2"][110.69](2, -1), mpts) self.assertEqual(cacdir["harmonic"][8.00](2, 2), ts_h5) # test get self.assertIs(cacdir.get("bubu"), None) self.assertEqual(cacdir.get("harmonic")[8.00](2, 2), ts_h5) # test __getitem__ with self.assertRaises(KeyError): cacdir["bubu"] # test __contains__ self.assertIn("phi2", cacdir) # test keys() self.assertCountEqual(cacdir.keys(), ["harmonic", "phi2", "psi4"]) # test __str__() self.assertIn("harmonic", cacdir.__str__())
def test_is_regularly_sampled(self): self.assertTrue(self.TS.is_regularly_sampled()) # Log space is not regular times = np.logspace(0, 1, 100) ts_log = ts.TimeSeries(times, self.values) self.assertFalse(ts_log.is_regularly_sampled()) # If the series is only one point long, an error should be raised with self.assertRaises(RuntimeError): ts.TimeSeries([1], [1]).is_regularly_sampled()
def test_div(self): # Errors are tested by test_apply_binary with self.assertRaises(ValueError): out = self.TS / 0 # Let's avoid division by 0 times = np.linspace(np.pi / 3, np.pi / 2, 100) values = np.sin(times) sins = ts.TimeSeries(times, values) out = sins / sins self.assertTrue(np.allclose(out.y, 1)) # Test rtrudiv out = 1 / sins self.assertTrue(np.allclose(out.y, 1 / values)) # Scalar out = sins / 3 self.assertTrue(np.allclose(out.y, np.sin(times) / 3)) # Test itruediv out /= 2 self.assertTrue(np.allclose(out.y, np.sin(times) / 6)) out /= sins self.assertTrue(np.allclose(out.y, 1 / 6))
def test_ts(name, *args): np_func = getattr(np.ma, f"masked_{name}") # We will edit in place t t = self.TS.copy() getattr(t, f"mask_{name}")(*args) self.assertTrue( t, ts.TimeSeries(self.TS.x, np_func(self.TS.y, *args)))
def setUp(self): # Let's test with a TimeSeries, a UniformGridData, and a # HierarchicalGridData x = np.linspace(0, 2 * np.pi, 100) y = np.sin(x) self.TS = ts.TimeSeries(x, y) self.grid_2d = gd.UniformGrid([10, 20], x0=[0.5, 1], dx=[1, 1]) self.ugd = gdu.sample_function_from_uniformgrid( lambda x, y: x * (y + 2), self.grid_2d) grid_2d_1 = gd.UniformGrid([10, 20], x0=[0.5, 1], dx=[1, 1], ref_level=0) self.ugd1 = gdu.sample_function_from_uniformgrid( lambda x, y: x * (y + 2), grid_2d_1) grid_2d_2 = gd.UniformGrid([10, 20], x0=[1, 2], dx=[3, 0.4], ref_level=1) self.ugd2 = gdu.sample_function_from_uniformgrid( lambda x, y: x * (y + 2), grid_2d_2) self.hg = gd.HierarchicalGridData([self.ugd1, self.ugd2])
def _multipoles_from_h5file(path): """Read multipole data from a HDF5 file. :param path: File to read. :type path: str :returns: Multipole data. :rtype: :py:class:`~.TimeSeries` """ alldets = [] # This regex matches : l(number)_m(-number)_r(number) fieldname_pattern = re.compile(r"l(\d+)_m([-]?\d+)_r([0-9.]+)") with h5py.File(path, "r") as data: # Loop over the groups in the hdf5 for entry in data.keys(): matched = fieldname_pattern.match(entry) if matched: mult_l = int(matched.group(1)) mult_m = int(matched.group(2)) radius = float(matched.group(3)) # Read the actual data a = data[entry][()].T ts = timeseries.TimeSeries(a[0], a[1] + 1j * a[2]) alldets.append((mult_l, mult_m, radius, ts)) return alldets
def test_extrapolation(self): # Test too many radii for the extrapolation with self.assertRaises(RuntimeError): self.gwdir._extrapolate_waves_to_infinity([1, 2], [1, 2], [1, 2], 1, order=3) # Number of radii is not the same as waves with self.assertRaises(RuntimeError): self.gwdir._extrapolate_waves_to_infinity([1, 2], [1, 2], [1, 2, 3], 1, order=1) # TODO: Write real tests for these functions. Compare with POWER? # NOTE: These tests are not physical tests! # Smoke test, we just check that the code returns expected data types times = np.linspace(0, 2 * np.pi, 100) sins = ts.TimeSeries(times, np.sin(times)) sins_plus_one = ts.TimeSeries(times, np.sin(times + 1)) self.gwdir._extrapolate_waves_to_infinity( [sins, sins_plus_one], np.linspace(-12, -11, 100), [10, 11], 1, order=1, ) self.gwdir.extrapolate_strain_lm_to_infinity(2, 2, 0.1, [110.69, 110.69], [2791, 2791.1], order=0) self.gwdir.extrapolate_strain_lm_to_infinity( 2, 2, 0.1, [110.69, 110.69], [2791, 2791.1], order=0, extrapolate_amplitude_phase=True, )
def test_eq(self): times = np.linspace(0, 2 * np.pi, 100) values = np.sin(times) sins = ts.TimeSeries(times, values) self.assertFalse(sins == 1) self.assertTrue(self.TS == sins)
def test_phase_shift(self): sins = ts.TimeSeries(self.times, self.values) self.assertTrue( np.allclose(sins.phase_shifted(np.pi / 2).y, 1j * self.values)) sins.phase_shift(np.pi / 2) self.assertTrue(np.allclose(sins.y, 1j * self.values))
def test_align_maximum_minimum(self): t = np.linspace(0, 1, 100) tseries = ts.TimeSeries(t, t) # Should shift everything of -1, so new times should be from -1 to 0 tseries.align_at_maximum() self.assertTrue(np.allclose(tseries.t, t - 1)) # Minimum is at t = 1, notice we use the above t, so this is a line # that goes from -1 to 0. The absolute minimum is at the end. y2 = np.linspace(-1, 0, 100) tseries2 = ts.TimeSeries(t, y2) tseries2.align_at_minimum() self.assertTrue(np.allclose(tseries2.t, t - 1))
def test_WavesOneDet(self): t1 = np.linspace(0, np.pi, 100) t2 = np.linspace(2 * np.pi, 3 * np.pi, 100) y1 = np.sin(t1) y2 = np.sin(t2) ts1 = ts.TimeSeries(t1, y1) ts2 = ts.TimeSeries(t2, y2) dist1 = 100 data1 = [(2, 2, ts1), (2, 2, ts2)] data2 = [(1, 1, ts1), (1, 0, ts2), (1, -1, ts2)] gw = cw.GravitationalWavesOneDet(dist1, data1) em = cw.ElectromagneticWavesOneDet(dist1, data2) self.assertEqual(gw.l_min, 2) self.assertEqual(em.l_min, 1)
def test_remove_duplicate_iters(self): t = np.array([1, 2, 3, 4, 2, 3]) y = np.array([0, 0, 0, 0, 0, 0]) self.assertEqual( ts.remove_duplicate_iters(t, y), ts.TimeSeries([1, 2, 3], [0, 0, 0]), )
def test_power(self): # Errors are tested by test_apply_binary times = np.linspace(0, 2 * np.pi, 100) values = np.array([2] * len(times)) out = self.TS ** ts.TimeSeries(times, values) self.assertTrue(np.allclose(out.y, np.sin(times) ** 2)) # Scalar out = self.TS ** 2 self.assertTrue(np.allclose(out.y, np.sin(times) ** 2)) # Test ipow out **= 2 self.assertTrue(np.allclose(out.y, np.sin(times) ** 4)) out **= ts.TimeSeries(times, values) self.assertTrue(np.allclose(out.y, np.sin(times) ** 8))
def test_mask_apply(self): ts_mask = ts.TimeSeries(self.times, np.ma.masked_less_equal(self.times, 1)) ts_nomask = ts.TimeSeries(self.times, self.times) ts_nomask.mask_apply(ts_mask.mask) self.assertEqual(ts_mask, ts_nomask) # Check with series already masked, by applying a second # mask ts_mask05 = ts.TimeSeries(self.times, np.ma.masked_less_equal(self.times, 0.5)) ts_nomask.mask_apply(ts_mask05.mask) self.assertEqual(ts_mask05, ts_nomask)
def test_time_shift(self): times = np.logspace(0, 1, 100) sins = ts.TimeSeries(times, self.values) self.assertTrue(np.allclose(sins.time_shifted(1).t, times + 1)) sins.time_shift(1) self.assertTrue(np.allclose(sins.t, times + 1))
def test_combine_ts(self): times1 = np.linspace(0, 2 * np.pi, 100) sins1 = np.sin(times1) times2 = np.linspace(np.pi, 3 * np.pi, 100) coss1 = np.cos(times2) # A sine wave + half a cos wave expected_early = np.append(sins1, np.cos(times2[50:])) expected_late = np.append(sins1[:50], np.cos(times2)) ts1 = ts.TimeSeries(times1, sins1) ts2 = ts.TimeSeries(times2, coss1) self.assertTrue( np.allclose( ts.combine_ts([ts1, ts2], prefer_late=False).y, expected_early ) ) self.assertTrue( np.allclose(ts.combine_ts([ts1, ts2]).y, expected_late) ) # Here we test two timeseries with same tmin times4 = np.linspace(0, 2 * np.pi, 100) times5 = np.linspace(0, 3 * np.pi, 100) sins4 = np.sin(times4) coss5 = np.sin(times5) ts4 = ts.TimeSeries(times4, sins4) ts5 = ts.TimeSeries(times5, coss5) self.assertTrue( np.allclose( ts.combine_ts([ts1, ts2], prefer_late=False).y, expected_early ) ) self.assertTrue( np.allclose(ts.combine_ts([ts4, ts5], prefer_late=True).y, coss5) )
def test_mean_remove(self): # Check unevenly-space time times = np.logspace(0, 1, 100) sins = ts.TimeSeries(times, self.values + 1) self.assertTrue(np.allclose(sins.mean_removed().y, self.values)) sins.mean_remove() self.assertTrue(np.allclose(sins.y, self.values))
def test_add(self): # Errors are tested by test_apply_binary times = np.linspace(0, 2 * np.pi, 100) values = np.sin(times) out = self.TS + ts.TimeSeries(times, values) self.assertTrue(np.allclose(out.y, 2 * np.sin(times))) # Scalar out = self.TS + 1 self.assertTrue(np.allclose(out.y, 1 + np.sin(times))) out = 1 + self.TS self.assertTrue(np.allclose(out.y, 1 + np.sin(times))) # Test iadd out += 1 self.assertTrue(np.allclose(out.y, 2 + np.sin(times))) out += self.TS self.assertTrue(np.allclose(out.y, 2 + 2 * np.sin(times))) # Everything should work with masked data too out = self.TS_cm + ts.TimeSeries(times, values) self.assertTrue(np.allclose(out.y, self.vals_cm + values)) # Scalar out = self.TS_cm + 1 self.assertTrue(np.allclose(out.y, 1 + self.vals_cm)) out = 1 + self.TS_cm self.assertTrue(np.allclose(out.y, 1 + self.vals_cm)) # Test iadd out += 1 self.assertTrue(np.allclose(out.y, 2 + self.vals_cm)) out += self.TS_cm self.assertTrue(np.allclose(out.y, 2 + 2 * self.vals_cm))
def test_total_function_on_available_lm(self): # The two series must have the same times ts3 = ts.TimeSeries(self.t1, self.y2) data = [(2, 2, self.ts1), (1, -1, ts3)] mult = mp.MultipoleOneDet(100, data) # Test larger and smaller l with self.assertRaises(ValueError): mult.total_function_on_available_lm(lambda x: x, l_max=100) with self.assertRaises(ValueError): mult.total_function_on_available_lm(lambda x: x, l_max=0) # First, let's try with identity as function # The output should be just ts1 + ts2 def identity(x, *args): return x self.assertEqual( mult.total_function_on_available_lm(identity), self.ts1 + ts3, ) # Next, we use the l, m, r, information def func1(x, mult_l, mult_m, mult_r): return mult_l * mult_m * mult_r * x self.assertEqual( mult.total_function_on_available_lm(func1), 2 * 2 * 100 * self.ts1 + 1 * (-1) * 100 * ts3, ) # Next, we use args and kwargs def func2(x, mult_l, mult_m, mult_r, add, add2=0): return mult_l * mult_m * mult_r * x + add + add2 # This will just add (add + add2) (2 + 3) self.assertEqual( mult.total_function_on_available_lm(func2, 2, add2=3), (2 * 2 * 100 * self.ts1 + 2 + 3 + 1 * (-1) * 100 * ts3 + 2 + 3), ) # Finally, test l_max self.assertEqual( mult.total_function_on_available_lm(identity, l_max=1), ts3, ) # Test no multiple moments with self.assertRaises(RuntimeError): mult._multipoles = {} mult.total_function_on_available_lm(lambda x: x, l_max=1)