From 8043785885329f0d1a5aff9cebbaa92885653b68 Mon Sep 17 00:00:00 2001 From: gac-x02da Date: Wed, 18 Jun 2025 18:14:24 +0200 Subject: [PATCH] Test fixes --- tomcat_bec/devices/aerotech/AerotechPso.py | 2 +- .../AerotechSimpleSequenceTemplate.ascript | 2 +- .../AerotechSnapAndStepTemplate.ascript | 2 +- tomcat_bec/devices/aerotech/__init__.py | 4 + .../devices/aerotech/test/autoHilTest.py | 229 ++++++------------ .../test/testSequenceScanTemplate.ascript | 2 +- 6 files changed, 80 insertions(+), 161 deletions(-) diff --git a/tomcat_bec/devices/aerotech/AerotechPso.py b/tomcat_bec/devices/aerotech/AerotechPso.py index 3c3d8b6..a43f7b0 100644 --- a/tomcat_bec/devices/aerotech/AerotechPso.py +++ b/tomcat_bec/devices/aerotech/AerotechPso.py @@ -280,7 +280,7 @@ class aa1AxisPsoDistance(AerotechPsoBase): """Fire a single PSO event (i.e. manual software trigger)""" # Only trigger if distance was set to invalid # if self.dstDistanceVal.get() == 0: - logger.warning(f"[{self.name}] Triggerin...") + # logger.warning(f"[{self.name}] Triggerin...") return self.fire(settle_time) def arm(self) -> None: diff --git a/tomcat_bec/devices/aerotech/AerotechSimpleSequenceTemplate.ascript b/tomcat_bec/devices/aerotech/AerotechSimpleSequenceTemplate.ascript index b7b0c21..5159e72 100644 --- a/tomcat_bec/devices/aerotech/AerotechSimpleSequenceTemplate.ascript +++ b/tomcat_bec/devices/aerotech/AerotechSimpleSequenceTemplate.ascript @@ -33,7 +33,7 @@ program ////////////////////////////////////////////////////////////////////////// // Internal parameters - dont use - var $axis as axis = ROTY + var $axis as axis = {{ scan.rotaxis or 'ROTY' }} var $ii as integer var $axisFaults as integer = 0 var $iDdcSafeSpace as integer = 4096 diff --git a/tomcat_bec/devices/aerotech/AerotechSnapAndStepTemplate.ascript b/tomcat_bec/devices/aerotech/AerotechSnapAndStepTemplate.ascript index 80657d0..b308436 100644 --- a/tomcat_bec/devices/aerotech/AerotechSnapAndStepTemplate.ascript +++ b/tomcat_bec/devices/aerotech/AerotechSnapAndStepTemplate.ascript @@ -20,7 +20,7 @@ program // Internal - var $axis as axis = ROTY + var $axis as axis = {{ scan.rotaxis or 'ROTY' }} var $ii as integer var $axisFaults as integer = 0 diff --git a/tomcat_bec/devices/aerotech/__init__.py b/tomcat_bec/devices/aerotech/__init__.py index 5fe62b6..1b56826 100644 --- a/tomcat_bec/devices/aerotech/__init__.py +++ b/tomcat_bec/devices/aerotech/__init__.py @@ -7,3 +7,7 @@ from .AerotechAutomation1 import ( aa1GlobalVariableBindings, aa1AxisIo, ) +from .AerotechAutomation1Enums import ( + DriveDataCaptureInput, + DriveDataCaptureTrigger, +) \ No newline at end of file diff --git a/tomcat_bec/devices/aerotech/test/autoHilTest.py b/tomcat_bec/devices/aerotech/test/autoHilTest.py index 33b3fde..8293277 100644 --- a/tomcat_bec/devices/aerotech/test/autoHilTest.py +++ b/tomcat_bec/devices/aerotech/test/autoHilTest.py @@ -16,7 +16,7 @@ import time import os import jinja2 import numpy as np -from ophyd import Component, EpicsMotor, EpicsSignal +from ophyd import Component, EpicsMotor, EpicsSignal, EpicsSignalRO from tomcat_bec.devices.aerotech import ( @@ -27,21 +27,22 @@ from tomcat_bec.devices.aerotech import ( aa1Tasks, aa1AxisDriveDataCollection, aa1AxisPsoDistance, -) - - -from tomcat_bec.devices.aerotech.AerotechAutomation1Enums import ( DriveDataCaptureInput, DriveDataCaptureTrigger, ) -os.environ["EPICS_CA_ADDR_LIST"] = "129.129.106.255" + +os.environ["EPICS_CA_ADDR_LIST"] = "129.129.106.255 129.129.99.255" AA1_IOC_NAME = "X02DA-ES1-SMP1" -AA1_AXIS_NAME = "ROTY" -MOTOR_TOL = 1.0 +AA1_IOC_AXIS = "ROTY" +AA1_DRV_AXIS = "RY" +AXIS_VELOCITY = 42 +AXIS_TRAVEL = 80 +AXIS_TOL = 1.0 class AerotechMotor(EpicsMotor): """ EpicsMotor extension with additional PVs""" + motor_enable_rbv = Component(EpicsSignalRO, "-EnaAct", kind="omitted", auto_monitor=True) motor_enable = Component(EpicsSignal, ".CNEN", kind="omitted", auto_monitor=True) @@ -56,7 +57,7 @@ class AerotechAutomation1Test(unittest.TestCase): # HIL testing only if there's hardware dev = aa1Controller(AA1_IOC_NAME + ":CTRL:", name="aa1") dev.wait_for_connection() - mot = AerotechMotor(AA1_IOC_NAME + ":" + AA1_AXIS_NAME, name="mot") + mot = AerotechMotor(AA1_IOC_NAME + ":" + AA1_IOC_AXIS, name="mot") mot.wait_for_connection() mot.motor_enable.set(1, settle_time=0.1).wait() cls._isConnected = True @@ -83,7 +84,7 @@ class AerotechAutomation1Test(unittest.TestCase): print("TASK: Testing the 'run' command (run text with intermediary file)") # Send another empty program - filename = "unittesting2.ascript" + filename = "test_program.ascript" text = "program\nvar $positions[4] as real = [2, 4, 8, 16]\nend" dev.configure({'script_file': filename, 'script_task': 3, 'script_text': text}) dev.arm() @@ -120,21 +121,21 @@ class AerotechAutomation1Test(unittest.TestCase): # # Attempt to run a short motion command using the Execute interface print("TASK: Testing a short motion command") - text = """ + text = f""" var $fDist as real = 90 - var $fVelo as real = 200 - var $axis as axis = ROTY + var $fVelo as real = 60 + var $axis as axis = {AA1_DRV_AXIS} Enable($axis) MoveLinear($axis, $fDist, $fVelo) """ - dev.configure({'script_task': 3, 'script_text': text}) + dev.configure({'script_task': 3, 'script_text': text, 'script_file': "test_shortmove.ascript"}) dev.arm() t_start = time.time() dev.kickoff() dev.complete().wait() t_end = time.time() t_elapsed = t_end - t_start - self.assertTrue( 0 < t_elapsed < 4, f"Motion finished outside of window in: {t_elapsed}") + self.assertTrue( 1 < t_elapsed < 4, f"Motion finished outside of window in: {t_elapsed}") dev.unstage() print("TASK: Done testing TASK module!") @@ -268,7 +269,7 @@ class AerotechAutomation1Test(unittest.TestCase): $iglobal[1]={val_i} $rglobal[1]={val_f} """ - tsk.configure({'script_text': text, 'script_task': 4}) + tsk.configure({'script_text': text, 'script_task': 4, 'script_file': "test_global.ascript"}) tsk.arm() tsk.launch() tsk.complete().wait() @@ -285,19 +286,30 @@ class AerotechAutomation1Test(unittest.TestCase): def test_05_axis_motorrecord(self): """Tests the basic move functionality of the MotorRecord""" - mot = AerotechMotor(AA1_IOC_NAME + ":" + AA1_AXIS_NAME, name="x") + mot = AerotechMotor(AA1_IOC_NAME + ":" + AA1_IOC_AXIS, name="x") mot.wait_for_connection() mot.motor_enable.set(1, settle_time=0.1).wait() - mot.velocity.set(200).wait() + mot.velocity.set(AXIS_VELOCITY).wait() print("\nMR: Checking the standard EPICS motor record") + # Test enabling/disabling the axis + mot.motor_enable.set(1, settle_time=0.1).wait() + time.sleep(1) + self.assertTrue(mot.motor_enable_rbv.value, "Motor should be enabled") + mot.motor_enable.set(0, settle_time=0.1).wait() + time.sleep(1) + self.assertFalse(mot.motor_enable_rbv.value, "Motor should be disabled") + mot.motor_enable.set(1, settle_time=0.1).wait() + time.sleep(1) + self.assertTrue(mot.motor_enable_rbv.value, "Motor should be enabled") + # Four test with absolute moves def move_rel(dist): target = mot.position + dist print(f"Absolute move to {target}, distance: {dist}") mot.move(target, wait=True) self.assertTrue( - np.abs(target - mot.position) < MOTOR_TOL, + np.abs(target - mot.position) < AXIS_TOL, f"Final position {mot.position} is too far from target {target}", ) @@ -311,7 +323,7 @@ class AerotechAutomation1Test(unittest.TestCase): def test_06_axis_io(self): """Test axis IO bindings""" # Throws if IOC is not available or PVs are incorrect - dev = aa1AxisIo(AA1_IOC_NAME + ":" + AA1_AXIS_NAME + ":IO:", name="io") + dev = aa1AxisIo(AA1_IOC_NAME + ":" + AA1_IOC_AXIS + ":IO:", name="io") dev.wait_for_connection() # Writing random values to analog/digital outputs @@ -338,9 +350,9 @@ class AerotechAutomation1Test(unittest.TestCase): configuration, state monitoring and readback. """ # Throws if IOC is not available or PVs are incorrect - dev = aa1AxisDriveDataCollection(AA1_IOC_NAME + ":" + AA1_AXIS_NAME + ":DDC:", name="ddc") + dev = aa1AxisDriveDataCollection(AA1_IOC_NAME + ":" + AA1_IOC_AXIS + ":DDC:", name="ddc") event = EpicsSignal( - AA1_IOC_NAME + ":" + AA1_AXIS_NAME + ":PSO:EVENT:SINGLE", put_complete=True + AA1_IOC_NAME + ":" + AA1_IOC_AXIS + ":PSO:EVENT:SINGLE", put_complete=True ) dev.wait_for_connection() event.wait_for_connection() @@ -464,9 +476,9 @@ class AerotechAutomation1Test(unittest.TestCase): the PSO module and the polled feedback. """ # Throws if IOC is not available or PVs are incorrect - pso = aa1AxisPsoDistance(AA1_IOC_NAME + ":" + AA1_AXIS_NAME + ":PSO:", name="pso1") - ddc = aa1AxisDriveDataCollection(AA1_IOC_NAME + ":" + AA1_AXIS_NAME + ":DDC:", name="ddc") - mot = AerotechMotor(AA1_IOC_NAME + ":" + AA1_AXIS_NAME, name=AA1_AXIS_NAME.lower()) + pso = aa1AxisPsoDistance(AA1_IOC_NAME + ":" + AA1_IOC_AXIS + ":PSO:", name="pso1") + ddc = aa1AxisDriveDataCollection(AA1_IOC_NAME + ":" + AA1_IOC_AXIS + ":DDC:", name="ddc") + mot = AerotechMotor(AA1_IOC_NAME + ":" + AA1_IOC_AXIS, name=AA1_IOC_AXIS.lower()) mot.wait_for_connection() pso.wait_for_connection() ddc.wait_for_connection() @@ -479,7 +491,7 @@ class AerotechAutomation1Test(unittest.TestCase): # Configure steps and move to middle of range pso.configure({"pso_distance": 5, "pso_wavemode": "toggle"}) pso.arm() - mot.velocity.set(200).wait() + mot.velocity.set(AXIS_VELOCITY).wait() mot.move(mot.position + 2.5, wait=True) ddc.arm() @@ -527,7 +539,7 @@ class AerotechAutomation1Test(unittest.TestCase): pso.disarm() ddc.disarm() - print("AX:PSO: Checking basic 'pulsed' event generation with DDC (3/5)") + print("AX:PSO: Checking basic 'pulsed' event generation with DDC (3/3)") # Configure steps and move to middle of range pso.configure({"pso_distance": 1.8, "pso_wavemode": "pulsed", "pso_n_pulse": 3}) pso.arm() @@ -565,9 +577,9 @@ class AerotechAutomation1Test(unittest.TestCase): and compares them to the expected values. """ # Throws if IOC is not available or PVs are incorrect - pso = aa1AxisPsoDistance(AA1_IOC_NAME + ":" + AA1_AXIS_NAME + ":PSO:", name="pso1") - ddc = aa1AxisDriveDataCollection(AA1_IOC_NAME + ":" + AA1_AXIS_NAME + ":DDC:", name="ddc") - mot = AerotechMotor(AA1_IOC_NAME + ":" + AA1_AXIS_NAME, name="x") + pso = aa1AxisPsoDistance(AA1_IOC_NAME + ":" + AA1_IOC_AXIS + ":PSO:", name="pso1") + ddc = aa1AxisDriveDataCollection(AA1_IOC_NAME + ":" + AA1_IOC_AXIS + ":DDC:", name="ddc") + mot = AerotechMotor(AA1_IOC_NAME + ":" + AA1_IOC_AXIS, name="x") mot.wait_for_connection() pso.wait_for_connection() ddc.wait_for_connection() @@ -578,7 +590,7 @@ class AerotechAutomation1Test(unittest.TestCase): "\ntest_09_PsoIntegration01: Integration test for vector PSO triggering (advanced)" ) - print("AX:PSO: Testing standard 'enable' style PSO triggering with DDC (1/3)") + print("AX:PSO: Testing standard 'enable' style PSO triggering with DDC (1/2)") # This is one line of the Tomcat sequence scan! acc_dist = 0.5 * mot.velocity.value * mot.acceleration.value vec_dist = [acc_dist, 18, 0.01, 18, 0.01, 18, 0.01, 18, 0.01, 18, 0.01, 18] @@ -615,7 +627,7 @@ class AerotechAutomation1Test(unittest.TestCase): pso.unstage() ddc.unstage() - print("AX:PSO: Checking 'individual' style trigger signal with DDC (2/5)") + print("AX:PSO: Checking 'individual' style trigger signal with DDC (2/2)") # This is practically golden ratio tomography! acc_dist = 0.5 * mot.velocity.value * mot.acceleration.value vec_dist = [acc_dist] @@ -654,114 +666,16 @@ class AerotechAutomation1Test(unittest.TestCase): pso.unstage() ddc.unstage() - # def test_10_AxisPsoWindow1(self): - # """ Test basic PSO window mode functionality - - # This module tests basic PSO distance functionality, like events and - # waveform generation. The goal is to ensure the basic operation of - # the PSO module and the polled feedback. - # """ - # # Throws if IOC is not available or PVs are incorrect - # pso = aa1AxisPsoWindow(AA1_IOC_NAME + ":" + AA1_AXIS_NAME + ":PSO:", name="pso1") - # ddc = aa1AxisDriveDataCollection(AA1_IOC_NAME + ":" + AA1_AXIS_NAME + ":DDC:", name="ddc") - # mot = AerotechMotor(AA1_IOC_NAME + ":" + AA1_AXIS_NAME, name="x") - # mot.wait_for_connection() - # pso.wait_for_connection() - # ddc.wait_for_connection() - # pso.unstage() - # ddc.unstage() - # mot.unstage() - # print("\nAX:PSO: Checking axis PSO in window mode (basic)") - - # print("AX:PSO: Directly checking basic window output (1/3)") - # # Configure steps and move to middle of range - # pso.configure({'bounds': (5, 13), 'pso_wavemode': "output"}) - # time.sleep(1) - # # Move half a step - # mot.move(mot.position + 0.1) - # dist = 0.1 - - # # Start moving in steps, while checking output - # for ii in range(42): - # mot.move(mot.position + 0.2) - # dist += 0.2 - # time.sleep(1) - # if 5 < dist < 13: - # self.assertTrue(pso.output.value == 1, - # f"Expected HIGH PSO output inside the window at distance {dist}") - # else: - # self.assertTrue(pso.output.value == 0, - # f"Expected LOW PSO output outside the window at distance {dist}") - - # print("AX:PSO: The next tests fail due to encoder jitter!") - # pso.unstage() - # return - - # print("AX:PSO: Checking basic window event generation with DDC (2/3)") - # # Move to acceleration position - # acc_dist = 0.5 * mot.velocity.value * mot.acceleration.value - # print(f"Acceleration distance: {acc_dist}") - # start_position = mot.position - # mot.move(start_position - acc_dist) - # # Configure PSO in window mode - # cfg = {'bounds': (acc_dist, 30 + acc_dist), 'pso_wavemode': "pulsed", "emode": 'Both'} - # dev.configure(cfg) - # # Configure the data capture (must be performed in start position) - # cfg = {'ntotal': 5*10, 'trigger': DriveDataCaptureTrigger.PsoOutput} - # ddc.configure(cfg) - # ddc.arm() - # npoints_rbv = ddc.nsamples_rbv.value - # self.assertEqual(npoints_rbv, 0, - # f"DDC.stage should reset the number of DDC points but got: {npoints_rbv}") - # # Repeated line scan - # for ii in range(10): - # dev.arm() - # mot.move(start_position + 30 + acc_dist) - # dev.unstage() - # mot.move(start_position - acc_dist) - # time.sleep(0.5) - # npoints_rbv = ddc.nsamples_rbv.value - # self.assertTrue(np.abs(npoints_rbv - 50) < 1, - # f"Expected to record 10 points but got {npoints_rbv}") - - # print("AX:PSO: Checking basic 'toggled' event generation with DDC (3/3)") - # print("Test removed as there's some heavy jitter on the PSO output flag") - # # Move to acceleration position - # acc_dist = 0.5 * mot.velocity.value * mot.acceleration.value - # print(f"Acceleration distance: {acc_dist}") - # mot.move(mot.position - acc_dist) - # # Configure PSO in window mode - # cfg = {'bounds': (acc_dist, 30 + acc_dist + 1), 'pso_wavemode': "output"} - # dev.configure(cfg) - # dev.arm() - # # Configure the data capture - # cfg = {'ntotal': 10, 'trigger': DriveDataCaptureTrigger.PsoOutput} - # ddc.configure(cfg) - # ddc.arm() - # npoints_rbv = ddc.nsamples_rbv.value - # self.assertEqual(npoints_rbv, 0, - # f"DDC.stage should reset the number of DDC points but got: {npoints_rbv}") - # # Snake scan - # for ii in range(10): - # if ii % 2 == 0: - # mot.move(mot.position + 30 + 2 * acc_dist + 0.1) - # else: - # mot.move(mot.position - 30 - 2 * acc_dist - 0.1) - # time.sleep(0.5) - # npoints_rbv = ddc.nsamples_rbv.value - # self.assertTrue(np.abs(npoints_rbv - 10) < 1, - # f"Expected to record 10 points but got {npoints_rbv}") - - def test_12_StepScan(self): + def test_10_StepScan(self): """Test a simple blusky style step scan (via BEC) This module tests manual PSO trigger functionality. The goal is to ensure the basic operation of the PSO module and the polled feedback. """ # Throws if IOC is not available or PVs are incorrect - pso = aa1AxisPsoDistance(AA1_IOC_NAME + ":" + AA1_AXIS_NAME + ":PSO:", name="pso1") - ddc = aa1AxisDriveDataCollection(AA1_IOC_NAME + ":" + AA1_AXIS_NAME + ":DDC:", name="ddc") - mot = AerotechMotor(AA1_IOC_NAME + ":" + AA1_AXIS_NAME, name="x") + pso = aa1AxisPsoDistance(AA1_IOC_NAME + ":" + AA1_IOC_AXIS + ":PSO:", name="pso1") + ddc = aa1AxisDriveDataCollection(AA1_IOC_NAME + ":" + AA1_IOC_AXIS + ":DDC:", name="ddc") + mot = AerotechMotor(AA1_IOC_NAME + ":" + AA1_IOC_AXIS, name="x") mot.wait_for_connection() pso.wait_for_connection() ddc.wait_for_connection() @@ -769,7 +683,7 @@ class AerotechAutomation1Test(unittest.TestCase): ddc.disarm() mot.unstage() t_start = time.time() - print("\ntest_12_StepScan: Simple step scan (via Ophyd)") + print("\ntest_10_StepScan: Simple step scan (via Ophyd)") pos_start = 112.0 scan_range = 180 @@ -787,7 +701,7 @@ class AerotechAutomation1Test(unittest.TestCase): f"Expected to move to scan start position {pos_start}, now at {mot.position}", ) # PSO setup (very large pulse distance) - pso.configure(d={"pso_n_pulse": 2, "pso_distance": 99999}) + pso.configure(d={"pso_n_pulse": 2, "pso_distance": 9999}) # DDC setup (trigger at each point plus some extra) cfg = {"num_points_total": 1000 * (scan_steps + 1), "ddc_trigger": DriveDataCaptureTrigger.PsoOutput} ddc.configure(cfg) @@ -800,7 +714,7 @@ class AerotechAutomation1Test(unittest.TestCase): for ii in range(len(positions)): mot.move(positions[ii]) self.assertTrue( - np.abs(mot.position - positions[ii]) < MOTOR_TOL, + np.abs(mot.position - positions[ii]) < AXIS_TOL, f"Expected to reach {positions[ii]}, now is at {mot.position} on step {ii}", ) pso.trigger() @@ -824,7 +738,7 @@ class AerotechAutomation1Test(unittest.TestCase): f"Expected to record {len(positions)} DDC points, got: {npoints_rbv}", ) - def test_13_TomcatSequenceScan(self): + def test_11_TomcatSequenceScan(self): """Test the zig-zag sequence scan from Tomcat (via BEC) This module tests basic PSO distance functionality, like events and @@ -832,9 +746,9 @@ class AerotechAutomation1Test(unittest.TestCase): the PSO module and the polled feedback. """ # Throws if IOC is not available or PVs are incorrect - pso = aa1AxisPsoDistance(AA1_IOC_NAME + ":" + AA1_AXIS_NAME + ":PSO:", name="pso1") - ddc = aa1AxisDriveDataCollection(AA1_IOC_NAME + ":" + AA1_AXIS_NAME + ":DDC:", name="ddc") - mot = AerotechMotor(AA1_IOC_NAME + ":" + AA1_AXIS_NAME, name="x") + pso = aa1AxisPsoDistance(AA1_IOC_NAME + ":" + AA1_IOC_AXIS + ":PSO:", name="pso1") + ddc = aa1AxisDriveDataCollection(AA1_IOC_NAME + ":" + AA1_IOC_AXIS + ":DDC:", name="ddc") + mot = AerotechMotor(AA1_IOC_NAME + ":" + AA1_IOC_AXIS, name="x") mot.wait_for_connection() pso.wait_for_connection() ddc.wait_for_connection() @@ -842,7 +756,7 @@ class AerotechAutomation1Test(unittest.TestCase): ddc.disarm() mot.unstage() t_start = time.time() - print("\ntest_13_TomcatSequenceScan: TOMCAT Sequeence scan (via Ophyd)") + print("\ntest_11_TomcatSequenceScan: TOMCAT Sequeence scan (via Ophyd)") scan_start = 42.0 scan_range = 180 @@ -850,14 +764,14 @@ class AerotechAutomation1Test(unittest.TestCase): scan_type = "PosNeg" # Dynamic properties - scan_vel = 90 + scan_vel = AXIS_VELOCITY scan_acc = 500 dist_safe = 10.0 ###################################################################### print("\tConfigure") # Scan range - dist_acc = 0.5 * scan_vel * scan_vel / scan_acc + dist_safe + dist_acc = 0.5 * AXIS_VELOCITY * AXIS_VELOCITY / scan_acc + dist_safe if scan_type in ["PosNeg", "Pos"]: pos_start = scan_start - dist_acc pos_end = scan_start + scan_range + dist_acc @@ -868,8 +782,8 @@ class AerotechAutomation1Test(unittest.TestCase): raise RuntimeError(f"Unexpected ScanType: {scan_type}") # Motor setup - mot.velocity.set(scan_vel).wait() - mot.acceleration.set(scan_vel / scan_acc).wait() + mot.velocity.set(AXIS_VELOCITY).wait() + mot.acceleration.set(AXIS_VELOCITY / scan_acc).wait() mot.move(pos_start) self.assertTrue( np.abs(mot.position - pos_start) < 1.0, @@ -897,12 +811,12 @@ class AerotechAutomation1Test(unittest.TestCase): if scan_type in ["Pos", "Neg"]: mot.move(pos_end) self.assertTrue( - np.abs(mot.position - pos_end) < MOTOR_TOL, + np.abs(mot.position - pos_end) < AXIS_TOL, f"Expected to reach {pos_end}, now is at {mot.position} on iteration {ii}", ) mot.move(pos_start) self.assertTrue( - np.abs(mot.position - pos_start) < MOTOR_TOL, + np.abs(mot.position - pos_start) < AXIS_TOL, f"Expected to rewind to {pos_start}, now at {mot.position} on iteration {ii}", ) @@ -910,13 +824,13 @@ class AerotechAutomation1Test(unittest.TestCase): if ii % 2 == 0: mot.move(pos_end, wait=True) self.assertTrue( - np.abs(mot.position - pos_end) < MOTOR_TOL, + np.abs(mot.position - pos_end) < AXIS_TOL, f"Expected to reach {pos_end}, now at {mot.position} on iteration {ii}", ) else: mot.move(pos_start, wait=True) self.assertTrue( - np.abs(mot.position - pos_start) < MOTOR_TOL, + np.abs(mot.position - pos_start) < AXIS_TOL, f"Expected to reach {pos_start}, now at {mot.position} on iteration {ii}", ) @@ -946,7 +860,7 @@ class AerotechAutomation1Test(unittest.TestCase): f"Expected to record {num_repeat} DDC points, but got: {npoints_rbv}", ) - def test_14_JinjaTomcatSequenceScan(self): + def test_12_JinjaTomcatSequenceScan(self): """ Run a test sequence scan with template substitution""" # Load the test file path = os.path.dirname(os.path.realpath(__file__)) @@ -955,17 +869,18 @@ class AerotechAutomation1Test(unittest.TestCase): templatetext = f.read() scanconfig = { + "rotaxis": "RY", "startpos": 42, "scanrange": 180, "nrepeat": 13, "scandir": "NEGPOS", "npoints": 1300, - "scanvel": 150, + "scanvel": AXIS_VELOCITY, "scanacc": 500, - "accdist": 0.5*150*150/500, + "accdist": 0.5*AXIS_VELOCITY*AXIS_VELOCITY/500, "psotrigger": "PsoEvent", - "psoBoundsPos": [0.5*150*150/500, 180], - "psoBoundsNeg": [0.5*150*150/500, 180] + "psoBoundsPos": [0.5*AXIS_VELOCITY*AXIS_VELOCITY/500, 180], + "psoBoundsNeg": [0.5*AXIS_VELOCITY*AXIS_VELOCITY/500, 180] } tm = jinja2.Template(templatetext) text = tm.render(scan=scanconfig) @@ -974,10 +889,10 @@ class AerotechAutomation1Test(unittest.TestCase): # Throws if IOC is not available or PVs are incorrect tsk = aa1Tasks(AA1_IOC_NAME + ":TASK:", name="tsk") - ddc = aa1AxisDriveDataCollection(AA1_IOC_NAME + ":" + AA1_AXIS_NAME + ":DDC:", name="ddc") + ddc = aa1AxisDriveDataCollection(AA1_IOC_NAME + ":" + AA1_IOC_AXIS + ":DDC:", name="ddc") tsk.wait_for_connection() ddc.wait_for_connection() - print("\nTOMCAT Sequeence scan (via Jinjad AeroScript)") + print("\ntest_12_JinjaTomcatSequenceScan: TOMCAT Sequeence scan (via Jinjad AeroScript)") # Copy file to controller and run it t_start = time.time() diff --git a/tomcat_bec/devices/aerotech/test/testSequenceScanTemplate.ascript b/tomcat_bec/devices/aerotech/test/testSequenceScanTemplate.ascript index 9d87cf9..a7aaf9b 100644 --- a/tomcat_bec/devices/aerotech/test/testSequenceScanTemplate.ascript +++ b/tomcat_bec/devices/aerotech/test/testSequenceScanTemplate.ascript @@ -33,7 +33,7 @@ program ////////////////////////////////////////////////////////////////////////// // Internal parameters - dont use - var $axis as axis = ROTY + var $axis as axis = {{ scan.rotaxis or 'ROTY' }} var $ii as integer var $axisFaults as integer = 0 var $iDdcSafeSpace as integer = 4096