import unittest from datetime import datetime import numpy as np from damaris.data.ADC_Result import ADC_Result def rotate_reference(y, degrees): "reference rotation of the two channels by degrees" rad = np.deg2rad(degrees) cos, sin = np.cos(rad), np.sin(rad) return [cos * y[0] - sin * y[1], sin * y[0] + cos * y[1]] class TestSignalpath(unittest.TestCase): @staticmethod def create_adc_result(): x = np.arange(4, dtype="float32") y = [np.array([10, 20, 30, 40], dtype="int16"), np.array([15, 25, 35, 45], dtype="int16")] index = [(0, 3)] job_date = datetime(2023, 1, 1) desc = {"key": "value"} sampl_freq = 1000.0 job_id = 11 adc = ADC_Result(x, y, index, sampl_freq, desc, job_id, job_date) adc.set_nChannels(2) return adc def assertRotated(self, adc, degrees): rotated = adc.phase(degrees) expected = rotate_reference(adc.y, degrees) np.testing.assert_allclose(rotated.y[0], expected[0]) np.testing.assert_allclose(rotated.y[1], expected[1]) return rotated def test_phase_positive_quarter_turns(self): """Test phase() with 0, 90, 180 and 270 degrees.""" adc = self.create_adc_result() for degrees in (0, 90, 180, 270): self.assertRotated(adc, degrees) def test_phase_negative_quarter_turns(self): """Test phase() with negative multiples of 90 degrees.""" adc = self.create_adc_result() for degrees in (-90, -180, -270, -360): self.assertRotated(adc, degrees) def test_phase_negative_arbitrary_angles(self): """Test phase() with arbitrary (not multiple of 90) negative angles.""" adc = self.create_adc_result() for degrees in (-45, -120, -315): self.assertRotated(adc, degrees) def test_phase_equals_equivalent_positive_angle(self): """Test that negative angles give the same result as the equivalent positive angle.""" adc = self.create_adc_result() for degrees in (-90, -45, -120): np.testing.assert_allclose(adc.phase(degrees).y, adc.phase(degrees + 360).y) def test_phase_does_not_modify_original(self): """Test that phase() leaves the original data (and its arrays) untouched.""" adc = self.create_adc_result() original = [adc.y[0].copy(), adc.y[1].copy()] for degrees in (0, 90, 180, 270, -90, -45, 45): rotated = adc.phase(degrees) self.assertIsNot(rotated, adc) self.assertIsNot(rotated.y, adc.y) for ch in (0, 1): self.assertIsNot(rotated.y[ch], original[ch]) np.testing.assert_array_equal(adc.y[ch], original[ch]) def test_phase_result_independent(self): """Test that modifying the phase-rotated copy does not affect the original.""" adc = self.create_adc_result() rotated = adc.phase(-90) rotated.y[0][:] = 9999 np.testing.assert_array_equal(adc.y[0], [10, 20, 30, 40]) def test_phase_chaining(self): """Test that chained phase() calls add up correctly.""" adc = self.create_adc_result() np.testing.assert_allclose(adc.phase(-90).phase(-90).y, adc.phase(-180).y) np.testing.assert_allclose(adc.phase(-90).phase(90).y, adc.phase(0).y) def test_phase_wrong_channel_number(self): """Test the Exception raised for signalpaths with other than 2 channels.""" adc = self.create_adc_result() adc.y.pop() self.assertRaises(Exception, adc.phase, -90) if __name__ == "__main__": unittest.main()