From ef11824f8b4bbb046ff6ef4d4afce555a57f5e5a Mon Sep 17 00:00:00 2001 From: Markus Rosenstihl Date: Fri, 16 Oct 2026 11:31:37 +0200 Subject: [PATCH] Experiment.set_phase(): normalize negative phases to [0, 360) The phase was passed to the backend job file verbatim, so negative values (e.g. from rf_pulse(phase=-90)) reached the backend unchanged. set_phase(), set_frequency() and thus rf_pulse() now write the phase normalized with phase % 360. Add unittests for the normalization. --- src/damaris/experiments/Experiment.py | 7 ++-- tests/test_Experiment.py | 47 +++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 3 deletions(-) create mode 100644 tests/test_Experiment.py diff --git a/src/damaris/experiments/Experiment.py b/src/damaris/experiments/Experiment.py index 9c0b954..70a25d8 100644 --- a/src/damaris/experiments/Experiment.py +++ b/src/damaris/experiments/Experiment.py @@ -402,10 +402,10 @@ class Experiment: The state length is 2 µs. Stabilisation time depends on RF source. :param float frequency: frequency to set in Hz - :param float phase: phase to set + :param float phase: phase to set, normalized to the range [0, 360) :param int ttls: default=0, additional ttl lines to set (integer) """ - s_content = '' % (frequency, phase) + s_content = '' % (frequency, phase % 360) if ttls != 0: s_content += '' % ttls self.state_list.append(StateSimple(2e-6, s_content)) @@ -580,8 +580,9 @@ class Experiment: - The state length for this command is 0.5 µs. - The stabilization time for the phase change is RF source dependent. A typical value for PTS310 is 2 µs. - The phase is relative to the initial phase set at start of the experiment. + - Negative phases are normalized to the range [0, 360) before writing the job file. """ - s_content = '' % (phase) + s_content = '' % (phase % 360) if ttls!=0: s_content += '' % ttls self.state_list.append(StateSimple(0.5e-6, s_content)) diff --git a/tests/test_Experiment.py b/tests/test_Experiment.py new file mode 100644 index 0000000..6479b63 --- /dev/null +++ b/tests/test_Experiment.py @@ -0,0 +1,47 @@ +import re +import unittest + +from damaris.experiments.Experiment import Experiment + + +def phase_of_state(state): + "extracts the phase value from a state's XML content" + match = re.search(r'phase="([-0-9.]+)"', state.content) + assert match, "no phase in state: %s" % state.content + return float(match.group(1)) + + +class TestExperimentPhase(unittest.TestCase): + def test_set_phase_negative_normalized(self): + """Test that set_phase() normalizes negative phases to [0, 360).""" + e = Experiment() + for degrees, expected in ((-90, 270.0), (-45.5, 314.5), + (-270, 90.0), (-360, 0.0)): + e.set_phase(degrees) + self.assertEqual(phase_of_state(e.state_list.list[-1]), expected) + + def test_set_phase_positive_unchanged(self): + """Test that set_phase() passes positive phases through unchanged.""" + e = Experiment() + for degrees, expected in ((0, 0.0), (90, 90.0), (270, 270.0), + (45.5, 45.5)): + e.set_phase(degrees) + self.assertEqual(phase_of_state(e.state_list.list[-1]), expected) + + def test_set_frequency_negative_phase_normalized(self): + """Test that set_frequency() normalizes a negative phase.""" + e = Experiment() + e.set_frequency(85e6, -90) + state = e.state_list.list[-1] + self.assertEqual(phase_of_state(state), 270.0) + self.assertIn('f="85000000.000000"', state.content) + + def test_rf_pulse_negative_phase_normalized(self): + """Test that rf_pulse() normalizes a negative pulse phase.""" + e = Experiment(gating=1e-6, rf_sources=[1], rf_gates=[2]) + e.rf_pulse(length=1e-6, phase=-90, source=0) + self.assertEqual(phase_of_state(e.state_list.list[0]), 270.0) + + +if __name__ == "__main__": + unittest.main()