diff --git a/docs/ioc/ioc_overview.md b/docs/ioc/ioc_overview.md
index 5d5d558..22a0c6c 100644
--- a/docs/ioc/ioc_overview.md
+++ b/docs/ioc/ioc_overview.md
@@ -8,3 +8,4 @@ The ports are configured in the [service registry](../../docs/ioc/ioc_overview.m
| AGEBD-CPCL-NTURNS | IOC providing PVs for the DBPM3 stage0 and stage1 nr. of turns calculation service |
| AGEBD-CPCL-DBPM3CURR | |
| AGEBD-CPCL-TAUBPM | |
+| AGEBD-CPCL-SHIFTTOOL | |
diff --git a/services/dbpm3curr/current/app/uv.lock b/services/dbpm3curr/current/app/uv.lock
index 3a2bed0..3134b83 100644
--- a/services/dbpm3curr/current/app/uv.lock
+++ b/services/dbpm3curr/current/app/uv.lock
@@ -7,11 +7,15 @@ name = "agebd"
version = "0.1.0"
source = { editable = "../../../../packages/agebd" }
dependencies = [
+ { name = "h5py" },
{ name = "typer" },
]
[package.metadata]
-requires-dist = [{ name = "typer", specifier = ">=0.23.2" }]
+requires-dist = [
+ { name = "h5py", specifier = ">=3.16.0" },
+ { name = "typer", specifier = ">=0.23.2" },
+]
[package.metadata.requires-dev]
dev = [
@@ -79,6 +83,24 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" },
]
+[[package]]
+name = "h5py"
+version = "3.16.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "numpy" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/db/33/acd0ce6863b6c0d7735007df01815403f5589a21ff8c2e1ee2587a38f548/h5py-3.16.0.tar.gz", hash = "sha256:a0dbaad796840ccaa67a4c144a0d0c8080073c34c76d5a6941d6818678ef2738", size = 446526, upload-time = "2026-03-06T13:49:08.07Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/3a/6b/231413e58a787a89b316bb0d1777da3c62257e4797e09afd8d17ad3549dc/h5py-3.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e06f864bedb2c8e7c1358e6c73af48519e317457c444d6f3d332bb4e8fa6d7d9", size = 3724137, upload-time = "2026-03-06T13:47:35.242Z" },
+ { url = "https://files.pythonhosted.org/packages/74/f9/557ce3aad0fe8471fb5279bab0fc56ea473858a022c4ce8a0b8f303d64e9/h5py-3.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ec86d4fffd87a0f4cb3d5796ceb5a50123a2a6d99b43e616e5504e66a953eca3", size = 3090112, upload-time = "2026-03-06T13:47:37.634Z" },
+ { url = "https://files.pythonhosted.org/packages/7a/f5/e15b3d0dc8a18e56409a839e6468d6fb589bc5207c917399c2e0706eeb44/h5py-3.16.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:86385ea895508220b8a7e45efa428aeafaa586bd737c7af9ee04661d8d84a10d", size = 4844847, upload-time = "2026-03-06T13:47:39.811Z" },
+ { url = "https://files.pythonhosted.org/packages/cb/92/a8851d936547efe30cc0ce5245feac01f3ec6171f7899bc3f775c72030b3/h5py-3.16.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:8975273c2c5921c25700193b408e28d6bdd0111c37468b2d4e25dcec4cd1d84d", size = 5065352, upload-time = "2026-03-06T13:47:41.489Z" },
+ { url = "https://files.pythonhosted.org/packages/2b/ae/f2adc5d0ca9626db3277a3d87516e124cbc5d0eea0bd79bc085702d04f2c/h5py-3.16.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:1677ad48b703f44efc9ea0c3ab284527f81bc4f318386aaaebc5fede6bbae56f", size = 4839173, upload-time = "2026-03-06T13:47:43.586Z" },
+ { url = "https://files.pythonhosted.org/packages/64/0b/e0c8c69da1d8838da023a50cd3080eae5d475691f7636b35eff20bb6ef20/h5py-3.16.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7c4dd4cf5f0a4e36083f73172f6cfc25a5710789269547f132a20975bfe2434c", size = 5076216, upload-time = "2026-03-06T13:47:45.315Z" },
+ { url = "https://files.pythonhosted.org/packages/66/35/d88fd6718832133c885004c61ceeeb24dbd6397ef877dbed6b3a64d6a286/h5py-3.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:bdef06507725b455fccba9c16529121a5e1fbf56aa375f7d9713d9e8ff42454d", size = 3183639, upload-time = "2026-03-06T13:47:47.041Z" },
+]
+
[[package]]
name = "iniconfig"
version = "2.3.0"
diff --git a/services/dbpm3curr/current/ioc/cfg/AGEBD-CPCL-DBPM3CURR_set1.req b/services/dbpm3curr/current/ioc/cfg/AGEBD-CPCL-DBPM3CURR_set1.req
new file mode 100644
index 0000000..8c8c606
--- /dev/null
+++ b/services/dbpm3curr/current/ioc/cfg/AGEBD-CPCL-DBPM3CURR_set1.req
@@ -0,0 +1 @@
+AGEBD-DBPM3CURR:ACCUMULATED-BEAM-DOSE
\ No newline at end of file
diff --git a/services/injectionguard/current/app/pyproject.toml b/services/injectionguard/current/app/pyproject.toml
new file mode 100644
index 0000000..211a63c
--- /dev/null
+++ b/services/injectionguard/current/app/pyproject.toml
@@ -0,0 +1,48 @@
+[project]
+name = "agebd-injectionguard"
+version = "0.1.0"
+description = "AGEBD-INJECTIONGUARD Service"
+requires-python = "==3.10.*"
+dependencies = [
+ "agebd",
+ "numpy>=2.0.2",
+]
+
+[dependency-groups]
+dev = [
+ "pyepics>=3.5.8",
+ "pytest>=8.4.2",
+ "ruff>=0.15.20",
+]
+
+[tool.uv.sources]
+# Path is relative to where agebd package is deployed on hla
+# machines (see CI/CD in .gitea/workflows)
+agebd = { path = "../../../../packages/agebd", editable = true }
+
+[build-system]
+requires = ["hatchling"]
+build-backend = "hatchling.build"
+
+[tool.uv]
+package = true
+
+[tool.pytest.ini_options]
+pythonpath = ["src"]
+env = [
+ "AGEBD_ENV=local",
+]
+
+[tool.ruff]
+include = [
+ "src/**/*.py",
+ "tests/**/*.py",
+]
+line-length = 100
+
+[tool.ruff.lint]
+# use isort to sort imports
+extend-select = ["I"]
+
+[tool.ruff.lint.isort]
+known-first-party = ["agebd"]
diff --git a/services/injectionguard/current/app/src/agebd_injectionguard/__init__.py b/services/injectionguard/current/app/src/agebd_injectionguard/__init__.py
new file mode 100644
index 0000000..1800c27
--- /dev/null
+++ b/services/injectionguard/current/app/src/agebd_injectionguard/__init__.py
@@ -0,0 +1 @@
+from .service import PVs, Service
diff --git a/services/injectionguard/current/app/src/agebd_injectionguard/main.py b/services/injectionguard/current/app/src/agebd_injectionguard/main.py
new file mode 100644
index 0000000..afd7c4a
--- /dev/null
+++ b/services/injectionguard/current/app/src/agebd_injectionguard/main.py
@@ -0,0 +1,31 @@
+import typer
+
+from agebd.enums import LogLevel
+from agebd.runner import CallbackRunner
+from agebd.utils import init_logging
+from agebd_injectionguard import PVs, Service
+
+
+# TODO: remove: cicd test 10
+
+def main(
+ log_level: LogLevel = typer.Option(
+ LogLevel.INFO,
+ "--log-level",
+ "-l",
+ # Looks at the OS env variable first. If empty, falls back to "INFO"
+ envvar="AGEBD_LOG_LEVEL",
+ # help="Set log level: DEBUG, INFO, WARNING, ERROR, CRITICAL",
+ case_sensitive=False,
+ ),
+):
+ init_logging(log_level)
+ service_name = "INJECTIONGUARD"
+ pvs = PVs(service_name=service_name)
+ service = Service(name=service_name, pvs=pvs)
+ runner = CallbackRunner(service=service)
+ runner.start()
+
+
+if __name__ == "__main__":
+ typer.run(main)
diff --git a/services/injectionguard/current/app/src/agebd_injectionguard/service.py b/services/injectionguard/current/app/src/agebd_injectionguard/service.py
new file mode 100644
index 0000000..c816633
--- /dev/null
+++ b/services/injectionguard/current/app/src/agebd_injectionguard/service.py
@@ -0,0 +1,3984 @@
+import inspect
+from datetime import datetime
+
+import numpy as np
+
+from agebd.pv import get_pv_class
+from agebd.service.base import BaseService
+from agebd.service.pvs import BasePVs
+from agebd.utils import printgetversion
+
+__version__ = printgetversion(__file__)
+
+PV = get_pv_class()
+
+
+class PVs(BasePVs):
+ # logging pvs
+ logbook_pause = PV("AGEBD-INJECTIONGUARD:LOG-PAUSE.VAL")
+ logbook = PV("AGEBD-INJECTIONGUARD:LOG")
+ logclear = PV("AGEBD-INJECTIONGUARD:LOG-CLEAR.VAL")
+
+ # Service Callback PVs
+ CallbackPV = PV("AGETI-CVME-MASTER-TMA:Evt-Old-BO-SYN.VALA", auto_monitor=True)
+
+ # Service Check Output PVs
+ checks_output = {
+ "Beam Dump Kicker": PV("AGEBD-INJECTIONGUARD:CHECK-01.VAL"),
+ "Dump Valve": PV("AGEBD-INJECTIONGUARD:CHECK-02.VAL"),
+ "MIS": PV("AGEBD-INJECTIONGUARD:CHECK-03.VAL"),
+ "VCS": PV("AGEBD-INJECTIONGUARD:CHECK-04.VAL"),
+ "Linac KV/BB/BY": PV("AGEBD-INJECTIONGUARD:CHECK-05.VAL"),
+ "RF Linac": PV("AGEBD-INJECTIONGUARD:CHECK-06.VAL"),
+ "RF Booster": PV("AGEBD-INJECTIONGUARD:CHECK-07.VAL"),
+ "RF Ring": PV("AGEBD-INJECTIONGUARD:CHECK-08.VAL"),
+ "Magnets Pulsed": PV("AGEBD-INJECTIONGUARD:CHECK-09.VAL"),
+ "Magnets Booster": PV("AGEBD-INJECTIONGUARD:CHECK-10.VAL"),
+ "Magnets Corrector": PV("AGEBD-INJECTIONGUARD:CHECK-11.VAL"),
+ "Magnets Ring": PV("AGEBD-INJECTIONGUARD:CHECK-12.VAL"),
+ "Current Limit": PV("AGEBD-INJECTIONGUARD:CHECK-13.VAL"),
+ "IDs Ready": PV("AGEBD-INJECTIONGUARD:CHECK-14.VAL"),
+ "Single Bunch Charge": PV("AGEBD-INJECTIONGUARD:CHECK-15.VAL"),
+ "Injection Quality": PV("AGEBD-INJECTIONGUARD:CHECK-16.VAL"),
+ "Dump Quality": PV("AGEBD-INJECTIONGUARD:CHECK-17.VAL"),
+ "Lifetime": PV("AGEBD-INJECTIONGUARD:CHECK-18.VAL"),
+ "Tune": PV("AGEBD-INJECTIONGUARD:CHECK-19.VAL"),
+ "Pingers": PV("AGEBD-INJECTIONGUARD:CHECK-20.VAL"),
+ "Vacuum Pressure": PV("AGEBD-INJECTIONGUARD:CHECK-21.VAL"),
+ "Orbit Deviation": PV("AGEBD-INJECTIONGUARD:CHECK-22.VAL"),
+ "Beam Dump Controller": PV("AGEBD-INJECTIONGUARD:CHECK-23.VAL"),
+ }
+
+ checks_input = {
+ "Beam Dump Kicker": [
+ [
+ # prepare list of pv links for the first check group
+ PV("ARS01-MKIK-BD:STATUS-GROUP.VAL"),
+ PV("ARS01-MKIK-0050-1:ILK-GET-EMERGENCY.VAL"),
+ PV("ARS01-MKIK-0050-1:ILK-GET-PULSER.VAL"),
+ PV("ARS01-MKIK-0050-1:ILK-GET-VCS.VAL"),
+ PV("ARS01-MKIK-0050-1:ILK-GET-BREAKERS.VAL"),
+ PV("ARS01-MKIK-0050-1:ILK-GET-MIS.VAL"),
+ PV("ARS01-MKIK-0050-1:CTRL-VAC.VAL"),
+ PV("ARS01-MKIK-0050-1:ILK-GET-OVERLOAD.VAL"),
+ PV("ARS01-MKIK-0050-1:ILK-GET-POWERAVG.VAL"),
+ PV("ARS01-MKIK-0050-1:ILK-GET-RELAY.VAL"),
+ PV("ARS01-MKIK-0050-1:ILK-GET-ACK.VAL"),
+ PV("ARS01-MKIK-0050-1:STATUS-GET-OPT-LINK.VAL"),
+ PV("ARS01-MKIK-0050-1:CTRL-ON-OFF"),
+ PV("ARS01-MKIK-0050-1:I-SET.VAL"),
+ PV("ARS01-MKIK-0050-1:HVPS-V-SCALED.VAL"),
+ PV("ARS01-MKIK-0050-1:HVPS-V-SET.VAL"),
+ PV("ARS01-MKIK-0050-2:STATUS-GET-OPT-LINK.VAL"),
+ PV("ARS01-MKIK-0050-3:STATUS-GET-OPT-LINK.VAL"),
+ PV("ARS01-MKIK-0050-4:STATUS-GET-OPT-LINK.VAL"),
+ ],
+ [
+ # prepare list of lamda functions doing checks on vals with vals = [pv.get() for pv in links]
+ lambda vls: vls["ARS01-MKIK-BD:STATUS-GROUP.VAL"] == 1,
+ lambda vls: vls["ARS01-MKIK-0050-1:ILK-GET-EMERGENCY.VAL"] == 0,
+ lambda vls: vls["ARS01-MKIK-0050-1:ILK-GET-PULSER.VAL"] == 0,
+ lambda vls: vls["ARS01-MKIK-0050-1:ILK-GET-VCS.VAL"] == 0,
+ lambda vls: vls["ARS01-MKIK-0050-1:ILK-GET-BREAKERS.VAL"] == 0,
+ lambda vls: vls["ARS01-MKIK-0050-1:ILK-GET-MIS.VAL"] == 0,
+ lambda vls: vls["ARS01-MKIK-0050-1:CTRL-VAC.VAL"] == 0,
+ lambda vls: vls["ARS01-MKIK-0050-1:ILK-GET-OVERLOAD.VAL"] == 0,
+ lambda vls: vls["ARS01-MKIK-0050-1:ILK-GET-POWERAVG.VAL"] == 0,
+ lambda vls: vls["ARS01-MKIK-0050-1:ILK-GET-RELAY.VAL"] == 0,
+ lambda vls: vls["ARS01-MKIK-0050-1:ILK-GET-ACK.VAL"] == 0,
+ lambda vls: vls["ARS01-MKIK-0050-1:STATUS-GET-OPT-LINK.VAL"] == 0,
+ lambda vls: vls["ARS01-MKIK-0050-2:STATUS-GET-OPT-LINK.VAL"] == 0,
+ lambda vls: vls["ARS01-MKIK-0050-3:STATUS-GET-OPT-LINK.VAL"] == 0,
+ lambda vls: vls["ARS01-MKIK-0050-4:STATUS-GET-OPT-LINK.VAL"] == 0,
+ lambda vls: vls["ARS01-MKIK-0050-1:CTRL-ON-OFF"] == 1,
+ lambda vls: 5900 < vls["ARS01-MKIK-0050-1:I-SET.VAL"] < 7100,
+ lambda vls: (
+ 980 * vls["ARS01-MKIK-0050-1:HVPS-V-SET.VAL"]
+ < vls["ARS01-MKIK-0050-1:HVPS-V-SCALED.VAL"]
+ < 1020 * vls["ARS01-MKIK-0050-1:HVPS-V-SET.VAL"]
+ ),
+ ],
+ ],
+ "Dump Valve": [
+ [
+ PV("ARS01-VVPG-0210:PLC_OPEN.VAL"),
+ ],
+ [
+ lambda vls: vls["ARS01-VVPG-0210:PLC_OPEN.VAL"] == 1,
+ ],
+ ],
+ "MIS": [
+ [PV("ARS00-MIS-PLC-01:AlarmCnt.VAL")],
+ [
+ lambda vls: vls["ARS00-MIS-PLC-01:AlarmCnt.VAL"] == 0,
+ ],
+ ],
+ "VCS": [
+ [PV("ARS00-VCS:PLC_AlarmCnt.VAL")],
+ [
+ lambda vls: vls["ARS00-VCS:PLC_AlarmCnt.VAL"] == 0,
+ ],
+ ],
+ "Linac KV/BB/BY": [
+ [
+ PV("ALI00-SGEN-PSYS:ALBSA-BB-OPEN.VAL"),
+ PV("ALI00-SGEN-PSYS:ALBSA-KV-OPEN.VAL"),
+ PV("ALIMA-BY:I-READ.VAL"),
+ ],
+ [
+ lambda vls: vls["ALI00-SGEN-PSYS:ALBSA-BB-OPEN.VAL"] == 1,
+ lambda vls: vls["ALI00-SGEN-PSYS:ALBSA-KV-OPEN.VAL"] == 1,
+ lambda vls: vls["ALIMA-BY:I-READ.VAL"] < 25,
+ ],
+ ],
+ "RF Linac": [
+ [
+ PV("ALIRF-GUN:SM-HV-STATUS.VAL"),
+ PV("ALIRF-SPB:AM-VSWR.VAL"),
+ PV("ALIRF-A1-MOD:SM-RF-STATUS.VAL"),
+ PV("ALIRF-A2-MOD:SM-RF-STATUS.VAL"),
+ PV("ALIRF-A1-MOD:VHVPS-READ.VAL"),
+ PV("ALIRF-A2-MOD:VHVPS-READ.VAL"),
+ PV("ALIRF-A1-PBU:PH-SET-PosErr.VAL"), # formerly ALIRF-A1-PBU:PH-COMP
+ PV("ALIRF-A1-FBU:PH-SET-PosErr.VAL"), # formerly ALIRF-A1-FBU:PH-COMP
+ PV("ALIRF-AS-1:Ph-COMP.VAL"),
+ PV("ALIRF-AS-2:Ph-COMP.VAL"),
+ PV("ALIRF-A1-MOD:VPULSE-READ.VAL"),
+ PV("ALIRF-A2-MOD:VPULSE-READ.VAL"),
+ ],
+ [
+ lambda vls: vls["ALIRF-GUN:SM-HV-STATUS.VAL"] == 5,
+ lambda vls: vls["ALIRF-SPB:AM-VSWR.VAL"] == 1,
+ lambda vls: vls["ALIRF-A1-MOD:SM-RF-STATUS.VAL"] == 5,
+ lambda vls: vls["ALIRF-A2-MOD:SM-RF-STATUS.VAL"] == 5,
+ lambda vls: vls["ALIRF-A1-MOD:VHVPS-READ.VAL"] > 29,
+ lambda vls: vls["ALIRF-A2-MOD:VHVPS-READ.VAL"] > 32,
+ lambda vls: np.abs(vls["ALIRF-A1-PBU:PH-SET-PosErr.VAL"]) < 0.1,
+ lambda vls: np.abs(vls["ALIRF-A1-FBU:PH-SET-PosErr.VAL"]) < 0.1,
+ lambda vls: vls["ALIRF-AS-1:Ph-COMP.VAL"] < 10,
+ lambda vls: vls["ALIRF-AS-2:Ph-COMP.VAL"] < 10,
+ lambda vls: vls["ALIRF-A1-MOD:VPULSE-READ.VAL"] > 200,
+ lambda vls: vls["ALIRF-A2-MOD:VPULSE-READ.VAL"] > 200,
+ ],
+ ],
+ "RF Booster": [
+ [
+ PV("ABORF-CAV0:PU-AMPLT-MAX.VAL"),
+ PV("ABORF-ILK0:PENDINGSUM.VAL"),
+ PV("ABORF-LLE0:CTRLPHASE-E-STATUS.VAL"),
+ ],
+ [
+ lambda vls: vls["ABORF-CAV0:PU-AMPLT-MAX.VAL"] > 549.6,
+ lambda vls: vls["ABORF-ILK0:PENDINGSUM.VAL"] == 1,
+ lambda vls: vls["ABORF-LLE0:CTRLPHASE-E-STATUS.VAL"] == 1,
+ ],
+ ],
+ "RF Ring": [
+ [
+ PV("ARS05-RSYS-0060:VOLTAGE-GET.VAL"),
+ PV("ARS05-RSYS-0140:VOLTAGE-GET.VAL"),
+ PV("ARS05-RSYS-0230:VOLTAGE-GET.VAL"),
+ PV("ARS05-RSYS-0310:VOLTAGE-GET.VAL"),
+ PV("ARS05-RCCS-0060:SumILK.VAL"),
+ PV("ARS05-RCCS-0140:SumILK.VAL"),
+ PV("ARS05-RCCS-0230:SumILK.VAL"),
+ PV("ARS05-RCCS-0310:SumILK.VAL"),
+ PV("ARS05-RCCS-0060:SumILK.VAL"),
+ PV("ARS05-RCCS-0140:SumILK.VAL"),
+ PV("ARS05-RCCS-0230:SumILK.VAL"),
+ PV("ARS05-RCCS-0310:SumILK.VAL"),
+ PV("ARS05-RLLE-0060:CTRLPHASE-E-STATUS.VAL"),
+ PV("ARS05-RLLE-0140:CTRLPHASE-E-STATUS.VAL"),
+ PV("ARS05-RLLE-0230:CTRLPHASE-E-STATUS.VAL"),
+ PV("ARS05-RLLE-0310:CTRLPHASE-E-STATUS.VAL"),
+ ],
+ [
+ lambda vls: vls["ARS05-RSYS-0060:VOLTAGE-GET.VAL"] > 439.5,
+ lambda vls: vls["ARS05-RSYS-0140:VOLTAGE-GET.VAL"] > 439.5,
+ lambda vls: vls["ARS05-RSYS-0230:VOLTAGE-GET.VAL"] > 439.5,
+ lambda vls: vls["ARS05-RSYS-0310:VOLTAGE-GET.VAL"] > 439.5,
+ lambda vls: vls["ARS05-RCCS-0060:SumILK.VAL"] == 1,
+ lambda vls: vls["ARS05-RCCS-0140:SumILK.VAL"] == 1,
+ lambda vls: vls["ARS05-RCCS-0230:SumILK.VAL"] == 1,
+ lambda vls: vls["ARS05-RCCS-0310:SumILK.VAL"] == 1,
+ lambda vls: vls["ARS05-RCCS-0060:SumILK.VAL"] == 1,
+ lambda vls: vls["ARS05-RCCS-0140:SumILK.VAL"] == 1,
+ lambda vls: vls["ARS05-RCCS-0230:SumILK.VAL"] == 1,
+ lambda vls: vls["ARS05-RCCS-0310:SumILK.VAL"] == 1,
+ lambda vls: vls["ARS05-RLLE-0060:CTRLPHASE-E-STATUS.VAL"] == 1,
+ lambda vls: vls["ARS05-RLLE-0140:CTRLPHASE-E-STATUS.VAL"] == 1,
+ lambda vls: vls["ARS05-RLLE-0230:CTRLPHASE-E-STATUS.VAL"] == 1,
+ lambda vls: vls["ARS05-RLLE-0310:CTRLPHASE-E-STATUS.VAL"] == 1,
+ ],
+ ],
+ "Magnets Pulsed": [
+ [
+ # Booster Injection
+ PV("ABOMA-YIN:CTRL-ON-OFF.VAL"),
+ PV("ABOMA-KIN:CTRL-ON-OFF.VAL"),
+ PV("ABOMA-YIN:STATUS-ALL.VAL"),
+ PV("ABOMA-KIN:STATUS-ALL.VAL"),
+ PV("ABOMA-YIN:I-SET.VAL"),
+ PV("ABOMA-KIN:I-SET.VAL"),
+ PV("ABOMA-YIN:I-READ-POS.VAL"),
+ PV("ABOMA-KIN:I-READ-POS.VAL"),
+ PV("ABOMA-YIN:CTRL-CALC-LED.VAL"),
+ PV("ABOMA-KIN:CTRL-CALC-LED.VAL"),
+ # Booster Extraction
+ PV("ABOMA-KEX:CTRL-ON-OFF.VAL"),
+ PV("ABOMA-YEX:CTRL-ON-OFF.VAL"),
+ PV("ABOMA-KEX:STATUS-ALL.VAL"),
+ PV("ABOMA-YEX:STATUS-ALL.VAL"),
+ PV("ABOMA-KEX:I-SET.VAL"),
+ PV("ABOMA-YEX:I-SET.VAL"),
+ PV("ABOMA-KEX:I-READ-POS.VAL"),
+ PV("ABOMA-YEX:I-READ-POS.VAL"),
+ PV("ABOMA-KEX:CTRL-CALC-LED.VAL"),
+ PV("ABOMA-YEX:CTRL-CALC-LED.VAL"),
+ # Ring Injection
+ PV("ARS01-MSEP-0670:CTRL-ON-OFF.VAL"),
+ PV("ARS01-MKIK1-4:AMP-ON-OFF.VAL"),
+ PV("ARS01-MKIK-0140:CTRL-ON-OFF.VAL"),
+ PV("ARS01-MKIK-0220:CTRL-ON-OFF.VAL"),
+ PV("ARS01-MKIK-0850:CTRL-ON-OFF.VAL"),
+ PV("ARS01-MKIK-0940:CTRL-ON-OFF.VAL"),
+ PV("ARS01-MSEP-0670:STATUS-ALL.VAL"),
+ PV("ARS01-MKIK1-4:STATUS-GROUP.VAL"),
+ PV("ARS01-MKIK-0140:STATUS-ALL.VAL"),
+ PV("ARS01-MKIK-0220:STATUS-ALL.VAL"),
+ PV("ARS01-MKIK-0850:STATUS-ALL.VAL"),
+ PV("ARS01-MKIK-0940:STATUS-ALL.VAL"),
+ PV("ARS01-MSEP-0670:I-SET.VAL"),
+ PV("ARS01-MKIK-0140:I-SET.VAL"),
+ PV("ARS01-MKIK-0220:I-SET.VAL"),
+ PV("ARS01-MKIK-0850:I-SET.VAL"),
+ PV("ARS01-MKIK-0940:I-SET.VAL"),
+ PV("ARS01-MSEP-0670:I-READ-POS.VAL"),
+ PV("ARS01-MKIK-0140:I-READ-POS.VAL"),
+ PV("ARS01-MKIK-0220:I-READ-POS.VAL"),
+ PV("ARS01-MKIK-0850:I-READ-POS.VAL"),
+ PV("ARS01-MKIK-0940:I-READ-POS.VAL"),
+ PV("ARS01-MSEP-0670:CTRL-CALC-LED.VAL"),
+ PV("ARS01-MKIK-0140:CTRL-CALC-LED.VAL"),
+ PV("ARS01-MKIK-0220:CTRL-CALC-LED.VAL"),
+ PV("ARS01-MKIK-0850:CTRL-CALC-LED.VAL"),
+ PV("ARS01-MKIK-0940:CTRL-CALC-LED.VAL"),
+ ],
+ [
+ # Booster Injection
+ lambda vls: vls["ABOMA-YIN:CTRL-ON-OFF.VAL"] == 1,
+ lambda vls: vls["ABOMA-KIN:CTRL-ON-OFF.VAL"] == 1,
+ lambda vls: vls["ABOMA-YIN:STATUS-ALL.VAL"] == 1,
+ lambda vls: vls["ABOMA-KIN:STATUS-ALL.VAL"] == 1,
+ lambda vls: (
+ 0.9 * vls["ABOMA-YIN:I-SET.VAL"]
+ < vls["ABOMA-YIN:I-READ-POS.VAL"]
+ < 1.1 * vls["ABOMA-YIN:I-SET.VAL"]
+ ),
+ lambda vls: (
+ 0.9 * vls["ABOMA-KIN:I-SET.VAL"]
+ < vls["ABOMA-KIN:I-READ-POS.VAL"]
+ < 1.1 * vls["ABOMA-KIN:I-SET.VAL"]
+ ),
+ lambda vls: vls["ABOMA-YIN:CTRL-CALC-LED.VAL"] == 1,
+ lambda vls: vls["ABOMA-KIN:CTRL-CALC-LED.VAL"] == 1,
+ # Booster Extraction
+ lambda vls: vls["ABOMA-KEX:CTRL-ON-OFF.VAL"] == 1,
+ lambda vls: vls["ABOMA-YEX:CTRL-ON-OFF.VAL"] == 1,
+ lambda vls: vls["ABOMA-KEX:STATUS-ALL.VAL"] == 1,
+ lambda vls: vls["ABOMA-YEX:STATUS-ALL.VAL"] == 1,
+ lambda vls: (
+ 0.9 * vls["ABOMA-KEX:I-SET.VAL"]
+ < vls["ABOMA-KEX:I-READ-POS.VAL"]
+ < 1.1 * vls["ABOMA-KEX:I-SET.VAL"]
+ ),
+ lambda vls: (
+ 0.9 * vls["ABOMA-YEX:I-SET.VAL"]
+ < vls["ABOMA-YEX:I-READ-POS.VAL"]
+ < 1.1 * vls["ABOMA-YEX:I-SET.VAL"]
+ ),
+ lambda vls: vls["ABOMA-KEX:CTRL-CALC-LED.VAL"] == 1,
+ lambda vls: vls["ABOMA-YEX:CTRL-CALC-LED.VAL"] == 1,
+ # Ring Injection
+ lambda vls: vls["ARS01-MSEP-0670:CTRL-ON-OFF.VAL"] == 1,
+ lambda vls: vls["ARS01-MKIK1-4:AMP-ON-OFF.VAL"] == 1,
+ lambda vls: vls["ARS01-MKIK-0140:CTRL-ON-OFF.VAL"] == 1,
+ lambda vls: vls["ARS01-MKIK-0220:CTRL-ON-OFF.VAL"] == 1,
+ lambda vls: vls["ARS01-MKIK-0850:CTRL-ON-OFF.VAL"] == 1,
+ lambda vls: vls["ARS01-MKIK-0940:CTRL-ON-OFF.VAL"] == 1,
+ lambda vls: vls["ARS01-MSEP-0670:STATUS-ALL.VAL"] == 1,
+ lambda vls: vls["ARS01-MKIK1-4:STATUS-GROUP.VAL"] == 1,
+ lambda vls: vls["ARS01-MKIK-0140:STATUS-ALL.VAL"] == 1,
+ lambda vls: vls["ARS01-MKIK-0220:STATUS-ALL.VAL"] == 1,
+ lambda vls: vls["ARS01-MKIK-0850:STATUS-ALL.VAL"] == 1,
+ lambda vls: vls["ARS01-MKIK-0940:STATUS-ALL.VAL"] == 1,
+ lambda vls: (
+ 0.9 * vls["ARS01-MSEP-0670:I-SET.VAL"]
+ < vls["ARS01-MSEP-0670:I-READ-POS.VAL"]
+ < 1.1 * vls["ARS01-MSEP-0670:I-SET.VAL"]
+ ),
+ lambda vls: (
+ 0.9 * vls["ARS01-MKIK-0140:I-SET.VAL"]
+ < vls["ARS01-MKIK-0140:I-READ-POS.VAL"]
+ < 1.1 * vls["ARS01-MKIK-0140:I-SET.VAL"]
+ ),
+ lambda vls: (
+ 0.9 * vls["ARS01-MKIK-0220:I-SET.VAL"]
+ < vls["ARS01-MKIK-0220:I-READ-POS.VAL"]
+ < 1.1 * vls["ARS01-MKIK-0220:I-SET.VAL"]
+ ),
+ lambda vls: (
+ 0.9 * vls["ARS01-MKIK-0850:I-SET.VAL"]
+ < vls["ARS01-MKIK-0850:I-READ-POS.VAL"]
+ < 1.1 * vls["ARS01-MKIK-0850:I-SET.VAL"]
+ ),
+ lambda vls: (
+ 0.9 * vls["ARS01-MKIK-0940:I-SET.VAL"]
+ < vls["ARS01-MKIK-0940:I-READ-POS.VAL"]
+ < 1.1 * vls["ARS01-MKIK-0940:I-SET.VAL"]
+ ),
+ lambda vls: vls["ARS01-MSEP-0670:CTRL-CALC-LED.VAL"] == 1,
+ lambda vls: vls["ARS01-MKIK-0140:CTRL-CALC-LED.VAL"] == 1,
+ lambda vls: vls["ARS01-MKIK-0220:CTRL-CALC-LED.VAL"] == 1,
+ lambda vls: vls["ARS01-MKIK-0850:CTRL-CALC-LED.VAL"] == 1,
+ lambda vls: vls["ARS01-MKIK-0940:CTRL-CALC-LED.VAL"] == 1,
+ ],
+ ],
+ "Magnets Booster": [
+ [
+ PV("ABOMA-B:PS-MODE.VAL"),
+ PV("ABOMA-CBF:PS-MODE.VAL"),
+ PV("ABOMA-QD:PS-MODE.VAL"),
+ PV("ABOMA-QE:PS-MODE.VAL"),
+ PV("ABOMA-QF:PS-MODE.VAL"),
+ PV("ABOMA-SD:PS-MODE.VAL"),
+ PV("ABOMA-SF:PS-MODE.VAL"),
+ PV("ABOMA-CH-1A:PS-MODE.VAL"),
+ PV("ABOMA-CH-1B:PS-MODE.VAL"),
+ PV("ABOMA-CH-1C:PS-MODE.VAL"),
+ PV("ABOMA-CH-1D:PS-MODE.VAL"),
+ PV("ABOMA-CH-1E:PS-MODE.VAL"),
+ PV("ABOMA-CH-1F:PS-MODE.VAL"),
+ PV("ABOMA-CH-1G:PS-MODE.VAL"),
+ PV("ABOMA-CH-1H:PS-MODE.VAL"),
+ PV("ABOMA-CH-1S:PS-MODE.VAL"),
+ PV("ABOMA-CH-2A:PS-MODE.VAL"),
+ PV("ABOMA-CH-2B:PS-MODE.VAL"),
+ PV("ABOMA-CH-2C:PS-MODE.VAL"),
+ PV("ABOMA-CH-2D:PS-MODE.VAL"),
+ PV("ABOMA-CH-2E:PS-MODE.VAL"),
+ PV("ABOMA-CH-2F:PS-MODE.VAL"),
+ PV("ABOMA-CH-2G:PS-MODE.VAL"),
+ PV("ABOMA-CH-2H:PS-MODE.VAL"),
+ PV("ABOMA-CH-2S:PS-MODE.VAL"),
+ PV("ABOMA-CH-3A:PS-MODE.VAL"),
+ PV("ABOMA-CH-3B:PS-MODE.VAL"),
+ PV("ABOMA-CH-3C:PS-MODE.VAL"),
+ PV("ABOMA-CH-3D:PS-MODE.VAL"),
+ PV("ABOMA-CH-3E:PS-MODE.VAL"),
+ PV("ABOMA-CH-3F:PS-MODE.VAL"),
+ PV("ABOMA-CH-3G:PS-MODE.VAL"),
+ PV("ABOMA-CH-3H:PS-MODE.VAL"),
+ PV("ABOMA-CH-3S:PS-MODE.VAL"),
+ PV("ABOMA-CH-4A:PS-MODE.VAL"),
+ PV("ABOMA-CH-4B:PS-MODE.VAL"),
+ PV("ABOMA-CH-4C:PS-MODE.VAL"),
+ PV("ABOMA-CH-4D:PS-MODE.VAL"),
+ PV("ABOMA-CH-4E:PS-MODE.VAL"),
+ PV("ABOMA-CH-4F:PS-MODE.VAL"),
+ PV("ABOMA-CH-4G:PS-MODE.VAL"),
+ PV("ABOMA-CH-4H:PS-MODE.VAL"),
+ PV("ABOMA-CH-4S:PS-MODE.VAL"),
+ PV("ABOMA-CH-5A:PS-MODE.VAL"),
+ PV("ABOMA-CH-5B:PS-MODE.VAL"),
+ PV("ABOMA-CH-5C:PS-MODE.VAL"),
+ PV("ABOMA-CH-5D:PS-MODE.VAL"),
+ PV("ABOMA-CH-5E:PS-MODE.VAL"),
+ PV("ABOMA-CH-5F:PS-MODE.VAL"),
+ PV("ABOMA-CH-5G:PS-MODE.VAL"),
+ PV("ABOMA-CH-5H:PS-MODE.VAL"),
+ PV("ABOMA-CH-5S:PS-MODE.VAL"),
+ PV("ABOMA-CH-6A:PS-MODE.VAL"),
+ PV("ABOMA-CH-6B:PS-MODE.VAL"),
+ PV("ABOMA-CH-6C:PS-MODE.VAL"),
+ PV("ABOMA-CH-6D:PS-MODE.VAL"),
+ PV("ABOMA-CH-6E:PS-MODE.VAL"),
+ PV("ABOMA-CH-6F:PS-MODE.VAL"),
+ PV("ABOMA-CH-6G:PS-MODE.VAL"),
+ PV("ABOMA-CH-6H:PS-MODE.VAL"),
+ PV("ABOMA-CH-6S:PS-MODE.VAL"),
+ PV("ABOMA-CV-1A:PS-MODE.VAL"),
+ PV("ABOMA-CV-1B:PS-MODE.VAL"),
+ PV("ABOMA-CV-1C:PS-MODE.VAL"),
+ PV("ABOMA-CV-1D:PS-MODE.VAL"),
+ PV("ABOMA-CV-1E:PS-MODE.VAL"),
+ PV("ABOMA-CV-1F:PS-MODE.VAL"),
+ PV("ABOMA-CV-1G:PS-MODE.VAL"),
+ PV("ABOMA-CV-1H:PS-MODE.VAL"),
+ PV("ABOMA-CV-1S:PS-MODE.VAL"),
+ PV("ABOMA-CV-2A:PS-MODE.VAL"),
+ PV("ABOMA-CV-2B:PS-MODE.VAL"),
+ PV("ABOMA-CV-2C:PS-MODE.VAL"),
+ PV("ABOMA-CV-2D:PS-MODE.VAL"),
+ PV("ABOMA-CV-2E:PS-MODE.VAL"),
+ PV("ABOMA-CV-2F:PS-MODE.VAL"),
+ PV("ABOMA-CV-2G:PS-MODE.VAL"),
+ PV("ABOMA-CV-2H:PS-MODE.VAL"),
+ PV("ABOMA-CV-2S:PS-MODE.VAL"),
+ PV("ABOMA-CV-3A:PS-MODE.VAL"),
+ PV("ABOMA-CV-3B:PS-MODE.VAL"),
+ PV("ABOMA-CV-3C:PS-MODE.VAL"),
+ PV("ABOMA-CV-3D:PS-MODE.VAL"),
+ PV("ABOMA-CV-3E:PS-MODE.VAL"),
+ PV("ABOMA-CV-3F:PS-MODE.VAL"),
+ PV("ABOMA-CV-3G:PS-MODE.VAL"),
+ PV("ABOMA-CV-3H:PS-MODE.VAL"),
+ PV("ABOMA-CV-3S:PS-MODE.VAL"),
+ PV("ABOMA-CV-4A:PS-MODE.VAL"),
+ PV("ABOMA-CV-4B:PS-MODE.VAL"),
+ PV("ABOMA-CV-4C:PS-MODE.VAL"),
+ PV("ABOMA-CV-4D:PS-MODE.VAL"),
+ PV("ABOMA-CV-4E:PS-MODE.VAL"),
+ PV("ABOMA-CV-4F:PS-MODE.VAL"),
+ PV("ABOMA-CV-4G:PS-MODE.VAL"),
+ PV("ABOMA-CV-4H:PS-MODE.VAL"),
+ PV("ABOMA-CV-4S:PS-MODE.VAL"),
+ PV("ABOMA-CV-5A:PS-MODE.VAL"),
+ PV("ABOMA-CV-5B:PS-MODE.VAL"),
+ PV("ABOMA-CV-5C:PS-MODE.VAL"),
+ PV("ABOMA-CV-5D:PS-MODE.VAL"),
+ PV("ABOMA-CV-5E:PS-MODE.VAL"),
+ PV("ABOMA-CV-5F:PS-MODE.VAL"),
+ PV("ABOMA-CV-5G:PS-MODE.VAL"),
+ PV("ABOMA-CV-5H:PS-MODE.VAL"),
+ PV("ABOMA-CV-5S:PS-MODE.VAL"),
+ PV("ABOMA-CV-6A:PS-MODE.VAL"),
+ PV("ABOMA-CV-6B:PS-MODE.VAL"),
+ PV("ABOMA-CV-6C:PS-MODE.VAL"),
+ PV("ABOMA-CV-6D:PS-MODE.VAL"),
+ PV("ABOMA-CV-6E:PS-MODE.VAL"),
+ PV("ABOMA-CV-6F:PS-MODE.VAL"),
+ PV("ABOMA-CV-6G:PS-MODE.VAL"),
+ PV("ABOMA-CV-6H:PS-MODE.VAL"),
+ PV("ABOMA-CV-6S:PS-MODE.VAL"),
+ PV("ABOMA-B:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CBF:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-QD:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-QE:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-QF:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-SD:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-SF:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-1A:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-1B:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-1C:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-1D:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-1E:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-1F:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-1G:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-1H:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-1S:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-2A:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-2B:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-2C:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-2D:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-2E:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-2F:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-2G:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-2H:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-2S:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-3A:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-3B:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-3C:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-3D:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-3E:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-3F:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-3G:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-3H:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-3S:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-4A:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-4B:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-4C:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-4D:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-4E:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-4F:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-4G:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-4H:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-4S:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-5A:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-5B:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-5C:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-5D:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-5E:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-5F:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-5G:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-5H:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-5S:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-6A:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-6B:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-6C:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-6D:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-6E:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-6F:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-6G:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-6H:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CH-6S:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-1A:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-1B:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-1C:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-1D:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-1E:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-1F:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-1G:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-1H:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-1S:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-2A:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-2B:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-2C:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-2D:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-2E:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-2F:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-2G:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-2H:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-2S:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-3A:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-3B:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-3C:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-3D:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-3E:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-3F:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-3G:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-3H:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-3S:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-4A:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-4B:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-4C:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-4D:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-4E:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-4F:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-4G:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-4H:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-4S:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-5A:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-5B:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-5C:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-5D:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-5E:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-5F:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-5G:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-5H:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-5S:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-6A:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-6B:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-6C:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-6D:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-6E:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-6F:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-6G:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-6H:IW-ACTWF-RB.VAL"),
+ PV("ABOMA-CV-6S:IW-ACTWF-RB.VAL"),
+ ],
+ [
+ lambda vls: vls["ABOMA-B:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CBF:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-QD:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-QE:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-QF:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-SD:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-SF:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-1A:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-1B:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-1C:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-1D:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-1E:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-1F:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-1G:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-1H:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-1S:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-2A:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-2B:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-2C:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-2D:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-2E:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-2F:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-2G:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-2H:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-2S:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-3A:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-3B:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-3C:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-3D:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-3E:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-3F:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-3G:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-3H:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-3S:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-4A:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-4B:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-4C:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-4D:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-4E:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-4F:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-4G:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-4H:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-4S:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-5A:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-5B:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-5C:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-5D:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-5E:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-5F:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-5G:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-5H:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-5S:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-6A:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-6B:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-6C:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-6D:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-6E:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-6F:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-6G:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-6H:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CH-6S:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-1A:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-1B:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-1C:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-1D:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-1E:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-1F:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-1G:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-1H:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-1S:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-2A:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-2B:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-2C:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-2D:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-2E:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-2F:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-2G:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-2H:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-2S:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-3A:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-3B:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-3C:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-3D:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-3E:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-3F:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-3G:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-3H:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-3S:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-4A:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-4B:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-4C:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-4D:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-4E:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-4F:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-4G:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-4H:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-4S:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-5A:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-5B:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-5C:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-5D:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-5E:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-5F:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-5G:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-5H:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-5S:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-6A:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-6B:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-6C:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-6D:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-6E:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-6F:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-6G:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-6H:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-CV-6S:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ABOMA-B:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CBF:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-QD:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-QE:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-QF:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-SD:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-SF:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-1A:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-1B:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-1C:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-1D:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-1E:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-1F:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-1G:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-1H:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-1S:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-2A:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-2B:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-2C:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-2D:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-2E:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-2F:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-2G:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-2H:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-2S:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-3A:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-3B:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-3C:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-3D:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-3E:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-3F:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-3G:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-3H:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-3S:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-4A:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-4B:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-4C:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-4D:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-4E:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-4F:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-4G:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-4H:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-4S:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-5A:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-5B:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-5C:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-5D:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-5E:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-5F:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-5G:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-5H:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-5S:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-6A:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-6B:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-6C:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-6D:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-6E:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-6F:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-6G:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-6H:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CH-6S:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-1A:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-1B:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-1C:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-1D:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-1E:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-1F:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-1G:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-1H:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-1S:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-2A:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-2B:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-2C:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-2D:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-2E:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-2F:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-2G:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-2H:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-2S:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-3A:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-3B:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-3C:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-3D:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-3E:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-3F:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-3G:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-3H:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-3S:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-4A:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-4B:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-4C:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-4D:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-4E:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-4F:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-4G:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-4H:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-4S:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-5A:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-5B:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-5C:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-5D:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-5E:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-5F:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-5G:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-5H:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-5S:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-6A:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-6B:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-6C:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-6D:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-6E:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-6F:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-6G:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-6H:IW-ACTWF-RB.VAL"] == 1,
+ lambda vls: vls["ABOMA-CV-6S:IW-ACTWF-RB.VAL"] == 1,
+ ],
+ ],
+ "Magnets Corrector": [
+ [
+ PV("ARS01-MCOX-0410:PS-MODE.VAL"),
+ PV("ARS01-MCOX-0740:PS-MODE.VAL"),
+ PV("ARS01-MCOX-1090:PS-MODE.VAL"),
+ PV("ARS01-MCOX-1470:PS-MODE.VAL"),
+ PV("ARS01-MCOX-1910:PS-MODE.VAL"),
+ PV("ARS01-MCOX-2420:PS-MODE.VAL"),
+ PV("ARS01-MCOX-2920:PS-MODE.VAL"),
+ PV("ARS01-MCOX-4230:PS-MODE.VAL"),
+ PV("ARS01-MCOX-4730:PS-MODE.VAL"),
+ PV("ARS01-MCOX-5260:PS-MODE.VAL"),
+ PV("ARS01-MCOX-5890:PS-MODE.VAL"),
+ PV("ARS02-MCOX-1090:PS-MODE.VAL"),
+ PV("ARS02-MCOX-1470:PS-MODE.VAL"),
+ PV("ARS02-MCOX-1910:PS-MODE.VAL"),
+ PV("ARS02-MCOX-2420:PS-MODE.VAL"),
+ PV("ARS02-MCOX-2920:PS-MODE.VAL"),
+ PV("ARS02-MCOX-4230:PS-MODE.VAL"),
+ PV("ARS02-MCOX-4730:PS-MODE.VAL"),
+ PV("ARS02-MCOX-5260:PS-MODE.VAL"),
+ PV("ARS02-MCOX-5890:PS-MODE.VAL"),
+ PV("ARS03-MCOX-0820:PS-MODE.VAL"),
+ PV("ARS03-MCOX-1090:PS-MODE.VAL"),
+ PV("ARS03-MCOX-1470:PS-MODE.VAL"),
+ PV("ARS03-MCOX-1910:PS-MODE.VAL"),
+ PV("ARS03-MCOX-2420:PS-MODE.VAL"),
+ PV("ARS03-MCOX-2920:PS-MODE.VAL"),
+ PV("ARS03-MCOX-4230:PS-MODE.VAL"),
+ PV("ARS03-MCOX-4730:PS-MODE.VAL"),
+ PV("ARS03-MCOX-5260:PS-MODE.VAL"),
+ PV("ARS03-MCOX-5890:PS-MODE.VAL"),
+ PV("ARS04-MCOX-1090:PS-MODE.VAL"),
+ PV("ARS04-MCOX-1470:PS-MODE.VAL"),
+ PV("ARS04-MCOX-1910:PS-MODE.VAL"),
+ PV("ARS04-MCOX-2420:PS-MODE.VAL"),
+ PV("ARS04-MCOX-2920:PS-MODE.VAL"),
+ PV("ARS04-MCOX-4230:PS-MODE.VAL"),
+ PV("ARS04-MCOX-4730:PS-MODE.VAL"),
+ PV("ARS04-MCOX-5260:PS-MODE.VAL"),
+ PV("ARS04-MCOX-5890:PS-MODE.VAL"),
+ PV("ARS05-MCOX-0420:PS-MODE.VAL"),
+ PV("ARS05-MCOX-1090:PS-MODE.VAL"),
+ PV("ARS05-MCOX-1470:PS-MODE.VAL"),
+ PV("ARS05-MCOX-1910:PS-MODE.VAL"),
+ PV("ARS05-MCOX-2420:PS-MODE.VAL"),
+ PV("ARS05-MCOX-2920:PS-MODE.VAL"),
+ PV("ARS05-MCOX-4230:PS-MODE.VAL"),
+ PV("ARS05-MCOX-4730:PS-MODE.VAL"),
+ PV("ARS05-MCOX-5260:PS-MODE.VAL"),
+ PV("ARS05-MCOX-5890:PS-MODE.VAL"),
+ PV("ARS06-MCOX-1090:PS-MODE.VAL"),
+ PV("ARS06-MCOX-1470:PS-MODE.VAL"),
+ PV("ARS06-MCOX-1910:PS-MODE.VAL"),
+ PV("ARS06-MCOX-2420:PS-MODE.VAL"),
+ PV("ARS06-MCOX-2920:PS-MODE.VAL"),
+ PV("ARS06-MCOX-4230:PS-MODE.VAL"),
+ PV("ARS06-MCOX-4730:PS-MODE.VAL"),
+ PV("ARS06-MCOX-5260:PS-MODE.VAL"),
+ PV("ARS06-MCOX-5890:PS-MODE.VAL"),
+ PV("ARS07-MCOX-0820:PS-MODE.VAL"),
+ PV("ARS07-MCOX-1090:PS-MODE.VAL"),
+ PV("ARS07-MCOX-1470:PS-MODE.VAL"),
+ PV("ARS07-MCOX-1910:PS-MODE.VAL"),
+ PV("ARS07-MCOX-2420:PS-MODE.VAL"),
+ PV("ARS07-MCOX-2920:PS-MODE.VAL"),
+ PV("ARS07-MCOX-4230:PS-MODE.VAL"),
+ PV("ARS07-MCOX-4730:PS-MODE.VAL"),
+ PV("ARS07-MCOX-5260:PS-MODE.VAL"),
+ PV("ARS07-MCOX-5890:PS-MODE.VAL"),
+ PV("ARS08-MCOX-1090:PS-MODE.VAL"),
+ PV("ARS08-MCOX-1470:PS-MODE.VAL"),
+ PV("ARS08-MCOX-1910:PS-MODE.VAL"),
+ PV("ARS08-MCOX-2420:PS-MODE.VAL"),
+ PV("ARS08-MCOX-2920:PS-MODE.VAL"),
+ PV("ARS08-MCOX-4230:PS-MODE.VAL"),
+ PV("ARS08-MCOX-4730:PS-MODE.VAL"),
+ PV("ARS08-MCOX-5260:PS-MODE.VAL"),
+ PV("ARS08-MCOX-5890:PS-MODE.VAL"),
+ PV("ARS09-MCOX-0580:PS-MODE.VAL"),
+ PV("ARS09-MCOX-1090:PS-MODE.VAL"),
+ PV("ARS09-MCOX-1470:PS-MODE.VAL"),
+ PV("ARS09-MCOX-1910:PS-MODE.VAL"),
+ PV("ARS09-MCOX-2420:PS-MODE.VAL"),
+ PV("ARS09-MCOX-2920:PS-MODE.VAL"),
+ PV("ARS09-MCOX-4230:PS-MODE.VAL"),
+ PV("ARS09-MCOX-4730:PS-MODE.VAL"),
+ PV("ARS09-MCOX-5260:PS-MODE.VAL"),
+ PV("ARS09-MCOX-5890:PS-MODE.VAL"),
+ PV("ARS10-MCOX-1090:PS-MODE.VAL"),
+ PV("ARS10-MCOX-1470:PS-MODE.VAL"),
+ PV("ARS10-MCOX-1910:PS-MODE.VAL"),
+ PV("ARS10-MCOX-2420:PS-MODE.VAL"),
+ PV("ARS10-MCOX-2920:PS-MODE.VAL"),
+ PV("ARS10-MCOX-4230:PS-MODE.VAL"),
+ PV("ARS10-MCOX-4730:PS-MODE.VAL"),
+ PV("ARS10-MCOX-5260:PS-MODE.VAL"),
+ PV("ARS10-MCOX-5890:PS-MODE.VAL"),
+ PV("ARS11-MCOX-0860:PS-MODE.VAL"),
+ PV("ARS11-MCOX-1090:PS-MODE.VAL"),
+ PV("ARS11-MCOX-1470:PS-MODE.VAL"),
+ PV("ARS11-MCOX-1910:PS-MODE.VAL"),
+ PV("ARS11-MCOX-2420:PS-MODE.VAL"),
+ PV("ARS11-MCOX-2920:PS-MODE.VAL"),
+ PV("ARS11-MCOX-4230:PS-MODE.VAL"),
+ PV("ARS11-MCOX-4730:PS-MODE.VAL"),
+ PV("ARS11-MCOX-5260:PS-MODE.VAL"),
+ PV("ARS11-MCOX-5890:PS-MODE.VAL"),
+ PV("ARS12-MCOX-1090:PS-MODE.VAL"),
+ PV("ARS12-MCOX-1470:PS-MODE.VAL"),
+ PV("ARS12-MCOX-1910:PS-MODE.VAL"),
+ PV("ARS12-MCOX-2420:PS-MODE.VAL"),
+ PV("ARS12-MCOX-2920:PS-MODE.VAL"),
+ PV("ARS12-MCOX-4230:PS-MODE.VAL"),
+ PV("ARS12-MCOX-4730:PS-MODE.VAL"),
+ PV("ARS12-MCOX-5260:PS-MODE.VAL"),
+ PV("ARS12-MCOX-5890:PS-MODE.VAL"),
+ PV("ARS01-MCOY-0400:PS-MODE.VAL"),
+ PV("ARS01-MCOY-0750:PS-MODE.VAL"),
+ PV("ARS01-MCOY-1110:PS-MODE.VAL"),
+ PV("ARS01-MCOY-1490:PS-MODE.VAL"),
+ PV("ARS01-MCOY-1930:PS-MODE.VAL"),
+ PV("ARS01-MCOY-2430:PS-MODE.VAL"),
+ PV("ARS01-MCOY-2930:PS-MODE.VAL"),
+ PV("ARS01-MCOY-4240:PS-MODE.VAL"),
+ PV("ARS01-MCOY-4740:PS-MODE.VAL"),
+ PV("ARS01-MCOY-5270:PS-MODE.VAL"),
+ PV("ARS01-MCOY-5900:PS-MODE.VAL"),
+ PV("ARS02-MCOY-1110:PS-MODE.VAL"),
+ PV("ARS02-MCOY-1490:PS-MODE.VAL"),
+ PV("ARS02-MCOY-1930:PS-MODE.VAL"),
+ PV("ARS02-MCOY-2430:PS-MODE.VAL"),
+ PV("ARS02-MCOY-2930:PS-MODE.VAL"),
+ PV("ARS02-MCOY-4240:PS-MODE.VAL"),
+ PV("ARS02-MCOY-4740:PS-MODE.VAL"),
+ PV("ARS02-MCOY-5270:PS-MODE.VAL"),
+ PV("ARS02-MCOY-5900:PS-MODE.VAL"),
+ PV("ARS03-MCOY-0830:PS-MODE.VAL"),
+ PV("ARS03-MCOY-1110:PS-MODE.VAL"),
+ PV("ARS03-MCOY-1490:PS-MODE.VAL"),
+ PV("ARS03-MCOY-1930:PS-MODE.VAL"),
+ PV("ARS03-MCOY-2430:PS-MODE.VAL"),
+ PV("ARS03-MCOY-2930:PS-MODE.VAL"),
+ PV("ARS03-MCOY-4240:PS-MODE.VAL"),
+ PV("ARS03-MCOY-4740:PS-MODE.VAL"),
+ PV("ARS03-MCOY-5270:PS-MODE.VAL"),
+ PV("ARS03-MCOY-5900:PS-MODE.VAL"),
+ PV("ARS04-MCOY-1110:PS-MODE.VAL"),
+ PV("ARS04-MCOY-1490:PS-MODE.VAL"),
+ PV("ARS04-MCOY-1930:PS-MODE.VAL"),
+ PV("ARS04-MCOY-2430:PS-MODE.VAL"),
+ PV("ARS04-MCOY-2930:PS-MODE.VAL"),
+ PV("ARS04-MCOY-4240:PS-MODE.VAL"),
+ PV("ARS04-MCOY-4740:PS-MODE.VAL"),
+ PV("ARS04-MCOY-5270:PS-MODE.VAL"),
+ PV("ARS04-MCOY-5900:PS-MODE.VAL"),
+ PV("ARS05-MCOY-0430:PS-MODE.VAL"),
+ PV("ARS05-MCOY-1110:PS-MODE.VAL"),
+ PV("ARS05-MCOY-1490:PS-MODE.VAL"),
+ PV("ARS05-MCOY-1930:PS-MODE.VAL"),
+ PV("ARS05-MCOY-2430:PS-MODE.VAL"),
+ PV("ARS05-MCOY-2930:PS-MODE.VAL"),
+ PV("ARS05-MCOY-4240:PS-MODE.VAL"),
+ PV("ARS05-MCOY-4740:PS-MODE.VAL"),
+ PV("ARS05-MCOY-5270:PS-MODE.VAL"),
+ PV("ARS05-MCOY-5900:PS-MODE.VAL"),
+ PV("ARS06-MCOY-1110:PS-MODE.VAL"),
+ PV("ARS06-MCOY-1490:PS-MODE.VAL"),
+ PV("ARS06-MCOY-1930:PS-MODE.VAL"),
+ PV("ARS06-MCOY-2430:PS-MODE.VAL"),
+ PV("ARS06-MCOY-2930:PS-MODE.VAL"),
+ PV("ARS06-MCOY-4240:PS-MODE.VAL"),
+ PV("ARS06-MCOY-4740:PS-MODE.VAL"),
+ PV("ARS06-MCOY-5270:PS-MODE.VAL"),
+ PV("ARS06-MCOY-5900:PS-MODE.VAL"),
+ PV("ARS07-MCOY-0830:PS-MODE.VAL"),
+ PV("ARS07-MCOY-1110:PS-MODE.VAL"),
+ PV("ARS07-MCOY-1490:PS-MODE.VAL"),
+ PV("ARS07-MCOY-1930:PS-MODE.VAL"),
+ PV("ARS07-MCOY-2430:PS-MODE.VAL"),
+ PV("ARS07-MCOY-2930:PS-MODE.VAL"),
+ PV("ARS07-MCOY-4240:PS-MODE.VAL"),
+ PV("ARS07-MCOY-4740:PS-MODE.VAL"),
+ PV("ARS07-MCOY-5270:PS-MODE.VAL"),
+ PV("ARS07-MCOY-5900:PS-MODE.VAL"),
+ PV("ARS08-MCOY-1110:PS-MODE.VAL"),
+ PV("ARS08-MCOY-1490:PS-MODE.VAL"),
+ PV("ARS08-MCOY-1930:PS-MODE.VAL"),
+ PV("ARS08-MCOY-2430:PS-MODE.VAL"),
+ PV("ARS08-MCOY-2930:PS-MODE.VAL"),
+ PV("ARS08-MCOY-4240:PS-MODE.VAL"),
+ PV("ARS08-MCOY-4740:PS-MODE.VAL"),
+ PV("ARS08-MCOY-5270:PS-MODE.VAL"),
+ PV("ARS08-MCOY-5900:PS-MODE.VAL"),
+ PV("ARS09-MCOY-0590:PS-MODE.VAL"),
+ PV("ARS09-MCOY-1110:PS-MODE.VAL"),
+ PV("ARS09-MCOY-1490:PS-MODE.VAL"),
+ PV("ARS09-MCOY-1930:PS-MODE.VAL"),
+ PV("ARS09-MCOY-2430:PS-MODE.VAL"),
+ PV("ARS09-MCOY-2930:PS-MODE.VAL"),
+ PV("ARS09-MCOY-4240:PS-MODE.VAL"),
+ PV("ARS09-MCOY-4740:PS-MODE.VAL"),
+ PV("ARS09-MCOY-5270:PS-MODE.VAL"),
+ PV("ARS09-MCOY-5900:PS-MODE.VAL"),
+ PV("ARS10-MCOY-1110:PS-MODE.VAL"),
+ PV("ARS10-MCOY-1490:PS-MODE.VAL"),
+ PV("ARS10-MCOY-1930:PS-MODE.VAL"),
+ PV("ARS10-MCOY-2430:PS-MODE.VAL"),
+ PV("ARS10-MCOY-2930:PS-MODE.VAL"),
+ PV("ARS10-MCOY-4240:PS-MODE.VAL"),
+ PV("ARS10-MCOY-4740:PS-MODE.VAL"),
+ PV("ARS10-MCOY-5270:PS-MODE.VAL"),
+ PV("ARS10-MCOY-5900:PS-MODE.VAL"),
+ PV("ARS11-MCOY-0870:PS-MODE.VAL"),
+ PV("ARS11-MCOY-1110:PS-MODE.VAL"),
+ PV("ARS11-MCOY-1490:PS-MODE.VAL"),
+ PV("ARS11-MCOY-1930:PS-MODE.VAL"),
+ PV("ARS11-MCOY-2430:PS-MODE.VAL"),
+ PV("ARS11-MCOY-2930:PS-MODE.VAL"),
+ PV("ARS11-MCOY-4240:PS-MODE.VAL"),
+ PV("ARS11-MCOY-4740:PS-MODE.VAL"),
+ PV("ARS11-MCOY-5270:PS-MODE.VAL"),
+ PV("ARS11-MCOY-5900:PS-MODE.VAL"),
+ PV("ARS12-MCOY-1110:PS-MODE.VAL"),
+ PV("ARS12-MCOY-1490:PS-MODE.VAL"),
+ PV("ARS12-MCOY-1930:PS-MODE.VAL"),
+ PV("ARS12-MCOY-2430:PS-MODE.VAL"),
+ PV("ARS12-MCOY-2930:PS-MODE.VAL"),
+ PV("ARS12-MCOY-4240:PS-MODE.VAL"),
+ PV("ARS12-MCOY-4740:PS-MODE.VAL"),
+ PV("ARS12-MCOY-5270:PS-MODE.VAL"),
+ PV("ARS12-MCOY-5900:PS-MODE.VAL"),
+ PV("ARS01-MCOX-0410:I-READ.VAL"),
+ PV("ARS01-MCOX-0740:I-READ.VAL"),
+ PV("ARS01-MCOX-1090:I-READ.VAL"),
+ PV("ARS01-MCOX-1470:I-READ.VAL"),
+ PV("ARS01-MCOX-1910:I-READ.VAL"),
+ PV("ARS01-MCOX-2420:I-READ.VAL"),
+ PV("ARS01-MCOX-2920:I-READ.VAL"),
+ PV("ARS01-MCOX-4230:I-READ.VAL"),
+ PV("ARS01-MCOX-4730:I-READ.VAL"),
+ PV("ARS01-MCOX-5260:I-READ.VAL"),
+ PV("ARS01-MCOX-5890:I-READ.VAL"),
+ PV("ARS02-MCOX-1090:I-READ.VAL"),
+ PV("ARS02-MCOX-1470:I-READ.VAL"),
+ PV("ARS02-MCOX-1910:I-READ.VAL"),
+ PV("ARS02-MCOX-2420:I-READ.VAL"),
+ PV("ARS02-MCOX-2920:I-READ.VAL"),
+ PV("ARS02-MCOX-4230:I-READ.VAL"),
+ PV("ARS02-MCOX-4730:I-READ.VAL"),
+ PV("ARS02-MCOX-5260:I-READ.VAL"),
+ PV("ARS02-MCOX-5890:I-READ.VAL"),
+ PV("ARS03-MCOX-0820:I-READ.VAL"),
+ PV("ARS03-MCOX-1090:I-READ.VAL"),
+ PV("ARS03-MCOX-1470:I-READ.VAL"),
+ PV("ARS03-MCOX-1910:I-READ.VAL"),
+ PV("ARS03-MCOX-2420:I-READ.VAL"),
+ PV("ARS03-MCOX-2920:I-READ.VAL"),
+ PV("ARS03-MCOX-4230:I-READ.VAL"),
+ PV("ARS03-MCOX-4730:I-READ.VAL"),
+ PV("ARS03-MCOX-5260:I-READ.VAL"),
+ PV("ARS03-MCOX-5890:I-READ.VAL"),
+ PV("ARS04-MCOX-1090:I-READ.VAL"),
+ PV("ARS04-MCOX-1470:I-READ.VAL"),
+ PV("ARS04-MCOX-1910:I-READ.VAL"),
+ PV("ARS04-MCOX-2420:I-READ.VAL"),
+ PV("ARS04-MCOX-2920:I-READ.VAL"),
+ PV("ARS04-MCOX-4230:I-READ.VAL"),
+ PV("ARS04-MCOX-4730:I-READ.VAL"),
+ PV("ARS04-MCOX-5260:I-READ.VAL"),
+ PV("ARS04-MCOX-5890:I-READ.VAL"),
+ PV("ARS05-MCOX-0420:I-READ.VAL"),
+ PV("ARS05-MCOX-1090:I-READ.VAL"),
+ PV("ARS05-MCOX-1470:I-READ.VAL"),
+ PV("ARS05-MCOX-1910:I-READ.VAL"),
+ PV("ARS05-MCOX-2420:I-READ.VAL"),
+ PV("ARS05-MCOX-2920:I-READ.VAL"),
+ PV("ARS05-MCOX-4230:I-READ.VAL"),
+ PV("ARS05-MCOX-4730:I-READ.VAL"),
+ PV("ARS05-MCOX-5260:I-READ.VAL"),
+ PV("ARS05-MCOX-5890:I-READ.VAL"),
+ PV("ARS06-MCOX-1090:I-READ.VAL"),
+ PV("ARS06-MCOX-1470:I-READ.VAL"),
+ PV("ARS06-MCOX-1910:I-READ.VAL"),
+ PV("ARS06-MCOX-2420:I-READ.VAL"),
+ PV("ARS06-MCOX-2920:I-READ.VAL"),
+ PV("ARS06-MCOX-4230:I-READ.VAL"),
+ PV("ARS06-MCOX-4730:I-READ.VAL"),
+ PV("ARS06-MCOX-5260:I-READ.VAL"),
+ PV("ARS06-MCOX-5890:I-READ.VAL"),
+ PV("ARS07-MCOX-0820:I-READ.VAL"),
+ PV("ARS07-MCOX-1090:I-READ.VAL"),
+ PV("ARS07-MCOX-1470:I-READ.VAL"),
+ PV("ARS07-MCOX-1910:I-READ.VAL"),
+ PV("ARS07-MCOX-2420:I-READ.VAL"),
+ PV("ARS07-MCOX-2920:I-READ.VAL"),
+ PV("ARS07-MCOX-4230:I-READ.VAL"),
+ PV("ARS07-MCOX-4730:I-READ.VAL"),
+ PV("ARS07-MCOX-5260:I-READ.VAL"),
+ PV("ARS07-MCOX-5890:I-READ.VAL"),
+ PV("ARS08-MCOX-1090:I-READ.VAL"),
+ PV("ARS08-MCOX-1470:I-READ.VAL"),
+ PV("ARS08-MCOX-1910:I-READ.VAL"),
+ PV("ARS08-MCOX-2420:I-READ.VAL"),
+ PV("ARS08-MCOX-2920:I-READ.VAL"),
+ PV("ARS08-MCOX-4230:I-READ.VAL"),
+ PV("ARS08-MCOX-4730:I-READ.VAL"),
+ PV("ARS08-MCOX-5260:I-READ.VAL"),
+ PV("ARS08-MCOX-5890:I-READ.VAL"),
+ PV("ARS09-MCOX-0580:I-READ.VAL"),
+ PV("ARS09-MCOX-1090:I-READ.VAL"),
+ PV("ARS09-MCOX-1470:I-READ.VAL"),
+ PV("ARS09-MCOX-1910:I-READ.VAL"),
+ PV("ARS09-MCOX-2420:I-READ.VAL"),
+ PV("ARS09-MCOX-2920:I-READ.VAL"),
+ PV("ARS09-MCOX-4230:I-READ.VAL"),
+ PV("ARS09-MCOX-4730:I-READ.VAL"),
+ PV("ARS09-MCOX-5260:I-READ.VAL"),
+ PV("ARS09-MCOX-5890:I-READ.VAL"),
+ PV("ARS10-MCOX-1090:I-READ.VAL"),
+ PV("ARS10-MCOX-1470:I-READ.VAL"),
+ PV("ARS10-MCOX-1910:I-READ.VAL"),
+ PV("ARS10-MCOX-2420:I-READ.VAL"),
+ PV("ARS10-MCOX-2920:I-READ.VAL"),
+ PV("ARS10-MCOX-4230:I-READ.VAL"),
+ PV("ARS10-MCOX-4730:I-READ.VAL"),
+ PV("ARS10-MCOX-5260:I-READ.VAL"),
+ PV("ARS10-MCOX-5890:I-READ.VAL"),
+ PV("ARS11-MCOX-0860:I-READ.VAL"),
+ PV("ARS11-MCOX-1090:I-READ.VAL"),
+ PV("ARS11-MCOX-1470:I-READ.VAL"),
+ PV("ARS11-MCOX-1910:I-READ.VAL"),
+ PV("ARS11-MCOX-2420:I-READ.VAL"),
+ PV("ARS11-MCOX-2920:I-READ.VAL"),
+ PV("ARS11-MCOX-4230:I-READ.VAL"),
+ PV("ARS11-MCOX-4730:I-READ.VAL"),
+ PV("ARS11-MCOX-5260:I-READ.VAL"),
+ PV("ARS11-MCOX-5890:I-READ.VAL"),
+ PV("ARS12-MCOX-1090:I-READ.VAL"),
+ PV("ARS12-MCOX-1470:I-READ.VAL"),
+ PV("ARS12-MCOX-1910:I-READ.VAL"),
+ PV("ARS12-MCOX-2420:I-READ.VAL"),
+ PV("ARS12-MCOX-2920:I-READ.VAL"),
+ PV("ARS12-MCOX-4230:I-READ.VAL"),
+ PV("ARS12-MCOX-4730:I-READ.VAL"),
+ PV("ARS12-MCOX-5260:I-READ.VAL"),
+ PV("ARS12-MCOX-5890:I-READ.VAL"),
+ PV("ARS01-MCOY-0400:I-READ.VAL"),
+ PV("ARS01-MCOY-0750:I-READ.VAL"),
+ PV("ARS01-MCOY-1110:I-READ.VAL"),
+ PV("ARS01-MCOY-1490:I-READ.VAL"),
+ PV("ARS01-MCOY-1930:I-READ.VAL"),
+ PV("ARS01-MCOY-2430:I-READ.VAL"),
+ PV("ARS01-MCOY-2930:I-READ.VAL"),
+ PV("ARS01-MCOY-4240:I-READ.VAL"),
+ PV("ARS01-MCOY-4740:I-READ.VAL"),
+ PV("ARS01-MCOY-5270:I-READ.VAL"),
+ PV("ARS01-MCOY-5900:I-READ.VAL"),
+ PV("ARS02-MCOY-1110:I-READ.VAL"),
+ PV("ARS02-MCOY-1490:I-READ.VAL"),
+ PV("ARS02-MCOY-1930:I-READ.VAL"),
+ PV("ARS02-MCOY-2430:I-READ.VAL"),
+ PV("ARS02-MCOY-2930:I-READ.VAL"),
+ PV("ARS02-MCOY-4240:I-READ.VAL"),
+ PV("ARS02-MCOY-4740:I-READ.VAL"),
+ PV("ARS02-MCOY-5270:I-READ.VAL"),
+ PV("ARS02-MCOY-5900:I-READ.VAL"),
+ PV("ARS03-MCOY-0830:I-READ.VAL"),
+ PV("ARS03-MCOY-1110:I-READ.VAL"),
+ PV("ARS03-MCOY-1490:I-READ.VAL"),
+ PV("ARS03-MCOY-1930:I-READ.VAL"),
+ PV("ARS03-MCOY-2430:I-READ.VAL"),
+ PV("ARS03-MCOY-2930:I-READ.VAL"),
+ PV("ARS03-MCOY-4240:I-READ.VAL"),
+ PV("ARS03-MCOY-4740:I-READ.VAL"),
+ PV("ARS03-MCOY-5270:I-READ.VAL"),
+ PV("ARS03-MCOY-5900:I-READ.VAL"),
+ PV("ARS04-MCOY-1110:I-READ.VAL"),
+ PV("ARS04-MCOY-1490:I-READ.VAL"),
+ PV("ARS04-MCOY-1930:I-READ.VAL"),
+ PV("ARS04-MCOY-2430:I-READ.VAL"),
+ PV("ARS04-MCOY-2930:I-READ.VAL"),
+ PV("ARS04-MCOY-4240:I-READ.VAL"),
+ PV("ARS04-MCOY-4740:I-READ.VAL"),
+ PV("ARS04-MCOY-5270:I-READ.VAL"),
+ PV("ARS04-MCOY-5900:I-READ.VAL"),
+ PV("ARS05-MCOY-0430:I-READ.VAL"),
+ PV("ARS05-MCOY-1110:I-READ.VAL"),
+ PV("ARS05-MCOY-1490:I-READ.VAL"),
+ PV("ARS05-MCOY-1930:I-READ.VAL"),
+ PV("ARS05-MCOY-2430:I-READ.VAL"),
+ PV("ARS05-MCOY-2930:I-READ.VAL"),
+ PV("ARS05-MCOY-4240:I-READ.VAL"),
+ PV("ARS05-MCOY-4740:I-READ.VAL"),
+ PV("ARS05-MCOY-5270:I-READ.VAL"),
+ PV("ARS05-MCOY-5900:I-READ.VAL"),
+ PV("ARS06-MCOY-1110:I-READ.VAL"),
+ PV("ARS06-MCOY-1490:I-READ.VAL"),
+ PV("ARS06-MCOY-1930:I-READ.VAL"),
+ PV("ARS06-MCOY-2430:I-READ.VAL"),
+ PV("ARS06-MCOY-2930:I-READ.VAL"),
+ PV("ARS06-MCOY-4240:I-READ.VAL"),
+ PV("ARS06-MCOY-4740:I-READ.VAL"),
+ PV("ARS06-MCOY-5270:I-READ.VAL"),
+ PV("ARS06-MCOY-5900:I-READ.VAL"),
+ PV("ARS07-MCOY-0830:I-READ.VAL"),
+ PV("ARS07-MCOY-1110:I-READ.VAL"),
+ PV("ARS07-MCOY-1490:I-READ.VAL"),
+ PV("ARS07-MCOY-1930:I-READ.VAL"),
+ PV("ARS07-MCOY-2430:I-READ.VAL"),
+ PV("ARS07-MCOY-2930:I-READ.VAL"),
+ PV("ARS07-MCOY-4240:I-READ.VAL"),
+ PV("ARS07-MCOY-4740:I-READ.VAL"),
+ PV("ARS07-MCOY-5270:I-READ.VAL"),
+ PV("ARS07-MCOY-5900:I-READ.VAL"),
+ PV("ARS08-MCOY-1110:I-READ.VAL"),
+ PV("ARS08-MCOY-1490:I-READ.VAL"),
+ PV("ARS08-MCOY-1930:I-READ.VAL"),
+ PV("ARS08-MCOY-2430:I-READ.VAL"),
+ PV("ARS08-MCOY-2930:I-READ.VAL"),
+ PV("ARS08-MCOY-4240:I-READ.VAL"),
+ PV("ARS08-MCOY-4740:I-READ.VAL"),
+ PV("ARS08-MCOY-5270:I-READ.VAL"),
+ PV("ARS08-MCOY-5900:I-READ.VAL"),
+ PV("ARS09-MCOY-0590:I-READ.VAL"),
+ PV("ARS09-MCOY-1110:I-READ.VAL"),
+ PV("ARS09-MCOY-1490:I-READ.VAL"),
+ PV("ARS09-MCOY-1930:I-READ.VAL"),
+ PV("ARS09-MCOY-2430:I-READ.VAL"),
+ PV("ARS09-MCOY-2930:I-READ.VAL"),
+ PV("ARS09-MCOY-4240:I-READ.VAL"),
+ PV("ARS09-MCOY-4740:I-READ.VAL"),
+ PV("ARS09-MCOY-5270:I-READ.VAL"),
+ PV("ARS09-MCOY-5900:I-READ.VAL"),
+ PV("ARS10-MCOY-1110:I-READ.VAL"),
+ PV("ARS10-MCOY-1490:I-READ.VAL"),
+ PV("ARS10-MCOY-1930:I-READ.VAL"),
+ PV("ARS10-MCOY-2430:I-READ.VAL"),
+ PV("ARS10-MCOY-2930:I-READ.VAL"),
+ PV("ARS10-MCOY-4240:I-READ.VAL"),
+ PV("ARS10-MCOY-4740:I-READ.VAL"),
+ PV("ARS10-MCOY-5270:I-READ.VAL"),
+ PV("ARS10-MCOY-5900:I-READ.VAL"),
+ PV("ARS11-MCOY-0870:I-READ.VAL"),
+ PV("ARS11-MCOY-1110:I-READ.VAL"),
+ PV("ARS11-MCOY-1490:I-READ.VAL"),
+ PV("ARS11-MCOY-1930:I-READ.VAL"),
+ PV("ARS11-MCOY-2430:I-READ.VAL"),
+ PV("ARS11-MCOY-2930:I-READ.VAL"),
+ PV("ARS11-MCOY-4240:I-READ.VAL"),
+ PV("ARS11-MCOY-4740:I-READ.VAL"),
+ PV("ARS11-MCOY-5270:I-READ.VAL"),
+ PV("ARS11-MCOY-5900:I-READ.VAL"),
+ PV("ARS12-MCOY-1110:I-READ.VAL"),
+ PV("ARS12-MCOY-1490:I-READ.VAL"),
+ PV("ARS12-MCOY-1930:I-READ.VAL"),
+ PV("ARS12-MCOY-2430:I-READ.VAL"),
+ PV("ARS12-MCOY-2930:I-READ.VAL"),
+ PV("ARS12-MCOY-4240:I-READ.VAL"),
+ PV("ARS12-MCOY-4740:I-READ.VAL"),
+ PV("ARS12-MCOY-5270:I-READ.VAL"),
+ PV("ARS12-MCOY-5900:I-READ.VAL"),
+ ],
+ [
+ lambda vls: vls["ARS01-MCOX-0410:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MCOX-0740:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MCOX-1090:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MCOX-1470:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MCOX-1910:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MCOX-2420:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MCOX-2920:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MCOX-4230:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MCOX-4730:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MCOX-5260:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MCOX-5890:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MCOX-1090:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MCOX-1470:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MCOX-1910:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MCOX-2420:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MCOX-2920:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MCOX-4230:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MCOX-4730:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MCOX-5260:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MCOX-5890:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MCOX-0820:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MCOX-1090:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MCOX-1470:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MCOX-1910:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MCOX-2420:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MCOX-2920:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MCOX-4230:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MCOX-4730:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MCOX-5260:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MCOX-5890:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MCOX-1090:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MCOX-1470:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MCOX-1910:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MCOX-2420:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MCOX-2920:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MCOX-4230:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MCOX-4730:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MCOX-5260:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MCOX-5890:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MCOX-0420:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MCOX-1090:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MCOX-1470:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MCOX-1910:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MCOX-2420:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MCOX-2920:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MCOX-4230:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MCOX-4730:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MCOX-5260:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MCOX-5890:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MCOX-1090:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MCOX-1470:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MCOX-1910:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MCOX-2420:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MCOX-2920:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MCOX-4230:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MCOX-4730:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MCOX-5260:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MCOX-5890:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MCOX-0820:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MCOX-1090:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MCOX-1470:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MCOX-1910:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MCOX-2420:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MCOX-2920:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MCOX-4230:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MCOX-4730:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MCOX-5260:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MCOX-5890:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MCOX-1090:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MCOX-1470:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MCOX-1910:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MCOX-2420:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MCOX-2920:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MCOX-4230:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MCOX-4730:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MCOX-5260:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MCOX-5890:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MCOX-0580:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MCOX-1090:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MCOX-1470:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MCOX-1910:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MCOX-2420:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MCOX-2920:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MCOX-4230:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MCOX-4730:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MCOX-5260:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MCOX-5890:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MCOX-1090:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MCOX-1470:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MCOX-1910:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MCOX-2420:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MCOX-2920:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MCOX-4230:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MCOX-4730:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MCOX-5260:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MCOX-5890:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MCOX-0860:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MCOX-1090:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MCOX-1470:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MCOX-1910:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MCOX-2420:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MCOX-2920:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MCOX-4230:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MCOX-4730:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MCOX-5260:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MCOX-5890:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MCOX-1090:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MCOX-1470:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MCOX-1910:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MCOX-2420:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MCOX-2920:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MCOX-4230:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MCOX-4730:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MCOX-5260:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MCOX-5890:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MCOY-0400:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MCOY-0750:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MCOY-1110:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MCOY-1490:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MCOY-1930:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MCOY-2430:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MCOY-2930:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MCOY-4240:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MCOY-4740:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MCOY-5270:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MCOY-5900:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MCOY-1110:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MCOY-1490:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MCOY-1930:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MCOY-2430:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MCOY-2930:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MCOY-4240:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MCOY-4740:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MCOY-5270:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MCOY-5900:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MCOY-0830:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MCOY-1110:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MCOY-1490:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MCOY-1930:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MCOY-2430:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MCOY-2930:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MCOY-4240:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MCOY-4740:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MCOY-5270:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MCOY-5900:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MCOY-1110:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MCOY-1490:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MCOY-1930:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MCOY-2430:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MCOY-2930:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MCOY-4240:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MCOY-4740:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MCOY-5270:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MCOY-5900:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MCOY-0430:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MCOY-1110:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MCOY-1490:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MCOY-1930:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MCOY-2430:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MCOY-2930:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MCOY-4240:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MCOY-4740:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MCOY-5270:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MCOY-5900:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MCOY-1110:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MCOY-1490:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MCOY-1930:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MCOY-2430:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MCOY-2930:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MCOY-4240:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MCOY-4740:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MCOY-5270:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MCOY-5900:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MCOY-0830:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MCOY-1110:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MCOY-1490:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MCOY-1930:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MCOY-2430:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MCOY-2930:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MCOY-4240:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MCOY-4740:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MCOY-5270:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MCOY-5900:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MCOY-1110:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MCOY-1490:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MCOY-1930:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MCOY-2430:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MCOY-2930:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MCOY-4240:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MCOY-4740:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MCOY-5270:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MCOY-5900:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MCOY-0590:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MCOY-1110:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MCOY-1490:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MCOY-1930:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MCOY-2430:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MCOY-2930:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MCOY-4240:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MCOY-4740:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MCOY-5270:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MCOY-5900:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MCOY-1110:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MCOY-1490:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MCOY-1930:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MCOY-2430:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MCOY-2930:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MCOY-4240:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MCOY-4740:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MCOY-5270:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MCOY-5900:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MCOY-0870:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MCOY-1110:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MCOY-1490:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MCOY-1930:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MCOY-2430:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MCOY-2930:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MCOY-4240:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MCOY-4740:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MCOY-5270:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MCOY-5900:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MCOY-1110:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MCOY-1490:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MCOY-1930:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MCOY-2430:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MCOY-2930:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MCOY-4240:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MCOY-4740:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MCOY-5270:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MCOY-5900:PS-MODE.VAL"] == 2,
+ lambda vls: -4.95 < vls["ARS01-MCOX-0410:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS01-MCOX-0740:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS01-MCOX-1090:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS01-MCOX-1470:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS01-MCOX-1910:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS01-MCOX-2420:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS01-MCOX-2920:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS01-MCOX-4230:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS01-MCOX-4730:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS01-MCOX-5260:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS01-MCOX-5890:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS02-MCOX-1090:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS02-MCOX-1470:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS02-MCOX-1910:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS02-MCOX-2420:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS02-MCOX-2920:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS02-MCOX-4230:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS02-MCOX-4730:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS02-MCOX-5260:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS02-MCOX-5890:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS03-MCOX-0820:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS03-MCOX-1090:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS03-MCOX-1470:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS03-MCOX-1910:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS03-MCOX-2420:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS03-MCOX-2920:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS03-MCOX-4230:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS03-MCOX-4730:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS03-MCOX-5260:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS03-MCOX-5890:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS04-MCOX-1090:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS04-MCOX-1470:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS04-MCOX-1910:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS04-MCOX-2420:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS04-MCOX-2920:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS04-MCOX-4230:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS04-MCOX-4730:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS04-MCOX-5260:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS04-MCOX-5890:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS05-MCOX-0420:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS05-MCOX-1090:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS05-MCOX-1470:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS05-MCOX-1910:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS05-MCOX-2420:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS05-MCOX-2920:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS05-MCOX-4230:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS05-MCOX-4730:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS05-MCOX-5260:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS05-MCOX-5890:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS06-MCOX-1090:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS06-MCOX-1470:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS06-MCOX-1910:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS06-MCOX-2420:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS06-MCOX-2920:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS06-MCOX-4230:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS06-MCOX-4730:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS06-MCOX-5260:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS06-MCOX-5890:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS07-MCOX-0820:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS07-MCOX-1090:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS07-MCOX-1470:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS07-MCOX-1910:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS07-MCOX-2420:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS07-MCOX-2920:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS07-MCOX-4230:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS07-MCOX-4730:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS07-MCOX-5260:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS07-MCOX-5890:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS08-MCOX-1090:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS08-MCOX-1470:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS08-MCOX-1910:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS08-MCOX-2420:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS08-MCOX-2920:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS08-MCOX-4230:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS08-MCOX-4730:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS08-MCOX-5260:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS08-MCOX-5890:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS09-MCOX-0580:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS09-MCOX-1090:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS09-MCOX-1470:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS09-MCOX-1910:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS09-MCOX-2420:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS09-MCOX-2920:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS09-MCOX-4230:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS09-MCOX-4730:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS09-MCOX-5260:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS09-MCOX-5890:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS10-MCOX-1090:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS10-MCOX-1470:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS10-MCOX-1910:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS10-MCOX-2420:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS10-MCOX-2920:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS10-MCOX-4230:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS10-MCOX-4730:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS10-MCOX-5260:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS10-MCOX-5890:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS11-MCOX-0860:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS11-MCOX-1090:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS11-MCOX-1470:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS11-MCOX-1910:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS11-MCOX-2420:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS11-MCOX-2920:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS11-MCOX-4230:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS11-MCOX-4730:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS11-MCOX-5260:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS11-MCOX-5890:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS12-MCOX-1090:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS12-MCOX-1470:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS12-MCOX-1910:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS12-MCOX-2420:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS12-MCOX-2920:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS12-MCOX-4230:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS12-MCOX-4730:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS12-MCOX-5260:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS12-MCOX-5890:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS01-MCOY-0400:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS01-MCOY-0750:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS01-MCOY-1110:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS01-MCOY-1490:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS01-MCOY-1930:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS01-MCOY-2430:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS01-MCOY-2930:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS01-MCOY-4240:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS01-MCOY-4740:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS01-MCOY-5270:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS01-MCOY-5900:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS02-MCOY-1110:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS02-MCOY-1490:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS02-MCOY-1930:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS02-MCOY-2430:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS02-MCOY-2930:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS02-MCOY-4240:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS02-MCOY-4740:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS02-MCOY-5270:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS02-MCOY-5900:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS03-MCOY-0830:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS03-MCOY-1110:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS03-MCOY-1490:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS03-MCOY-1930:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS03-MCOY-2430:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS03-MCOY-2930:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS03-MCOY-4240:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS03-MCOY-4740:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS03-MCOY-5270:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS03-MCOY-5900:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS04-MCOY-1110:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS04-MCOY-1490:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS04-MCOY-1930:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS04-MCOY-2430:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS04-MCOY-2930:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS04-MCOY-4240:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS04-MCOY-4740:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS04-MCOY-5270:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS04-MCOY-5900:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS05-MCOY-0430:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS05-MCOY-1110:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS05-MCOY-1490:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS05-MCOY-1930:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS05-MCOY-2430:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS05-MCOY-2930:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS05-MCOY-4240:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS05-MCOY-4740:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS05-MCOY-5270:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS05-MCOY-5900:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS06-MCOY-1110:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS06-MCOY-1490:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS06-MCOY-1930:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS06-MCOY-2430:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS06-MCOY-2930:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS06-MCOY-4240:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS06-MCOY-4740:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS06-MCOY-5270:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS06-MCOY-5900:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS07-MCOY-0830:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS07-MCOY-1110:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS07-MCOY-1490:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS07-MCOY-1930:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS07-MCOY-2430:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS07-MCOY-2930:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS07-MCOY-4240:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS07-MCOY-4740:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS07-MCOY-5270:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS07-MCOY-5900:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS08-MCOY-1110:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS08-MCOY-1490:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS08-MCOY-1930:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS08-MCOY-2430:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS08-MCOY-2930:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS08-MCOY-4240:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS08-MCOY-4740:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS08-MCOY-5270:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS08-MCOY-5900:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS09-MCOY-0590:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS09-MCOY-1110:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS09-MCOY-1490:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS09-MCOY-1930:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS09-MCOY-2430:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS09-MCOY-2930:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS09-MCOY-4240:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS09-MCOY-4740:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS09-MCOY-5270:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS09-MCOY-5900:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS10-MCOY-1110:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS10-MCOY-1490:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS10-MCOY-1930:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS10-MCOY-2430:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS10-MCOY-2930:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS10-MCOY-4240:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS10-MCOY-4740:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS10-MCOY-5270:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS10-MCOY-5900:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS11-MCOY-0870:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS11-MCOY-1110:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS11-MCOY-1490:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS11-MCOY-1930:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS11-MCOY-2430:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS11-MCOY-2930:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS11-MCOY-4240:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS11-MCOY-4740:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS11-MCOY-5270:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS11-MCOY-5900:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS12-MCOY-1110:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS12-MCOY-1490:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS12-MCOY-1930:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS12-MCOY-2430:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS12-MCOY-2930:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS12-MCOY-4240:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS12-MCOY-4740:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS12-MCOY-5270:I-READ.VAL"] < 4.95,
+ lambda vls: -4.95 < vls["ARS12-MCOY-5900:I-READ.VAL"] < 4.95,
+ ],
+ ],
+ "Magnets Ring": [
+ [
+ PV("ARS01-MQUA-0550:PS-MODE.VAL"),
+ PV("ARS01-MQUA-0630:PS-MODE.VAL"),
+ PV("ARS01-MQUA-0710:PS-MODE.VAL"),
+ PV("ARS01-MQUA-0790:PS-MODE.VAL"),
+ PV("ARS01-MQUA-1050:PS-MODE.VAL"),
+ PV("ARS01-MQUA-1150:PS-MODE.VAL"),
+ PV("ARS01-MQUA-1260:PS-MODE.VAL"),
+ PV("ARS01-MQUA-1370:PS-MODE.VAL"),
+ PV("ARS01-MQUA-5620:PS-MODE.VAL"),
+ PV("ARS01-MQUA-5730:PS-MODE.VAL"),
+ PV("ARS01-MQUA-5840:PS-MODE.VAL"),
+ PV("ARS01-MQUA-5940:PS-MODE.VAL"),
+ PV("ARS02-MQUA-1050:PS-MODE.VAL"),
+ PV("ARS02-MQUA-1150:PS-MODE.VAL"),
+ PV("ARS02-MQUA-1260:PS-MODE.VAL"),
+ PV("ARS02-MQUA-1370:PS-MODE.VAL"),
+ PV("ARS02-MQUA-5620:PS-MODE.VAL"),
+ PV("ARS02-MQUA-5730:PS-MODE.VAL"),
+ PV("ARS02-MQUA-5840:PS-MODE.VAL"),
+ PV("ARS02-MQUA-5940:PS-MODE.VAL"),
+ PV("ARS03-MQUA-0790:PS-MODE.VAL"),
+ PV("ARS03-MQUA-0850:PS-MODE.VAL"),
+ PV("ARS03-MQUA-1050:PS-MODE.VAL"),
+ PV("ARS03-MQUA-1150:PS-MODE.VAL"),
+ PV("ARS03-MQUA-1260:PS-MODE.VAL"),
+ PV("ARS03-MQUA-1370:PS-MODE.VAL"),
+ PV("ARS03-MQUA-5620:PS-MODE.VAL"),
+ PV("ARS03-MQUA-5730:PS-MODE.VAL"),
+ PV("ARS03-MQUA-5840:PS-MODE.VAL"),
+ PV("ARS03-MQUA-5940:PS-MODE.VAL"),
+ PV("ARS04-MQUA-1050:PS-MODE.VAL"),
+ PV("ARS04-MQUA-1150:PS-MODE.VAL"),
+ PV("ARS04-MQUA-1260:PS-MODE.VAL"),
+ PV("ARS04-MQUA-1370:PS-MODE.VAL"),
+ PV("ARS04-MQUA-5620:PS-MODE.VAL"),
+ PV("ARS04-MQUA-5730:PS-MODE.VAL"),
+ PV("ARS04-MQUA-5840:PS-MODE.VAL"),
+ PV("ARS04-MQUA-5940:PS-MODE.VAL"),
+ PV("ARS05-MQUA-0400:PS-MODE.VAL"),
+ PV("ARS05-MQUA-0440:PS-MODE.VAL"),
+ PV("ARS05-MQUA-0460:PS-MODE.VAL"),
+ PV("ARS05-MQUA-1050:PS-MODE.VAL"),
+ PV("ARS05-MQUA-1150:PS-MODE.VAL"),
+ PV("ARS05-MQUA-1260:PS-MODE.VAL"),
+ PV("ARS05-MQUA-1370:PS-MODE.VAL"),
+ PV("ARS05-MQUA-5620:PS-MODE.VAL"),
+ PV("ARS05-MQUA-5730:PS-MODE.VAL"),
+ PV("ARS05-MQUA-5840:PS-MODE.VAL"),
+ PV("ARS05-MQUA-5940:PS-MODE.VAL"),
+ PV("ARS06-MQUA-1050:PS-MODE.VAL"),
+ PV("ARS06-MQUA-1150:PS-MODE.VAL"),
+ PV("ARS06-MQUA-1260:PS-MODE.VAL"),
+ PV("ARS06-MQUA-1370:PS-MODE.VAL"),
+ PV("ARS06-MQUA-5620:PS-MODE.VAL"),
+ PV("ARS06-MQUA-5730:PS-MODE.VAL"),
+ PV("ARS06-MQUA-5840:PS-MODE.VAL"),
+ PV("ARS06-MQUA-5940:PS-MODE.VAL"),
+ PV("ARS07-MQUA-0790:PS-MODE.VAL"),
+ PV("ARS07-MQUA-0850:PS-MODE.VAL"),
+ PV("ARS07-MQUA-1050:PS-MODE.VAL"),
+ PV("ARS07-MQUA-1150:PS-MODE.VAL"),
+ PV("ARS07-MQUA-1260:PS-MODE.VAL"),
+ PV("ARS07-MQUA-1370:PS-MODE.VAL"),
+ PV("ARS07-MQUA-5620:PS-MODE.VAL"),
+ PV("ARS07-MQUA-5730:PS-MODE.VAL"),
+ PV("ARS07-MQUA-5840:PS-MODE.VAL"),
+ PV("ARS07-MQUA-5940:PS-MODE.VAL"),
+ PV("ARS08-MQUA-1050:PS-MODE.VAL"),
+ PV("ARS08-MQUA-1150:PS-MODE.VAL"),
+ PV("ARS08-MQUA-1260:PS-MODE.VAL"),
+ PV("ARS08-MQUA-1370:PS-MODE.VAL"),
+ PV("ARS08-MQUA-5620:PS-MODE.VAL"),
+ PV("ARS08-MQUA-5730:PS-MODE.VAL"),
+ PV("ARS08-MQUA-5840:PS-MODE.VAL"),
+ PV("ARS08-MQUA-5940:PS-MODE.VAL"),
+ PV("ARS09-MQUA-0530:PS-MODE.VAL"),
+ PV("ARS09-MQUA-0560:PS-MODE.VAL"),
+ PV("ARS09-MQUA-0600:PS-MODE.VAL"),
+ PV("ARS09-MQUA-1050:PS-MODE.VAL"),
+ PV("ARS09-MQUA-1150:PS-MODE.VAL"),
+ PV("ARS09-MQUA-1260:PS-MODE.VAL"),
+ PV("ARS09-MQUA-1370:PS-MODE.VAL"),
+ PV("ARS09-MQUA-5620:PS-MODE.VAL"),
+ PV("ARS09-MQUA-5730:PS-MODE.VAL"),
+ PV("ARS09-MQUA-5840:PS-MODE.VAL"),
+ PV("ARS09-MQUA-5940:PS-MODE.VAL"),
+ PV("ARS10-MQUA-1050:PS-MODE.VAL"),
+ PV("ARS10-MQUA-1150:PS-MODE.VAL"),
+ PV("ARS10-MQUA-1260:PS-MODE.VAL"),
+ PV("ARS10-MQUA-1370:PS-MODE.VAL"),
+ PV("ARS10-MQUA-5620:PS-MODE.VAL"),
+ PV("ARS10-MQUA-5730:PS-MODE.VAL"),
+ PV("ARS10-MQUA-5840:PS-MODE.VAL"),
+ PV("ARS10-MQUA-5940:PS-MODE.VAL"),
+ PV("ARS11-MQUA-0830:PS-MODE.VAL"),
+ PV("ARS11-MQUA-0890:PS-MODE.VAL"),
+ PV("ARS11-MQUA-1050:PS-MODE.VAL"),
+ PV("ARS11-MQUA-1150:PS-MODE.VAL"),
+ PV("ARS11-MQUA-1260:PS-MODE.VAL"),
+ PV("ARS11-MQUA-1370:PS-MODE.VAL"),
+ PV("ARS11-MQUA-5620:PS-MODE.VAL"),
+ PV("ARS11-MQUA-5730:PS-MODE.VAL"),
+ PV("ARS11-MQUA-5840:PS-MODE.VAL"),
+ PV("ARS11-MQUA-5940:PS-MODE.VAL"),
+ PV("ARS12-MQUA-1050:PS-MODE.VAL"),
+ PV("ARS12-MQUA-1150:PS-MODE.VAL"),
+ PV("ARS12-MQUA-1260:PS-MODE.VAL"),
+ PV("ARS12-MQUA-1370:PS-MODE.VAL"),
+ PV("ARS12-MQUA-5620:PS-MODE.VAL"),
+ PV("ARS12-MQUA-5730:PS-MODE.VAL"),
+ PV("ARS12-MQUA-5840:PS-MODE.VAL"),
+ PV("ARS12-MQUA-5940:PS-MODE.VAL"),
+ PV("ARS01-MSXT-1190:PS-MODE.VAL"),
+ PV("ARS01-MSXT-1300:PS-MODE.VAL"),
+ PV("ARS01-MSXT-1410:PS-MODE.VAL"),
+ PV("ARS01-MSXT-1590:PS-MODE.VAL"),
+ PV("ARS01-MSXT-1810:PS-MODE.VAL"),
+ PV("ARS01-MSXT-1980:PS-MODE.VAL"),
+ PV("ARS01-MSXT-2200:PS-MODE.VAL"),
+ PV("ARS01-MSXT-2330:PS-MODE.VAL"),
+ PV("ARS01-MSXT-2480:PS-MODE.VAL"),
+ PV("ARS01-MSXT-2700:PS-MODE.VAL"),
+ PV("ARS01-MSXT-2830:PS-MODE.VAL"),
+ PV("ARS01-MSXT-2980:PS-MODE.VAL"),
+ PV("ARS01-MSXT-4010:PS-MODE.VAL"),
+ PV("ARS01-MSXT-4160:PS-MODE.VAL"),
+ PV("ARS01-MSXT-4290:PS-MODE.VAL"),
+ PV("ARS01-MSXT-4510:PS-MODE.VAL"),
+ PV("ARS01-MSXT-4660:PS-MODE.VAL"),
+ PV("ARS01-MSXT-4790:PS-MODE.VAL"),
+ PV("ARS01-MSXT-5010:PS-MODE.VAL"),
+ PV("ARS01-MSXT-5180:PS-MODE.VAL"),
+ PV("ARS01-MSXT-5400:PS-MODE.VAL"),
+ PV("ARS01-MSXT-5580:PS-MODE.VAL"),
+ PV("ARS01-MSXT-5690:PS-MODE.VAL"),
+ PV("ARS01-MSXT-5800:PS-MODE.VAL"),
+ PV("ARS02-MSXT-2980:PS-MODE.VAL"),
+ PV("ARS02-MSXT-4010:PS-MODE.VAL"),
+ PV("ARS03-MSXT-1590:PS-MODE.VAL"),
+ PV("ARS03-MSXT-2980:PS-MODE.VAL"),
+ PV("ARS03-MSXT-4010:PS-MODE.VAL"),
+ PV("ARS03-MSXT-5400:PS-MODE.VAL"),
+ PV("ARS05-MSXT-1190:PS-MODE.VAL"),
+ PV("ARS05-MSXT-1300:PS-MODE.VAL"),
+ PV("ARS05-MSXT-1410:PS-MODE.VAL"),
+ PV("ARS05-MSXT-1590:PS-MODE.VAL"),
+ PV("ARS05-MSXT-5400:PS-MODE.VAL"),
+ PV("ARS05-MSXT-5580:PS-MODE.VAL"),
+ PV("ARS05-MSXT-5690:PS-MODE.VAL"),
+ PV("ARS05-MSXT-5800:PS-MODE.VAL"),
+ PV("ARS07-MSXT-1590:PS-MODE.VAL"),
+ PV("ARS07-MSXT-1810:PS-MODE.VAL"),
+ PV("ARS07-MSXT-1980:PS-MODE.VAL"),
+ PV("ARS07-MSXT-2200:PS-MODE.VAL"),
+ PV("ARS07-MSXT-2330:PS-MODE.VAL"),
+ PV("ARS07-MSXT-2480:PS-MODE.VAL"),
+ PV("ARS07-MSXT-2700:PS-MODE.VAL"),
+ PV("ARS07-MSXT-2830:PS-MODE.VAL"),
+ PV("ARS07-MSXT-2980:PS-MODE.VAL"),
+ PV("ARS07-MSXT-4010:PS-MODE.VAL"),
+ PV("ARS07-MSXT-4160:PS-MODE.VAL"),
+ PV("ARS07-MSXT-4290:PS-MODE.VAL"),
+ PV("ARS07-MSXT-4510:PS-MODE.VAL"),
+ PV("ARS07-MSXT-4660:PS-MODE.VAL"),
+ PV("ARS07-MSXT-4790:PS-MODE.VAL"),
+ PV("ARS07-MSXT-5010:PS-MODE.VAL"),
+ PV("ARS07-MSXT-5180:PS-MODE.VAL"),
+ PV("ARS07-MSXT-5400:PS-MODE.VAL"),
+ PV("ARS09-MSXT-1190:PS-MODE.VAL"),
+ PV("ARS09-MSXT-1300:PS-MODE.VAL"),
+ PV("ARS09-MSXT-1410:PS-MODE.VAL"),
+ PV("ARS09-MSXT-1590:PS-MODE.VAL"),
+ PV("ARS09-MSXT-5400:PS-MODE.VAL"),
+ PV("ARS09-MSXT-5580:PS-MODE.VAL"),
+ PV("ARS09-MSXT-5690:PS-MODE.VAL"),
+ PV("ARS09-MSXT-5800:PS-MODE.VAL"),
+ PV("ARS11-MSXT-1590:PS-MODE.VAL"),
+ PV("ARS11-MSXT-5400:PS-MODE.VAL"),
+ PV("ARS01-MOCT-1230-OC:PS-MODE.VAL"),
+ PV("ARS01-MOCT-1330-OC:PS-MODE.VAL"),
+ PV("ARS01-MOCT-1440-OC:PS-MODE.VAL"),
+ PV("ARS01-MOCT-1840-OC:PS-MODE.VAL"),
+ PV("ARS01-MOCT-1950-OC:PS-MODE.VAL"),
+ PV("ARS01-MOCT-2230-OC:PS-MODE.VAL"),
+ PV("ARS01-MOCT-2360-OC:PS-MODE.VAL"),
+ PV("ARS01-MOCT-2450-OC:PS-MODE.VAL"),
+ PV("ARS01-MOCT-2730-OC:PS-MODE.VAL"),
+ PV("ARS01-MOCT-2860-OC:PS-MODE.VAL"),
+ PV("ARS01-MOCT-2950-OC:PS-MODE.VAL"),
+ PV("ARS01-MOCT-4040-OC:PS-MODE.VAL"),
+ PV("ARS01-MOCT-4130-OC:PS-MODE.VAL"),
+ PV("ARS01-MOCT-4260-OC:PS-MODE.VAL"),
+ PV("ARS01-MOCT-4540-OC:PS-MODE.VAL"),
+ PV("ARS01-MOCT-4630-OC:PS-MODE.VAL"),
+ PV("ARS01-MOCT-4760-OC:PS-MODE.VAL"),
+ PV("ARS01-MOCT-5040-OC:PS-MODE.VAL"),
+ PV("ARS01-MOCT-5150-OC:PS-MODE.VAL"),
+ PV("ARS01-MOCT-5550-OC:PS-MODE.VAL"),
+ PV("ARS01-MOCT-5660-OC:PS-MODE.VAL"),
+ PV("ARS01-MOCT-5760-OC:PS-MODE.VAL"),
+ PV("ARS02-MOCT-1230-OC:PS-MODE.VAL"),
+ PV("ARS02-MOCT-1330-OC:PS-MODE.VAL"),
+ PV("ARS02-MOCT-1440-OC:PS-MODE.VAL"),
+ PV("ARS02-MOCT-1840-OC:PS-MODE.VAL"),
+ PV("ARS02-MOCT-1950-OC:PS-MODE.VAL"),
+ PV("ARS02-MOCT-2230-OC:PS-MODE.VAL"),
+ PV("ARS02-MOCT-2360-OC:PS-MODE.VAL"),
+ PV("ARS02-MOCT-2450-OC:PS-MODE.VAL"),
+ PV("ARS02-MOCT-2730-OC:PS-MODE.VAL"),
+ PV("ARS02-MOCT-2860-OC:PS-MODE.VAL"),
+ PV("ARS02-MOCT-2950-OC:PS-MODE.VAL"),
+ PV("ARS02-MOCT-4040-OC:PS-MODE.VAL"),
+ PV("ARS02-MOCT-4130-OC:PS-MODE.VAL"),
+ PV("ARS02-MOCT-4260-OC:PS-MODE.VAL"),
+ PV("ARS02-MOCT-4540-OC:PS-MODE.VAL"),
+ PV("ARS02-MOCT-4630-OC:PS-MODE.VAL"),
+ PV("ARS02-MOCT-4760-OC:PS-MODE.VAL"),
+ PV("ARS02-MOCT-5040-OC:PS-MODE.VAL"),
+ PV("ARS02-MOCT-5150-OC:PS-MODE.VAL"),
+ PV("ARS02-MOCT-5550-OC:PS-MODE.VAL"),
+ PV("ARS02-MOCT-5660-OC:PS-MODE.VAL"),
+ PV("ARS02-MOCT-5760-OC:PS-MODE.VAL"),
+ PV("ARS03-MOCT-1230-OC:PS-MODE.VAL"),
+ PV("ARS03-MOCT-1330-OC:PS-MODE.VAL"),
+ PV("ARS03-MOCT-1440-OC:PS-MODE.VAL"),
+ PV("ARS03-MOCT-1840-OC:PS-MODE.VAL"),
+ PV("ARS03-MOCT-1950-OC:PS-MODE.VAL"),
+ PV("ARS03-MOCT-2230-OC:PS-MODE.VAL"),
+ PV("ARS03-MOCT-2360-OC:PS-MODE.VAL"),
+ PV("ARS03-MOCT-2450-OC:PS-MODE.VAL"),
+ PV("ARS03-MOCT-2730-OC:PS-MODE.VAL"),
+ PV("ARS03-MOCT-2860-OC:PS-MODE.VAL"),
+ PV("ARS03-MOCT-2950-OC:PS-MODE.VAL"),
+ PV("ARS03-MOCT-4040-OC:PS-MODE.VAL"),
+ PV("ARS03-MOCT-4130-OC:PS-MODE.VAL"),
+ PV("ARS03-MOCT-4260-OC:PS-MODE.VAL"),
+ PV("ARS03-MOCT-4540-OC:PS-MODE.VAL"),
+ PV("ARS03-MOCT-4630-OC:PS-MODE.VAL"),
+ PV("ARS03-MOCT-4760-OC:PS-MODE.VAL"),
+ PV("ARS03-MOCT-5040-OC:PS-MODE.VAL"),
+ PV("ARS03-MOCT-5150-OC:PS-MODE.VAL"),
+ PV("ARS03-MOCT-5550-OC:PS-MODE.VAL"),
+ PV("ARS03-MOCT-5660-OC:PS-MODE.VAL"),
+ PV("ARS03-MOCT-5760-OC:PS-MODE.VAL"),
+ PV("ARS04-MOCT-1230-OC:PS-MODE.VAL"),
+ PV("ARS04-MOCT-1330-OC:PS-MODE.VAL"),
+ PV("ARS04-MOCT-1440-OC:PS-MODE.VAL"),
+ PV("ARS04-MOCT-1840-OC:PS-MODE.VAL"),
+ PV("ARS04-MOCT-1950-OC:PS-MODE.VAL"),
+ PV("ARS04-MOCT-2230-OC:PS-MODE.VAL"),
+ PV("ARS04-MOCT-2360-OC:PS-MODE.VAL"),
+ PV("ARS04-MOCT-2450-OC:PS-MODE.VAL"),
+ PV("ARS04-MOCT-2730-OC:PS-MODE.VAL"),
+ PV("ARS04-MOCT-2860-OC:PS-MODE.VAL"),
+ PV("ARS04-MOCT-2950-OC:PS-MODE.VAL"),
+ PV("ARS04-MOCT-4040-OC:PS-MODE.VAL"),
+ PV("ARS04-MOCT-4130-OC:PS-MODE.VAL"),
+ PV("ARS04-MOCT-4260-OC:PS-MODE.VAL"),
+ PV("ARS04-MOCT-4540-OC:PS-MODE.VAL"),
+ PV("ARS04-MOCT-4630-OC:PS-MODE.VAL"),
+ PV("ARS04-MOCT-4760-OC:PS-MODE.VAL"),
+ PV("ARS04-MOCT-5040-OC:PS-MODE.VAL"),
+ PV("ARS04-MOCT-5150-OC:PS-MODE.VAL"),
+ PV("ARS04-MOCT-5550-OC:PS-MODE.VAL"),
+ PV("ARS04-MOCT-5660-OC:PS-MODE.VAL"),
+ PV("ARS04-MOCT-5760-OC:PS-MODE.VAL"),
+ PV("ARS05-MOCT-1230-OC:PS-MODE.VAL"),
+ PV("ARS05-MOCT-1330-OC:PS-MODE.VAL"),
+ PV("ARS05-MOCT-1440-OC:PS-MODE.VAL"),
+ PV("ARS05-MOCT-1840-OC:PS-MODE.VAL"),
+ PV("ARS05-MOCT-1950-OC:PS-MODE.VAL"),
+ PV("ARS05-MOCT-2230-OC:PS-MODE.VAL"),
+ PV("ARS05-MOCT-2360-OC:PS-MODE.VAL"),
+ PV("ARS05-MOCT-2450-OC:PS-MODE.VAL"),
+ PV("ARS05-MOCT-2730-OC:PS-MODE.VAL"),
+ PV("ARS05-MOCT-2860-OC:PS-MODE.VAL"),
+ PV("ARS05-MOCT-2950-OC:PS-MODE.VAL"),
+ PV("ARS05-MOCT-4040-OC:PS-MODE.VAL"),
+ PV("ARS05-MOCT-4130-OC:PS-MODE.VAL"),
+ PV("ARS05-MOCT-4260-OC:PS-MODE.VAL"),
+ PV("ARS05-MOCT-4540-OC:PS-MODE.VAL"),
+ PV("ARS05-MOCT-4630-OC:PS-MODE.VAL"),
+ PV("ARS05-MOCT-4760-OC:PS-MODE.VAL"),
+ PV("ARS05-MOCT-5040-OC:PS-MODE.VAL"),
+ PV("ARS05-MOCT-5150-OC:PS-MODE.VAL"),
+ PV("ARS05-MOCT-5550-OC:PS-MODE.VAL"),
+ PV("ARS05-MOCT-5660-OC:PS-MODE.VAL"),
+ PV("ARS05-MOCT-5760-OC:PS-MODE.VAL"),
+ PV("ARS06-MOCT-1230-OC:PS-MODE.VAL"),
+ PV("ARS06-MOCT-1330-OC:PS-MODE.VAL"),
+ PV("ARS06-MOCT-1440-OC:PS-MODE.VAL"),
+ PV("ARS06-MOCT-1840-OC:PS-MODE.VAL"),
+ PV("ARS06-MOCT-1950-OC:PS-MODE.VAL"),
+ PV("ARS06-MOCT-2230-OC:PS-MODE.VAL"),
+ PV("ARS06-MOCT-2360-OC:PS-MODE.VAL"),
+ PV("ARS06-MOCT-2450-OC:PS-MODE.VAL"),
+ PV("ARS06-MOCT-2730-OC:PS-MODE.VAL"),
+ PV("ARS06-MOCT-2860-OC:PS-MODE.VAL"),
+ PV("ARS06-MOCT-2950-OC:PS-MODE.VAL"),
+ PV("ARS06-MOCT-4040-OC:PS-MODE.VAL"),
+ PV("ARS06-MOCT-4130-OC:PS-MODE.VAL"),
+ PV("ARS06-MOCT-4260-OC:PS-MODE.VAL"),
+ PV("ARS06-MOCT-4540-OC:PS-MODE.VAL"),
+ PV("ARS06-MOCT-4630-OC:PS-MODE.VAL"),
+ PV("ARS06-MOCT-4760-OC:PS-MODE.VAL"),
+ PV("ARS06-MOCT-5040-OC:PS-MODE.VAL"),
+ PV("ARS06-MOCT-5150-OC:PS-MODE.VAL"),
+ PV("ARS06-MOCT-5550-OC:PS-MODE.VAL"),
+ PV("ARS06-MOCT-5660-OC:PS-MODE.VAL"),
+ PV("ARS06-MOCT-5760-OC:PS-MODE.VAL"),
+ PV("ARS07-MOCT-1230-OC:PS-MODE.VAL"),
+ PV("ARS07-MOCT-1330-OC:PS-MODE.VAL"),
+ PV("ARS07-MOCT-1440-OC:PS-MODE.VAL"),
+ PV("ARS07-MOCT-1840-OC:PS-MODE.VAL"),
+ PV("ARS07-MOCT-1950-OC:PS-MODE.VAL"),
+ PV("ARS07-MOCT-2230-OC:PS-MODE.VAL"),
+ PV("ARS07-MOCT-2360-OC:PS-MODE.VAL"),
+ PV("ARS07-MOCT-2450-OC:PS-MODE.VAL"),
+ PV("ARS07-MOCT-2730-OC:PS-MODE.VAL"),
+ PV("ARS07-MOCT-2860-OC:PS-MODE.VAL"),
+ PV("ARS07-MOCT-2950-OC:PS-MODE.VAL"),
+ PV("ARS07-MOCT-4040-OC:PS-MODE.VAL"),
+ PV("ARS07-MOCT-4130-OC:PS-MODE.VAL"),
+ PV("ARS07-MOCT-4260-OC:PS-MODE.VAL"),
+ PV("ARS07-MOCT-4540-OC:PS-MODE.VAL"),
+ PV("ARS07-MOCT-4630-OC:PS-MODE.VAL"),
+ PV("ARS07-MOCT-4760-OC:PS-MODE.VAL"),
+ PV("ARS07-MOCT-5040-OC:PS-MODE.VAL"),
+ PV("ARS07-MOCT-5150-OC:PS-MODE.VAL"),
+ PV("ARS07-MOCT-5550-OC:PS-MODE.VAL"),
+ PV("ARS07-MOCT-5660-OC:PS-MODE.VAL"),
+ PV("ARS07-MOCT-5760-OC:PS-MODE.VAL"),
+ PV("ARS08-MOCT-1230-OC:PS-MODE.VAL"),
+ PV("ARS08-MOCT-1330-OC:PS-MODE.VAL"),
+ PV("ARS08-MOCT-1440-OC:PS-MODE.VAL"),
+ PV("ARS08-MOCT-1840-OC:PS-MODE.VAL"),
+ PV("ARS08-MOCT-1950-OC:PS-MODE.VAL"),
+ PV("ARS08-MOCT-2230-OC:PS-MODE.VAL"),
+ PV("ARS08-MOCT-2360-OC:PS-MODE.VAL"),
+ PV("ARS08-MOCT-2450-OC:PS-MODE.VAL"),
+ PV("ARS08-MOCT-2730-OC:PS-MODE.VAL"),
+ PV("ARS08-MOCT-2860-OC:PS-MODE.VAL"),
+ PV("ARS08-MOCT-2950-OC:PS-MODE.VAL"),
+ PV("ARS08-MOCT-4040-OC:PS-MODE.VAL"),
+ PV("ARS08-MOCT-4130-OC:PS-MODE.VAL"),
+ PV("ARS08-MOCT-4260-OC:PS-MODE.VAL"),
+ PV("ARS08-MOCT-4540-OC:PS-MODE.VAL"),
+ PV("ARS08-MOCT-4630-OC:PS-MODE.VAL"),
+ PV("ARS08-MOCT-4760-OC:PS-MODE.VAL"),
+ PV("ARS08-MOCT-5040-OC:PS-MODE.VAL"),
+ PV("ARS08-MOCT-5150-OC:PS-MODE.VAL"),
+ PV("ARS08-MOCT-5550-OC:PS-MODE.VAL"),
+ PV("ARS08-MOCT-5660-OC:PS-MODE.VAL"),
+ PV("ARS08-MOCT-5760-OC:PS-MODE.VAL"),
+ PV("ARS09-MOCT-1230-OC:PS-MODE.VAL"),
+ PV("ARS09-MOCT-1330-OC:PS-MODE.VAL"),
+ PV("ARS09-MOCT-1440-OC:PS-MODE.VAL"),
+ PV("ARS09-MOCT-1840-OC:PS-MODE.VAL"),
+ PV("ARS09-MOCT-1950-OC:PS-MODE.VAL"),
+ PV("ARS09-MOCT-2230-OC:PS-MODE.VAL"),
+ PV("ARS09-MOCT-2360-OC:PS-MODE.VAL"),
+ PV("ARS09-MOCT-2450-OC:PS-MODE.VAL"),
+ PV("ARS09-MOCT-2730-OC:PS-MODE.VAL"),
+ PV("ARS09-MOCT-2860-OC:PS-MODE.VAL"),
+ PV("ARS09-MOCT-2950-OC:PS-MODE.VAL"),
+ PV("ARS09-MOCT-4040-OC:PS-MODE.VAL"),
+ PV("ARS09-MOCT-4130-OC:PS-MODE.VAL"),
+ PV("ARS09-MOCT-4260-OC:PS-MODE.VAL"),
+ PV("ARS09-MOCT-4540-OC:PS-MODE.VAL"),
+ PV("ARS09-MOCT-4630-OC:PS-MODE.VAL"),
+ PV("ARS09-MOCT-4760-OC:PS-MODE.VAL"),
+ PV("ARS09-MOCT-5040-OC:PS-MODE.VAL"),
+ PV("ARS09-MOCT-5150-OC:PS-MODE.VAL"),
+ PV("ARS09-MOCT-5550-OC:PS-MODE.VAL"),
+ PV("ARS09-MOCT-5660-OC:PS-MODE.VAL"),
+ PV("ARS09-MOCT-5760-OC:PS-MODE.VAL"),
+ PV("ARS10-MOCT-1230-OC:PS-MODE.VAL"),
+ PV("ARS10-MOCT-1330-OC:PS-MODE.VAL"),
+ PV("ARS10-MOCT-1440-OC:PS-MODE.VAL"),
+ PV("ARS10-MOCT-1840-OC:PS-MODE.VAL"),
+ PV("ARS10-MOCT-1950-OC:PS-MODE.VAL"),
+ PV("ARS10-MOCT-2230-OC:PS-MODE.VAL"),
+ PV("ARS10-MOCT-2360-OC:PS-MODE.VAL"),
+ PV("ARS10-MOCT-2450-OC:PS-MODE.VAL"),
+ PV("ARS10-MOCT-2730-OC:PS-MODE.VAL"),
+ PV("ARS10-MOCT-2860-OC:PS-MODE.VAL"),
+ PV("ARS10-MOCT-2950-OC:PS-MODE.VAL"),
+ PV("ARS10-MOCT-4040-OC:PS-MODE.VAL"),
+ PV("ARS10-MOCT-4130-OC:PS-MODE.VAL"),
+ PV("ARS10-MOCT-4260-OC:PS-MODE.VAL"),
+ PV("ARS10-MOCT-4540-OC:PS-MODE.VAL"),
+ PV("ARS10-MOCT-4630-OC:PS-MODE.VAL"),
+ PV("ARS10-MOCT-4760-OC:PS-MODE.VAL"),
+ PV("ARS10-MOCT-5040-OC:PS-MODE.VAL"),
+ PV("ARS10-MOCT-5150-OC:PS-MODE.VAL"),
+ PV("ARS10-MOCT-5550-OC:PS-MODE.VAL"),
+ PV("ARS10-MOCT-5660-OC:PS-MODE.VAL"),
+ PV("ARS10-MOCT-5760-OC:PS-MODE.VAL"),
+ PV("ARS11-MOCT-1230-OC:PS-MODE.VAL"),
+ PV("ARS11-MOCT-1330-OC:PS-MODE.VAL"),
+ PV("ARS11-MOCT-1440-OC:PS-MODE.VAL"),
+ PV("ARS11-MOCT-1840-OC:PS-MODE.VAL"),
+ PV("ARS11-MOCT-1950-OC:PS-MODE.VAL"),
+ PV("ARS11-MOCT-2230-OC:PS-MODE.VAL"),
+ PV("ARS11-MOCT-2360-OC:PS-MODE.VAL"),
+ PV("ARS11-MOCT-2450-OC:PS-MODE.VAL"),
+ PV("ARS11-MOCT-2730-OC:PS-MODE.VAL"),
+ PV("ARS11-MOCT-2860-OC:PS-MODE.VAL"),
+ PV("ARS11-MOCT-2950-OC:PS-MODE.VAL"),
+ PV("ARS11-MOCT-4040-OC:PS-MODE.VAL"),
+ PV("ARS11-MOCT-4130-OC:PS-MODE.VAL"),
+ PV("ARS11-MOCT-4260-OC:PS-MODE.VAL"),
+ PV("ARS11-MOCT-4540-OC:PS-MODE.VAL"),
+ PV("ARS11-MOCT-4630-OC:PS-MODE.VAL"),
+ PV("ARS11-MOCT-4760-OC:PS-MODE.VAL"),
+ PV("ARS11-MOCT-5040-OC:PS-MODE.VAL"),
+ PV("ARS11-MOCT-5150-OC:PS-MODE.VAL"),
+ PV("ARS11-MOCT-5550-OC:PS-MODE.VAL"),
+ PV("ARS11-MOCT-5660-OC:PS-MODE.VAL"),
+ PV("ARS11-MOCT-5760-OC:PS-MODE.VAL"),
+ PV("ARS12-MOCT-1230-OC:PS-MODE.VAL"),
+ PV("ARS12-MOCT-1330-OC:PS-MODE.VAL"),
+ PV("ARS12-MOCT-1440-OC:PS-MODE.VAL"),
+ PV("ARS12-MOCT-1840-OC:PS-MODE.VAL"),
+ PV("ARS12-MOCT-1950-OC:PS-MODE.VAL"),
+ PV("ARS12-MOCT-2230-OC:PS-MODE.VAL"),
+ PV("ARS12-MOCT-2360-OC:PS-MODE.VAL"),
+ PV("ARS12-MOCT-2450-OC:PS-MODE.VAL"),
+ PV("ARS12-MOCT-2730-OC:PS-MODE.VAL"),
+ PV("ARS12-MOCT-2860-OC:PS-MODE.VAL"),
+ PV("ARS12-MOCT-2950-OC:PS-MODE.VAL"),
+ PV("ARS12-MOCT-4040-OC:PS-MODE.VAL"),
+ PV("ARS12-MOCT-4130-OC:PS-MODE.VAL"),
+ PV("ARS12-MOCT-4260-OC:PS-MODE.VAL"),
+ PV("ARS12-MOCT-4540-OC:PS-MODE.VAL"),
+ PV("ARS12-MOCT-4630-OC:PS-MODE.VAL"),
+ PV("ARS12-MOCT-4760-OC:PS-MODE.VAL"),
+ PV("ARS12-MOCT-5040-OC:PS-MODE.VAL"),
+ PV("ARS12-MOCT-5150-OC:PS-MODE.VAL"),
+ PV("ARS12-MOCT-5550-OC:PS-MODE.VAL"),
+ PV("ARS12-MOCT-5660-OC:PS-MODE.VAL"),
+ PV("ARS12-MOCT-5760-OC:PS-MODE.VAL"),
+ PV("ARS01-MOCT-1230-QA:PS-MODE.VAL"),
+ PV("ARS01-MOCT-1330-QA:PS-MODE.VAL"),
+ PV("ARS01-MOCT-1440-QA:PS-MODE.VAL"),
+ PV("ARS01-MOCT-1840-QA:PS-MODE.VAL"),
+ PV("ARS01-MOCT-1950-QA:PS-MODE.VAL"),
+ PV("ARS01-MOCT-2230-QA:PS-MODE.VAL"),
+ PV("ARS01-MOCT-2360-QA:PS-MODE.VAL"),
+ PV("ARS01-MOCT-2450-QA:PS-MODE.VAL"),
+ PV("ARS01-MOCT-2730-QA:PS-MODE.VAL"),
+ PV("ARS01-MOCT-2860-QA:PS-MODE.VAL"),
+ PV("ARS01-MOCT-2950-QA:PS-MODE.VAL"),
+ PV("ARS01-MOCT-4040-QA:PS-MODE.VAL"),
+ PV("ARS01-MOCT-4130-QA:PS-MODE.VAL"),
+ PV("ARS01-MOCT-4260-QA:PS-MODE.VAL"),
+ PV("ARS01-MOCT-4540-QA:PS-MODE.VAL"),
+ PV("ARS01-MOCT-4630-QA:PS-MODE.VAL"),
+ PV("ARS01-MOCT-4760-QA:PS-MODE.VAL"),
+ PV("ARS01-MOCT-5040-QA:PS-MODE.VAL"),
+ PV("ARS01-MOCT-5150-QA:PS-MODE.VAL"),
+ PV("ARS01-MOCT-5550-QA:PS-MODE.VAL"),
+ PV("ARS01-MOCT-5660-QA:PS-MODE.VAL"),
+ PV("ARS01-MOCT-5760-QA:PS-MODE.VAL"),
+ PV("ARS02-MOCT-1230-QA:PS-MODE.VAL"),
+ PV("ARS02-MOCT-1330-QA:PS-MODE.VAL"),
+ PV("ARS02-MOCT-1440-QA:PS-MODE.VAL"),
+ PV("ARS02-MOCT-1840-QA:PS-MODE.VAL"),
+ PV("ARS02-MOCT-1950-QA:PS-MODE.VAL"),
+ PV("ARS02-MOCT-2230-QA:PS-MODE.VAL"),
+ PV("ARS02-MOCT-2360-QA:PS-MODE.VAL"),
+ PV("ARS02-MOCT-2450-QA:PS-MODE.VAL"),
+ PV("ARS02-MOCT-2730-QA:PS-MODE.VAL"),
+ PV("ARS02-MOCT-2860-QA:PS-MODE.VAL"),
+ PV("ARS02-MOCT-2950-QA:PS-MODE.VAL"),
+ PV("ARS02-MOCT-4040-QA:PS-MODE.VAL"),
+ PV("ARS02-MOCT-4130-QA:PS-MODE.VAL"),
+ PV("ARS02-MOCT-4260-QA:PS-MODE.VAL"),
+ PV("ARS02-MOCT-4540-QA:PS-MODE.VAL"),
+ PV("ARS02-MOCT-4630-QA:PS-MODE.VAL"),
+ PV("ARS02-MOCT-4760-QA:PS-MODE.VAL"),
+ PV("ARS02-MOCT-5040-QA:PS-MODE.VAL"),
+ PV("ARS02-MOCT-5150-QA:PS-MODE.VAL"),
+ PV("ARS02-MOCT-5550-QA:PS-MODE.VAL"),
+ PV("ARS02-MOCT-5660-QA:PS-MODE.VAL"),
+ PV("ARS02-MOCT-5760-QA:PS-MODE.VAL"),
+ PV("ARS03-MOCT-1230-QA:PS-MODE.VAL"),
+ PV("ARS03-MOCT-1330-QA:PS-MODE.VAL"),
+ PV("ARS03-MOCT-1440-QA:PS-MODE.VAL"),
+ PV("ARS03-MOCT-1840-QA:PS-MODE.VAL"),
+ PV("ARS03-MOCT-1950-QA:PS-MODE.VAL"),
+ PV("ARS03-MOCT-2230-QA:PS-MODE.VAL"),
+ PV("ARS03-MOCT-2360-QA:PS-MODE.VAL"),
+ PV("ARS03-MOCT-2450-QA:PS-MODE.VAL"),
+ PV("ARS03-MOCT-2730-QA:PS-MODE.VAL"),
+ PV("ARS03-MOCT-2860-QA:PS-MODE.VAL"),
+ PV("ARS03-MOCT-2950-QA:PS-MODE.VAL"),
+ PV("ARS03-MOCT-4040-QA:PS-MODE.VAL"),
+ PV("ARS03-MOCT-4130-QA:PS-MODE.VAL"),
+ PV("ARS03-MOCT-4260-QA:PS-MODE.VAL"),
+ PV("ARS03-MOCT-4540-QA:PS-MODE.VAL"),
+ PV("ARS03-MOCT-4630-QA:PS-MODE.VAL"),
+ PV("ARS03-MOCT-4760-QA:PS-MODE.VAL"),
+ PV("ARS03-MOCT-5040-QA:PS-MODE.VAL"),
+ PV("ARS03-MOCT-5150-QA:PS-MODE.VAL"),
+ PV("ARS03-MOCT-5550-QA:PS-MODE.VAL"),
+ PV("ARS03-MOCT-5660-QA:PS-MODE.VAL"),
+ PV("ARS03-MOCT-5760-QA:PS-MODE.VAL"),
+ PV("ARS04-MOCT-1230-QA:PS-MODE.VAL"),
+ PV("ARS04-MOCT-1330-QA:PS-MODE.VAL"),
+ PV("ARS04-MOCT-1440-QA:PS-MODE.VAL"),
+ PV("ARS04-MOCT-1840-QA:PS-MODE.VAL"),
+ PV("ARS04-MOCT-1950-QA:PS-MODE.VAL"),
+ PV("ARS04-MOCT-2230-QA:PS-MODE.VAL"),
+ PV("ARS04-MOCT-2360-QA:PS-MODE.VAL"),
+ PV("ARS04-MOCT-2450-QA:PS-MODE.VAL"),
+ PV("ARS04-MOCT-2730-QA:PS-MODE.VAL"),
+ PV("ARS04-MOCT-2860-QA:PS-MODE.VAL"),
+ PV("ARS04-MOCT-2950-QA:PS-MODE.VAL"),
+ PV("ARS04-MOCT-4040-QA:PS-MODE.VAL"),
+ PV("ARS04-MOCT-4130-QA:PS-MODE.VAL"),
+ PV("ARS04-MOCT-4260-QA:PS-MODE.VAL"),
+ PV("ARS04-MOCT-4540-QA:PS-MODE.VAL"),
+ PV("ARS04-MOCT-4630-QA:PS-MODE.VAL"),
+ PV("ARS04-MOCT-4760-QA:PS-MODE.VAL"),
+ PV("ARS04-MOCT-5040-QA:PS-MODE.VAL"),
+ PV("ARS04-MOCT-5150-QA:PS-MODE.VAL"),
+ PV("ARS04-MOCT-5550-QA:PS-MODE.VAL"),
+ PV("ARS04-MOCT-5660-QA:PS-MODE.VAL"),
+ PV("ARS04-MOCT-5760-QA:PS-MODE.VAL"),
+ PV("ARS05-MOCT-1230-QA:PS-MODE.VAL"),
+ PV("ARS05-MOCT-1330-QA:PS-MODE.VAL"),
+ PV("ARS05-MOCT-1440-QA:PS-MODE.VAL"),
+ PV("ARS05-MOCT-1840-QA:PS-MODE.VAL"),
+ PV("ARS05-MOCT-1950-QA:PS-MODE.VAL"),
+ PV("ARS05-MOCT-2230-QA:PS-MODE.VAL"),
+ PV("ARS05-MOCT-2360-QA:PS-MODE.VAL"),
+ PV("ARS05-MOCT-2450-QA:PS-MODE.VAL"),
+ PV("ARS05-MOCT-2730-QA:PS-MODE.VAL"),
+ PV("ARS05-MOCT-2860-QA:PS-MODE.VAL"),
+ PV("ARS05-MOCT-2950-QA:PS-MODE.VAL"),
+ PV("ARS05-MOCT-4040-QA:PS-MODE.VAL"),
+ PV("ARS05-MOCT-4130-QA:PS-MODE.VAL"),
+ PV("ARS05-MOCT-4260-QA:PS-MODE.VAL"),
+ PV("ARS05-MOCT-4540-QA:PS-MODE.VAL"),
+ PV("ARS05-MOCT-4630-QA:PS-MODE.VAL"),
+ PV("ARS05-MOCT-4760-QA:PS-MODE.VAL"),
+ PV("ARS05-MOCT-5040-QA:PS-MODE.VAL"),
+ PV("ARS05-MOCT-5150-QA:PS-MODE.VAL"),
+ PV("ARS05-MOCT-5550-QA:PS-MODE.VAL"),
+ PV("ARS05-MOCT-5660-QA:PS-MODE.VAL"),
+ PV("ARS05-MOCT-5760-QA:PS-MODE.VAL"),
+ PV("ARS06-MOCT-1230-QA:PS-MODE.VAL"),
+ PV("ARS06-MOCT-1330-QA:PS-MODE.VAL"),
+ PV("ARS06-MOCT-1440-QA:PS-MODE.VAL"),
+ PV("ARS06-MOCT-1840-QA:PS-MODE.VAL"),
+ PV("ARS06-MOCT-1950-QA:PS-MODE.VAL"),
+ PV("ARS06-MOCT-2230-QA:PS-MODE.VAL"),
+ PV("ARS06-MOCT-2360-QA:PS-MODE.VAL"),
+ PV("ARS06-MOCT-2450-QA:PS-MODE.VAL"),
+ PV("ARS06-MOCT-2730-QA:PS-MODE.VAL"),
+ PV("ARS06-MOCT-2860-QA:PS-MODE.VAL"),
+ PV("ARS06-MOCT-2950-QA:PS-MODE.VAL"),
+ PV("ARS06-MOCT-4040-QA:PS-MODE.VAL"),
+ PV("ARS06-MOCT-4130-QA:PS-MODE.VAL"),
+ PV("ARS06-MOCT-4260-QA:PS-MODE.VAL"),
+ PV("ARS06-MOCT-4540-QA:PS-MODE.VAL"),
+ PV("ARS06-MOCT-4630-QA:PS-MODE.VAL"),
+ PV("ARS06-MOCT-4760-QA:PS-MODE.VAL"),
+ PV("ARS06-MOCT-5040-QA:PS-MODE.VAL"),
+ PV("ARS06-MOCT-5150-QA:PS-MODE.VAL"),
+ PV("ARS06-MOCT-5550-QA:PS-MODE.VAL"),
+ PV("ARS06-MOCT-5660-QA:PS-MODE.VAL"),
+ PV("ARS06-MOCT-5760-QA:PS-MODE.VAL"),
+ PV("ARS07-MOCT-1230-QA:PS-MODE.VAL"),
+ PV("ARS07-MOCT-1330-QA:PS-MODE.VAL"),
+ PV("ARS07-MOCT-1440-QA:PS-MODE.VAL"),
+ PV("ARS07-MOCT-1840-QA:PS-MODE.VAL"),
+ PV("ARS07-MOCT-1950-QA:PS-MODE.VAL"),
+ PV("ARS07-MOCT-2230-QA:PS-MODE.VAL"),
+ PV("ARS07-MOCT-2360-QA:PS-MODE.VAL"),
+ PV("ARS07-MOCT-2450-QA:PS-MODE.VAL"),
+ PV("ARS07-MOCT-2730-QA:PS-MODE.VAL"),
+ PV("ARS07-MOCT-2860-QA:PS-MODE.VAL"),
+ PV("ARS07-MOCT-2950-QA:PS-MODE.VAL"),
+ PV("ARS07-MOCT-4040-QA:PS-MODE.VAL"),
+ PV("ARS07-MOCT-4130-QA:PS-MODE.VAL"),
+ PV("ARS07-MOCT-4260-QA:PS-MODE.VAL"),
+ PV("ARS07-MOCT-4540-QA:PS-MODE.VAL"),
+ PV("ARS07-MOCT-4630-QA:PS-MODE.VAL"),
+ PV("ARS07-MOCT-4760-QA:PS-MODE.VAL"),
+ PV("ARS07-MOCT-5040-QA:PS-MODE.VAL"),
+ PV("ARS07-MOCT-5150-QA:PS-MODE.VAL"),
+ PV("ARS07-MOCT-5550-QA:PS-MODE.VAL"),
+ PV("ARS07-MOCT-5660-QA:PS-MODE.VAL"),
+ PV("ARS07-MOCT-5760-QA:PS-MODE.VAL"),
+ PV("ARS08-MOCT-1230-QA:PS-MODE.VAL"),
+ PV("ARS08-MOCT-1330-QA:PS-MODE.VAL"),
+ PV("ARS08-MOCT-1440-QA:PS-MODE.VAL"),
+ PV("ARS08-MOCT-1840-QA:PS-MODE.VAL"),
+ PV("ARS08-MOCT-1950-QA:PS-MODE.VAL"),
+ PV("ARS08-MOCT-2230-QA:PS-MODE.VAL"),
+ PV("ARS08-MOCT-2360-QA:PS-MODE.VAL"),
+ PV("ARS08-MOCT-2450-QA:PS-MODE.VAL"),
+ PV("ARS08-MOCT-2730-QA:PS-MODE.VAL"),
+ PV("ARS08-MOCT-2860-QA:PS-MODE.VAL"),
+ PV("ARS08-MOCT-2950-QA:PS-MODE.VAL"),
+ PV("ARS08-MOCT-4040-QA:PS-MODE.VAL"),
+ PV("ARS08-MOCT-4130-QA:PS-MODE.VAL"),
+ PV("ARS08-MOCT-4260-QA:PS-MODE.VAL"),
+ PV("ARS08-MOCT-4540-QA:PS-MODE.VAL"),
+ PV("ARS08-MOCT-4630-QA:PS-MODE.VAL"),
+ PV("ARS08-MOCT-4760-QA:PS-MODE.VAL"),
+ PV("ARS08-MOCT-5040-QA:PS-MODE.VAL"),
+ PV("ARS08-MOCT-5150-QA:PS-MODE.VAL"),
+ PV("ARS08-MOCT-5550-QA:PS-MODE.VAL"),
+ PV("ARS08-MOCT-5660-QA:PS-MODE.VAL"),
+ PV("ARS08-MOCT-5760-QA:PS-MODE.VAL"),
+ PV("ARS09-MOCT-1230-QA:PS-MODE.VAL"),
+ PV("ARS09-MOCT-1330-QA:PS-MODE.VAL"),
+ PV("ARS09-MOCT-1440-QA:PS-MODE.VAL"),
+ PV("ARS09-MOCT-1840-QA:PS-MODE.VAL"),
+ PV("ARS09-MOCT-1950-QA:PS-MODE.VAL"),
+ PV("ARS09-MOCT-2230-QA:PS-MODE.VAL"),
+ PV("ARS09-MOCT-2360-QA:PS-MODE.VAL"),
+ PV("ARS09-MOCT-2450-QA:PS-MODE.VAL"),
+ PV("ARS09-MOCT-2730-QA:PS-MODE.VAL"),
+ PV("ARS09-MOCT-2860-QA:PS-MODE.VAL"),
+ PV("ARS09-MOCT-2950-QA:PS-MODE.VAL"),
+ PV("ARS09-MOCT-4040-QA:PS-MODE.VAL"),
+ PV("ARS09-MOCT-4130-QA:PS-MODE.VAL"),
+ PV("ARS09-MOCT-4260-QA:PS-MODE.VAL"),
+ PV("ARS09-MOCT-4540-QA:PS-MODE.VAL"),
+ PV("ARS09-MOCT-4630-QA:PS-MODE.VAL"),
+ PV("ARS09-MOCT-4760-QA:PS-MODE.VAL"),
+ PV("ARS09-MOCT-5040-QA:PS-MODE.VAL"),
+ PV("ARS09-MOCT-5150-QA:PS-MODE.VAL"),
+ PV("ARS09-MOCT-5550-QA:PS-MODE.VAL"),
+ PV("ARS09-MOCT-5660-QA:PS-MODE.VAL"),
+ PV("ARS09-MOCT-5760-QA:PS-MODE.VAL"),
+ PV("ARS10-MOCT-1230-QA:PS-MODE.VAL"),
+ PV("ARS10-MOCT-1330-QA:PS-MODE.VAL"),
+ PV("ARS10-MOCT-1440-QA:PS-MODE.VAL"),
+ PV("ARS10-MOCT-1840-QA:PS-MODE.VAL"),
+ PV("ARS10-MOCT-1950-QA:PS-MODE.VAL"),
+ PV("ARS10-MOCT-2230-QA:PS-MODE.VAL"),
+ PV("ARS10-MOCT-2360-QA:PS-MODE.VAL"),
+ PV("ARS10-MOCT-2450-QA:PS-MODE.VAL"),
+ PV("ARS10-MOCT-2730-QA:PS-MODE.VAL"),
+ PV("ARS10-MOCT-2860-QA:PS-MODE.VAL"),
+ PV("ARS10-MOCT-2950-QA:PS-MODE.VAL"),
+ PV("ARS10-MOCT-4040-QA:PS-MODE.VAL"),
+ PV("ARS10-MOCT-4130-QA:PS-MODE.VAL"),
+ PV("ARS10-MOCT-4260-QA:PS-MODE.VAL"),
+ PV("ARS10-MOCT-4540-QA:PS-MODE.VAL"),
+ PV("ARS10-MOCT-4630-QA:PS-MODE.VAL"),
+ PV("ARS10-MOCT-4760-QA:PS-MODE.VAL"),
+ PV("ARS10-MOCT-5040-QA:PS-MODE.VAL"),
+ PV("ARS10-MOCT-5150-QA:PS-MODE.VAL"),
+ PV("ARS10-MOCT-5550-QA:PS-MODE.VAL"),
+ PV("ARS10-MOCT-5660-QA:PS-MODE.VAL"),
+ PV("ARS10-MOCT-5760-QA:PS-MODE.VAL"),
+ PV("ARS11-MOCT-1230-QA:PS-MODE.VAL"),
+ PV("ARS11-MOCT-1330-QA:PS-MODE.VAL"),
+ PV("ARS11-MOCT-1440-QA:PS-MODE.VAL"),
+ PV("ARS11-MOCT-1840-QA:PS-MODE.VAL"),
+ PV("ARS11-MOCT-1950-QA:PS-MODE.VAL"),
+ PV("ARS11-MOCT-2230-QA:PS-MODE.VAL"),
+ PV("ARS11-MOCT-2360-QA:PS-MODE.VAL"),
+ PV("ARS11-MOCT-2450-QA:PS-MODE.VAL"),
+ PV("ARS11-MOCT-2730-QA:PS-MODE.VAL"),
+ PV("ARS11-MOCT-2860-QA:PS-MODE.VAL"),
+ PV("ARS11-MOCT-2950-QA:PS-MODE.VAL"),
+ PV("ARS11-MOCT-4040-QA:PS-MODE.VAL"),
+ PV("ARS11-MOCT-4130-QA:PS-MODE.VAL"),
+ PV("ARS11-MOCT-4260-QA:PS-MODE.VAL"),
+ PV("ARS11-MOCT-4540-QA:PS-MODE.VAL"),
+ PV("ARS11-MOCT-4630-QA:PS-MODE.VAL"),
+ PV("ARS11-MOCT-4760-QA:PS-MODE.VAL"),
+ PV("ARS11-MOCT-5040-QA:PS-MODE.VAL"),
+ PV("ARS11-MOCT-5150-QA:PS-MODE.VAL"),
+ PV("ARS11-MOCT-5550-QA:PS-MODE.VAL"),
+ PV("ARS11-MOCT-5660-QA:PS-MODE.VAL"),
+ PV("ARS11-MOCT-5760-QA:PS-MODE.VAL"),
+ PV("ARS12-MOCT-1230-QA:PS-MODE.VAL"),
+ PV("ARS12-MOCT-1330-QA:PS-MODE.VAL"),
+ PV("ARS12-MOCT-1440-QA:PS-MODE.VAL"),
+ PV("ARS12-MOCT-1840-QA:PS-MODE.VAL"),
+ PV("ARS12-MOCT-1950-QA:PS-MODE.VAL"),
+ PV("ARS12-MOCT-2230-QA:PS-MODE.VAL"),
+ PV("ARS12-MOCT-2360-QA:PS-MODE.VAL"),
+ PV("ARS12-MOCT-2450-QA:PS-MODE.VAL"),
+ PV("ARS12-MOCT-2730-QA:PS-MODE.VAL"),
+ PV("ARS12-MOCT-2860-QA:PS-MODE.VAL"),
+ PV("ARS12-MOCT-2950-QA:PS-MODE.VAL"),
+ PV("ARS12-MOCT-4040-QA:PS-MODE.VAL"),
+ PV("ARS12-MOCT-4130-QA:PS-MODE.VAL"),
+ PV("ARS12-MOCT-4260-QA:PS-MODE.VAL"),
+ PV("ARS12-MOCT-4540-QA:PS-MODE.VAL"),
+ PV("ARS12-MOCT-4630-QA:PS-MODE.VAL"),
+ PV("ARS12-MOCT-4760-QA:PS-MODE.VAL"),
+ PV("ARS12-MOCT-5040-QA:PS-MODE.VAL"),
+ PV("ARS12-MOCT-5150-QA:PS-MODE.VAL"),
+ PV("ARS12-MOCT-5550-QA:PS-MODE.VAL"),
+ PV("ARS12-MOCT-5660-QA:PS-MODE.VAL"),
+ PV("ARS12-MOCT-5760-QA:PS-MODE.VAL"),
+ PV("ARS01-MOCT-1230-QS:PS-MODE.VAL"),
+ PV("ARS01-MOCT-1330-QS:PS-MODE.VAL"),
+ PV("ARS01-MOCT-1440-QS:PS-MODE.VAL"),
+ PV("ARS01-MOCT-1840-QS:PS-MODE.VAL"),
+ PV("ARS01-MOCT-1950-QS:PS-MODE.VAL"),
+ PV("ARS01-MOCT-2230-QS:PS-MODE.VAL"),
+ PV("ARS01-MOCT-2360-QS:PS-MODE.VAL"),
+ PV("ARS01-MOCT-2450-QS:PS-MODE.VAL"),
+ PV("ARS01-MOCT-2730-QS:PS-MODE.VAL"),
+ PV("ARS01-MOCT-2860-QS:PS-MODE.VAL"),
+ PV("ARS01-MOCT-2950-QS:PS-MODE.VAL"),
+ PV("ARS01-MOCT-4040-QS:PS-MODE.VAL"),
+ PV("ARS01-MOCT-4130-QS:PS-MODE.VAL"),
+ PV("ARS01-MOCT-4260-QS:PS-MODE.VAL"),
+ PV("ARS01-MOCT-4540-QS:PS-MODE.VAL"),
+ PV("ARS01-MOCT-4630-QS:PS-MODE.VAL"),
+ PV("ARS01-MOCT-4760-QS:PS-MODE.VAL"),
+ PV("ARS01-MOCT-5040-QS:PS-MODE.VAL"),
+ PV("ARS01-MOCT-5150-QS:PS-MODE.VAL"),
+ PV("ARS01-MOCT-5550-QS:PS-MODE.VAL"),
+ PV("ARS01-MOCT-5660-QS:PS-MODE.VAL"),
+ PV("ARS01-MOCT-5760-QS:PS-MODE.VAL"),
+ PV("ARS02-MOCT-1230-QS:PS-MODE.VAL"),
+ PV("ARS02-MOCT-1330-QS:PS-MODE.VAL"),
+ PV("ARS02-MOCT-1440-QS:PS-MODE.VAL"),
+ PV("ARS02-MOCT-1840-QS:PS-MODE.VAL"),
+ PV("ARS02-MOCT-1950-QS:PS-MODE.VAL"),
+ PV("ARS02-MOCT-2230-QS:PS-MODE.VAL"),
+ PV("ARS02-MOCT-2360-QS:PS-MODE.VAL"),
+ PV("ARS02-MOCT-2450-QS:PS-MODE.VAL"),
+ PV("ARS02-MOCT-2730-QS:PS-MODE.VAL"),
+ PV("ARS02-MOCT-2860-QS:PS-MODE.VAL"),
+ PV("ARS02-MOCT-2950-QS:PS-MODE.VAL"),
+ PV("ARS02-MOCT-4040-QS:PS-MODE.VAL"),
+ PV("ARS02-MOCT-4130-QS:PS-MODE.VAL"),
+ PV("ARS02-MOCT-4260-QS:PS-MODE.VAL"),
+ PV("ARS02-MOCT-4540-QS:PS-MODE.VAL"),
+ PV("ARS02-MOCT-4630-QS:PS-MODE.VAL"),
+ PV("ARS02-MOCT-4760-QS:PS-MODE.VAL"),
+ PV("ARS02-MOCT-5040-QS:PS-MODE.VAL"),
+ PV("ARS02-MOCT-5150-QS:PS-MODE.VAL"),
+ PV("ARS02-MOCT-5550-QS:PS-MODE.VAL"),
+ PV("ARS02-MOCT-5660-QS:PS-MODE.VAL"),
+ PV("ARS02-MOCT-5760-QS:PS-MODE.VAL"),
+ PV("ARS03-MOCT-1230-QS:PS-MODE.VAL"),
+ PV("ARS03-MOCT-1330-QS:PS-MODE.VAL"),
+ PV("ARS03-MOCT-1440-QS:PS-MODE.VAL"),
+ PV("ARS03-MOCT-1840-QS:PS-MODE.VAL"),
+ PV("ARS03-MOCT-1950-QS:PS-MODE.VAL"),
+ PV("ARS03-MOCT-2230-QS:PS-MODE.VAL"),
+ PV("ARS03-MOCT-2360-QS:PS-MODE.VAL"),
+ PV("ARS03-MOCT-2450-QS:PS-MODE.VAL"),
+ PV("ARS03-MOCT-2730-QS:PS-MODE.VAL"),
+ PV("ARS03-MOCT-2860-QS:PS-MODE.VAL"),
+ PV("ARS03-MOCT-2950-QS:PS-MODE.VAL"),
+ PV("ARS03-MOCT-4040-QS:PS-MODE.VAL"),
+ PV("ARS03-MOCT-4130-QS:PS-MODE.VAL"),
+ PV("ARS03-MOCT-4260-QS:PS-MODE.VAL"),
+ PV("ARS03-MOCT-4540-QS:PS-MODE.VAL"),
+ PV("ARS03-MOCT-4630-QS:PS-MODE.VAL"),
+ PV("ARS03-MOCT-4760-QS:PS-MODE.VAL"),
+ PV("ARS03-MOCT-5040-QS:PS-MODE.VAL"),
+ PV("ARS03-MOCT-5150-QS:PS-MODE.VAL"),
+ PV("ARS03-MOCT-5550-QS:PS-MODE.VAL"),
+ PV("ARS03-MOCT-5660-QS:PS-MODE.VAL"),
+ PV("ARS03-MOCT-5760-QS:PS-MODE.VAL"),
+ PV("ARS04-MOCT-1230-QS:PS-MODE.VAL"),
+ PV("ARS04-MOCT-1330-QS:PS-MODE.VAL"),
+ PV("ARS04-MOCT-1440-QS:PS-MODE.VAL"),
+ PV("ARS04-MOCT-1840-QS:PS-MODE.VAL"),
+ PV("ARS04-MOCT-1950-QS:PS-MODE.VAL"),
+ PV("ARS04-MOCT-2230-QS:PS-MODE.VAL"),
+ PV("ARS04-MOCT-2360-QS:PS-MODE.VAL"),
+ PV("ARS04-MOCT-2450-QS:PS-MODE.VAL"),
+ PV("ARS04-MOCT-2730-QS:PS-MODE.VAL"),
+ PV("ARS04-MOCT-2860-QS:PS-MODE.VAL"),
+ PV("ARS04-MOCT-2950-QS:PS-MODE.VAL"),
+ PV("ARS04-MOCT-4040-QS:PS-MODE.VAL"),
+ PV("ARS04-MOCT-4130-QS:PS-MODE.VAL"),
+ PV("ARS04-MOCT-4260-QS:PS-MODE.VAL"),
+ PV("ARS04-MOCT-4540-QS:PS-MODE.VAL"),
+ PV("ARS04-MOCT-4630-QS:PS-MODE.VAL"),
+ PV("ARS04-MOCT-4760-QS:PS-MODE.VAL"),
+ PV("ARS04-MOCT-5040-QS:PS-MODE.VAL"),
+ PV("ARS04-MOCT-5150-QS:PS-MODE.VAL"),
+ PV("ARS04-MOCT-5550-QS:PS-MODE.VAL"),
+ PV("ARS04-MOCT-5660-QS:PS-MODE.VAL"),
+ PV("ARS04-MOCT-5760-QS:PS-MODE.VAL"),
+ PV("ARS05-MOCT-1230-QS:PS-MODE.VAL"),
+ PV("ARS05-MOCT-1330-QS:PS-MODE.VAL"),
+ PV("ARS05-MOCT-1440-QS:PS-MODE.VAL"),
+ PV("ARS05-MOCT-1840-QS:PS-MODE.VAL"),
+ PV("ARS05-MOCT-1950-QS:PS-MODE.VAL"),
+ PV("ARS05-MOCT-2230-QS:PS-MODE.VAL"),
+ PV("ARS05-MOCT-2360-QS:PS-MODE.VAL"),
+ PV("ARS05-MOCT-2450-QS:PS-MODE.VAL"),
+ PV("ARS05-MOCT-2730-QS:PS-MODE.VAL"),
+ PV("ARS05-MOCT-2860-QS:PS-MODE.VAL"),
+ PV("ARS05-MOCT-2950-QS:PS-MODE.VAL"),
+ PV("ARS05-MOCT-4040-QS:PS-MODE.VAL"),
+ PV("ARS05-MOCT-4130-QS:PS-MODE.VAL"),
+ PV("ARS05-MOCT-4260-QS:PS-MODE.VAL"),
+ PV("ARS05-MOCT-4540-QS:PS-MODE.VAL"),
+ PV("ARS05-MOCT-4630-QS:PS-MODE.VAL"),
+ PV("ARS05-MOCT-4760-QS:PS-MODE.VAL"),
+ PV("ARS05-MOCT-5040-QS:PS-MODE.VAL"),
+ PV("ARS05-MOCT-5150-QS:PS-MODE.VAL"),
+ PV("ARS05-MOCT-5550-QS:PS-MODE.VAL"),
+ PV("ARS05-MOCT-5660-QS:PS-MODE.VAL"),
+ PV("ARS05-MOCT-5760-QS:PS-MODE.VAL"),
+ PV("ARS06-MOCT-1230-QS:PS-MODE.VAL"),
+ PV("ARS06-MOCT-1330-QS:PS-MODE.VAL"),
+ PV("ARS06-MOCT-1440-QS:PS-MODE.VAL"),
+ PV("ARS06-MOCT-1840-QS:PS-MODE.VAL"),
+ PV("ARS06-MOCT-1950-QS:PS-MODE.VAL"),
+ PV("ARS06-MOCT-2230-QS:PS-MODE.VAL"),
+ PV("ARS06-MOCT-2360-QS:PS-MODE.VAL"),
+ PV("ARS06-MOCT-2450-QS:PS-MODE.VAL"),
+ PV("ARS06-MOCT-2730-QS:PS-MODE.VAL"),
+ PV("ARS06-MOCT-2860-QS:PS-MODE.VAL"),
+ PV("ARS06-MOCT-2950-QS:PS-MODE.VAL"),
+ PV("ARS06-MOCT-4040-QS:PS-MODE.VAL"),
+ PV("ARS06-MOCT-4130-QS:PS-MODE.VAL"),
+ PV("ARS06-MOCT-4260-QS:PS-MODE.VAL"),
+ PV("ARS06-MOCT-4540-QS:PS-MODE.VAL"),
+ PV("ARS06-MOCT-4630-QS:PS-MODE.VAL"),
+ PV("ARS06-MOCT-4760-QS:PS-MODE.VAL"),
+ PV("ARS06-MOCT-5040-QS:PS-MODE.VAL"),
+ PV("ARS06-MOCT-5150-QS:PS-MODE.VAL"),
+ PV("ARS06-MOCT-5550-QS:PS-MODE.VAL"),
+ PV("ARS06-MOCT-5660-QS:PS-MODE.VAL"),
+ PV("ARS06-MOCT-5760-QS:PS-MODE.VAL"),
+ PV("ARS07-MOCT-1230-QS:PS-MODE.VAL"),
+ PV("ARS07-MOCT-1330-QS:PS-MODE.VAL"),
+ PV("ARS07-MOCT-1440-QS:PS-MODE.VAL"),
+ PV("ARS07-MOCT-1840-QS:PS-MODE.VAL"),
+ PV("ARS07-MOCT-1950-QS:PS-MODE.VAL"),
+ PV("ARS07-MOCT-2230-QS:PS-MODE.VAL"),
+ PV("ARS07-MOCT-2360-QS:PS-MODE.VAL"),
+ PV("ARS07-MOCT-2450-QS:PS-MODE.VAL"),
+ PV("ARS07-MOCT-2730-QS:PS-MODE.VAL"),
+ PV("ARS07-MOCT-2860-QS:PS-MODE.VAL"),
+ PV("ARS07-MOCT-2950-QS:PS-MODE.VAL"),
+ PV("ARS07-MOCT-4040-QS:PS-MODE.VAL"),
+ PV("ARS07-MOCT-4130-QS:PS-MODE.VAL"),
+ PV("ARS07-MOCT-4260-QS:PS-MODE.VAL"),
+ PV("ARS07-MOCT-4540-QS:PS-MODE.VAL"),
+ PV("ARS07-MOCT-4630-QS:PS-MODE.VAL"),
+ PV("ARS07-MOCT-4760-QS:PS-MODE.VAL"),
+ PV("ARS07-MOCT-5040-QS:PS-MODE.VAL"),
+ PV("ARS07-MOCT-5150-QS:PS-MODE.VAL"),
+ PV("ARS07-MOCT-5550-QS:PS-MODE.VAL"),
+ PV("ARS07-MOCT-5660-QS:PS-MODE.VAL"),
+ PV("ARS07-MOCT-5760-QS:PS-MODE.VAL"),
+ PV("ARS08-MOCT-1230-QS:PS-MODE.VAL"),
+ PV("ARS08-MOCT-1330-QS:PS-MODE.VAL"),
+ PV("ARS08-MOCT-1440-QS:PS-MODE.VAL"),
+ PV("ARS08-MOCT-1840-QS:PS-MODE.VAL"),
+ PV("ARS08-MOCT-1950-QS:PS-MODE.VAL"),
+ PV("ARS08-MOCT-2230-QS:PS-MODE.VAL"),
+ PV("ARS08-MOCT-2360-QS:PS-MODE.VAL"),
+ PV("ARS08-MOCT-2450-QS:PS-MODE.VAL"),
+ PV("ARS08-MOCT-2730-QS:PS-MODE.VAL"),
+ PV("ARS08-MOCT-2860-QS:PS-MODE.VAL"),
+ PV("ARS08-MOCT-2950-QS:PS-MODE.VAL"),
+ PV("ARS08-MOCT-4040-QS:PS-MODE.VAL"),
+ PV("ARS08-MOCT-4130-QS:PS-MODE.VAL"),
+ PV("ARS08-MOCT-4260-QS:PS-MODE.VAL"),
+ PV("ARS08-MOCT-4540-QS:PS-MODE.VAL"),
+ PV("ARS08-MOCT-4630-QS:PS-MODE.VAL"),
+ PV("ARS08-MOCT-4760-QS:PS-MODE.VAL"),
+ PV("ARS08-MOCT-5040-QS:PS-MODE.VAL"),
+ PV("ARS08-MOCT-5150-QS:PS-MODE.VAL"),
+ PV("ARS08-MOCT-5550-QS:PS-MODE.VAL"),
+ PV("ARS08-MOCT-5660-QS:PS-MODE.VAL"),
+ PV("ARS08-MOCT-5760-QS:PS-MODE.VAL"),
+ PV("ARS09-MOCT-1230-QS:PS-MODE.VAL"),
+ PV("ARS09-MOCT-1330-QS:PS-MODE.VAL"),
+ PV("ARS09-MOCT-1440-QS:PS-MODE.VAL"),
+ PV("ARS09-MOCT-1840-QS:PS-MODE.VAL"),
+ PV("ARS09-MOCT-1950-QS:PS-MODE.VAL"),
+ PV("ARS09-MOCT-2230-QS:PS-MODE.VAL"),
+ PV("ARS09-MOCT-2360-QS:PS-MODE.VAL"),
+ PV("ARS09-MOCT-2450-QS:PS-MODE.VAL"),
+ PV("ARS09-MOCT-2730-QS:PS-MODE.VAL"),
+ PV("ARS09-MOCT-2860-QS:PS-MODE.VAL"),
+ PV("ARS09-MOCT-2950-QS:PS-MODE.VAL"),
+ PV("ARS09-MOCT-4040-QS:PS-MODE.VAL"),
+ PV("ARS09-MOCT-4130-QS:PS-MODE.VAL"),
+ PV("ARS09-MOCT-4260-QS:PS-MODE.VAL"),
+ PV("ARS09-MOCT-4540-QS:PS-MODE.VAL"),
+ PV("ARS09-MOCT-4630-QS:PS-MODE.VAL"),
+ PV("ARS09-MOCT-4760-QS:PS-MODE.VAL"),
+ PV("ARS09-MOCT-5040-QS:PS-MODE.VAL"),
+ PV("ARS09-MOCT-5150-QS:PS-MODE.VAL"),
+ PV("ARS09-MOCT-5550-QS:PS-MODE.VAL"),
+ PV("ARS09-MOCT-5660-QS:PS-MODE.VAL"),
+ PV("ARS09-MOCT-5760-QS:PS-MODE.VAL"),
+ PV("ARS10-MOCT-1230-QS:PS-MODE.VAL"),
+ PV("ARS10-MOCT-1330-QS:PS-MODE.VAL"),
+ PV("ARS10-MOCT-1440-QS:PS-MODE.VAL"),
+ PV("ARS10-MOCT-1840-QS:PS-MODE.VAL"),
+ PV("ARS10-MOCT-1950-QS:PS-MODE.VAL"),
+ PV("ARS10-MOCT-2230-QS:PS-MODE.VAL"),
+ PV("ARS10-MOCT-2360-QS:PS-MODE.VAL"),
+ PV("ARS10-MOCT-2450-QS:PS-MODE.VAL"),
+ PV("ARS10-MOCT-2730-QS:PS-MODE.VAL"),
+ PV("ARS10-MOCT-2860-QS:PS-MODE.VAL"),
+ PV("ARS10-MOCT-2950-QS:PS-MODE.VAL"),
+ PV("ARS10-MOCT-4040-QS:PS-MODE.VAL"),
+ PV("ARS10-MOCT-4130-QS:PS-MODE.VAL"),
+ PV("ARS10-MOCT-4260-QS:PS-MODE.VAL"),
+ PV("ARS10-MOCT-4540-QS:PS-MODE.VAL"),
+ PV("ARS10-MOCT-4630-QS:PS-MODE.VAL"),
+ PV("ARS10-MOCT-4760-QS:PS-MODE.VAL"),
+ PV("ARS10-MOCT-5040-QS:PS-MODE.VAL"),
+ PV("ARS10-MOCT-5150-QS:PS-MODE.VAL"),
+ PV("ARS10-MOCT-5550-QS:PS-MODE.VAL"),
+ PV("ARS10-MOCT-5660-QS:PS-MODE.VAL"),
+ PV("ARS10-MOCT-5760-QS:PS-MODE.VAL"),
+ PV("ARS11-MOCT-1230-QS:PS-MODE.VAL"),
+ PV("ARS11-MOCT-1330-QS:PS-MODE.VAL"),
+ PV("ARS11-MOCT-1440-QS:PS-MODE.VAL"),
+ PV("ARS11-MOCT-1840-QS:PS-MODE.VAL"),
+ PV("ARS11-MOCT-1950-QS:PS-MODE.VAL"),
+ PV("ARS11-MOCT-2230-QS:PS-MODE.VAL"),
+ PV("ARS11-MOCT-2360-QS:PS-MODE.VAL"),
+ PV("ARS11-MOCT-2450-QS:PS-MODE.VAL"),
+ PV("ARS11-MOCT-2730-QS:PS-MODE.VAL"),
+ PV("ARS11-MOCT-2860-QS:PS-MODE.VAL"),
+ PV("ARS11-MOCT-2950-QS:PS-MODE.VAL"),
+ PV("ARS11-MOCT-4040-QS:PS-MODE.VAL"),
+ PV("ARS11-MOCT-4130-QS:PS-MODE.VAL"),
+ PV("ARS11-MOCT-4260-QS:PS-MODE.VAL"),
+ PV("ARS11-MOCT-4540-QS:PS-MODE.VAL"),
+ PV("ARS11-MOCT-4630-QS:PS-MODE.VAL"),
+ PV("ARS11-MOCT-4760-QS:PS-MODE.VAL"),
+ PV("ARS11-MOCT-5040-QS:PS-MODE.VAL"),
+ PV("ARS11-MOCT-5150-QS:PS-MODE.VAL"),
+ PV("ARS11-MOCT-5550-QS:PS-MODE.VAL"),
+ PV("ARS11-MOCT-5660-QS:PS-MODE.VAL"),
+ PV("ARS11-MOCT-5760-QS:PS-MODE.VAL"),
+ PV("ARS12-MOCT-1230-QS:PS-MODE.VAL"),
+ PV("ARS12-MOCT-1330-QS:PS-MODE.VAL"),
+ PV("ARS12-MOCT-1440-QS:PS-MODE.VAL"),
+ PV("ARS12-MOCT-1840-QS:PS-MODE.VAL"),
+ PV("ARS12-MOCT-1950-QS:PS-MODE.VAL"),
+ PV("ARS12-MOCT-2230-QS:PS-MODE.VAL"),
+ PV("ARS12-MOCT-2360-QS:PS-MODE.VAL"),
+ PV("ARS12-MOCT-2450-QS:PS-MODE.VAL"),
+ PV("ARS12-MOCT-2730-QS:PS-MODE.VAL"),
+ PV("ARS12-MOCT-2860-QS:PS-MODE.VAL"),
+ PV("ARS12-MOCT-2950-QS:PS-MODE.VAL"),
+ PV("ARS12-MOCT-4040-QS:PS-MODE.VAL"),
+ PV("ARS12-MOCT-4130-QS:PS-MODE.VAL"),
+ PV("ARS12-MOCT-4260-QS:PS-MODE.VAL"),
+ PV("ARS12-MOCT-4540-QS:PS-MODE.VAL"),
+ PV("ARS12-MOCT-4630-QS:PS-MODE.VAL"),
+ PV("ARS12-MOCT-4760-QS:PS-MODE.VAL"),
+ PV("ARS12-MOCT-5040-QS:PS-MODE.VAL"),
+ PV("ARS12-MOCT-5150-QS:PS-MODE.VAL"),
+ PV("ARS12-MOCT-5550-QS:PS-MODE.VAL"),
+ PV("ARS12-MOCT-5660-QS:PS-MODE.VAL"),
+ PV("ARS12-MOCT-5760-QS:PS-MODE.VAL"),
+ ],
+ [
+ lambda vls: vls["ARS01-MQUA-0550:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MQUA-0630:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MQUA-0710:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MQUA-0790:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MQUA-1050:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MQUA-1150:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MQUA-1260:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MQUA-1370:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MQUA-5620:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MQUA-5730:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MQUA-5840:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MQUA-5940:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MQUA-1050:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MQUA-1150:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MQUA-1260:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MQUA-1370:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MQUA-5620:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MQUA-5730:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MQUA-5840:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MQUA-5940:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MQUA-0790:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MQUA-0850:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MQUA-1050:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MQUA-1150:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MQUA-1260:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MQUA-1370:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MQUA-5620:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MQUA-5730:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MQUA-5840:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MQUA-5940:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MQUA-1050:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MQUA-1150:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MQUA-1260:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MQUA-1370:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MQUA-5620:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MQUA-5730:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MQUA-5840:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MQUA-5940:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MQUA-0400:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MQUA-0440:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MQUA-0460:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MQUA-1050:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MQUA-1150:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MQUA-1260:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MQUA-1370:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MQUA-5620:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MQUA-5730:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MQUA-5840:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MQUA-5940:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MQUA-1050:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MQUA-1150:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MQUA-1260:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MQUA-1370:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MQUA-5620:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MQUA-5730:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MQUA-5840:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MQUA-5940:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MQUA-0790:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MQUA-0850:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MQUA-1050:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MQUA-1150:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MQUA-1260:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MQUA-1370:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MQUA-5620:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MQUA-5730:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MQUA-5840:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MQUA-5940:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MQUA-1050:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MQUA-1150:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MQUA-1260:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MQUA-1370:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MQUA-5620:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MQUA-5730:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MQUA-5840:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MQUA-5940:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MQUA-0530:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MQUA-0560:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MQUA-0600:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MQUA-1050:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MQUA-1150:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MQUA-1260:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MQUA-1370:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MQUA-5620:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MQUA-5730:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MQUA-5840:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MQUA-5940:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MQUA-1050:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MQUA-1150:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MQUA-1260:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MQUA-1370:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MQUA-5620:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MQUA-5730:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MQUA-5840:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MQUA-5940:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MQUA-0830:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MQUA-0890:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MQUA-1050:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MQUA-1150:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MQUA-1260:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MQUA-1370:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MQUA-5620:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MQUA-5730:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MQUA-5840:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MQUA-5940:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MQUA-1050:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MQUA-1150:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MQUA-1260:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MQUA-1370:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MQUA-5620:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MQUA-5730:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MQUA-5840:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MQUA-5940:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MSXT-1190:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MSXT-1300:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MSXT-1410:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MSXT-1590:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MSXT-1810:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MSXT-1980:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MSXT-2200:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MSXT-2330:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MSXT-2480:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MSXT-2700:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MSXT-2830:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MSXT-2980:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MSXT-4010:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MSXT-4160:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MSXT-4290:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MSXT-4510:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MSXT-4660:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MSXT-4790:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MSXT-5010:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MSXT-5180:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MSXT-5400:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MSXT-5580:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MSXT-5690:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MSXT-5800:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MSXT-2980:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MSXT-4010:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MSXT-1590:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MSXT-2980:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MSXT-4010:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MSXT-5400:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MSXT-1190:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MSXT-1300:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MSXT-1410:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MSXT-1590:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MSXT-5400:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MSXT-5580:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MSXT-5690:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MSXT-5800:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MSXT-1590:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MSXT-1810:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MSXT-1980:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MSXT-2200:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MSXT-2330:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MSXT-2480:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MSXT-2700:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MSXT-2830:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MSXT-2980:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MSXT-4010:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MSXT-4160:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MSXT-4290:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MSXT-4510:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MSXT-4660:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MSXT-4790:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MSXT-5010:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MSXT-5180:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MSXT-5400:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MSXT-1190:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MSXT-1300:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MSXT-1410:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MSXT-1590:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MSXT-5400:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MSXT-5580:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MSXT-5690:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MSXT-5800:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MSXT-1590:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MSXT-5400:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-1230-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-1330-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-1440-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-1840-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-1950-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-2230-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-2360-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-2450-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-2730-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-2860-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-2950-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-4040-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-4130-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-4260-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-4540-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-4630-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-4760-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-5040-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-5150-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-5550-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-5660-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-5760-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-1230-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-1330-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-1440-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-1840-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-1950-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-2230-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-2360-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-2450-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-2730-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-2860-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-2950-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-4040-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-4130-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-4260-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-4540-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-4630-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-4760-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-5040-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-5150-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-5550-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-5660-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-5760-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-1230-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-1330-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-1440-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-1840-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-1950-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-2230-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-2360-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-2450-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-2730-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-2860-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-2950-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-4040-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-4130-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-4260-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-4540-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-4630-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-4760-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-5040-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-5150-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-5550-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-5660-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-5760-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-1230-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-1330-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-1440-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-1840-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-1950-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-2230-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-2360-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-2450-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-2730-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-2860-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-2950-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-4040-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-4130-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-4260-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-4540-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-4630-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-4760-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-5040-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-5150-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-5550-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-5660-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-5760-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-1230-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-1330-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-1440-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-1840-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-1950-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-2230-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-2360-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-2450-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-2730-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-2860-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-2950-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-4040-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-4130-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-4260-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-4540-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-4630-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-4760-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-5040-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-5150-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-5550-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-5660-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-5760-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-1230-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-1330-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-1440-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-1840-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-1950-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-2230-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-2360-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-2450-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-2730-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-2860-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-2950-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-4040-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-4130-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-4260-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-4540-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-4630-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-4760-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-5040-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-5150-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-5550-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-5660-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-5760-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-1230-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-1330-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-1440-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-1840-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-1950-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-2230-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-2360-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-2450-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-2730-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-2860-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-2950-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-4040-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-4130-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-4260-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-4540-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-4630-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-4760-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-5040-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-5150-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-5550-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-5660-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-5760-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-1230-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-1330-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-1440-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-1840-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-1950-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-2230-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-2360-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-2450-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-2730-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-2860-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-2950-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-4040-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-4130-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-4260-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-4540-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-4630-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-4760-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-5040-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-5150-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-5550-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-5660-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-5760-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-1230-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-1330-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-1440-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-1840-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-1950-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-2230-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-2360-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-2450-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-2730-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-2860-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-2950-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-4040-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-4130-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-4260-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-4540-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-4630-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-4760-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-5040-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-5150-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-5550-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-5660-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-5760-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-1230-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-1330-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-1440-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-1840-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-1950-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-2230-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-2360-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-2450-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-2730-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-2860-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-2950-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-4040-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-4130-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-4260-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-4540-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-4630-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-4760-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-5040-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-5150-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-5550-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-5660-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-5760-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-1230-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-1330-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-1440-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-1840-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-1950-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-2230-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-2360-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-2450-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-2730-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-2860-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-2950-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-4040-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-4130-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-4260-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-4540-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-4630-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-4760-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-5040-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-5150-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-5550-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-5660-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-5760-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-1230-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-1330-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-1440-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-1840-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-1950-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-2230-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-2360-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-2450-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-2730-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-2860-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-2950-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-4040-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-4130-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-4260-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-4540-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-4630-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-4760-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-5040-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-5150-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-5550-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-5660-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-5760-OC:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-1230-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-1330-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-1440-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-1840-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-1950-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-2230-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-2360-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-2450-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-2730-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-2860-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-2950-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-4040-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-4130-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-4260-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-4540-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-4630-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-4760-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-5040-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-5150-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-5550-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-5660-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-5760-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-1230-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-1330-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-1440-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-1840-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-1950-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-2230-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-2360-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-2450-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-2730-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-2860-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-2950-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-4040-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-4130-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-4260-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-4540-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-4630-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-4760-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-5040-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-5150-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-5550-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-5660-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-5760-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-1230-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-1330-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-1440-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-1840-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-1950-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-2230-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-2360-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-2450-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-2730-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-2860-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-2950-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-4040-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-4130-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-4260-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-4540-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-4630-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-4760-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-5040-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-5150-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-5550-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-5660-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-5760-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-1230-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-1330-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-1440-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-1840-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-1950-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-2230-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-2360-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-2450-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-2730-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-2860-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-2950-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-4040-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-4130-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-4260-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-4540-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-4630-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-4760-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-5040-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-5150-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-5550-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-5660-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-5760-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-1230-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-1330-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-1440-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-1840-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-1950-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-2230-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-2360-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-2450-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-2730-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-2860-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-2950-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-4040-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-4130-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-4260-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-4540-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-4630-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-4760-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-5040-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-5150-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-5550-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-5660-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-5760-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-1230-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-1330-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-1440-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-1840-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-1950-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-2230-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-2360-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-2450-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-2730-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-2860-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-2950-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-4040-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-4130-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-4260-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-4540-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-4630-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-4760-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-5040-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-5150-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-5550-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-5660-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-5760-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-1230-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-1330-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-1440-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-1840-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-1950-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-2230-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-2360-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-2450-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-2730-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-2860-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-2950-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-4040-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-4130-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-4260-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-4540-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-4630-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-4760-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-5040-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-5150-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-5550-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-5660-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-5760-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-1230-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-1330-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-1440-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-1840-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-1950-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-2230-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-2360-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-2450-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-2730-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-2860-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-2950-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-4040-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-4130-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-4260-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-4540-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-4630-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-4760-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-5040-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-5150-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-5550-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-5660-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-5760-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-1230-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-1330-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-1440-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-1840-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-1950-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-2230-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-2360-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-2450-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-2730-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-2860-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-2950-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-4040-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-4130-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-4260-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-4540-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-4630-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-4760-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-5040-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-5150-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-5550-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-5660-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-5760-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-1230-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-1330-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-1440-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-1840-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-1950-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-2230-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-2360-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-2450-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-2730-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-2860-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-2950-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-4040-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-4130-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-4260-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-4540-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-4630-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-4760-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-5040-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-5150-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-5550-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-5660-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-5760-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-1230-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-1330-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-1440-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-1840-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-1950-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-2230-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-2360-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-2450-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-2730-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-2860-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-2950-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-4040-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-4130-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-4260-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-4540-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-4630-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-4760-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-5040-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-5150-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-5550-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-5660-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-5760-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-1230-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-1330-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-1440-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-1840-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-1950-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-2230-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-2360-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-2450-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-2730-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-2860-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-2950-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-4040-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-4130-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-4260-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-4540-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-4630-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-4760-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-5040-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-5150-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-5550-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-5660-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-5760-QA:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-1230-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-1330-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-1440-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-1840-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-1950-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-2230-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-2360-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-2450-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-2730-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-2860-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-2950-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-4040-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-4130-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-4260-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-4540-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-4630-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-4760-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-5040-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-5150-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-5550-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-5660-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS01-MOCT-5760-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-1230-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-1330-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-1440-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-1840-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-1950-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-2230-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-2360-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-2450-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-2730-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-2860-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-2950-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-4040-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-4130-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-4260-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-4540-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-4630-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-4760-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-5040-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-5150-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-5550-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-5660-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS02-MOCT-5760-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-1230-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-1330-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-1440-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-1840-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-1950-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-2230-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-2360-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-2450-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-2730-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-2860-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-2950-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-4040-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-4130-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-4260-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-4540-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-4630-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-4760-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-5040-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-5150-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-5550-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-5660-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS03-MOCT-5760-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-1230-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-1330-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-1440-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-1840-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-1950-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-2230-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-2360-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-2450-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-2730-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-2860-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-2950-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-4040-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-4130-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-4260-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-4540-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-4630-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-4760-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-5040-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-5150-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-5550-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-5660-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS04-MOCT-5760-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-1230-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-1330-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-1440-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-1840-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-1950-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-2230-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-2360-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-2450-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-2730-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-2860-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-2950-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-4040-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-4130-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-4260-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-4540-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-4630-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-4760-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-5040-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-5150-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-5550-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-5660-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS05-MOCT-5760-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-1230-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-1330-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-1440-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-1840-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-1950-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-2230-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-2360-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-2450-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-2730-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-2860-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-2950-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-4040-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-4130-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-4260-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-4540-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-4630-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-4760-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-5040-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-5150-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-5550-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-5660-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS06-MOCT-5760-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-1230-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-1330-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-1440-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-1840-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-1950-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-2230-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-2360-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-2450-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-2730-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-2860-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-2950-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-4040-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-4130-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-4260-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-4540-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-4630-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-4760-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-5040-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-5150-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-5550-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-5660-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS07-MOCT-5760-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-1230-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-1330-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-1440-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-1840-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-1950-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-2230-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-2360-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-2450-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-2730-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-2860-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-2950-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-4040-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-4130-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-4260-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-4540-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-4630-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-4760-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-5040-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-5150-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-5550-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-5660-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS08-MOCT-5760-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-1230-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-1330-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-1440-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-1840-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-1950-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-2230-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-2360-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-2450-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-2730-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-2860-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-2950-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-4040-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-4130-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-4260-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-4540-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-4630-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-4760-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-5040-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-5150-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-5550-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-5660-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS09-MOCT-5760-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-1230-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-1330-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-1440-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-1840-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-1950-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-2230-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-2360-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-2450-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-2730-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-2860-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-2950-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-4040-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-4130-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-4260-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-4540-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-4630-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-4760-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-5040-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-5150-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-5550-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-5660-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS10-MOCT-5760-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-1230-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-1330-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-1440-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-1840-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-1950-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-2230-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-2360-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-2450-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-2730-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-2860-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-2950-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-4040-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-4130-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-4260-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-4540-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-4630-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-4760-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-5040-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-5150-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-5550-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-5660-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS11-MOCT-5760-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-1230-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-1330-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-1440-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-1840-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-1950-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-2230-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-2360-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-2450-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-2730-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-2860-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-2950-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-4040-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-4130-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-4260-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-4540-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-4630-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-4760-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-5040-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-5150-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-5550-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-5660-QS:PS-MODE.VAL"] == 2,
+ lambda vls: vls["ARS12-MOCT-5760-QS:PS-MODE.VAL"] == 2,
+ ],
+ ],
+ "Current Limit": [
+ [
+ PV("ARS07-DPCT-0000:CURR.VAL"),
+ PV("ARS07-DPCT-0100:CURR.VAL"),
+ PV("ARS07-DPCT-0200:CURR.VAL"),
+ PV("AGEBD-PARAMS:CURRENTLIMIT.VAL"),
+ ],
+ [
+ lambda vls: vls["ARS07-DPCT-0000:CURR.VAL"] < vls["AGEBD-PARAMS:CURRENTLIMIT.VAL"],
+ lambda vls: vls["ARS07-DPCT-0100:CURR.VAL"] < vls["AGEBD-PARAMS:CURRENTLIMIT.VAL"],
+ lambda vls: vls["ARS07-DPCT-0200:CURR.VAL"] < vls["AGEBD-PARAMS:CURRENTLIMIT.VAL"],
+ ],
+ ],
+ "IDs Ready": [
+ [
+ PV("AGEOP-BL:IDS-ARE-OPEN.VAL"),
+ PV("ARS07-DPCT-0000:CURR.VAL"),
+ ],
+ [
+ lambda vls: (
+ False
+ if vls["ARS07-DPCT-0000:CURR.VAL"] < 350
+ and vls["AGEOP-BL:IDS-ARE-OPEN.VAL"] == 0
+ else True
+ )
+ ],
+ ],
+ "Single Bunch Charge": [
+ [
+ PV("ARSGE-CECL-FPFB:BEAM-DUMP-ABS-ADC-DATA.VAL"),
+ PV("ARSGE-CECL-FPFB:FPFB-BEAM-DUMP-THR.VAL"),
+ ],
+ [
+ lambda vls: (
+ np.max(vls["ARSGE-CECL-FPFB:BEAM-DUMP-ABS-ADC-DATA.VAL"])
+ < 0.95 * vls["ARSGE-CECL-FPFB:FPFB-BEAM-DUMP-THR.VAL"]
+ )
+ ],
+ ],
+ "Injection Quality": [
+ [
+ # ...
+ ],
+ [
+ lambda vls: True,
+ ],
+ ],
+ "Dump Quality": [
+ [
+ # ...
+ ],
+ [
+ lambda vls: True,
+ ],
+ ],
+ "Lifetime": [
+ [
+ # ...
+ ],
+ [
+ lambda vls: True,
+ ],
+ ],
+ "Tune": [
+ [
+ # ...
+ ],
+ [
+ lambda vls: True,
+ ],
+ ],
+ "Pingers": [
+ [
+ PV("ARS01-MKIK-0290:CTRL-ON-OFF.VAL"),
+ PV("ARS01-MKIK-0320:CTRL-ON-OFF.VAL"),
+ PV("AGETI-CVME-MASTER-TMA:Evt-SR-Pinger-H-Ena-Sel.VAL"),
+ PV("AGETI-CVME-MASTER-TMA:Evt-SR-Pinger-V-Ena-Sel.VAL"),
+ ],
+ [
+ lambda vls: (
+ not bool(
+ (
+ vls["ARS01-MKIK-0290:CTRL-ON-OFF.VAL"]
+ or vls["ARS01-MKIK-0320:CTRL-ON-OFF.VAL"]
+ )
+ and vls["AGETI-CVME-MASTER-TMA:Evt-SR-Pinger-H-Ena-Sel.VAL"]
+ )
+ ),
+ lambda vls: (
+ not bool(
+ vls["ARS01-MKIK-0320:CTRL-ON-OFF.VAL"]
+ and vls["AGETI-CVME-MASTER-TMA:Evt-SR-Pinger-V-Ena-Sel.VAL"]
+ )
+ ),
+ ],
+ ],
+ "Vacuum Pressure": [
+ [
+ PV("ARIVA-VMAVE:PRESS-MAX.VAL"),
+ ],
+ [
+ lambda vls: vls["ARIVA-VMAVE:PRESS-MAX.VAL"] < 3e-8,
+ ],
+ ],
+ "Orbit Deviation": [
+ [
+ PV("ARS07-DPCT-0000:CURR.VAL"),
+ PV("ARSGE-CECL-FOFB1:B-ERR-X-RMS.VAL"),
+ PV("ARSGE-CECL-FOFB1:B-ERR-Y-RMS.VAL"),
+ ],
+ [
+ lambda vls: (
+ vls["ARSGE-CECL-FOFB1:B-ERR-X-RMS.VAL"] < 0.02
+ if vls["ARS07-DPCT-0000:CURR.VAL"] > 22
+ else True
+ ),
+ lambda vls: (
+ vls["ARSGE-CECL-FOFB1:B-ERR-Y-RMS.VAL"] < 0.02
+ if vls["ARS07-DPCT-0000:CURR.VAL"] > 22
+ else True
+ ),
+ ],
+ ],
+ "Beam Dump Controller": [
+ [
+ PV("AGESA-SBDC-0000:SUM_INPUT_NOT_OK_LATCHED.VAL"),
+ ],
+ [
+ lambda vls: vls["AGESA-SBDC-0000:SUM_INPUT_NOT_OK_LATCHED.VAL"] == 0,
+ ],
+ ],
+ }
+
+ def __init__(self, service_name: str, pv_factory=PV):
+ super().__init__(service_name, pv_factory)
+
+ if len(self.checks_input) != len(self.checks_output):
+ msg = "amount of defined checks and according ouput check PVs do not match"
+ print(msg)
+ raise RuntimeError(msg)
+
+
+"""
+Beam Transfer Checks
+
+ 1. Check that all EVR counters increment after according event is released
+
+ Beam Dump (here not an event but the BDC is start of chain)
+ AGESA-SBDC-0000:INT-COUNTER
+ AGETI-CVME-MASTER-TMA:Evt-Beam-Dump-EVRCount-I
+ AGETI-CVME-MASTER-EVR0:Event-41-Cnt-I (= AGETI-CVME-MASTER-TMA:Evt-Beam-Dump-EVRCount-I.INPA)
+ ARS01-MKIK-0050-1:TRIG-CNT
+ ARS01-MKIK-0050-2:TRIG-CNT
+ ARS01-MKIK-0050-3:TRIG-CNT
+ ARS01-MKIK-0050-4:TRIG-CNT
+
+ SR Injection
+ AGETI-CVME-MASTER-TMA:Evt-SR-Inj-EVRCount-I
+ AGETI-CVME-MASTER-EVR0:Event-32-Cnt-I
+ ARS01-MKIK-0140:TRIG-CNT
+ ARS01-MKIK-0220:TRIG-CNT
+ ARS01-MKIK-0850:TRIG-CNT
+ ARS01-MKIK-0940:TRIG-CNT
+ ARS01-MSEP-0670:TRIG-CNT
+
+ Booster Extraction
+ AGETI-CVME-MASTER-TMA:Evt-BO-Ext-EVRCount-I
+ AGETI-CVME-MASTER-EVR0:Event-24-Cnt-I
+ ABOMA-YEX:TRIG-CNT
+ ABOMA-KEX:TRIG-CNT
+
+ Booster Injection
+ AGETI-CVME-MASTER-TMA:Evt-BO-Inj-EVRCount-I
+ AGETI-CVME-MASTER-EVR0:Event-23-Cnt-I
+ ABOMA-YIN:TRIG-CNT
+ ABOMA-KIN:TRIG-CNT
+
+ 2. Check that the transmission stays above limits, e.g.:
+
+ 60 % per shot
+ 80 % per 5 shot average
+ 90 % per 4 h average
+
+ requires:
+ - reliable injection indicator and reliable transmission calculation
+ - reliable correleated PCT readings from booster and ring
+ - limits as pv for flexibility
+
+"""
+
+
+class Service(BaseService[PVs]):
+ def __init__(
+ self,
+ name: str,
+ pvs: PVs,
+ version: str = __version__,
+ sleep_interval: float = 0.1,
+ ):
+ super().__init__(name, pvs, version, sleep_interval)
+
+ self.logs = []
+
+ # initiate vals and results dicts
+ self.timestamp = str(datetime.now())
+ self.timestamp5 = self.timestamp[:-5]
+ self.timestamp7 = self.timestamp[:-7]
+ self.vals = {}
+ self.results = {}
+ for check_group in pvs.checks_input:
+ self.results[check_group] = 0
+
+ links, _ = pvs.checks_input[check_group]
+
+ for pv in links:
+ pvname = pv.pvname
+ self.vals[pvname] = pv.get()
+
+ def update(self):
+ pvs = self.pvs
+
+ # when callback is fired, this code will be executed
+ if self.CallbackFired:
+ self.timestamp = str(datetime.now())
+ self.timestamp5 = self.timestamp[:-5]
+ self.timestamp7 = self.timestamp[:-7]
+
+ if pvs.logclear.get():
+ self.logs = []
+ pvs.logclear.put(0)
+ pvs.logbook.put("Injection Guard Alarm Log Cleared, " + self.timestamp5 + "\n")
+
+ for check_group in pvs.checks_input:
+ links, checks = pvs.checks_input[check_group]
+
+ # update vals dict for all links of this check_group
+ for pv in links:
+ pvname = pv.pvname
+
+ if pv.connected:
+ self.vals[pvname] = pv.get()
+ else:
+ self.logs.append(
+ "{:} {:35} = not connected".format(self.timestamp7, pvname)
+ )
+ self.vals[pvname] = np.nan
+
+ self.results[check_group] = 1
+
+ # do all checks of this check_group using vals dict
+ for check in checks:
+ try:
+ if not check(self.vals):
+ self.results[check_group] = 0
+ code = (
+ inspect.getsource(check)
+ .split("vls: ")[1]
+ .strip("\n")
+ .strip(",")
+ .replace("vls[", "")
+ .replace(".VAL']", "")
+ .replace("'", "")
+ )
+ self.logs.append("{:} failed: {:}".format(self.timestamp7, code))
+ # self.logs.append('{:} values: {:}'.format(self.timestamp7, self.vals))
+ except:
+ self.results[check_group] = 0
+ code = (
+ inspect.getsource(check)
+ .split("vls: ")[1]
+ .strip("\n")
+ .strip(",")
+ .replace("vls[", "")
+ .replace(".VAL']", "")
+ .replace("'", "")
+ )
+ self.logs.append("{:} exception: {:}".format(self.timestamp7, code))
+ # self.logs.append('{:} values: {:}'.format(self.timestamp7, self.vals))
+
+ try:
+ if pvs.checks_output[check_group].connected:
+ pvs.checks_output[check_group].put(self.results[check_group])
+ else:
+ self.logs.append(
+ "{:} {:35} = not connected".format(
+ self.timestamp7, pvs.checks_output[check_group].pvname
+ )
+ )
+ except:
+ print("Cannot find check group {:}".format(check_group))
+
+ if len(self.logs) > 100:
+ self.logs = self.logs[:100]
+
+ if not pvs.logbook_pause.get():
+ log_header = ["Injection Guard Alarm Log, " + self.timestamp5 + "\n"]
+ pvs.logbook.put("\n".join(log_header + self.logs[::-1]))
+
+ # callback done
+ self.CallbackFired = 0
diff --git a/services/injectionguard/current/app/tests/test_app.py b/services/injectionguard/current/app/tests/test_app.py
new file mode 100644
index 0000000..c6a1df9
--- /dev/null
+++ b/services/injectionguard/current/app/tests/test_app.py
@@ -0,0 +1,9 @@
+from agebd_injectionguard import PVs, Service
+
+
+def test_app():
+ service_name = "DUMMY"
+ pvs = PVs(service_name=service_name)
+ service = Service(name=service_name, pvs=pvs)
+ service.CallbackFired = 1
+ service.update()
diff --git a/services/injectionguard/current/app/uv.lock b/services/injectionguard/current/app/uv.lock
new file mode 100644
index 0000000..345e744
--- /dev/null
+++ b/services/injectionguard/current/app/uv.lock
@@ -0,0 +1,301 @@
+version = 1
+revision = 3
+requires-python = "==3.10.*"
+
+[[package]]
+name = "agebd"
+version = "0.1.0"
+source = { editable = "../../../../packages/agebd" }
+dependencies = [
+ { name = "h5py" },
+ { name = "typer" },
+]
+
+[package.metadata]
+requires-dist = [
+ { name = "h5py", specifier = ">=3.16.0" },
+ { name = "typer", specifier = ">=0.23.2" },
+]
+
+[package.metadata.requires-dev]
+dev = [
+ { name = "pyright", specifier = ">=1.1.410" },
+ { name = "pytest", specifier = ">=8.4.2" },
+ { name = "ruff", specifier = ">=0.15.19" },
+]
+
+[[package]]
+name = "agebd-injectionguard"
+version = "0.1.0"
+source = { editable = "." }
+dependencies = [
+ { name = "agebd" },
+ { name = "numpy" },
+]
+
+[package.dev-dependencies]
+dev = [
+ { name = "pyepics" },
+ { name = "pytest" },
+ { name = "ruff" },
+]
+
+[package.metadata]
+requires-dist = [
+ { name = "agebd", editable = "../../../../packages/agebd" },
+ { name = "numpy", specifier = ">=2.0.2" },
+]
+
+[package.metadata.requires-dev]
+dev = [
+ { name = "pyepics", specifier = ">=3.5.8" },
+ { name = "pytest", specifier = ">=8.4.2" },
+ { name = "ruff", specifier = ">=0.15.20" },
+]
+
+[[package]]
+name = "annotated-doc"
+version = "0.0.4"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/57/ba/046ceea27344560984e26a590f90bc7f4a75b06701f653222458922b558c/annotated_doc-0.0.4.tar.gz", hash = "sha256:fbcda96e87e9c92ad167c2e53839e57503ecfda18804ea28102353485033faa4", size = 7288, upload-time = "2025-11-10T22:07:42.062Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl", hash = "sha256:571ac1dc6991c450b25a9c2d84a3705e2ae7a53467b5d111c24fa8baabbed320", size = 5303, upload-time = "2025-11-10T22:07:40.673Z" },
+]
+
+[[package]]
+name = "colorama"
+version = "0.4.6"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" },
+]
+
+[[package]]
+name = "exceptiongroup"
+version = "1.3.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "typing-extensions" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" },
+]
+
+[[package]]
+name = "h5py"
+version = "3.16.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "numpy" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/db/33/acd0ce6863b6c0d7735007df01815403f5589a21ff8c2e1ee2587a38f548/h5py-3.16.0.tar.gz", hash = "sha256:a0dbaad796840ccaa67a4c144a0d0c8080073c34c76d5a6941d6818678ef2738", size = 446526, upload-time = "2026-03-06T13:49:08.07Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/3a/6b/231413e58a787a89b316bb0d1777da3c62257e4797e09afd8d17ad3549dc/h5py-3.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e06f864bedb2c8e7c1358e6c73af48519e317457c444d6f3d332bb4e8fa6d7d9", size = 3724137, upload-time = "2026-03-06T13:47:35.242Z" },
+ { url = "https://files.pythonhosted.org/packages/74/f9/557ce3aad0fe8471fb5279bab0fc56ea473858a022c4ce8a0b8f303d64e9/h5py-3.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ec86d4fffd87a0f4cb3d5796ceb5a50123a2a6d99b43e616e5504e66a953eca3", size = 3090112, upload-time = "2026-03-06T13:47:37.634Z" },
+ { url = "https://files.pythonhosted.org/packages/7a/f5/e15b3d0dc8a18e56409a839e6468d6fb589bc5207c917399c2e0706eeb44/h5py-3.16.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:86385ea895508220b8a7e45efa428aeafaa586bd737c7af9ee04661d8d84a10d", size = 4844847, upload-time = "2026-03-06T13:47:39.811Z" },
+ { url = "https://files.pythonhosted.org/packages/cb/92/a8851d936547efe30cc0ce5245feac01f3ec6171f7899bc3f775c72030b3/h5py-3.16.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:8975273c2c5921c25700193b408e28d6bdd0111c37468b2d4e25dcec4cd1d84d", size = 5065352, upload-time = "2026-03-06T13:47:41.489Z" },
+ { url = "https://files.pythonhosted.org/packages/2b/ae/f2adc5d0ca9626db3277a3d87516e124cbc5d0eea0bd79bc085702d04f2c/h5py-3.16.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:1677ad48b703f44efc9ea0c3ab284527f81bc4f318386aaaebc5fede6bbae56f", size = 4839173, upload-time = "2026-03-06T13:47:43.586Z" },
+ { url = "https://files.pythonhosted.org/packages/64/0b/e0c8c69da1d8838da023a50cd3080eae5d475691f7636b35eff20bb6ef20/h5py-3.16.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7c4dd4cf5f0a4e36083f73172f6cfc25a5710789269547f132a20975bfe2434c", size = 5076216, upload-time = "2026-03-06T13:47:45.315Z" },
+ { url = "https://files.pythonhosted.org/packages/66/35/d88fd6718832133c885004c61ceeeb24dbd6397ef877dbed6b3a64d6a286/h5py-3.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:bdef06507725b455fccba9c16529121a5e1fbf56aa375f7d9713d9e8ff42454d", size = 3183639, upload-time = "2026-03-06T13:47:47.041Z" },
+]
+
+[[package]]
+name = "iniconfig"
+version = "2.3.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" },
+]
+
+[[package]]
+name = "markdown-it-py"
+version = "4.2.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "mdurl" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/06/ff/7841249c247aa650a76b9ee4bbaeae59370dc8bfd2f6c01f3630c35eb134/markdown_it_py-4.2.0.tar.gz", hash = "sha256:04a21681d6fbb623de53f6f364d352309d4094dd4194040a10fd51833e418d49", size = 82454, upload-time = "2026-05-07T12:08:28.36Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl", hash = "sha256:9f7ebbcd14fe59494226453aed97c1070d83f8d24b6fc3a3bcf9a38092641c4a", size = 91687, upload-time = "2026-05-07T12:08:27.182Z" },
+]
+
+[[package]]
+name = "mdurl"
+version = "0.1.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" },
+]
+
+[[package]]
+name = "numpy"
+version = "2.2.6"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/76/21/7d2a95e4bba9dc13d043ee156a356c0a8f0c6309dff6b21b4d71a073b8a8/numpy-2.2.6.tar.gz", hash = "sha256:e29554e2bef54a90aa5cc07da6ce955accb83f21ab5de01a62c8478897b264fd", size = 20276440, upload-time = "2025-05-17T22:38:04.611Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/9a/3e/ed6db5be21ce87955c0cbd3009f2803f59fa08df21b5df06862e2d8e2bdd/numpy-2.2.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b412caa66f72040e6d268491a59f2c43bf03eb6c96dd8f0307829feb7fa2b6fb", size = 21165245, upload-time = "2025-05-17T21:27:58.555Z" },
+ { url = "https://files.pythonhosted.org/packages/22/c2/4b9221495b2a132cc9d2eb862e21d42a009f5a60e45fc44b00118c174bff/numpy-2.2.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e41fd67c52b86603a91c1a505ebaef50b3314de0213461c7a6e99c9a3beff90", size = 14360048, upload-time = "2025-05-17T21:28:21.406Z" },
+ { url = "https://files.pythonhosted.org/packages/fd/77/dc2fcfc66943c6410e2bf598062f5959372735ffda175b39906d54f02349/numpy-2.2.6-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:37e990a01ae6ec7fe7fa1c26c55ecb672dd98b19c3d0e1d1f326fa13cb38d163", size = 5340542, upload-time = "2025-05-17T21:28:30.931Z" },
+ { url = "https://files.pythonhosted.org/packages/7a/4f/1cb5fdc353a5f5cc7feb692db9b8ec2c3d6405453f982435efc52561df58/numpy-2.2.6-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:5a6429d4be8ca66d889b7cf70f536a397dc45ba6faeb5f8c5427935d9592e9cf", size = 6878301, upload-time = "2025-05-17T21:28:41.613Z" },
+ { url = "https://files.pythonhosted.org/packages/eb/17/96a3acd228cec142fcb8723bd3cc39c2a474f7dcf0a5d16731980bcafa95/numpy-2.2.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:efd28d4e9cd7d7a8d39074a4d44c63eda73401580c5c76acda2ce969e0a38e83", size = 14297320, upload-time = "2025-05-17T21:29:02.78Z" },
+ { url = "https://files.pythonhosted.org/packages/b4/63/3de6a34ad7ad6646ac7d2f55ebc6ad439dbbf9c4370017c50cf403fb19b5/numpy-2.2.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc7b73d02efb0e18c000e9ad8b83480dfcd5dfd11065997ed4c6747470ae8915", size = 16801050, upload-time = "2025-05-17T21:29:27.675Z" },
+ { url = "https://files.pythonhosted.org/packages/07/b6/89d837eddef52b3d0cec5c6ba0456c1bf1b9ef6a6672fc2b7873c3ec4e2e/numpy-2.2.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:74d4531beb257d2c3f4b261bfb0fc09e0f9ebb8842d82a7b4209415896adc680", size = 15807034, upload-time = "2025-05-17T21:29:51.102Z" },
+ { url = "https://files.pythonhosted.org/packages/01/c8/dc6ae86e3c61cfec1f178e5c9f7858584049b6093f843bca541f94120920/numpy-2.2.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8fc377d995680230e83241d8a96def29f204b5782f371c532579b4f20607a289", size = 18614185, upload-time = "2025-05-17T21:30:18.703Z" },
+ { url = "https://files.pythonhosted.org/packages/5b/c5/0064b1b7e7c89137b471ccec1fd2282fceaae0ab3a9550f2568782d80357/numpy-2.2.6-cp310-cp310-win32.whl", hash = "sha256:b093dd74e50a8cba3e873868d9e93a85b78e0daf2e98c6797566ad8044e8363d", size = 6527149, upload-time = "2025-05-17T21:30:29.788Z" },
+ { url = "https://files.pythonhosted.org/packages/a3/dd/4b822569d6b96c39d1215dbae0582fd99954dcbcf0c1a13c61783feaca3f/numpy-2.2.6-cp310-cp310-win_amd64.whl", hash = "sha256:f0fd6321b839904e15c46e0d257fdd101dd7f530fe03fd6359c1ea63738703f3", size = 12904620, upload-time = "2025-05-17T21:30:48.994Z" },
+ { url = "https://files.pythonhosted.org/packages/9e/3b/d94a75f4dbf1ef5d321523ecac21ef23a3cd2ac8b78ae2aac40873590229/numpy-2.2.6-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0b605b275d7bd0c640cad4e5d30fa701a8d59302e127e5f79138ad62762c3e3d", size = 21040391, upload-time = "2025-05-17T21:44:35.948Z" },
+ { url = "https://files.pythonhosted.org/packages/17/f4/09b2fa1b58f0fb4f7c7963a1649c64c4d315752240377ed74d9cd878f7b5/numpy-2.2.6-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:7befc596a7dc9da8a337f79802ee8adb30a552a94f792b9c9d18c840055907db", size = 6786754, upload-time = "2025-05-17T21:44:47.446Z" },
+ { url = "https://files.pythonhosted.org/packages/af/30/feba75f143bdc868a1cc3f44ccfa6c4b9ec522b36458e738cd00f67b573f/numpy-2.2.6-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce47521a4754c8f4593837384bd3424880629f718d87c5d44f8ed763edd63543", size = 16643476, upload-time = "2025-05-17T21:45:11.871Z" },
+ { url = "https://files.pythonhosted.org/packages/37/48/ac2a9584402fb6c0cd5b5d1a91dcf176b15760130dd386bbafdbfe3640bf/numpy-2.2.6-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d042d24c90c41b54fd506da306759e06e568864df8ec17ccc17e9e884634fd00", size = 12812666, upload-time = "2025-05-17T21:45:31.426Z" },
+]
+
+[[package]]
+name = "packaging"
+version = "26.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d7/f1/e7a6dd94a8d4a5626c03e4e99c87f241ba9e350cd9e6d75123f992427270/packaging-26.2.tar.gz", hash = "sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661", size = 228134, upload-time = "2026-04-24T20:15:23.917Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/df/b2/87e62e8c3e2f4b32e5fe99e0b86d576da1312593b39f47d8ceef365e95ed/packaging-26.2-py3-none-any.whl", hash = "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e", size = 100195, upload-time = "2026-04-24T20:15:22.081Z" },
+]
+
+[[package]]
+name = "pluggy"
+version = "1.6.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" },
+]
+
+[[package]]
+name = "pyepics"
+version = "3.5.10"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "numpy" },
+ { name = "pyparsing" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/69/57/29e1e9ef11ba2a3419f489946ae1d8190025a1e4f4e1c1686758bb2b6e0a/pyepics-3.5.10.tar.gz", hash = "sha256:f390cf9be40aba757b9528888114bc14d8db01086d0c93914720b1772460375b", size = 6150481, upload-time = "2026-05-20T18:44:36.336Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d6/36/e517fd83bd97d6bfe4105e0c6b322070c5cc36fb56a8fab2866e319f8804/pyepics-3.5.10-py3-none-any.whl", hash = "sha256:c9fac2c54f2b595268e66fc348cf5ec24e63718e7dbd07d73d1b37d4da6bfee1", size = 5332376, upload-time = "2026-05-20T18:44:34.242Z" },
+]
+
+[[package]]
+name = "pygments"
+version = "2.20.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" },
+]
+
+[[package]]
+name = "pyparsing"
+version = "3.3.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f3/91/9c6ee907786a473bf81c5f53cf703ba0957b23ab84c264080fb5a450416f/pyparsing-3.3.2.tar.gz", hash = "sha256:c777f4d763f140633dcb6d8a3eda953bf7a214dc4eff598413c070bcdc117cbc", size = 6851574, upload-time = "2026-01-21T03:57:59.36Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl", hash = "sha256:850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d", size = 122781, upload-time = "2026-01-21T03:57:55.912Z" },
+]
+
+[[package]]
+name = "pytest"
+version = "9.1.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "colorama", marker = "sys_platform == 'win32'" },
+ { name = "exceptiongroup" },
+ { name = "iniconfig" },
+ { name = "packaging" },
+ { name = "pluggy" },
+ { name = "pygments" },
+ { name = "tomli" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/e4/47/b9efed96c114afcfa3c9d3fe98a76a1d14c74a9e266d397cf6eb64be5e01/pytest-9.1.1.tar.gz", hash = "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313", size = 1636369, upload-time = "2026-06-19T10:58:32.857Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/24/25/1de2678b631f5a49215c6c96fff41ba892b0a34df68d6d80292b1b48aa7f/pytest-9.1.1-py3-none-any.whl", hash = "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c", size = 386536, upload-time = "2026-06-19T10:58:31.347Z" },
+]
+
+[[package]]
+name = "rich"
+version = "15.0.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "markdown-it-py" },
+ { name = "pygments" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/c0/8f/0722ca900cc807c13a6a0c696dacf35430f72e0ec571c4275d2371fca3e9/rich-15.0.0.tar.gz", hash = "sha256:edd07a4824c6b40189fb7ac9bc4c52536e9780fbbfbddf6f1e2502c31b068c36", size = 230680, upload-time = "2026-04-12T08:24:00.75Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl", hash = "sha256:33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb", size = 310654, upload-time = "2026-04-12T08:24:02.83Z" },
+]
+
+[[package]]
+name = "ruff"
+version = "0.15.21"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/0f/36/6f65aa9989acdec45d417192d8f4e7921931d8a6cf87ac74bce3eed98a8e/ruff-0.15.21.tar.gz", hash = "sha256:d0cfc841c572283c36548f82664a54ce6565567f1b0d5b4cf2caac693d8b7500", size = 4769401, upload-time = "2026-07-09T20:01:34.005Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d0/c6/ede15cac6839f3dbce52565c8f5164a8210e669c7bc4decb03e5bdf47d0d/ruff-0.15.21-py3-none-linux_armv6l.whl", hash = "sha256:63ea0e965e5d73c90e95b2434beeafc70820536717f561b32ab6e777cb9bdf5d", size = 10854342, upload-time = "2026-07-09T20:00:53.998Z" },
+ { url = "https://files.pythonhosted.org/packages/28/9d/d825b07ee7ea9e2d61df92a860033c94e06e7300d50a1c2653aac27d24fe/ruff-0.15.21-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:0f212c5d7d54c01bbfe6dcab02b724a39300f3e34ed7acbe995ccb320a2c58bd", size = 11139539, upload-time = "2026-07-09T20:00:57.809Z" },
+ { url = "https://files.pythonhosted.org/packages/f5/de/3b107712e642f063c7a9e0887c427b22cb44097de5aab36c05f2e280670c/ruff-0.15.21-py3-none-macosx_11_0_arm64.whl", hash = "sha256:e6312e41bc96791299614995ea3a977c5857c3b5662b1ecef6755b02b87cb646", size = 10595437, upload-time = "2026-07-09T20:01:00.006Z" },
+ { url = "https://files.pythonhosted.org/packages/9a/6f/b4523cc90ba239ede441447a19d0c968846a3012e5a0b0c5b62831a3d5e3/ruff-0.15.21-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01d65b4831c6b2a4ba8ee6faa84049d44d982b7a706e622c4094c509e51673be", size = 10990053, upload-time = "2026-07-09T20:01:02.187Z" },
+ { url = "https://files.pythonhosted.org/packages/92/cc/c6a9872a5375f0628875481cf2f66b13d7d865bf3ca2e57f91c7e762d976/ruff-0.15.21-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2c5a913a589120ce67933d5d05fd6ddbcc2481c6a054980ee767f7414c72b4fd", size = 10666096, upload-time = "2026-07-09T20:01:04.299Z" },
+ { url = "https://files.pythonhosted.org/packages/ab/97/c621f7a17e097f1790fa3af6374138823b330b2d03fc38337945daca212c/ruff-0.15.21-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ef04b681d02ad4dc9620f00f83ac5c22f652d0e9a9cfe431d219b16ad5ccc41", size = 11537011, upload-time = "2026-07-09T20:01:06.771Z" },
+ { url = "https://files.pythonhosted.org/packages/ea/51/d928727e476e25ccc57c6f449ffd80241a651a973ad949d39cfb2a771d28/ruff-0.15.21-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:16d090c0740916594157e75b80d666eab8e78083b39b3b0e1d698f4670a17b86", size = 12347101, upload-time = "2026-07-09T20:01:08.859Z" },
+ { url = "https://files.pythonhosted.org/packages/1e/88/8cd62026802b16018ad06931d87997cf795ba2a6239ab659606c87d96bf0/ruff-0.15.21-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3a10e74757dd65004d779b73e2f3c5210156d9980b41224d50d2ebcf1db51e67", size = 11572001, upload-time = "2026-07-09T20:01:11.092Z" },
+ { url = "https://files.pythonhosted.org/packages/b2/97/f63084cf55444fc110e8cb985ebfcc592af47f597d44453d778cb81bc156/ruff-0.15.21-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bab0905d2f29e0d9fbc3c373ed23db0095edaa3f71f1f4f519ec15134d9e85c8", size = 11549239, upload-time = "2026-07-09T20:01:13.27Z" },
+ { url = "https://files.pythonhosted.org/packages/9d/77/f107da4a2874b7715914b03f09ba9c54424de3ff8a1cc5d015d3ee2ce0ac/ruff-0.15.21-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:00eca240af5789fec6fe7df74c088cc1f9644ed83027113468efba7c92b94075", size = 11535340, upload-time = "2026-07-09T20:01:15.206Z" },
+ { url = "https://files.pythonhosted.org/packages/d5/e9/601deb322d3303a7bf212b0100ead6f2ee3f6a044d89c30f2f92bf83c731/ruff-0.15.21-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:262ab31557a75141325e32d3357f3597645a7f084e732b6b054dde428ecd9341", size = 10964048, upload-time = "2026-07-09T20:01:17.723Z" },
+ { url = "https://files.pythonhosted.org/packages/ea/2e/0f2176d1e99c15192caea19c8c3a0a955246b4cb4de795042eeb616345cd/ruff-0.15.21-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:659c4e7a4212f83306045ec7c5e5a356d16d9a6ef4ae0c7a4d872914fc655d9d", size = 10667055, upload-time = "2026-07-09T20:01:19.73Z" },
+ { url = "https://files.pythonhosted.org/packages/48/60/abd74a02e0c4214f12a68becfd30af7165cfdcb0e661ecdc60bbb949c09a/ruff-0.15.21-py3-none-musllinux_1_2_i686.whl", hash = "sha256:9e866eab611a5f959d36df2d10e446973a3610bc42b0c15b31dc27977d59c233", size = 11242043, upload-time = "2026-07-09T20:01:21.947Z" },
+ { url = "https://files.pythonhosted.org/packages/b2/c6/583075d8ccabb4b229345edcaf1545eb3d8d6be90f686a479d7e94088bbf/ruff-0.15.21-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e89bc93c0d3803ba870b55c29671bad9dc6d94bb1eb181b056b52eb05b52854f", size = 11648064, upload-time = "2026-07-09T20:01:24.023Z" },
+ { url = "https://files.pythonhosted.org/packages/3a/3c/37d0ecb729a7cc2d393ea7dce316fc585680f35d93b8d62139d7d0a3700c/ruff-0.15.21-py3-none-win32.whl", hash = "sha256:01f8d5be84823c172b389e123174f781f9daf86d6c58719d603f941932195cdd", size = 10896555, upload-time = "2026-07-09T20:01:26.941Z" },
+ { url = "https://files.pythonhosted.org/packages/c0/b8/e43466b2a6067ce91e669068f6e28d6c719a920f014b070d5c8731725de3/ruff-0.15.21-py3-none-win_amd64.whl", hash = "sha256:d4b8d9a2f0f12b816b50447f6eccb9f4bb01a6b82c86b50fb3b5354b458dc6d3", size = 12038772, upload-time = "2026-07-09T20:01:29.497Z" },
+ { url = "https://files.pythonhosted.org/packages/dd/75/e90ab9aeece218a9fc5a5bc3ec97d0ee6bb3c4ff95869463c1de58e29a1c/ruff-0.15.21-py3-none-win_arm64.whl", hash = "sha256:6e83115d4b9377c1cbc13abf0e051f069fab0ef815ea0504a8a008cee24dd0a8", size = 11375265, upload-time = "2026-07-09T20:01:31.772Z" },
+]
+
+[[package]]
+name = "shellingham"
+version = "1.5.4"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/58/15/8b3609fd3830ef7b27b655beb4b4e9c62313a4e8da8c676e142cc210d58e/shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de", size = 10310, upload-time = "2023-10-24T04:13:40.426Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755, upload-time = "2023-10-24T04:13:38.866Z" },
+]
+
+[[package]]
+name = "tomli"
+version = "2.4.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/22/de/48c59722572767841493b26183a0d1cc411d54fd759c5607c4590b6563a6/tomli-2.4.1.tar.gz", hash = "sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f", size = 17543, upload-time = "2026-03-25T20:22:03.828Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/7b/61/cceae43728b7de99d9b847560c262873a1f6c98202171fd5ed62640b494b/tomli-2.4.1-py3-none-any.whl", hash = "sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe", size = 14583, upload-time = "2026-03-25T20:22:03.012Z" },
+]
+
+[[package]]
+name = "typer"
+version = "0.27.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "annotated-doc" },
+ { name = "colorama", marker = "sys_platform == 'win32'" },
+ { name = "rich" },
+ { name = "shellingham" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/37/78/fda3361b56efc27944f24225f6ecd13d96d6fcfe37bd0eb34e2f4c63f9fc/typer-0.27.0.tar.gz", hash = "sha256:629bd12ea5d13a17148125d9a264f949eb171fb3f120f9b04d85873cab054fa5", size = 203430, upload-time = "2026-07-15T19:21:07.007Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/40/03/26a383c9e58c213199d1aad1c3d353cfc22d4444ec6d2c0bf8ad02523843/typer-0.27.0-py3-none-any.whl", hash = "sha256:6f4b27631e47f077871b7dc30e933ec0131c1390fbe0e387ea5574b5bac9ccf1", size = 122716, upload-time = "2026-07-15T19:21:05.553Z" },
+]
+
+[[package]]
+name = "typing-extensions"
+version = "4.16.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f6/cc/6253133b5bb138fc3306cebfbda2c520f545d36b5be2c7255cc528bb45d6/typing_extensions-4.16.0.tar.gz", hash = "sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5", size = 113555, upload-time = "2026-07-02T08:40:05.92Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/49/d3/b8441a820a491ddfc024b0b0cf0393375b75ea13866d9c66727e54c2fc80/typing_extensions-4.16.0-py3-none-any.whl", hash = "sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8", size = 45571, upload-time = "2026-07-02T08:40:04.659Z" },
+]
diff --git a/services/injectionguard/current/ioc/AGEBD-CPCL-INJECTIONGUARD_main.subs b/services/injectionguard/current/ioc/AGEBD-CPCL-INJECTIONGUARD_main.subs
new file mode 100644
index 0000000..10eab88
--- /dev/null
+++ b/services/injectionguard/current/ioc/AGEBD-CPCL-INJECTIONGUARD_main.subs
@@ -0,0 +1,31 @@
+file INJECTIONGUARD_individual.template {
+ pattern { DEVICE }
+ { AGEBD-INJECTIONGUARD{{ agebd_env }} }
+}
+
+file INJECTIONGUARD_automated.template {
+ pattern { DEVICE NR Latch Description }
+ { AGEBD-INJECTIONGUARD{{ agebd_env }} 01 1 "Beam Dump Kicker"}
+ { AGEBD-INJECTIONGUARD{{ agebd_env }} 02 1 "Dump Valve"}
+ { AGEBD-INJECTIONGUARD{{ agebd_env }} 03 1 "MIS"}
+ { AGEBD-INJECTIONGUARD{{ agebd_env }} 04 1 "VCS"}
+ { AGEBD-INJECTIONGUARD{{ agebd_env }} 05 1 "Linac KV/BB/BY"}
+ { AGEBD-INJECTIONGUARD{{ agebd_env }} 06 1 "RF Linac"}
+ { AGEBD-INJECTIONGUARD{{ agebd_env }} 07 1 "RF Booster"}
+ { AGEBD-INJECTIONGUARD{{ agebd_env }} 08 1 "RF Ring"}
+ { AGEBD-INJECTIONGUARD{{ agebd_env }} 09 1 "Magnets Pulsed"}
+ { AGEBD-INJECTIONGUARD{{ agebd_env }} 10 1 "Magnets Booster"}
+ { AGEBD-INJECTIONGUARD{{ agebd_env }} 11 1 "Magnets Corrector"}
+ { AGEBD-INJECTIONGUARD{{ agebd_env }} 12 1 "Magnets Ring"}
+ { AGEBD-INJECTIONGUARD{{ agebd_env }} 13 1 "Current Limit"}
+ { AGEBD-INJECTIONGUARD{{ agebd_env }} 14 1 "IDs Ready"}
+ { AGEBD-INJECTIONGUARD{{ agebd_env }} 15 1 "Single Bunch Charge"}
+ { AGEBD-INJECTIONGUARD{{ agebd_env }} 16 1 "Injection Quality"}
+ { AGEBD-INJECTIONGUARD{{ agebd_env }} 17 1 "Dump Quality"}
+ { AGEBD-INJECTIONGUARD{{ agebd_env }} 18 1 "Lifetime"}
+ { AGEBD-INJECTIONGUARD{{ agebd_env }} 19 1 "Tune"}
+ { AGEBD-INJECTIONGUARD{{ agebd_env }} 20 0 "Pingers"}
+ { AGEBD-INJECTIONGUARD{{ agebd_env }} 21 1 "Vacuum Pressure"}
+ { AGEBD-INJECTIONGUARD{{ agebd_env }} 22 1 "Orbit Deviation"}
+ { AGEBD-INJECTIONGUARD{{ agebd_env }} 23 1 "Beam Dump Controller"}
+}
diff --git a/services/injectionguard/current/ioc/AGEBD-CPCL-INJECTIONGUARD_parameters.yaml b/services/injectionguard/current/ioc/AGEBD-CPCL-INJECTIONGUARD_parameters.yaml
new file mode 100644
index 0000000..ff8e70f
--- /dev/null
+++ b/services/injectionguard/current/ioc/AGEBD-CPCL-INJECTIONGUARD_parameters.yaml
@@ -0,0 +1,6 @@
+cpu_architecture: x86_64
+epics_version: 7.0.8
+ioc_host: sls-vserv-bd-01{{ agebd_env }}
+ioc_port: {{ ioc_port }}
+os: RHEL8
+os_id: rhel
diff --git a/services/injectionguard/current/ioc/INJECTIONGUARD_automated.template b/services/injectionguard/current/ioc/INJECTIONGUARD_automated.template
new file mode 100644
index 0000000..3661b8b
--- /dev/null
+++ b/services/injectionguard/current/ioc/INJECTIONGUARD_automated.template
@@ -0,0 +1,87 @@
+record(bo, "$(DEVICE):CONTROL-BRIDGE-CHECK-$(NR)") {
+ field(DESC, "Only in MD mode: bridge check $(NR)")
+ field(ASG, "PROTECTED")
+ field(FLNK, "$(DEVICE):CHECK-$(NR)-MD")
+ field(VAL, "0")
+ field(ZSV, "NO_ALARM")
+ field(OSV, "MINOR")
+ field(PINI, "YES")
+}
+
+record(bo, "$(DEVICE):CHECK-$(NR)") {
+ field(DESC, "$(Description)")
+ field(ASG, "PROTECTED")
+ field(FLNK, "$(DEVICE):CHECK-$(NR)-MD")
+ field(ZSV, "MAJOR")
+ field(OSV, "NO_ALARM")
+ field(VAL, "1")
+ field(PINI, "YES")
+ field(HIGH, "1") # Seconds until automatic switch to Alarm
+}
+
+record(calc, "$(DEVICE):CHECK-$(NR)-MD") {
+ field(DESC, "Check $(NR) MD, written by IOC")
+ field(ASG, "READONLY")
+ field(FLNK, "$(DEVICE):CHECK-$(NR)-LATCHFWD")
+ field(LOLO, "0.1")
+ field(LLSV, "MAJOR")
+ field(CALC, "A ? 1 : B")
+ field(INPA, "$(DEVICE):CONTROL-BRIDGE-CHECK-$(NR)")
+ field(INPB, "$(DEVICE):CHECK-$(NR)")
+}
+
+# forward only alarm states to latch bo
+record(calcout, "$(DEVICE):CHECK-$(NR)-LATCHFWD") {
+ field(DESC, "Latchfwd for check $(NR)")
+ field(ASG, "READONLY")
+ field(FLNK, "$(DEVICE):CHECK-$(NR)-LATCH")
+ field(CALC, "$(Latch)? ( A? C : B ) : 1")
+ field(PINI, "YES")
+ field(INPA, "$(DEVICE):CONTROL-MODE CP")
+ field(INPB, "$(DEVICE):CHECK-$(NR) CP")
+ field(INPC, "$(DEVICE):CHECK-$(NR)-MD CP")
+ field(OOPT, "When Zero")
+ field(DOPT, "Use CALC")
+ field(OUT, "$(DEVICE):CHECK-$(NR)-LATCH.VAL")
+}
+
+# forward current state to latch bo on reset event
+record(calcout, "$(DEVICE):CHECK-$(NR)-LATCHRST") {
+ field(DESC, "Latchfwd for check $(NR)")
+ field(ASG, "READONLY")
+ field(FLNK, "$(DEVICE):CHECK-$(NR)-LATCH")
+ field(SCAN, "Event")
+ field(EVNT, "5")
+ field(CALC, "$(Latch)? ( A? C : B ) : 1")
+ field(PINI, "YES")
+ field(INPA, "$(DEVICE):CONTROL-MODE")
+ field(INPB, "$(DEVICE):CHECK-$(NR)")
+ field(INPC, "$(DEVICE):CHECK-$(NR)-MD")
+ field(OOPT, "Every Time")
+ field(DOPT, "Use CALC")
+ field(OUT, "$(DEVICE):CHECK-$(NR)-LATCH.VAL")
+}
+
+record(bo, "$(DEVICE):CHECK-$(NR)-LATCH") {
+ field(DESC, "$(Description)")
+ field(ASG, "READONLY")
+ field(FLNK, "$(DEVICE):CHECK-SUM-OP-A")
+ field(ZSV, "MINOR")
+ field(OSV, "NO_ALARM")
+ field(VAL, "1")
+ field(PINI, "YES")
+}
+
+# emit event for master rearm when alarm state is left and non latched
+record(calcout, "$(DEVICE):CHECK-$(NR)-REARM-MASTER") {
+ field(DESC, "Rearm Master for non latched checks")
+ field(ASG, "NOACCESS")
+ field(CALC, "!$(Latch)? ( A? C : B ) : 1")
+ field(PINI, "YES")
+ field(INPA, "$(DEVICE):CONTROL-MODE CP")
+ field(INPB, "$(DEVICE):CHECK-$(NR) CP")
+ field(INPC, "$(DEVICE):CHECK-$(NR)-MD CP")
+ field(OOPT, "Transition To Non-zero")
+ field(OEVT, "4")
+ field(ODLY, "0.1")
+}
diff --git a/services/injectionguard/current/ioc/INJECTIONGUARD_individual.template b/services/injectionguard/current/ioc/INJECTIONGUARD_individual.template
new file mode 100644
index 0000000..b6e66d2
--- /dev/null
+++ b/services/injectionguard/current/ioc/INJECTIONGUARD_individual.template
@@ -0,0 +1,304 @@
+# HLA Service Control Parameters
+
+record(mbbo, "$(DEVICE):CONTROL-MODE") {
+ field(DESC, "Mode of Injection Guard")
+ field(ASG, "PROTECTED")
+ field(FLNK, "$(DEVICE):CHECK-SUM")
+ field(ZRST, "User Operation")
+ field(ZRVL, "0")
+ field(ONST, "Machine Development")
+ field(ONVL, "1")
+ field(PINI, "YES")
+}
+
+# Local events on this IOC
+# 1 - secret master trigger inhibited
+# 2 - gun trigger inhibited
+# 3 - booster extraction trigger inhibited
+# 4 - rearm of master trigger if sum signal ok again
+# 5 - request to reset latches
+
+record(waveform,"$(DEVICE):LOG") {
+ field(DESC, "Last failed checks")
+ field(ASG, "PROTECTED")
+ field(FTVL, "CHAR")
+ field(NELM, "$(SIZE=60000)")
+ field(PINI, "YES")
+}
+
+record(bo, "$(DEVICE):LOG-PAUSE") {
+ field(DESC, "pause/start logging")
+ field(ASG, "PROTECTED")
+ field(ZNAM, "Start")
+ field(ONAM, "Pause")
+ field(VAL, "1")
+ field(PINI, "YES")
+ field(HIGH, "60") # Seconds until automatic switch back to run
+}
+
+record(bo,"$(DEVICE):LOG-CLEAR") {
+ field(DESC, "Clear log of last failed checks")
+ field(ASG, "PROTECTED")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(bi,"$(DEVICE):STATUS-SECRET-MASTER") {
+ field(DESC, "Status of secret master trigger")
+ field(ASG, "READONLY")
+ field(ZSV, "MAJOR" )
+ field(INP, "$(DEVICE):NOACCESS-SECRETMASTER CP")
+ field(PINI, "YES")
+}
+
+record(bi,"$(DEVICE):NOACCESS-SECRETMASTER") {
+ field(DESC, "Status of secret master trigger")
+ field(ASG, "NOACCESS")
+ field(INP, "AGETI-CVME-MASTER-TMA:SR-Inj-Status-Sel-I CP")
+ field(PINI, "YES")
+}
+
+record(calcout, "$(DEVICE):AUTO-REARM-MASTER-CALCOUT") {
+ field(DESC, "Automatic rearming of master trigger")
+ field(ASG, "READONLY")
+ field(SCAN, "Event")
+ field(EVNT, "4")
+ field(CALC, "(A > 0) ? 1 : 0")
+ field(INPA, "$(DEVICE):CHECK-SUM")
+ field(OOPT, "When Non-zero")
+ field(DOPT, "Use CALC")
+ field(OUT, "AGETI-CVME-MASTER-TMA:SR-Inj-Status-Sel")
+}
+
+record(calcout, "$(DEVICE):OUTLINK-2-ONBEAM-FORWARD") {
+ field(DESC, "activate secret trigger if checks ok")
+ field(ASG, "READONLY")
+ field(CALC, "(A > 0) ? 0 : 1")
+ field(INPA, "$(DEVICE):CHECK-SUM")
+ field(OOPT, "Transition To Zero")
+ field(ODLY, "0")
+ field(DOPT, "Use OCAL")
+ field(OCAL, "1")
+ field(OUT, "AGETI-CVME-MASTER-TMA:SR-Inj-Status-Sel-I")
+}
+
+record(calcout, "$(DEVICE):OUTLINK-2-ONBEAM-INHIBIT") {
+ field(DESC, "disable secret trigger if checks nok")
+ field(ASG, "READONLY")
+ field(CALC, "!A && B ? 0 : 1")
+ field(INPA, "$(DEVICE):CHECK-SUM")
+ field(INPB, "AGETI-CVME-MASTER-TMA:SR-Inj-Status-Sel-I CP")
+ field(OOPT, "When Zero")
+ field(OEVT, "1")
+ field(ODLY, "0")
+ field(DOPT, "Use CALC")
+ field(OUT, "AGETI-CVME-MASTER-TMA:SR-Inj-Status-Sel-I")
+}
+
+# record(calcout, "$(DEVICE):OUTLINK-2-GUNTRI") {
+# field(DESC, "disable gun if checks nok")
+# field(ASG, "READONLY")
+# field(CALC, "!A && B ? 0 : 1")
+# field(INPA, "$(DEVICE):CHECK-SUM")
+# field(INPB, "ALIRF-VME-A-GUN:CH1-MODE CP")
+# field(OOPT, "Transition To Zero")
+# field(OEVT, "2")
+# field(ODLY, "0")
+# field(DOPT, "Use CALC")
+# field(OUT, "ALIRF-VME-A-GUN:CH1-MODE")
+# }
+
+# record(calcout, "$(DEVICE):OUTLINK-2-BOOEXT") {
+# field(DESC, "disable booster extraction if checks nok")
+# field(ASG, "READONLY")
+# field(CALC, "!A && B ? 0 : 1")
+# field(INPA, "$(DEVICE):CHECK-SUM")
+# field(INPB, "AGETI-CVME-MASTER-TMA:Evt-10-Ena-Sel CP")
+# field(OOPT, "Transition To Zero")
+# field(OEVT, "3")
+# field(ODLY, "0")
+# field(DOPT, "Use CALC")
+# field(OUT, "AGETI-CVME-MASTER-TMA:Evt-10-Ena-Sel")
+# }
+
+# Overall Check SUM
+record(fanout, "$(DEVICE):CHECK-SUM-FANOUT") {
+ field(DESC, "FANOUT for checksum changes")
+ field(ASG, "READONLY")
+ field(SELM, "All")
+ field(LNK1, "$(DEVICE):OUTLINK-2-ONBEAM-FORWARD")
+ field(LNK2, "$(DEVICE):OUTLINK-2-ONBEAM-INHIBIT")
+ # field(LNK3, "$(DEVICE):OUTLINK-2-GUNTRI")
+ # field(LNK4, "$(DEVICE):OUTLINK-2-BOOEXT")
+}
+
+record(mbbi, "$(DEVICE):CHECK-SUM") {
+ field(DESC, "Check SUM overall, written by IOC")
+ field(FLNK, "$(DEVICE):CHECK-SUM-FANOUT")
+ field(ASG, "READONLY")
+ field(ZRST, "Injection Inhibit")
+ field(ZRVL, "0")
+ field(ZRSV, "MAJOR")
+ field(ONST, "Injection Enabled")
+ field(ONVL, "1")
+ field(ONSV, "NO_ALARM")
+ field(TWST, "Linac Mode")
+ field(TWVL, "2")
+ field(TWSV, "MINOR")
+}
+
+record(calcout, "$(DEVICE):CHECK-SUM-CALC") {
+ field(DESC, "Check SUM overall, written by IOC")
+ field(FLNK, "$(DEVICE):CHECK-SUM")
+ field(ASG, "READONLY")
+ field(CALC, "!E & !F ? 2 : (A ? B & D : C & D)")
+ field(INPA, "$(DEVICE):CONTROL-MODE")
+ field(INPB, "$(DEVICE):CHECK-SUM-MD")
+ field(INPC, "$(DEVICE):CHECK-SUM-OP")
+ field(INPD, "$(DEVICE):CHECK-SUM-LATCH")
+ field(INPE, "ALI00-SGEN-PSYS:ALBSA-BB-OPEN") # Linac Mode, (0 closed, 1 opened)
+ field(INPF, "ALI00-SGEN-PSYS:ALBSA-KV-OPEN") # Linac Mode, (0 closed, 1 opened)
+ field(DOPT, "Use CALC")
+ field(OUT, "$(DEVICE):CHECK-SUM")
+}
+
+# Check SUMs OP/MD
+record(calc, "$(DEVICE):CHECK-SUM-OP-A") {
+ field(DESC, "Check SUM OP Mode, written by IOC")
+ field(FLNK, "$(DEVICE):CHECK-SUM-OP")
+ field(ASG, "READONLY")
+ field(CALC, "A & B & C & D & E & F & G & H & I & J & K & L")
+ field(INPA, "$(DEVICE):CHECK-12")
+ field(INPB, "$(DEVICE):CHECK-13")
+ field(INPC, "$(DEVICE):CHECK-14")
+ field(INPD, "$(DEVICE):CHECK-15")
+ field(INPE, "$(DEVICE):CHECK-16")
+ field(INPF, "$(DEVICE):CHECK-17")
+ field(INPG, "$(DEVICE):CHECK-18")
+ field(INPH, "$(DEVICE):CHECK-19")
+ field(INPI, "$(DEVICE):CHECK-20")
+ field(INPJ, "$(DEVICE):CHECK-21")
+ field(INPK, "$(DEVICE):CHECK-22")
+ field(INPL, "$(DEVICE):CHECK-23")
+}
+
+record(calc, "$(DEVICE):CHECK-SUM-OP") {
+ field(DESC, "Check SUM OP Mode, written by IOC")
+ field(FLNK, "$(DEVICE):CHECK-SUM-MD-A")
+ field(ASG, "READONLY")
+ field(LOLO, "0.1")
+ field(LLSV, "MAJOR")
+ field(CALC, "A & B & C & D & E & F & G & H & I & J & K & L")
+ field(INPA, "$(DEVICE):CHECK-01")
+ field(INPB, "$(DEVICE):CHECK-02")
+ field(INPC, "$(DEVICE):CHECK-03")
+ field(INPD, "$(DEVICE):CHECK-04")
+ field(INPE, "$(DEVICE):CHECK-05")
+ field(INPF, "$(DEVICE):CHECK-06")
+ field(INPG, "$(DEVICE):CHECK-07")
+ field(INPH, "$(DEVICE):CHECK-08")
+ field(INPI, "$(DEVICE):CHECK-09")
+ field(INPJ, "$(DEVICE):CHECK-10")
+ field(INPK, "$(DEVICE):CHECK-11")
+ field(INPL, "$(DEVICE):CHECK-SUM-OP-A")
+}
+
+record(calc, "$(DEVICE):CHECK-SUM-MD-A") {
+ field(DESC, "Check SUM MD Mode, written by IOC")
+ field(FLNK, "$(DEVICE):CHECK-SUM-MD")
+ field(ASG, "READONLY")
+ field(CALC, "A & B & C & D & E & F & G & H & I & J & K & L")
+ field(INPA, "$(DEVICE):CHECK-12-MD")
+ field(INPB, "$(DEVICE):CHECK-13-MD")
+ field(INPC, "$(DEVICE):CHECK-14-MD")
+ field(INPD, "$(DEVICE):CHECK-15-MD")
+ field(INPE, "$(DEVICE):CHECK-16-MD")
+ field(INPF, "$(DEVICE):CHECK-17-MD")
+ field(INPG, "$(DEVICE):CHECK-18-MD")
+ field(INPH, "$(DEVICE):CHECK-19-MD")
+ field(INPI, "$(DEVICE):CHECK-20-MD")
+ field(INPJ, "$(DEVICE):CHECK-21-MD")
+ field(INPK, "$(DEVICE):CHECK-22-MD")
+ field(INPL, "$(DEVICE):CHECK-23-MD")
+}
+
+record(calc, "$(DEVICE):CHECK-SUM-MD") {
+ field(DESC, "Check SUM MD Mode, written by IOC")
+ field(FLNK, "$(DEVICE):CHECK-SUM-LATCH-A")
+ field(ASG, "READONLY")
+ field(LOLO, "0.1")
+ field(LLSV, "MAJOR")
+ field(CALC, "A & B & C & D & E & F & G & H & I & J & K & L")
+ field(INPA, "$(DEVICE):CHECK-01-MD")
+ field(INPB, "$(DEVICE):CHECK-02-MD")
+ field(INPC, "$(DEVICE):CHECK-03-MD")
+ field(INPD, "$(DEVICE):CHECK-04-MD")
+ field(INPE, "$(DEVICE):CHECK-05-MD")
+ field(INPF, "$(DEVICE):CHECK-06-MD")
+ field(INPG, "$(DEVICE):CHECK-07-MD")
+ field(INPH, "$(DEVICE):CHECK-08-MD")
+ field(INPI, "$(DEVICE):CHECK-09-MD")
+ field(INPJ, "$(DEVICE):CHECK-10-MD")
+ field(INPK, "$(DEVICE):CHECK-11-MD")
+ field(INPL, "$(DEVICE):CHECK-SUM-MD-A")
+}
+
+record(calc, "$(DEVICE):CHECK-SUM-LATCH-A") {
+ field(DESC, "Check SUM LATCH Mode, written by IOC")
+ field(FLNK, "$(DEVICE):CHECK-SUM-LATCH")
+ field(ASG, "READONLY")
+ field(CALC, "A & B & C & D & E & F & G & H & I & J & K & L")
+ field(INPA, "$(DEVICE):CHECK-12-LATCH")
+ field(INPB, "$(DEVICE):CHECK-13-LATCH")
+ field(INPC, "$(DEVICE):CHECK-14-LATCH")
+ field(INPD, "$(DEVICE):CHECK-15-LATCH")
+ field(INPE, "$(DEVICE):CHECK-16-LATCH")
+ field(INPF, "$(DEVICE):CHECK-17-LATCH")
+ field(INPG, "$(DEVICE):CHECK-18-LATCH")
+ field(INPH, "$(DEVICE):CHECK-19-LATCH")
+ field(INPI, "$(DEVICE):CHECK-20-LATCH")
+ field(INPJ, "$(DEVICE):CHECK-21-LATCH")
+ field(INPK, "$(DEVICE):CHECK-22-LATCH")
+ field(INPL, "$(DEVICE):CHECK-23-LATCH")
+}
+
+record(calc, "$(DEVICE):CHECK-SUM-LATCH") {
+ field(DESC, "Check SUM LATCH Mode, written by IOC")
+ field(FLNK, "$(DEVICE):CHECK-SUM-CALC")
+ field(ASG, "READONLY")
+ field(LOLO, "0.1")
+ field(LLSV, "MINOR")
+ field(CALC, "A & B & C & D & E & F & G & H & I & J & K & L")
+ field(INPA, "$(DEVICE):CHECK-01-LATCH")
+ field(INPB, "$(DEVICE):CHECK-02-LATCH")
+ field(INPC, "$(DEVICE):CHECK-03-LATCH")
+ field(INPD, "$(DEVICE):CHECK-04-LATCH")
+ field(INPE, "$(DEVICE):CHECK-05-LATCH")
+ field(INPF, "$(DEVICE):CHECK-06-LATCH")
+ field(INPG, "$(DEVICE):CHECK-07-LATCH")
+ field(INPH, "$(DEVICE):CHECK-08-LATCH")
+ field(INPI, "$(DEVICE):CHECK-09-LATCH")
+ field(INPJ, "$(DEVICE):CHECK-10-LATCH")
+ field(INPK, "$(DEVICE):CHECK-11-LATCH")
+ field(INPL, "$(DEVICE):CHECK-SUM-LATCH-A")
+}
+
+record(bo, "$(DEVICE):RESET-LATCHES") {
+ field(DESC, "Reset all Latches")
+ field(ASG, "PROTECTED")
+ field(FLNK, "$(DEVICE):RESET-LATCHES-CALCOUT")
+ field(VAL, "0")
+ field(PINI, "YES")
+ field(HIGH, "1") # Seconds until automatic switch to 0
+}
+
+record(calcout, "$(DEVICE):RESET-LATCHES-CALCOUT") {
+ field(DESC, "Reset all Latches")
+ field(ASG, "PROTECTED")
+ field(VAL, "0")
+ field(PINI, "YES")
+ field(CALC, "A")
+ field(INPA, "$(DEVICE):RESET-LATCHES")
+ field(OOPT, "Transition To Non-zero")
+ field(OEVT, "5")
+}
diff --git a/services/injectionguard/current/ioc/startup.script b/services/injectionguard/current/ioc/startup.script
new file mode 100644
index 0000000..0fa52ff
--- /dev/null
+++ b/services/injectionguard/current/ioc/startup.script
@@ -0,0 +1 @@
+epicsEnvSet("ENGINEER", "armborst")
diff --git a/services/injectionguard/current/qt/A_BD_InjectionGuard.ui b/services/injectionguard/current/qt/A_BD_InjectionGuard.ui
new file mode 100644
index 0000000..d452d7b
--- /dev/null
+++ b/services/injectionguard/current/qt/A_BD_InjectionGuard.ui
@@ -0,0 +1,988 @@
+
+
+ MainWindow
+
+
+
+ 0
+ 0
+ 600
+ 1195
+
+
+
+ MainWindow
+
+
+
+
+/*-----------------------------------------------*/
+/* Title */
+/*-----------------------------------------------*/
+/* Operation panels */
+caLabel[statusTip="Operation"]{
+ color: rgba(0, 0, 0, 255);
+ font: bold 18pt;
+ font-family: Sans Serif;
+ padding: 1px;
+ margin: 0px;
+ qproperty-alignment: AlignLeft;
+ qproperty-frameShape: StyledPanel;
+ /*qproperty-geometry: rect(-2 0 1600 33);*/
+ background: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1,
+ stop:0 rgba(218, 218, 218, 255),
+ stop:0.5 rgba(200, 200, 200, 255),
+ stop:1 rgba(218, 218, 218, 255));
+}
+
+
+
+
+
+
+ 670
+ 140
+ 70
+ 20
+
+
+
+
+
+
+ 670
+ 80
+ 70
+ 20
+
+
+
+ Reload
+
+
+ RELOAD
+
+
+ A
+
+
+ AGEBD-ALH:INJECTIONGUARD-GUIRELOAD
+
+
+ caCalc::TriggerZeroToOne
+
+
+
+
+
+
+ 10
+ 36
+ 110
+ 40
+
+
+
+
+ 25
+ 75
+ true
+
+
+
+ Mode
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+
+
+ 10
+ 78
+ 580
+ 60
+
+
+
+ AGEBD-INJECTIONGUARD:CHECK-SUM
+
+
+ caLineEdit::Alarm_Default
+
+
+ caLineEdit::onBackground
+
+
+ caLineEdit::User
+
+
+
+
+
+ 652
+ 394
+ 150
+ 22
+
+
+
+
+ 9
+
+
+
+ Ring Reset
+
+
+ ARS00-VCS:PLC_ARS_RESET_REQUEST
+
+
+ Ring Reset
+
+
+
+ 212
+ 219
+ 157
+
+
+
+ 1
+
+
+
+
+
+ 652
+ 346
+ 150
+ 22
+
+
+
+
+ 9
+
+
+
+ LI LTB Reset
+
+
+ ARS00-VCS:PLC_ALIVA_RESET_REQUEST
+
+
+ LI LTB Reset
+
+
+
+ 212
+ 219
+ 157
+
+
+
+ 1
+
+
+
+
+
+ 652
+ 370
+ 150
+ 22
+
+
+
+
+ 9
+
+
+
+ Boster Reset
+
+
+ ARS00-VCS:PLC_ABOVA_RESET_REQUEST
+
+
+ Boster Reset
+
+
+
+ 212
+ 219
+ 157
+
+
+
+ 1
+
+
+
+
+
+ 722
+ 438
+ 150
+ 22
+
+
+
+
+
+
+ MIS Alarm Reset
+
+
+ ARS00-MIS-PLC-01:Alarm_Reset
+
+
+ MIS Alarm Reset
+
+
+ 1
+
+
+
+
+
+ 722
+ 474
+ 150
+ 22
+
+
+
+
+
+
+ MIS-FE Alarm Reset
+
+
+ ACOSA-MIS-FE:ACKERR-REQUEST
+
+
+ MIS-FE Alarm Reset
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 722
+ 544
+ 150
+ 22
+
+
+
+
+
+
+ VCS ALIVA Reset
+
+
+ ARS00-VCS:PLC_ALIVA_RESET_REQUEST
+
+
+ VCS ALIVA Reset
+
+
+ 1
+
+
+
+
+
+ 722
+ 506
+ 150
+ 22
+
+
+
+
+
+
+ VCS ABOVA Reset
+
+
+ ARS00-VCS:PLC_ABOVA_RESET_REQUEST
+
+
+ VCS ABOVA Reset
+
+
+ 1
+
+
+
+
+
+ 726
+ 578
+ 150
+ 22
+
+
+
+
+
+
+ VCS ARS Reset
+
+
+ ARS00-VCS:PLC_ARS_RESET_REQUEST
+
+
+ VCS ARS Reset
+
+
+ 1
+
+
+
+
+
+ 10
+ 140
+ 580
+ 1050
+
+
+
+ 0
+
+
+
+ Checks
+
+
+
+
+ 10
+ 10
+ 40
+ 40
+
+
+
+ true
+
+
+ false
+
+
+ 30
+
+
+ 30
+
+
+ AGEBD-INJECTIONGUARD:STATUS-SECRET-MASTER
+
+
+ caLed::Alarm
+
+
+
+
+
+ 60
+ 10
+ 300
+ 40
+
+
+
+
+ Sans Serif
+ 16
+ 75
+ true
+
+
+
+ true
+
+
+ Qt::LeftToRight
+
+
+ Master Trigger Freigabe
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ QFrame::NoFrame
+
+
+
+
+
+ 0
+ 110
+ 580
+ 901
+
+
+
+ checknr=01,bridge=1,latch=1;checknr=02,bridge=1,latch=1;checknr=03,bridge=1,latch=1;checknr=04,bridge=1,latch=1;checknr=05,bridge=1,latch=1;checknr=06,bridge=1,latch=1;checknr=07,bridge=1,latch=1;checknr=08,bridge=1,latch=1;checknr=09,bridge=1,latch=1;checknr=10,bridge=1,latch=1;checknr=11,bridge=1,latch=1;checknr=12,bridge=1,latch=1;checknr=13,bridge=1,latch=1;checknr=14,bridge=1,latch=1;checknr=15,bridge=1,latch=1;checknr=16,bridge=1,latch=1;checknr=17,bridge=1,latch=1;checknr=18,bridge=1,latch=1;checknr=19,bridge=1,latch=1;checknr=20,bridge=0,latch=0;checknr=21,bridge=1,latch=1;checknr=22,bridge=1,latch=1;checknr=23,bridge=1,latch=1
+
+
+ A_BD_InjectionGuard_inc.ui
+
+
+ 23
+
+
+
+
+
+ 270
+ 60
+ 20
+ 900
+
+
+
+ Qt::Vertical
+
+
+
+
+
+ 10
+ 96
+ 560
+ 20
+
+
+
+ Qt::Horizontal
+
+
+
+
+
+ 210
+ 60
+ 20
+ 900
+
+
+
+ Qt::Vertical
+
+
+
+
+
+ 230
+ 66
+ 40
+ 30
+
+
+
+
+ Monospace
+ 19
+ 75
+ true
+ PreferDefault
+
+
+
+ OP
+
+
+ OP
+
+
+ Qt::AlignCenter
+
+
+ AGEBD-INJECTIONGUARD:CHECK-SUM-OP
+
+
+ caLineEdit::Alarm_Default
+
+
+ caLineEdit::onBackground
+
+
+ caLineEdit::User
+
+
+
+
+
+ 340
+ 66
+ 111
+ 30
+
+
+
+
+ 18
+ 75
+ false
+ true
+
+
+
+ false
+
+
+ BRIDGE
+
+
+ Qt::AlignCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 290
+ 66
+ 40
+ 30
+
+
+
+
+ Monospace
+ 19
+ 75
+ true
+ PreferDefault
+
+
+
+ M\D
+
+
+ MD
+
+
+ Qt::AlignCenter
+
+
+ AGEBD-INJECTIONGUARD:CHECK-SUM-MD
+
+
+ caLineEdit::Alarm_Default
+
+
+ caLineEdit::onBackground
+
+
+ caLineEdit::User
+
+
+
+
+
+ 9
+ 66
+ 201
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ Check
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 440
+ 60
+ 20
+ 900
+
+
+
+ Qt::Vertical
+
+
+
+
+
+ 470
+ 66
+ 80
+ 30
+
+
+
+
+ Monospace
+ 19
+ 75
+ true
+ PreferDefault
+
+
+
+ L\ATC\H
+
+
+ LATCH
+
+
+ Qt::AlignCenter
+
+
+ AGEBD-INJECTIONGUARD:CHECK-SUM-LATCH
+
+
+ caLineEdit::Alarm_Default
+
+
+ caLineEdit::onBackground
+
+
+ caLineEdit::User
+
+
+
+
+
+ 460
+ 10
+ 100
+ 40
+
+
+
+ Reset
+
+
+ false
+
+
+ AGEBD-INJECTIONGUARD:RESET-LATCHES
+
+
+ Reset
+
+
+
+ 160
+ 160
+ 160
+
+
+
+
+
+
+ 1
+
+
+
+
+
+ Logs
+
+
+
+
+ 0
+ 38
+ 575
+ 983
+
+
+
+
+ Monospace
+ 10
+ PreferDefault
+
+
+
+ Qt::ScrollBarAlwaysOn
+
+
+ Qt::ScrollBarAsNeeded
+
+
+ AGEBD-INJECTIONGUARD:LOG
+
+
+ caMultiLineString::None
+
+
+
+
+
+ 470
+ 2
+ 101
+ 30
+
+
+
+ Clear Logs
+
+
+ AGEBD-INJECTIONGUARD:LOG-CLEAR
+
+
+ Clear Logs
+
+
+
+ 160
+ 160
+ 160
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 10
+ 2
+ 101
+ 30
+
+
+
+ AGEBD-INJECTIONGUARD:LOG-PAUSE
+
+
+
+ 160
+ 160
+ 160
+
+
+
+ caChoice::Default
+
+
+ caChoice::Column
+
+
+ 1
+
+
+
+
+
+
+
+ -2
+ 2
+ 628
+ 30
+
+
+
+
+ Sans Serif
+ 18
+ 75
+ false
+ true
+
+
+
+ Operation
+
+
+ Injection Guard
+
+
+ Qt::AlignLeading
+
+
+
+ 218
+ 218
+ 218
+
+
+
+ caLabel::Default
+
+
+
+
+
+ 556
+ 6
+ 40
+ 22
+
+
+
+ -Wiki
+
+
+
+ 183
+ 157
+ 92
+
+
+
+ Injection Guard
+
+
+ https://acceleratorwiki.psi.ch/wiki/Injection_Guard
+
+
+
+
+
+
+
+
+
+ caMenu
+ QComboBox
+
+
+
+ caChoice
+ QWidget
+
+
+
+ caMessageButton
+ QPushButton
+
+
+
+ caLabel
+ QLabel
+
+
+
+ caInclude
+ QWidget
+
+
+
+ caLed
+ QWidget
+
+
+
+ caLineEdit
+ QLineEdit
+
+
+
+ caMultiLineString
+ QPlainTextEdit
+
+
+
+ caCalc
+ QLabel
+
+
+
+ wmSignalPropagator
+ QLabel
+
+
+
+ caMimeDisplay
+ QWidget
+
+
+
+
+
+
+ cacalc_2
+ emitSignal(bool)
+ wmsignalpropagator
+ reloadwindow()
+
+
+ 598
+ 89
+
+
+ 608
+ 152
+
+
+
+
+
diff --git a/services/injectionguard/current/qt/A_BD_InjectionGuard_inc.ui b/services/injectionguard/current/qt/A_BD_InjectionGuard_inc.ui
new file mode 100644
index 0000000..1170830
--- /dev/null
+++ b/services/injectionguard/current/qt/A_BD_InjectionGuard_inc.ui
@@ -0,0 +1,243 @@
+
+
+ MainWindow
+
+
+
+ 0
+ 0
+ 580
+ 30
+
+
+
+ MainWindow
+
+
+
+
+
+ 380
+ 6
+ 18
+ 18
+
+
+
+
+ 20
+ 20
+
+
+
+ AGEBD-INJECTIONGUARD:CONTROL-BRIDGE-CHECK-$(checknr)
+
+
+
+ 200
+ 200
+ 200
+
+
+
+ caToggleButton::Default
+
+
+ 1
+
+
+ caToggleButton::on_top
+
+
+
+
+
+ 220
+ 0
+ 40
+ 30
+
+
+
+ false
+
+
+ AGEBD-INJECTIONGUARD:CHECK-$(checknr)
+
+
+ caLed::Alarm
+
+
+
+
+
+ 280
+ 0
+ 40
+ 30
+
+
+
+ false
+
+
+ AGEBD-INJECTIONGUARD:CHECK-$(checknr)-MD
+
+
+ caLed::Alarm
+
+
+
+
+
+ 0
+ 0
+ 200
+ 30
+
+
+
+
+ Monospace
+ 13
+ PreferDefault
+
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ true
+
+
+ AGEBD-INJECTIONGUARD:CHECK-$(checknr).DESC
+
+
+
+ 160
+ 160
+ 164
+
+
+
+ caLineEdit::Static
+
+
+ caLineEdit::None
+
+
+
+
+
+ 460
+ 0
+ 120
+ 30
+
+
+
+
+ 160
+ 160
+ 164
+
+
+
+ caFrame::Outline
+
+
+ caFrame::Calc
+
+
+ caFrame::All
+
+
+ $(latch)
+
+
+
+
+
+
+
+ 40
+ 0
+ 40
+ 30
+
+
+
+ false
+
+
+ AGEBD-INJECTIONGUARD:CHECK-$(checknr)-LATCH
+
+
+ caLed::Alarm
+
+
+
+
+
+
+ 376
+ 4
+ 22
+ 23
+
+
+
+ true
+
+
+ false
+
+
+ 20
+
+
+ 20
+
+
+ AGEBD-INJECTIONGUARD:CONTROL-BRIDGE-CHECK-$(checknr)
+
+
+ caLed::Alarm
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+
+
+
+ caToggleButton
+ QCheckBox
+
+
+
+ caFrame
+ QFrame
+
+ 1
+
+
+ caLed
+ QWidget
+
+
+
+ caLineEdit
+ QLineEdit
+
+
+
+
+
+
+
diff --git a/services/injectionguard/current/systemd/AGEBD-SERVICE-INJECTIONGUARD.service b/services/injectionguard/current/systemd/AGEBD-SERVICE-INJECTIONGUARD.service
new file mode 100644
index 0000000..8bc6ae5
--- /dev/null
+++ b/services/injectionguard/current/systemd/AGEBD-SERVICE-INJECTIONGUARD.service
@@ -0,0 +1,16 @@
+[Unit]
+Description=AGEBD-SERVICE-INJECTIONGUARD
+After=network.target
+
+[Service]
+Environment=AGEBD_ENV={{ agebd_env }}
+ExecStart=/sls/bd/hla/{{ agebd_env }}/bin/start_service.sh INJECTIONGUARD
+Restart=no
+
+[Install]
+WantedBy=default.target
+
+# https://www.freedesktop.org/software/systemd/man/latest/systemd.service.html
+# systemctl --user daemon-reload
+# systemctl --user enable /sls/bd/bin/systemd/AGEBD-SERVICE-INJECTIONGUARD.service
+# systemctl --user start AGEBD-SERVICE-INJECTIONGUARD
diff --git a/services/master/current/app/uv.lock b/services/master/current/app/uv.lock
index 61aea7e..f9f6c6e 100644
--- a/services/master/current/app/uv.lock
+++ b/services/master/current/app/uv.lock
@@ -7,11 +7,15 @@ name = "agebd"
version = "0.1.0"
source = { editable = "../../../../packages/agebd" }
dependencies = [
+ { name = "h5py" },
{ name = "typer" },
]
[package.metadata]
-requires-dist = [{ name = "typer", specifier = ">=0.23.2" }]
+requires-dist = [
+ { name = "h5py", specifier = ">=3.16.0" },
+ { name = "typer", specifier = ">=0.23.2" },
+]
[package.metadata.requires-dev]
dev = [
@@ -79,6 +83,24 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" },
]
+[[package]]
+name = "h5py"
+version = "3.16.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "numpy" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/db/33/acd0ce6863b6c0d7735007df01815403f5589a21ff8c2e1ee2587a38f548/h5py-3.16.0.tar.gz", hash = "sha256:a0dbaad796840ccaa67a4c144a0d0c8080073c34c76d5a6941d6818678ef2738", size = 446526, upload-time = "2026-03-06T13:49:08.07Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/3a/6b/231413e58a787a89b316bb0d1777da3c62257e4797e09afd8d17ad3549dc/h5py-3.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e06f864bedb2c8e7c1358e6c73af48519e317457c444d6f3d332bb4e8fa6d7d9", size = 3724137, upload-time = "2026-03-06T13:47:35.242Z" },
+ { url = "https://files.pythonhosted.org/packages/74/f9/557ce3aad0fe8471fb5279bab0fc56ea473858a022c4ce8a0b8f303d64e9/h5py-3.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ec86d4fffd87a0f4cb3d5796ceb5a50123a2a6d99b43e616e5504e66a953eca3", size = 3090112, upload-time = "2026-03-06T13:47:37.634Z" },
+ { url = "https://files.pythonhosted.org/packages/7a/f5/e15b3d0dc8a18e56409a839e6468d6fb589bc5207c917399c2e0706eeb44/h5py-3.16.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:86385ea895508220b8a7e45efa428aeafaa586bd737c7af9ee04661d8d84a10d", size = 4844847, upload-time = "2026-03-06T13:47:39.811Z" },
+ { url = "https://files.pythonhosted.org/packages/cb/92/a8851d936547efe30cc0ce5245feac01f3ec6171f7899bc3f775c72030b3/h5py-3.16.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:8975273c2c5921c25700193b408e28d6bdd0111c37468b2d4e25dcec4cd1d84d", size = 5065352, upload-time = "2026-03-06T13:47:41.489Z" },
+ { url = "https://files.pythonhosted.org/packages/2b/ae/f2adc5d0ca9626db3277a3d87516e124cbc5d0eea0bd79bc085702d04f2c/h5py-3.16.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:1677ad48b703f44efc9ea0c3ab284527f81bc4f318386aaaebc5fede6bbae56f", size = 4839173, upload-time = "2026-03-06T13:47:43.586Z" },
+ { url = "https://files.pythonhosted.org/packages/64/0b/e0c8c69da1d8838da023a50cd3080eae5d475691f7636b35eff20bb6ef20/h5py-3.16.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7c4dd4cf5f0a4e36083f73172f6cfc25a5710789269547f132a20975bfe2434c", size = 5076216, upload-time = "2026-03-06T13:47:45.315Z" },
+ { url = "https://files.pythonhosted.org/packages/66/35/d88fd6718832133c885004c61ceeeb24dbd6397ef877dbed6b3a64d6a286/h5py-3.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:bdef06507725b455fccba9c16529121a5e1fbf56aa375f7d9713d9e8ff42454d", size = 3183639, upload-time = "2026-03-06T13:47:47.041Z" },
+]
+
[[package]]
name = "iniconfig"
version = "2.3.0"
diff --git a/services/nturns/current/app/uv.lock b/services/nturns/current/app/uv.lock
index 84c0e5e..891ecdd 100644
--- a/services/nturns/current/app/uv.lock
+++ b/services/nturns/current/app/uv.lock
@@ -7,11 +7,15 @@ name = "agebd"
version = "0.1.0"
source = { editable = "../../../../packages/agebd" }
dependencies = [
+ { name = "h5py" },
{ name = "typer" },
]
[package.metadata]
-requires-dist = [{ name = "typer", specifier = ">=0.23.2" }]
+requires-dist = [
+ { name = "h5py", specifier = ">=3.16.0" },
+ { name = "typer", specifier = ">=0.23.2" },
+]
[package.metadata.requires-dev]
dev = [
@@ -81,6 +85,24 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" },
]
+[[package]]
+name = "h5py"
+version = "3.16.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "numpy" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/db/33/acd0ce6863b6c0d7735007df01815403f5589a21ff8c2e1ee2587a38f548/h5py-3.16.0.tar.gz", hash = "sha256:a0dbaad796840ccaa67a4c144a0d0c8080073c34c76d5a6941d6818678ef2738", size = 446526, upload-time = "2026-03-06T13:49:08.07Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/3a/6b/231413e58a787a89b316bb0d1777da3c62257e4797e09afd8d17ad3549dc/h5py-3.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e06f864bedb2c8e7c1358e6c73af48519e317457c444d6f3d332bb4e8fa6d7d9", size = 3724137, upload-time = "2026-03-06T13:47:35.242Z" },
+ { url = "https://files.pythonhosted.org/packages/74/f9/557ce3aad0fe8471fb5279bab0fc56ea473858a022c4ce8a0b8f303d64e9/h5py-3.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ec86d4fffd87a0f4cb3d5796ceb5a50123a2a6d99b43e616e5504e66a953eca3", size = 3090112, upload-time = "2026-03-06T13:47:37.634Z" },
+ { url = "https://files.pythonhosted.org/packages/7a/f5/e15b3d0dc8a18e56409a839e6468d6fb589bc5207c917399c2e0706eeb44/h5py-3.16.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:86385ea895508220b8a7e45efa428aeafaa586bd737c7af9ee04661d8d84a10d", size = 4844847, upload-time = "2026-03-06T13:47:39.811Z" },
+ { url = "https://files.pythonhosted.org/packages/cb/92/a8851d936547efe30cc0ce5245feac01f3ec6171f7899bc3f775c72030b3/h5py-3.16.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:8975273c2c5921c25700193b408e28d6bdd0111c37468b2d4e25dcec4cd1d84d", size = 5065352, upload-time = "2026-03-06T13:47:41.489Z" },
+ { url = "https://files.pythonhosted.org/packages/2b/ae/f2adc5d0ca9626db3277a3d87516e124cbc5d0eea0bd79bc085702d04f2c/h5py-3.16.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:1677ad48b703f44efc9ea0c3ab284527f81bc4f318386aaaebc5fede6bbae56f", size = 4839173, upload-time = "2026-03-06T13:47:43.586Z" },
+ { url = "https://files.pythonhosted.org/packages/64/0b/e0c8c69da1d8838da023a50cd3080eae5d475691f7636b35eff20bb6ef20/h5py-3.16.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7c4dd4cf5f0a4e36083f73172f6cfc25a5710789269547f132a20975bfe2434c", size = 5076216, upload-time = "2026-03-06T13:47:45.315Z" },
+ { url = "https://files.pythonhosted.org/packages/66/35/d88fd6718832133c885004c61ceeeb24dbd6397ef877dbed6b3a64d6a286/h5py-3.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:bdef06507725b455fccba9c16529121a5e1fbf56aa375f7d9713d9e8ff42454d", size = 3183639, upload-time = "2026-03-06T13:47:47.041Z" },
+]
+
[[package]]
name = "iniconfig"
version = "2.3.0"
diff --git a/services/orbitbump/current/app/pyproject.toml b/services/orbitbump/current/app/pyproject.toml
new file mode 100644
index 0000000..7ef40d4
--- /dev/null
+++ b/services/orbitbump/current/app/pyproject.toml
@@ -0,0 +1,47 @@
+[project]
+name = "agebd-orbitbump"
+version = "0.1.0"
+description = "AGEBD-ORBITBUMP Service"
+requires-python = "==3.10.*"
+dependencies = [
+ "agebd",
+]
+
+[dependency-groups]
+dev = [
+ "pyepics>=3.5.8",
+ "pytest>=8.4.2",
+ "ruff>=0.15.20",
+]
+
+[tool.uv.sources]
+# Path is relative to where agebd package is deployed on hla
+# machines (see CI/CD in .gitea/workflows)
+agebd = { path = "../../../../packages/agebd", editable = true }
+
+[build-system]
+requires = ["hatchling"]
+build-backend = "hatchling.build"
+
+[tool.uv]
+package = true
+
+[tool.pytest.ini_options]
+pythonpath = ["src"]
+env = [
+ "AGEBD_ENV=local",
+]
+
+[tool.ruff]
+include = [
+ "src/**/*.py",
+ "tests/**/*.py",
+]
+line-length = 100
+
+[tool.ruff.lint]
+# use isort to sort imports
+extend-select = ["I"]
+
+[tool.ruff.lint.isort]
+known-first-party = ["agebd"]
diff --git a/services/orbitbump/current/app/src/agebd_orbitbump/__init__.py b/services/orbitbump/current/app/src/agebd_orbitbump/__init__.py
new file mode 100644
index 0000000..1800c27
--- /dev/null
+++ b/services/orbitbump/current/app/src/agebd_orbitbump/__init__.py
@@ -0,0 +1 @@
+from .service import PVs, Service
diff --git a/services/orbitbump/current/app/src/agebd_orbitbump/main.py b/services/orbitbump/current/app/src/agebd_orbitbump/main.py
new file mode 100644
index 0000000..d81391d
--- /dev/null
+++ b/services/orbitbump/current/app/src/agebd_orbitbump/main.py
@@ -0,0 +1,31 @@
+import typer
+
+from agebd.enums import LogLevel
+from agebd.runner import CallbackRunner
+from agebd.utils import init_logging
+from agebd_orbitbump import PVs, Service
+
+
+# TODO: remove: cicd test 10
+
+def main(
+ log_level: LogLevel = typer.Option(
+ LogLevel.INFO,
+ "--log-level",
+ "-l",
+ # Looks at the OS env variable first. If empty, falls back to "INFO"
+ envvar="AGEBD_LOG_LEVEL",
+ # help="Set log level: DEBUG, INFO, WARNING, ERROR, CRITICAL",
+ case_sensitive=False,
+ ),
+):
+ init_logging(log_level)
+ service_name = "ORBITBUMP"
+ pvs = PVs(service_name=service_name)
+ service = Service(name=service_name, pvs=pvs)
+ runner = CallbackRunner(service=service)
+ runner.start()
+
+
+if __name__ == "__main__":
+ typer.run(main)
diff --git a/services/orbitbump/current/app/src/agebd_orbitbump/service.py b/services/orbitbump/current/app/src/agebd_orbitbump/service.py
new file mode 100644
index 0000000..8b71fcb
--- /dev/null
+++ b/services/orbitbump/current/app/src/agebd_orbitbump/service.py
@@ -0,0 +1,93 @@
+import time
+
+from epics import dbr
+
+from agebd.pv import LocalPVLink
+from agebd.service.base import BaseService
+from agebd.service.pvs import BasePVs
+from agebd.utils import printgetversion
+from agebd.pv import get_pv_class
+
+__version__ = printgetversion(__file__)
+
+PV = get_pv_class()
+
+
+class PVs(BasePVs):
+ # Option 1:
+ ## Service specific PVs from dedicated IOC
+ my_pv1 = PV("AGEBD-ORBITBUMP:AO") # TODO: is this a good PV to use?
+
+ ## Service specific PVs from other IOCs
+ # ...
+
+ def __init__(self, service_name: str, pv_factory=PV):
+ super().__init__(service_name, pv_factory)
+ PV = pv_factory
+
+ # TODO: can we do this cleaner? Maybe mechanism for
+ # settings initial values in dev mode (e.g. ini file)
+ if isinstance(self.onoff, LocalPVLink):
+ self.onoff.value = True
+
+ # Option 2:
+ ## Service specific PVs from dedicated IOC
+ self.my_pv2 = PV(
+ "AGEBD-ORBITBUMP:BO"
+ ) # TODO: is this a good PV to use?
+
+ ## Service specific PVs from other IOCs
+ # ...
+
+ # TODO: class attribute names usually lowercase
+ # usually it is advisable to trigger the mainloop of a service on changes of certain PVs:
+ self.CallbackPV = PV(
+ "AGEBD-ORBITBUMP:CALLBACK", auto_monitor=dbr.DBE_VALUE
+ ) # TODO: ok?
+
+
+class Service(BaseService[PVs]):
+ def __init__(
+ self,
+ name: str,
+ pvs: PVs,
+ version: str = __version__,
+ sleep_interval: float = 0.1,
+ ):
+ super().__init__(name, pvs, version, sleep_interval)
+
+ # TODO: What is this for?
+ self.path = "sls/bd/bin"
+
+ def update(self):
+ # when callback is fired, this code will be executed
+ if self.CallbackFired:
+ #######################################################################################
+ #######################################################################################
+ # here goes all the code that your service
+ # is supposed to be running when the callback is fired
+ time.sleep(1)
+ #######################################################################################
+ #######################################################################################
+
+ # callback done
+ self.CallbackFired = 0
+
+ #######################################################################################
+ #######################################################################################
+ # here goes all the code that your service
+ # is supposed to be running in any case, e.g.,
+
+ # update some pvs/vals
+ my_pv1_random_val = str(time.clock_gettime_ns(0))[-1]
+ self.pvs.my_pv1.put(my_pv1_random_val)
+ # self.pvs.my_pv2.put("MY_PV2 value")
+
+ # get some pvs/vals
+ self.val1 = self.pvs.my_pv1.get()
+ self.val2 = self.pvs.my_pv2.get()
+
+ # maybe sleep to limit the update loop execution rate
+ time.sleep(1)
+ #######################################################################################
+ #######################################################################################
diff --git a/services/orbitbump/current/app/tests/test_app.py b/services/orbitbump/current/app/tests/test_app.py
new file mode 100644
index 0000000..a0e737f
--- /dev/null
+++ b/services/orbitbump/current/app/tests/test_app.py
@@ -0,0 +1,9 @@
+from agebd_orbitbump import PVs, Service
+
+
+def test_app():
+ service_name = "DUMMY"
+ pvs = PVs(service_name=service_name)
+ service = Service(name=service_name, pvs=pvs)
+ service.CallbackFired = 1
+ service.update()
diff --git a/services/orbitbump/current/app/uv.lock b/services/orbitbump/current/app/uv.lock
new file mode 100644
index 0000000..92d5e41
--- /dev/null
+++ b/services/orbitbump/current/app/uv.lock
@@ -0,0 +1,297 @@
+version = 1
+revision = 3
+requires-python = "==3.10.*"
+
+[[package]]
+name = "agebd"
+version = "0.1.0"
+source = { editable = "../../../../packages/agebd" }
+dependencies = [
+ { name = "h5py" },
+ { name = "typer" },
+]
+
+[package.metadata]
+requires-dist = [
+ { name = "h5py", specifier = ">=3.16.0" },
+ { name = "typer", specifier = ">=0.23.2" },
+]
+
+[package.metadata.requires-dev]
+dev = [
+ { name = "pyright", specifier = ">=1.1.410" },
+ { name = "pytest", specifier = ">=8.4.2" },
+ { name = "ruff", specifier = ">=0.15.19" },
+]
+
+[[package]]
+name = "agebd-orbitbump"
+version = "0.1.0"
+source = { editable = "." }
+dependencies = [
+ { name = "agebd" },
+]
+
+[package.dev-dependencies]
+dev = [
+ { name = "pyepics" },
+ { name = "pytest" },
+ { name = "ruff" },
+]
+
+[package.metadata]
+requires-dist = [{ name = "agebd", editable = "../../../../packages/agebd" }]
+
+[package.metadata.requires-dev]
+dev = [
+ { name = "pyepics", specifier = ">=3.5.8" },
+ { name = "pytest", specifier = ">=8.4.2" },
+ { name = "ruff", specifier = ">=0.15.20" },
+]
+
+[[package]]
+name = "annotated-doc"
+version = "0.0.4"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/57/ba/046ceea27344560984e26a590f90bc7f4a75b06701f653222458922b558c/annotated_doc-0.0.4.tar.gz", hash = "sha256:fbcda96e87e9c92ad167c2e53839e57503ecfda18804ea28102353485033faa4", size = 7288, upload-time = "2025-11-10T22:07:42.062Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl", hash = "sha256:571ac1dc6991c450b25a9c2d84a3705e2ae7a53467b5d111c24fa8baabbed320", size = 5303, upload-time = "2025-11-10T22:07:40.673Z" },
+]
+
+[[package]]
+name = "colorama"
+version = "0.4.6"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" },
+]
+
+[[package]]
+name = "exceptiongroup"
+version = "1.3.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "typing-extensions" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" },
+]
+
+[[package]]
+name = "h5py"
+version = "3.16.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "numpy" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/db/33/acd0ce6863b6c0d7735007df01815403f5589a21ff8c2e1ee2587a38f548/h5py-3.16.0.tar.gz", hash = "sha256:a0dbaad796840ccaa67a4c144a0d0c8080073c34c76d5a6941d6818678ef2738", size = 446526, upload-time = "2026-03-06T13:49:08.07Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/3a/6b/231413e58a787a89b316bb0d1777da3c62257e4797e09afd8d17ad3549dc/h5py-3.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e06f864bedb2c8e7c1358e6c73af48519e317457c444d6f3d332bb4e8fa6d7d9", size = 3724137, upload-time = "2026-03-06T13:47:35.242Z" },
+ { url = "https://files.pythonhosted.org/packages/74/f9/557ce3aad0fe8471fb5279bab0fc56ea473858a022c4ce8a0b8f303d64e9/h5py-3.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ec86d4fffd87a0f4cb3d5796ceb5a50123a2a6d99b43e616e5504e66a953eca3", size = 3090112, upload-time = "2026-03-06T13:47:37.634Z" },
+ { url = "https://files.pythonhosted.org/packages/7a/f5/e15b3d0dc8a18e56409a839e6468d6fb589bc5207c917399c2e0706eeb44/h5py-3.16.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:86385ea895508220b8a7e45efa428aeafaa586bd737c7af9ee04661d8d84a10d", size = 4844847, upload-time = "2026-03-06T13:47:39.811Z" },
+ { url = "https://files.pythonhosted.org/packages/cb/92/a8851d936547efe30cc0ce5245feac01f3ec6171f7899bc3f775c72030b3/h5py-3.16.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:8975273c2c5921c25700193b408e28d6bdd0111c37468b2d4e25dcec4cd1d84d", size = 5065352, upload-time = "2026-03-06T13:47:41.489Z" },
+ { url = "https://files.pythonhosted.org/packages/2b/ae/f2adc5d0ca9626db3277a3d87516e124cbc5d0eea0bd79bc085702d04f2c/h5py-3.16.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:1677ad48b703f44efc9ea0c3ab284527f81bc4f318386aaaebc5fede6bbae56f", size = 4839173, upload-time = "2026-03-06T13:47:43.586Z" },
+ { url = "https://files.pythonhosted.org/packages/64/0b/e0c8c69da1d8838da023a50cd3080eae5d475691f7636b35eff20bb6ef20/h5py-3.16.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7c4dd4cf5f0a4e36083f73172f6cfc25a5710789269547f132a20975bfe2434c", size = 5076216, upload-time = "2026-03-06T13:47:45.315Z" },
+ { url = "https://files.pythonhosted.org/packages/66/35/d88fd6718832133c885004c61ceeeb24dbd6397ef877dbed6b3a64d6a286/h5py-3.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:bdef06507725b455fccba9c16529121a5e1fbf56aa375f7d9713d9e8ff42454d", size = 3183639, upload-time = "2026-03-06T13:47:47.041Z" },
+]
+
+[[package]]
+name = "iniconfig"
+version = "2.3.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" },
+]
+
+[[package]]
+name = "markdown-it-py"
+version = "4.2.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "mdurl" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/06/ff/7841249c247aa650a76b9ee4bbaeae59370dc8bfd2f6c01f3630c35eb134/markdown_it_py-4.2.0.tar.gz", hash = "sha256:04a21681d6fbb623de53f6f364d352309d4094dd4194040a10fd51833e418d49", size = 82454, upload-time = "2026-05-07T12:08:28.36Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl", hash = "sha256:9f7ebbcd14fe59494226453aed97c1070d83f8d24b6fc3a3bcf9a38092641c4a", size = 91687, upload-time = "2026-05-07T12:08:27.182Z" },
+]
+
+[[package]]
+name = "mdurl"
+version = "0.1.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" },
+]
+
+[[package]]
+name = "numpy"
+version = "2.2.6"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/76/21/7d2a95e4bba9dc13d043ee156a356c0a8f0c6309dff6b21b4d71a073b8a8/numpy-2.2.6.tar.gz", hash = "sha256:e29554e2bef54a90aa5cc07da6ce955accb83f21ab5de01a62c8478897b264fd", size = 20276440, upload-time = "2025-05-17T22:38:04.611Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/9a/3e/ed6db5be21ce87955c0cbd3009f2803f59fa08df21b5df06862e2d8e2bdd/numpy-2.2.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b412caa66f72040e6d268491a59f2c43bf03eb6c96dd8f0307829feb7fa2b6fb", size = 21165245, upload-time = "2025-05-17T21:27:58.555Z" },
+ { url = "https://files.pythonhosted.org/packages/22/c2/4b9221495b2a132cc9d2eb862e21d42a009f5a60e45fc44b00118c174bff/numpy-2.2.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e41fd67c52b86603a91c1a505ebaef50b3314de0213461c7a6e99c9a3beff90", size = 14360048, upload-time = "2025-05-17T21:28:21.406Z" },
+ { url = "https://files.pythonhosted.org/packages/fd/77/dc2fcfc66943c6410e2bf598062f5959372735ffda175b39906d54f02349/numpy-2.2.6-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:37e990a01ae6ec7fe7fa1c26c55ecb672dd98b19c3d0e1d1f326fa13cb38d163", size = 5340542, upload-time = "2025-05-17T21:28:30.931Z" },
+ { url = "https://files.pythonhosted.org/packages/7a/4f/1cb5fdc353a5f5cc7feb692db9b8ec2c3d6405453f982435efc52561df58/numpy-2.2.6-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:5a6429d4be8ca66d889b7cf70f536a397dc45ba6faeb5f8c5427935d9592e9cf", size = 6878301, upload-time = "2025-05-17T21:28:41.613Z" },
+ { url = "https://files.pythonhosted.org/packages/eb/17/96a3acd228cec142fcb8723bd3cc39c2a474f7dcf0a5d16731980bcafa95/numpy-2.2.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:efd28d4e9cd7d7a8d39074a4d44c63eda73401580c5c76acda2ce969e0a38e83", size = 14297320, upload-time = "2025-05-17T21:29:02.78Z" },
+ { url = "https://files.pythonhosted.org/packages/b4/63/3de6a34ad7ad6646ac7d2f55ebc6ad439dbbf9c4370017c50cf403fb19b5/numpy-2.2.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc7b73d02efb0e18c000e9ad8b83480dfcd5dfd11065997ed4c6747470ae8915", size = 16801050, upload-time = "2025-05-17T21:29:27.675Z" },
+ { url = "https://files.pythonhosted.org/packages/07/b6/89d837eddef52b3d0cec5c6ba0456c1bf1b9ef6a6672fc2b7873c3ec4e2e/numpy-2.2.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:74d4531beb257d2c3f4b261bfb0fc09e0f9ebb8842d82a7b4209415896adc680", size = 15807034, upload-time = "2025-05-17T21:29:51.102Z" },
+ { url = "https://files.pythonhosted.org/packages/01/c8/dc6ae86e3c61cfec1f178e5c9f7858584049b6093f843bca541f94120920/numpy-2.2.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8fc377d995680230e83241d8a96def29f204b5782f371c532579b4f20607a289", size = 18614185, upload-time = "2025-05-17T21:30:18.703Z" },
+ { url = "https://files.pythonhosted.org/packages/5b/c5/0064b1b7e7c89137b471ccec1fd2282fceaae0ab3a9550f2568782d80357/numpy-2.2.6-cp310-cp310-win32.whl", hash = "sha256:b093dd74e50a8cba3e873868d9e93a85b78e0daf2e98c6797566ad8044e8363d", size = 6527149, upload-time = "2025-05-17T21:30:29.788Z" },
+ { url = "https://files.pythonhosted.org/packages/a3/dd/4b822569d6b96c39d1215dbae0582fd99954dcbcf0c1a13c61783feaca3f/numpy-2.2.6-cp310-cp310-win_amd64.whl", hash = "sha256:f0fd6321b839904e15c46e0d257fdd101dd7f530fe03fd6359c1ea63738703f3", size = 12904620, upload-time = "2025-05-17T21:30:48.994Z" },
+ { url = "https://files.pythonhosted.org/packages/9e/3b/d94a75f4dbf1ef5d321523ecac21ef23a3cd2ac8b78ae2aac40873590229/numpy-2.2.6-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0b605b275d7bd0c640cad4e5d30fa701a8d59302e127e5f79138ad62762c3e3d", size = 21040391, upload-time = "2025-05-17T21:44:35.948Z" },
+ { url = "https://files.pythonhosted.org/packages/17/f4/09b2fa1b58f0fb4f7c7963a1649c64c4d315752240377ed74d9cd878f7b5/numpy-2.2.6-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:7befc596a7dc9da8a337f79802ee8adb30a552a94f792b9c9d18c840055907db", size = 6786754, upload-time = "2025-05-17T21:44:47.446Z" },
+ { url = "https://files.pythonhosted.org/packages/af/30/feba75f143bdc868a1cc3f44ccfa6c4b9ec522b36458e738cd00f67b573f/numpy-2.2.6-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce47521a4754c8f4593837384bd3424880629f718d87c5d44f8ed763edd63543", size = 16643476, upload-time = "2025-05-17T21:45:11.871Z" },
+ { url = "https://files.pythonhosted.org/packages/37/48/ac2a9584402fb6c0cd5b5d1a91dcf176b15760130dd386bbafdbfe3640bf/numpy-2.2.6-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d042d24c90c41b54fd506da306759e06e568864df8ec17ccc17e9e884634fd00", size = 12812666, upload-time = "2025-05-17T21:45:31.426Z" },
+]
+
+[[package]]
+name = "packaging"
+version = "26.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d7/f1/e7a6dd94a8d4a5626c03e4e99c87f241ba9e350cd9e6d75123f992427270/packaging-26.2.tar.gz", hash = "sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661", size = 228134, upload-time = "2026-04-24T20:15:23.917Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/df/b2/87e62e8c3e2f4b32e5fe99e0b86d576da1312593b39f47d8ceef365e95ed/packaging-26.2-py3-none-any.whl", hash = "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e", size = 100195, upload-time = "2026-04-24T20:15:22.081Z" },
+]
+
+[[package]]
+name = "pluggy"
+version = "1.6.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" },
+]
+
+[[package]]
+name = "pyepics"
+version = "3.5.10"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "numpy" },
+ { name = "pyparsing" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/69/57/29e1e9ef11ba2a3419f489946ae1d8190025a1e4f4e1c1686758bb2b6e0a/pyepics-3.5.10.tar.gz", hash = "sha256:f390cf9be40aba757b9528888114bc14d8db01086d0c93914720b1772460375b", size = 6150481, upload-time = "2026-05-20T18:44:36.336Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d6/36/e517fd83bd97d6bfe4105e0c6b322070c5cc36fb56a8fab2866e319f8804/pyepics-3.5.10-py3-none-any.whl", hash = "sha256:c9fac2c54f2b595268e66fc348cf5ec24e63718e7dbd07d73d1b37d4da6bfee1", size = 5332376, upload-time = "2026-05-20T18:44:34.242Z" },
+]
+
+[[package]]
+name = "pygments"
+version = "2.20.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" },
+]
+
+[[package]]
+name = "pyparsing"
+version = "3.3.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f3/91/9c6ee907786a473bf81c5f53cf703ba0957b23ab84c264080fb5a450416f/pyparsing-3.3.2.tar.gz", hash = "sha256:c777f4d763f140633dcb6d8a3eda953bf7a214dc4eff598413c070bcdc117cbc", size = 6851574, upload-time = "2026-01-21T03:57:59.36Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl", hash = "sha256:850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d", size = 122781, upload-time = "2026-01-21T03:57:55.912Z" },
+]
+
+[[package]]
+name = "pytest"
+version = "9.1.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "colorama", marker = "sys_platform == 'win32'" },
+ { name = "exceptiongroup" },
+ { name = "iniconfig" },
+ { name = "packaging" },
+ { name = "pluggy" },
+ { name = "pygments" },
+ { name = "tomli" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/e4/47/b9efed96c114afcfa3c9d3fe98a76a1d14c74a9e266d397cf6eb64be5e01/pytest-9.1.1.tar.gz", hash = "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313", size = 1636369, upload-time = "2026-06-19T10:58:32.857Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/24/25/1de2678b631f5a49215c6c96fff41ba892b0a34df68d6d80292b1b48aa7f/pytest-9.1.1-py3-none-any.whl", hash = "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c", size = 386536, upload-time = "2026-06-19T10:58:31.347Z" },
+]
+
+[[package]]
+name = "rich"
+version = "15.0.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "markdown-it-py" },
+ { name = "pygments" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/c0/8f/0722ca900cc807c13a6a0c696dacf35430f72e0ec571c4275d2371fca3e9/rich-15.0.0.tar.gz", hash = "sha256:edd07a4824c6b40189fb7ac9bc4c52536e9780fbbfbddf6f1e2502c31b068c36", size = 230680, upload-time = "2026-04-12T08:24:00.75Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl", hash = "sha256:33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb", size = 310654, upload-time = "2026-04-12T08:24:02.83Z" },
+]
+
+[[package]]
+name = "ruff"
+version = "0.15.21"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/0f/36/6f65aa9989acdec45d417192d8f4e7921931d8a6cf87ac74bce3eed98a8e/ruff-0.15.21.tar.gz", hash = "sha256:d0cfc841c572283c36548f82664a54ce6565567f1b0d5b4cf2caac693d8b7500", size = 4769401, upload-time = "2026-07-09T20:01:34.005Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d0/c6/ede15cac6839f3dbce52565c8f5164a8210e669c7bc4decb03e5bdf47d0d/ruff-0.15.21-py3-none-linux_armv6l.whl", hash = "sha256:63ea0e965e5d73c90e95b2434beeafc70820536717f561b32ab6e777cb9bdf5d", size = 10854342, upload-time = "2026-07-09T20:00:53.998Z" },
+ { url = "https://files.pythonhosted.org/packages/28/9d/d825b07ee7ea9e2d61df92a860033c94e06e7300d50a1c2653aac27d24fe/ruff-0.15.21-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:0f212c5d7d54c01bbfe6dcab02b724a39300f3e34ed7acbe995ccb320a2c58bd", size = 11139539, upload-time = "2026-07-09T20:00:57.809Z" },
+ { url = "https://files.pythonhosted.org/packages/f5/de/3b107712e642f063c7a9e0887c427b22cb44097de5aab36c05f2e280670c/ruff-0.15.21-py3-none-macosx_11_0_arm64.whl", hash = "sha256:e6312e41bc96791299614995ea3a977c5857c3b5662b1ecef6755b02b87cb646", size = 10595437, upload-time = "2026-07-09T20:01:00.006Z" },
+ { url = "https://files.pythonhosted.org/packages/9a/6f/b4523cc90ba239ede441447a19d0c968846a3012e5a0b0c5b62831a3d5e3/ruff-0.15.21-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01d65b4831c6b2a4ba8ee6faa84049d44d982b7a706e622c4094c509e51673be", size = 10990053, upload-time = "2026-07-09T20:01:02.187Z" },
+ { url = "https://files.pythonhosted.org/packages/92/cc/c6a9872a5375f0628875481cf2f66b13d7d865bf3ca2e57f91c7e762d976/ruff-0.15.21-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2c5a913a589120ce67933d5d05fd6ddbcc2481c6a054980ee767f7414c72b4fd", size = 10666096, upload-time = "2026-07-09T20:01:04.299Z" },
+ { url = "https://files.pythonhosted.org/packages/ab/97/c621f7a17e097f1790fa3af6374138823b330b2d03fc38337945daca212c/ruff-0.15.21-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ef04b681d02ad4dc9620f00f83ac5c22f652d0e9a9cfe431d219b16ad5ccc41", size = 11537011, upload-time = "2026-07-09T20:01:06.771Z" },
+ { url = "https://files.pythonhosted.org/packages/ea/51/d928727e476e25ccc57c6f449ffd80241a651a973ad949d39cfb2a771d28/ruff-0.15.21-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:16d090c0740916594157e75b80d666eab8e78083b39b3b0e1d698f4670a17b86", size = 12347101, upload-time = "2026-07-09T20:01:08.859Z" },
+ { url = "https://files.pythonhosted.org/packages/1e/88/8cd62026802b16018ad06931d87997cf795ba2a6239ab659606c87d96bf0/ruff-0.15.21-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3a10e74757dd65004d779b73e2f3c5210156d9980b41224d50d2ebcf1db51e67", size = 11572001, upload-time = "2026-07-09T20:01:11.092Z" },
+ { url = "https://files.pythonhosted.org/packages/b2/97/f63084cf55444fc110e8cb985ebfcc592af47f597d44453d778cb81bc156/ruff-0.15.21-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bab0905d2f29e0d9fbc3c373ed23db0095edaa3f71f1f4f519ec15134d9e85c8", size = 11549239, upload-time = "2026-07-09T20:01:13.27Z" },
+ { url = "https://files.pythonhosted.org/packages/9d/77/f107da4a2874b7715914b03f09ba9c54424de3ff8a1cc5d015d3ee2ce0ac/ruff-0.15.21-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:00eca240af5789fec6fe7df74c088cc1f9644ed83027113468efba7c92b94075", size = 11535340, upload-time = "2026-07-09T20:01:15.206Z" },
+ { url = "https://files.pythonhosted.org/packages/d5/e9/601deb322d3303a7bf212b0100ead6f2ee3f6a044d89c30f2f92bf83c731/ruff-0.15.21-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:262ab31557a75141325e32d3357f3597645a7f084e732b6b054dde428ecd9341", size = 10964048, upload-time = "2026-07-09T20:01:17.723Z" },
+ { url = "https://files.pythonhosted.org/packages/ea/2e/0f2176d1e99c15192caea19c8c3a0a955246b4cb4de795042eeb616345cd/ruff-0.15.21-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:659c4e7a4212f83306045ec7c5e5a356d16d9a6ef4ae0c7a4d872914fc655d9d", size = 10667055, upload-time = "2026-07-09T20:01:19.73Z" },
+ { url = "https://files.pythonhosted.org/packages/48/60/abd74a02e0c4214f12a68becfd30af7165cfdcb0e661ecdc60bbb949c09a/ruff-0.15.21-py3-none-musllinux_1_2_i686.whl", hash = "sha256:9e866eab611a5f959d36df2d10e446973a3610bc42b0c15b31dc27977d59c233", size = 11242043, upload-time = "2026-07-09T20:01:21.947Z" },
+ { url = "https://files.pythonhosted.org/packages/b2/c6/583075d8ccabb4b229345edcaf1545eb3d8d6be90f686a479d7e94088bbf/ruff-0.15.21-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e89bc93c0d3803ba870b55c29671bad9dc6d94bb1eb181b056b52eb05b52854f", size = 11648064, upload-time = "2026-07-09T20:01:24.023Z" },
+ { url = "https://files.pythonhosted.org/packages/3a/3c/37d0ecb729a7cc2d393ea7dce316fc585680f35d93b8d62139d7d0a3700c/ruff-0.15.21-py3-none-win32.whl", hash = "sha256:01f8d5be84823c172b389e123174f781f9daf86d6c58719d603f941932195cdd", size = 10896555, upload-time = "2026-07-09T20:01:26.941Z" },
+ { url = "https://files.pythonhosted.org/packages/c0/b8/e43466b2a6067ce91e669068f6e28d6c719a920f014b070d5c8731725de3/ruff-0.15.21-py3-none-win_amd64.whl", hash = "sha256:d4b8d9a2f0f12b816b50447f6eccb9f4bb01a6b82c86b50fb3b5354b458dc6d3", size = 12038772, upload-time = "2026-07-09T20:01:29.497Z" },
+ { url = "https://files.pythonhosted.org/packages/dd/75/e90ab9aeece218a9fc5a5bc3ec97d0ee6bb3c4ff95869463c1de58e29a1c/ruff-0.15.21-py3-none-win_arm64.whl", hash = "sha256:6e83115d4b9377c1cbc13abf0e051f069fab0ef815ea0504a8a008cee24dd0a8", size = 11375265, upload-time = "2026-07-09T20:01:31.772Z" },
+]
+
+[[package]]
+name = "shellingham"
+version = "1.5.4"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/58/15/8b3609fd3830ef7b27b655beb4b4e9c62313a4e8da8c676e142cc210d58e/shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de", size = 10310, upload-time = "2023-10-24T04:13:40.426Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755, upload-time = "2023-10-24T04:13:38.866Z" },
+]
+
+[[package]]
+name = "tomli"
+version = "2.4.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/22/de/48c59722572767841493b26183a0d1cc411d54fd759c5607c4590b6563a6/tomli-2.4.1.tar.gz", hash = "sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f", size = 17543, upload-time = "2026-03-25T20:22:03.828Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/7b/61/cceae43728b7de99d9b847560c262873a1f6c98202171fd5ed62640b494b/tomli-2.4.1-py3-none-any.whl", hash = "sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe", size = 14583, upload-time = "2026-03-25T20:22:03.012Z" },
+]
+
+[[package]]
+name = "typer"
+version = "0.27.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "annotated-doc" },
+ { name = "colorama", marker = "sys_platform == 'win32'" },
+ { name = "rich" },
+ { name = "shellingham" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/37/78/fda3361b56efc27944f24225f6ecd13d96d6fcfe37bd0eb34e2f4c63f9fc/typer-0.27.0.tar.gz", hash = "sha256:629bd12ea5d13a17148125d9a264f949eb171fb3f120f9b04d85873cab054fa5", size = 203430, upload-time = "2026-07-15T19:21:07.007Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/40/03/26a383c9e58c213199d1aad1c3d353cfc22d4444ec6d2c0bf8ad02523843/typer-0.27.0-py3-none-any.whl", hash = "sha256:6f4b27631e47f077871b7dc30e933ec0131c1390fbe0e387ea5574b5bac9ccf1", size = 122716, upload-time = "2026-07-15T19:21:05.553Z" },
+]
+
+[[package]]
+name = "typing-extensions"
+version = "4.16.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f6/cc/6253133b5bb138fc3306cebfbda2c520f545d36b5be2c7255cc528bb45d6/typing_extensions-4.16.0.tar.gz", hash = "sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5", size = 113555, upload-time = "2026-07-02T08:40:05.92Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/49/d3/b8441a820a491ddfc024b0b0cf0393375b75ea13866d9c66727e54c2fc80/typing_extensions-4.16.0-py3-none-any.whl", hash = "sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8", size = 45571, upload-time = "2026-07-02T08:40:04.659Z" },
+]
diff --git a/services/orbitbump/current/ioc/AGEBD-CPCL-ORBITBUMP_main.subs b/services/orbitbump/current/ioc/AGEBD-CPCL-ORBITBUMP_main.subs
new file mode 100644
index 0000000..e485117
--- /dev/null
+++ b/services/orbitbump/current/ioc/AGEBD-CPCL-ORBITBUMP_main.subs
@@ -0,0 +1,62 @@
+file ORBITBUMP_machine.template {
+ pattern
+ {sourcepoint beamline LOX HIX X LOXP HIXP XP LOY HIY Y LOYP HIYP YP BPM1 C1xx C1xpx C1yy C1ypy BPM2 C2xx C2xpx C2yy C2ypy BPM3 C3xx C3xpx C3yy C3ypy BPM4 C4xx C4xpx C4yy C4ypy}
+ # Diagnostic dipole beamlines
+ {X01DD NEMO -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS01-DBPM-1080 -0.0009920 -0.0006308 -0.0001141 0.0001109 ARS01-DBPM-1460 0.9742755 -0.1432472 0.9455447 -0.0865934 ARS01-DBPM-1900 0.9277200 1.0454287 0.1445141 1.5920941 ARS01-DBPM-2410 -0.0809412 -0.0384293 0.0058229 0.1036650}
+ {X08DB DISCO -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS08-DBPM-1900 -0.2500389 -0.0365053 0.0001023 0.0000595 ARS08-DBPM-2410 1.2775662 -0.9246414 0.5814965 -0.4999301 ARS08-DBPM-2910 0.6885552 0.9211364 0.4873898 1.7550023 ARS08-DBPM-4220 -0.2391394 -0.0169593 0.0309046 0.1234665}
+ {X10DG X11HEAT -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS10-DBPM-4720 -0.0187 -0.0188 0 0 ARS10-DBPM-5250 1.6016 -1.2108 0.5496 -0.5376 ARS10-DBPM-5880 0.7075 1.0654 1.1093 1.9515 ARS11-DBPM-0850 0.0026 0.0044 0.0166 0.0304}
+ # User dipole beamlines
+ {X01DA DEBYE -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS01-DBPM-2410 -0.2169694 -0.0006291 0.0001170 0.0000325 ARS01-DBPM-2910 1.2765938 -0.9208697 0.5792863 -0.5011470 ARS01-DBPM-4220 0.6866207 0.9198858 0.4842977 1.7595080 ARS01-DBPM-4720 -0.1924402 0.0258918 0.0307458 0.1239361}
+ {X02DA S-TOMCAT -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS02-DBPM-2410 -0.2089937 0.0072435 0.0001169 0.0000325 ARS02-DBPM-2910 1.2772588 -0.9200089 0.5792866 -0.5011606 ARS02-DBPM-4220 0.6864959 0.9194778 0.4843170 1.7595616 ARS02-DBPM-4720 -0.1833930 0.0352770 0.0307471 0.1239392}
+ {X03DA PEARL -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS03-DBPM-2410 -0.2016647 0.0152728 0.0001171 0.0000326 ARS03-DBPM-2910 1.2831552 -0.9190247 0.5819894 -0.5004911 ARS03-DBPM-4220 0.6905553 0.9206615 0.4875028 1.7552635 ARS03-DBPM-4720 -0.1749243 0.0438144 0.0309089 0.1234182}
+ {X04DB VUV -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS04-DBPM-1900 -0.1917962 0.0214714 0.0001022 0.0000595 ARS04-DBPM-2410 1.2842031 -0.9179380 0.5814999 -0.5000284 ARS04-DBPM-2910 0.6887599 0.9211626 0.4874732 1.7553295 ARS04-DBPM-4220 -0.1710439 0.0514609 0.0309080 0.1234788}
+ {X05DA Optics -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS05-DBPM-2410 -0.2740176 -0.0571105 0.0001170 0.0000321 ARS05-DBPM-2910 1.2732647 -0.9287209 0.5819890 -0.5003730 ARS05-DBPM-4220 0.6913367 0.9213802 0.4873370 1.7548006 ARS05-DBPM-4720 -0.2592981 -0.0408063 0.0308988 0.1233928}
+ {X06DA PXIII -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS06-DBPM-2410 -0.2675305 -0.0508248 0.0001170 0.0000321 ARS06-DBPM-2910 1.2749858 -0.9266845 0.5818007 -0.5004548 ARS06-DBPM-4220 0.6916389 0.9218001 0.4871613 1.7552275 ARS06-DBPM-4720 -0.2517260 -0.0332473 0.0308895 0.1234316}
+ {X07DB nanoXAS -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS07-DBPM-1900 -0.2563387 -0.0425222 0.0001023 0.0000596 ARS07-DBPM-2410 1.2761628 -0.9263027 0.5814954 -0.4999177 ARS07-DBPM-2910 0.6888233 0.9216262 0.4873810 1.7549631 ARS07-DBPM-4220 -0.2469055 -0.0248794 0.0309043 0.1234651}
+ {X07DA PolLux -300 300 0 -150 150 0 -300 300 0 -250 250 0 ARS07-DBPM-2410 -0.2606076 -0.0450539 0.0001170 0.0000326 ARS07-DBPM-2910 1.2750718 -0.9205684 0.5819899 -0.4976199 ARS07-DBPM-4220 0.6915728 0.9246379 0.4873668 1.7572153 ARS07-DBPM-4720 -0.2433555 -0.0254434 0.0309006 0.1235450}
+ {X10DA SuperXAS -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS10-DBPM-2410 -0.2392400 -0.0226765 0.0001170 0.0000321 ARS10-DBPM-2910 1.2780895 -0.9235140 0.5818007 -0.5005005 ARS10-DBPM-4220 0.6911875 0.9212713 0.4872251 1.7554059 ARS10-DBPM-4720 -0.2190626 -0.0004438 0.0308933 0.1234413}
+ # ID beamlines
+ {X02SA I-TOMCAT -500 500 0 -150 150 0 -500 500 0 -150 150 0 ARS01-DBPM-5250 -0.0161762 0.0645315 -0.0000522 0.0002217 ARS01-DBPM-5880 1.3057217 -3.1586368 0.7340909 -1.7908669 ARS02-DBPM-1080 1.1637103 2.7703664 0.8405251 2.0415012 ARS02-DBPM-1460 0.0473369 0.1176477 0.0354851 0.0914118}
+ {X03MA ADRESS -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS02-DBPM-5250 -0.0056074 0.0805576 -0.0000533 0.0001427 ARS02-DBPM-5880 1.2522257 -3.5240592 0.7649336 -2.1576328 ARS03-DBPM-0810 1.1134798 3.0406278 0.8874945 2.4488073 ARS03-DBPM-1080 0.0367597 0.0902093 0.0491615 0.1421129}
+ {X04SA ADDAMS -500 500 0 -150 150 0 -500 500 0 -150 150 0 ARS03-DBPM-5250 0.0006041 0.0811354 -0.0000524 0.0002222 ARS03-DBPM-5880 1.3048037 -3.1594991 0.7340820 -1.7909262 ARS04-DBPM-1080 1.1649402 2.7718322 0.8405182 2.0415768 ARS04-DBPM-1460 0.0441826 0.1145073 0.0354841 0.0914133}
+ {X05LA QUEST -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS04-DBPM-5880 0.0008866 0.0002252 -0.0001045 0.0002529 ARS05-DBPM-0410 0.8976150 -2.8499257 1.0112790 -2.8592349 ARS05-DBPM-1080 1.0880889 5.0183256 0.9137175 4.2390359 ARS05-DBPM-1460 0.0421489 0.1947713 0.0433357 0.2067705}
+ {X06SA PXI -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS05-DBPM-5250 -0.0776973 0.0030268 -0.0000523 0.0002212 ARS05-DBPM-5880 1.3044906 -3.1590695 0.7341239 -1.7906420 ARS06-DBPM-1080 1.1642809 2.7699897 0.8405515 2.0412179 ARS06-DBPM-1460 0.0604868 0.1306028 0.0354886 0.0914055}
+ {X07MA Phoenix/XTreme -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS06-DBPM-5250 -0.0684380 0.0189547 -0.0000531 0.0001447 ARS06-DBPM-5880 1.2508776 -3.5845660 0.7649630 -2.1939024 ARS07-DBPM-0810 1.1137188 2.9863773 0.8875136 2.4060190 ARS07-DBPM-1080 0.0093629 0.0606390 0.0491634 0.1397441}
+ {X08SA micro-XAS -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS07-DBPM-5250 -0.0624701 0.0181621 -0.0000523 0.0002216 ARS07-DBPM-5880 1.3039931 -3.1597229 0.7341156 -1.7906968 ARS08-DBPM-1080 1.1652753 2.7714013 0.8405450 2.0412871 ARS08-DBPM-1460 0.0575855 0.1278140 0.0354876 0.0914065}
+ {X09LA PEARL/XIL-II -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS08-DBPM-5880 0.0011254 0.0009724 -0.0000942 0.0002317 ARS09-DBPM-0570 0.8843735 -2.4344684 1.1263977 -3.0082085 ARS09-DBPM-1080 1.0591734 3.0395499 0.9413643 2.7184391 ARS09-DBPM-1460 0.0394021 0.1139547 0.0465775 0.1402264}
+ {X10SA PXII -500 500 0 -150 150 0 -500 500 0 -150 150 0 ARS09-DBPM-5250 -0.0473875 0.0333454 -0.0000523 0.0002213 ARS09-DBPM-5880 1.3047178 -3.1592507 0.7341077 -1.7907518 ARS10-DBPM-1080 1.1639981 2.7701547 0.8405387 2.0413565 ARS10-DBPM-1460 0.0540084 0.1242161 0.0354869 0.0914087}
+ {X11MA SIM -500 500 0 -150 150 0 -500 500 0 -150 150 0 ARS10-DBPM-5250 -0.0383667 0.0514782 -0.0000499 0.0001646 ARS10-DBPM-5880 1.2526899 -3.7342542 0.7640638 -2.2804441 ARS11-DBPM-0850 1.1168967 3.1441871 0.8845808 2.5170397 ARS11-DBPM-1080 0.0219427 0.0928506 0.0546028 0.1626088}
+ {X12SA cSAXS -300 300 0 -150 150 0 -300 300 0 -150 150 0 ARS11-DBPM-5250 -0.0326376 0.0479239 -0.0000524 0.0002219 ARS11-DBPM-5880 1.3047910 -3.1591765 0.7340995 -1.7908066 ARS12-DBPM-1080 1.1653151 2.7718178 0.8405322 2.0414257 ARS12-DBPM-1460 0.0513287 0.1216036 0.0354860 0.0914097}
+}
+
+
+file ORBITBUMP_beamline.template {
+ pattern
+ {sourcepoint beamline DRVL DRVH X XP Y YP }
+ # Diagnostic dipole beamlines
+ {X01DD NEMO -10 10 0 0 0 0 }
+ {X08DB DISCO -10 10 0 0 0 0 }
+ {X10DG X11HEAT -10 10 0 0 0 0 }
+ # User dipole beamlines
+ {X01DA DEBYE -10 10 0 0 0 0 }
+ {X02DA S-TOMCAT -10 10 0 0 0 0 }
+ {X03DA PEARL -10 10 0 0 0 0 }
+ {X04DB VUV -10 10 0 0 0 0 }
+ {X05DA Optics -10 10 0 0 0 0 }
+ {X06DA PXIII -10 10 0 0 0 0 }
+ {X07DB nanoXAS -10 10 0 0 0 0 }
+ {X07DA PolLux -10 10 0 0 0 0 }
+ {X10DA SuperXAS -10 10 0 0 0 0 }
+ # ID beamlines
+ {X02SA I-TOMCAT -10 10 0 0 0 0 }
+ {X03MA ADRESS -10 10 0 0 0 0 }
+ {X04SA ADDAMS -10 10 0 0 0 0 }
+ {X05LA QUEST -10 10 0 0 0 0 }
+ {X06SA PXI -10 10 0 0 0 0 }
+ {X07MA Phoenix/XTreme -10 10 0 0 0 0 }
+ {X08SA micro-XAS -10 10 0 0 0 0 }
+ {X09LA PEARL/XIL-II -10 10 0 0 0 0 }
+ {X10SA PXII -10 10 0 0 0 0 }
+ {X11MA SIM -10 10 0 0 0 0 }
+ {X12SA cSAXS -10 10 0 0 0 0 }
+}
\ No newline at end of file
diff --git a/services/orbitbump/current/ioc/AGEBD-CPCL-ORBITBUMP_parameters.yaml b/services/orbitbump/current/ioc/AGEBD-CPCL-ORBITBUMP_parameters.yaml
new file mode 100644
index 0000000..ff8e70f
--- /dev/null
+++ b/services/orbitbump/current/ioc/AGEBD-CPCL-ORBITBUMP_parameters.yaml
@@ -0,0 +1,6 @@
+cpu_architecture: x86_64
+epics_version: 7.0.8
+ioc_host: sls-vserv-bd-01{{ agebd_env }}
+ioc_port: {{ ioc_port }}
+os: RHEL8
+os_id: rhel
diff --git a/services/orbitbump/current/ioc/ORBITBUMP_beamline.template b/services/orbitbump/current/ioc/ORBITBUMP_beamline.template
new file mode 100644
index 0000000..14ba98f
--- /dev/null
+++ b/services/orbitbump/current/ioc/ORBITBUMP_beamline.template
@@ -0,0 +1,87 @@
+record(ao, "$(sourcepoint)-ORBITBUMP:OFFSET-X") {
+ field(DESC, "Beamline x offset for $(beamline)")
+ field(ASG, "PROTECTED")
+ field(EGU, "um")
+ field(PREC, "0")
+ field(VAL, "$(X)")
+ field(PINI, "YES")
+ field(FLNK, "AGEBD-ORBITBUMP:$(sourcepoint)-OFFSET-X-TOTAL")
+ field(DRVH, "$(DRVH)")
+ field(DRVL, "$(DRVL)")
+ field(HOPR, "$(DRVH)")
+ field(LOPR, "$(DRVL)")
+ field(HIHI, "10")
+ field(HHSV, "MAJOR")
+ field(HIGH, "1")
+ field(HSV, "MINOR")
+ field(LOW, "-1")
+ field(LSV, "MINOR")
+ field(LOLO, "-10")
+ field(LLSV, "MAJOR")
+}
+
+record(ao, "$(sourcepoint)-ORBITBUMP:OFFSET-XP") {
+ field(DESC, "Beamline xp offset for $(beamline)")
+ field(ASG, "PROTECTED")
+ field(EGU, "urad")
+ field(PREC, "0")
+ field(VAL, "$(XP)")
+ field(PINI, "YES")
+ field(FLNK, "AGEBD-ORBITBUMP:$(sourcepoint)-OFFSET-XP-TOTAL")
+ field(DRVH, "$(DRVH)")
+ field(DRVL, "$(DRVL)")
+ field(HOPR, "$(DRVH)")
+ field(LOPR, "$(DRVL)")
+ field(HIHI, "10")
+ field(HHSV, "MAJOR")
+ field(HIGH, "1")
+ field(HSV, "MINOR")
+ field(LOW, "-1")
+ field(LSV, "MINOR")
+ field(LOLO, "-10")
+ field(LLSV, "MAJOR")
+}
+
+record(ao, "$(sourcepoint)-ORBITBUMP:OFFSET-Y") {
+ field(DESC, "Beamline y offset for $(beamline)")
+ field(ASG, "PROTECTED")
+ field(EGU, "um")
+ field(PREC, "0")
+ field(VAL, "$(Y)")
+ field(PINI, "YES")
+ field(FLNK, "AGEBD-ORBITBUMP:$(sourcepoint)-OFFSET-Y-TOTAL")
+ field(DRVH, "$(DRVH)")
+ field(DRVL, "$(DRVL)")
+ field(HOPR, "$(DRVH)")
+ field(LOPR, "$(DRVL)")
+ field(HIHI, "10")
+ field(HHSV, "MAJOR")
+ field(HIGH, "1")
+ field(HSV, "MINOR")
+ field(LOW, "-1")
+ field(LSV, "MINOR")
+ field(LOLO, "-10")
+ field(LLSV, "MAJOR")
+}
+
+record(ao, "$(sourcepoint)-ORBITBUMP:OFFSET-YP") {
+ field(DESC, "Beamline yp offset for $(beamline)")
+ field(ASG, "PROTECTED")
+ field(EGU, "urad")
+ field(PREC, "0")
+ field(VAL, "$(YP)")
+ field(PINI, "YES")
+ field(FLNK, "AGEBD-ORBITBUMP:$(sourcepoint)-OFFSET-YP-TOTAL")
+ field(DRVH, "$(DRVH)")
+ field(DRVL, "$(DRVL)")
+ field(HOPR, "$(DRVH)")
+ field(LOPR, "$(DRVL)")
+ field(HIHI, "10")
+ field(HHSV, "MAJOR")
+ field(HIGH, "1")
+ field(HSV, "MINOR")
+ field(LOW, "-1")
+ field(LSV, "MINOR")
+ field(LOLO, "-10")
+ field(LLSV, "MAJOR")
+}
\ No newline at end of file
diff --git a/services/orbitbump/current/ioc/ORBITBUMP_machine.template b/services/orbitbump/current/ioc/ORBITBUMP_machine.template
new file mode 100644
index 0000000..31b8ed0
--- /dev/null
+++ b/services/orbitbump/current/ioc/ORBITBUMP_machine.template
@@ -0,0 +1,504 @@
+# # on request writing total bump values to machine bumps and zero beamline bumps
+# record(bo, "AGEBD-ORBITBUMP:$(sourcepoint)-COPYOVER") {
+# field(DESC, "Request zeroing of beamline offsets")
+# field(ASG, "PROTECTED")
+# field(PINI, "YES")
+# field(ZNAM, "Idle")
+# field(ONAM, "Trigger")
+# field(OUT, "myDevice:addAndZero.PROC PP")
+# }
+
+# record(seq, "AGEBD-ORBITBUMP:$(sourcepoint)-COPYOVER") {
+# field(DESC, "On trigger: add PV_A to PV_B, zero PV_A")
+
+# field(DOL1, "myDevice:add_calc NPP NMS") # Value = A + B
+# field(LNK1, "myDevice:PV_B PP MS") # Step 1: write sum to PV_B
+
+# field(DLY1, "0.1") # Wait 0.1s before next step
+
+# field(DOL2, "0") # Value = 0
+# field(LNK2, "myDevice:PV_A PP MS") # Step 2: zero PV_A
+# }
+
+
+
+record(ao, "AGEBD-ORBITBUMP:$(sourcepoint)-OFFSET-X") {
+ field(DESC, "Machine x offset for $(beamline)")
+ field(ASG, "PROTECTED")
+ field(EGU, "um")
+ field(PREC, "0")
+ field(VAL, "$(X)")
+ field(PINI, "YES")
+ field(FLNK, "AGEBD-ORBITBUMP:$(sourcepoint)-OFFSET-X-TOTAL")
+ field(DRVH, "$(HIX)")
+ field(DRVL, "$(LOX)")
+ field(HOPR, "$(HIX)")
+ field(LOPR, "$(LOX)")
+ field(HIHI, "100")
+ field(HHSV, "MAJOR")
+ field(HIGH, "1")
+ field(HSV, "MINOR")
+ field(LOW, "-1")
+ field(LSV, "MINOR")
+ field(LOLO, "-100")
+ field(LLSV, "MAJOR")
+}
+
+record(ao, "AGEBD-ORBITBUMP:$(sourcepoint)-OFFSET-XP") {
+ field(DESC, "Machine xp offset for $(beamline)")
+ field(ASG, "PROTECTED")
+ field(EGU, "urad")
+ field(PREC, "0")
+ field(VAL, "$(XP)")
+ field(PINI, "YES")
+ field(FLNK, "AGEBD-ORBITBUMP:$(sourcepoint)-OFFSET-XP-TOTAL")
+ field(DRVH, "$(HIXP)")
+ field(DRVL, "$(LOXP)")
+ field(HOPR, "$(HIXP)")
+ field(LOPR, "$(LOXP)")
+ field(HIHI, "100")
+ field(HHSV, "MAJOR")
+ field(HIGH, "1")
+ field(HSV, "MINOR")
+ field(LOW, "-1")
+ field(LSV, "MINOR")
+ field(LOLO, "-100")
+ field(LLSV, "MAJOR")
+}
+
+record(ao, "AGEBD-ORBITBUMP:$(sourcepoint)-OFFSET-Y") {
+ field(DESC, "Machine y offset for $(beamline)")
+ field(ASG, "PROTECTED")
+ field(EGU, "um")
+ field(PREC, "0")
+ field(VAL, "$(Y)")
+ field(PINI, "YES")
+ field(FLNK, "AGEBD-ORBITBUMP:$(sourcepoint)-OFFSET-Y-TOTAL")
+ field(DRVH, "$(HIY)")
+ field(DRVL, "$(LOY)")
+ field(HOPR, "$(HIY)")
+ field(LOPR, "$(LOY)")
+ field(HIHI, "100")
+ field(HHSV, "MAJOR")
+ field(HIGH, "1")
+ field(HSV, "MINOR")
+ field(LOW, "-1")
+ field(LSV, "MINOR")
+ field(LOLO, "-100")
+ field(LLSV, "MAJOR")
+}
+
+record(ao, "AGEBD-ORBITBUMP:$(sourcepoint)-OFFSET-YP") {
+ field(DESC, "Machine yp offset for $(beamline)")
+ field(ASG, "PROTECTED")
+ field(EGU, "urad")
+ field(PREC, "0")
+ field(VAL, "$(YP)")
+ field(PINI, "YES")
+ field(FLNK, "AGEBD-ORBITBUMP:$(sourcepoint)-OFFSET-YP-TOTAL")
+ field(DRVH, "$(HIYP)")
+ field(DRVL, "$(LOYP)")
+ field(HOPR, "$(HIYP)")
+ field(LOPR, "$(LOYP)")
+ field(HIHI, "100")
+ field(HHSV, "MAJOR")
+ field(HIGH, "1")
+ field(HSV, "MINOR")
+ field(LOW, "-1")
+ field(LSV, "MINOR")
+ field(LOLO, "-100")
+ field(LLSV, "MAJOR")
+}
+
+# Sum PVs for total desired orbit bumps, i.e., sum of machine and beamline
+record(calcout, "AGEBD-ORBITBUMP:$(sourcepoint)-OFFSET-X-TOTAL") {
+ field(DESC, "Total x offset for $(beamline)")
+ field(ASG, "READONLY")
+ field(SCAN, "Passive")
+ field(PREC, "0")
+ field(CALC, "A + B")
+ field(INPA, "AGEBD-ORBITBUMP:$(sourcepoint)-OFFSET-X")
+ field(INPB, "$(sourcepoint)-ORBITBUMP:OFFSET-X")
+ field(OOPT, "On Change")
+ field(DOPT, "Use CALC")
+ field(FLNK, "AGEBD-ORBITBUMP:$(sourcepoint)-DELTAX-BPM1")
+ field(HIHI, "100")
+ field(HHSV, "MAJOR")
+ field(HIGH, "1")
+ field(HSV, "MINOR")
+ field(LOW, "-1")
+ field(LSV, "MINOR")
+ field(LOLO, "-100")
+ field(LLSV, "MAJOR")
+}
+
+record(calcout, "AGEBD-ORBITBUMP:$(sourcepoint)-OFFSET-XP-TOTAL") {
+ field(DESC, "Total xp offset for $(beamline)")
+ field(ASG, "READONLY")
+ field(SCAN, "Passive")
+ field(PREC, "0")
+ field(CALC, "A + B")
+ field(INPA, "AGEBD-ORBITBUMP:$(sourcepoint)-OFFSET-XP")
+ field(INPB, "$(sourcepoint)-ORBITBUMP:OFFSET-XP")
+ field(OOPT, "On Change")
+ field(DOPT, "Use CALC")
+ field(FLNK, "AGEBD-ORBITBUMP:$(sourcepoint)-DELTAX-BPM1")
+ field(HIHI, "100")
+ field(HHSV, "MAJOR")
+ field(HIGH, "1")
+ field(HSV, "MINOR")
+ field(LOW, "-1")
+ field(LSV, "MINOR")
+ field(LOLO, "-100")
+ field(LLSV, "MAJOR")
+}
+
+record(calcout, "AGEBD-ORBITBUMP:$(sourcepoint)-OFFSET-Y-TOTAL") {
+ field(DESC, "Total y offset for $(beamline)")
+ field(ASG, "READONLY")
+ field(SCAN, "Passive")
+ field(PREC, "0")
+ field(CALC, "A + B")
+ field(INPA, "AGEBD-ORBITBUMP:$(sourcepoint)-OFFSET-Y")
+ field(INPB, "$(sourcepoint)-ORBITBUMP:OFFSET-Y")
+ field(OOPT, "On Change")
+ field(DOPT, "Use CALC")
+ field(FLNK, "AGEBD-ORBITBUMP:$(sourcepoint)-DELTAY-BPM1")
+ field(HIHI, "100")
+ field(HHSV, "MAJOR")
+ field(HIGH, "1")
+ field(HSV, "MINOR")
+ field(LOW, "-1")
+ field(LSV, "MINOR")
+ field(LOLO, "-100")
+ field(LLSV, "MAJOR")
+}
+
+record(calcout, "AGEBD-ORBITBUMP:$(sourcepoint)-OFFSET-YP-TOTAL") {
+ field(DESC, "Total y offset for $(beamline)")
+ field(ASG, "READONLY")
+ field(SCAN, "Passive")
+ field(PREC, "0")
+ field(CALC, "A + B")
+ field(INPA, "AGEBD-ORBITBUMP:$(sourcepoint)-OFFSET-YP")
+ field(INPB, "$(sourcepoint)-ORBITBUMP:OFFSET-YP")
+ field(OOPT, "On Change")
+ field(DOPT, "Use CALC")
+ field(FLNK, "AGEBD-ORBITBUMP:$(sourcepoint)-DELTAY-BPM1")
+ field(HIHI, "100")
+ field(HHSV, "MAJOR")
+ field(HIGH, "1")
+ field(HSV, "MINOR")
+ field(LOW, "-1")
+ field(LSV, "MINOR")
+ field(LOLO, "-100")
+ field(LLSV, "MAJOR")
+}
+
+# BPM1, C1xx, C1xpx, C1yy, C1ypy,
+
+record(stringout, "AGEBD-ORBITBUMP:$(sourcepoint)-BPM1") {
+ field(DESC, "$(BPM1)")
+ field(ASG, "READONLY")
+ field(VAL, "$(BPM1)")
+ field(PINI, "YES")
+}
+
+record(ao, "AGEBD-ORBITBUMP:$(sourcepoint)-C1xx") {
+ field(DESC, "Coefficient dx2dx at $(BPM1)")
+ field(ASG, "READONLY")
+ field(EGU, "mm/mm")
+ field(PREC, "3")
+ field(VAL, "$(C1xx)")
+ field(PINI, "YES")
+}
+
+record(ao, "AGEBD-ORBITBUMP:$(sourcepoint)-C1xpx") {
+ field(DESC, "Coefficient dxp2dx at $(BPM1)")
+ field(ASG, "READONLY")
+ field(EGU, "mm/mrad")
+ field(PREC, "3")
+ field(VAL, "$(C1xpx)")
+ field(PINI, "YES")
+}
+
+record(ao, "AGEBD-ORBITBUMP:$(sourcepoint)-C1yy") {
+ field(DESC, "Coefficient dy2dy at $(BPM1)")
+ field(ASG, "READONLY")
+ field(EGU, "mm/mm")
+ field(PREC, "3")
+ field(VAL, "$(C1yy)")
+ field(PINI, "YES")
+}
+
+record(ao, "AGEBD-ORBITBUMP:$(sourcepoint)-C1ypy") {
+ field(DESC, "Coefficient dyp2dy at $(BPM1)")
+ field(ASG, "READONLY")
+ field(EGU, "mm/mrad")
+ field(PREC, "3")
+ field(VAL, "$(C1ypy)")
+ field(PINI, "YES")
+}
+
+record(calcout, "AGEBD-ORBITBUMP:$(sourcepoint)-DELTAX-BPM1") {
+ field(DESC, "Hor. change for $(BPM1)")
+ field(ASG, "READONLY")
+ field(SCAN, "Passive")
+ field(PREC, "3")
+ field(CALC, "A*B/1000 + C*D/1000")
+ field(INPA, "AGEBD-ORBITBUMP:$(sourcepoint)-C1xx")
+ field(INPB, "AGEBD-ORBITBUMP:$(sourcepoint)-OFFSET-X-TOTAL")
+ field(INPC, "AGEBD-ORBITBUMP:$(sourcepoint)-C1xpx")
+ field(INPD, "AGEBD-ORBITBUMP:$(sourcepoint)-OFFSET-XP-TOTAL")
+ field(OOPT, "On Change")
+ field(DOPT, "Use CALC")
+ field(OUT, "$(BPM1):X-B-REF-OP")
+ field(FLNK, "AGEBD-ORBITBUMP:$(sourcepoint)-DELTAX-BPM2")
+}
+
+record(calcout, "AGEBD-ORBITBUMP:$(sourcepoint)-DELTAY-BPM1") {
+ field(DESC, "Hor. change for $(BPM1)")
+ field(ASG, "READONLY")
+ field(SCAN, "Passive")
+ field(PREC, "3")
+ field(CALC, "A*B/1000 + C*D/1000")
+ field(INPA, "AGEBD-ORBITBUMP:$(sourcepoint)-C1yy")
+ field(INPB, "AGEBD-ORBITBUMP:$(sourcepoint)-OFFSET-Y-TOTAL")
+ field(INPC, "AGEBD-ORBITBUMP:$(sourcepoint)-C1ypy")
+ field(INPD, "AGEBD-ORBITBUMP:$(sourcepoint)-OFFSET-YP-TOTAL")
+ field(OOPT, "On Change")
+ field(DOPT, "Use CALC")
+ field(OUT, "$(BPM1):Y-B-REF-OP")
+ field(FLNK, "AGEBD-ORBITBUMP:$(sourcepoint)-DELTAY-BPM2")
+}
+
+# BPM2, C2xx, C2xpx, C2yy, C2ypy,
+
+record(stringout, "AGEBD-ORBITBUMP:$(sourcepoint)-BPM2") {
+ field(DESC, "$(BPM2)")
+ field(ASG, "READONLY")
+ field(VAL, "$(BPM2)")
+ field(PINI, "YES")
+}
+
+record(ao, "AGEBD-ORBITBUMP:$(sourcepoint)-C2xx") {
+ field(DESC, "Coefficient dx2dx at $(BPM2)")
+ field(ASG, "READONLY")
+ field(EGU, "mm/mm")
+ field(PREC, "3")
+ field(VAL, "$(C2xx)")
+ field(PINI, "YES")
+}
+
+record(ao, "AGEBD-ORBITBUMP:$(sourcepoint)-C2xpx") {
+ field(DESC, "Coefficient dxp2dx at $(BPM2)")
+ field(ASG, "READONLY")
+ field(EGU, "mm/mrad")
+ field(PREC, "3")
+ field(VAL, "$(C2xpx)")
+ field(PINI, "YES")
+}
+
+record(ao, "AGEBD-ORBITBUMP:$(sourcepoint)-C2yy") {
+ field(DESC, "Coefficient dy2dy at $(BPM2)")
+ field(ASG, "READONLY")
+ field(EGU, "mm/mm")
+ field(PREC, "3")
+ field(VAL, "$(C2yy)")
+ field(PINI, "YES")
+}
+
+record(ao, "AGEBD-ORBITBUMP:$(sourcepoint)-C2ypy") {
+ field(DESC, "Coefficient dyp2dy at $(BPM2)")
+ field(ASG, "READONLY")
+ field(EGU, "mm/mrad")
+ field(PREC, "3")
+ field(VAL, "$(C2ypy)")
+ field(PINI, "YES")
+}
+
+record(calcout, "AGEBD-ORBITBUMP:$(sourcepoint)-DELTAX-BPM2") {
+ field(DESC, "Hor. change for $(BPM2)")
+ field(ASG, "READONLY")
+ field(SCAN, "Passive")
+ field(PREC, "3")
+ field(CALC, "A*B/1000 + C*D/1000")
+ field(INPA, "AGEBD-ORBITBUMP:$(sourcepoint)-C2xx")
+ field(INPB, "AGEBD-ORBITBUMP:$(sourcepoint)-OFFSET-X-TOTAL")
+ field(INPC, "AGEBD-ORBITBUMP:$(sourcepoint)-C2xpx")
+ field(INPD, "AGEBD-ORBITBUMP:$(sourcepoint)-OFFSET-XP-TOTAL")
+ field(INPE, "$(sourcepoint)-ORBITBUMP:OFFSET-X")
+ field(INPF, "$(sourcepoint)-ORBITBUMP:OFFSET-XP")
+ field(OOPT, "On Change")
+ field(DOPT, "Use CALC")
+ field(OUT, "$(BPM2):X-B-REF-OP")
+ field(FLNK, "AGEBD-ORBITBUMP:$(sourcepoint)-DELTAX-BPM3")
+}
+
+record(calcout, "AGEBD-ORBITBUMP:$(sourcepoint)-DELTAY-BPM2") {
+ field(DESC, "Hor. change for $(BPM2)")
+ field(ASG, "READONLY")
+ field(SCAN, "Passive")
+ field(PREC, "3")
+ field(CALC, "A*B/1000 + C*D/1000")
+ field(INPA, "AGEBD-ORBITBUMP:$(sourcepoint)-C2yy")
+ field(INPB, "AGEBD-ORBITBUMP:$(sourcepoint)-OFFSET-Y-TOTAL")
+ field(INPC, "AGEBD-ORBITBUMP:$(sourcepoint)-C2ypy")
+ field(INPD, "AGEBD-ORBITBUMP:$(sourcepoint)-OFFSET-YP-TOTAL")
+ field(OOPT, "On Change")
+ field(DOPT, "Use CALC")
+ field(OUT, "$(BPM2):Y-B-REF-OP")
+ field(FLNK, "AGEBD-ORBITBUMP:$(sourcepoint)-DELTAY-BPM3")
+}
+
+# BPM3, C3xx, C3xpx, C3yy, C3ypy,
+
+record(stringout, "AGEBD-ORBITBUMP:$(sourcepoint)-BPM3") {
+ field(DESC, "$(BPM3)")
+ field(VAL, "$(BPM3)")
+ field(ASG, "READONLY")
+ field(PINI, "YES")
+}
+
+record(ao, "AGEBD-ORBITBUMP:$(sourcepoint)-C3xx") {
+ field(DESC, "Coefficient dx2dx at $(BPM3)")
+ field(EGU, "mm/mm")
+ field(PREC, "3")
+ field(VAL, "$(C3xx)")
+ field(PINI, "YES")
+}
+
+record(ao, "AGEBD-ORBITBUMP:$(sourcepoint)-C3xpx") {
+ field(DESC, "Coefficient dxp2dx at $(BPM3)")
+ field(EGU, "mm/mrad")
+ field(PREC, "3")
+ field(VAL, "$(C3xpx)")
+ field(PINI, "YES")
+}
+
+record(ao, "AGEBD-ORBITBUMP:$(sourcepoint)-C3yy") {
+ field(DESC, "Coefficient dy2dy at $(BPM3)")
+ field(EGU, "mm/mm")
+ field(PREC, "3")
+ field(VAL, "$(C3yy)")
+ field(PINI, "YES")
+}
+
+record(ao, "AGEBD-ORBITBUMP:$(sourcepoint)-C3ypy") {
+ field(DESC, "Coefficient dyp2dy at $(BPM3)")
+ field(EGU, "mm/mrad")
+ field(PREC, "3")
+ field(VAL, "$(C3ypy)")
+ field(PINI, "YES")
+}
+
+record(calcout, "AGEBD-ORBITBUMP:$(sourcepoint)-DELTAX-BPM3") {
+ field(DESC, "Hor. change for $(BPM3)")
+ field(ASG, "READONLY")
+ field(SCAN, "Passive")
+ field(PREC, "3")
+ field(CALC, "A*B/1000 + C*D/1000")
+ field(INPA, "AGEBD-ORBITBUMP:$(sourcepoint)-C3xx")
+ field(INPB, "AGEBD-ORBITBUMP:$(sourcepoint)-OFFSET-X-TOTAL")
+ field(INPC, "AGEBD-ORBITBUMP:$(sourcepoint)-C3xpx")
+ field(INPD, "AGEBD-ORBITBUMP:$(sourcepoint)-OFFSET-XP-TOTAL")
+ field(INPE, "$(sourcepoint)-ORBITBUMP:OFFSET-X")
+ field(INPF, "$(sourcepoint)-ORBITBUMP:OFFSET-XP")
+ field(OOPT, "On Change")
+ field(DOPT, "Use CALC")
+ field(OUT, "$(BPM3):X-B-REF-OP")
+ field(FLNK, "AGEBD-ORBITBUMP:$(sourcepoint)-DELTAX-BPM4")
+}
+
+record(calcout, "AGEBD-ORBITBUMP:$(sourcepoint)-DELTAY-BPM3") {
+ field(DESC, "Hor. change for $(BPM3)")
+ field(ASG, "READONLY")
+ field(SCAN, "Passive")
+ field(PREC, "3")
+ field(CALC, "A*B/1000 + C*D/1000")
+ field(INPA, "AGEBD-ORBITBUMP:$(sourcepoint)-C3yy")
+ field(INPB, "AGEBD-ORBITBUMP:$(sourcepoint)-OFFSET-Y-TOTAL")
+ field(INPC, "AGEBD-ORBITBUMP:$(sourcepoint)-C3ypy")
+ field(INPD, "AGEBD-ORBITBUMP:$(sourcepoint)-OFFSET-YP-TOTAL")
+ field(OOPT, "On Change")
+ field(DOPT, "Use CALC")
+ field(OUT, "$(BPM3):Y-B-REF-OP")
+ field(FLNK, "AGEBD-ORBITBUMP:$(sourcepoint)-DELTAY-BPM4")
+}
+
+# BPM4, C4xx, C4xpx, C4yy, C4ypy,
+
+record(stringout, "AGEBD-ORBITBUMP:$(sourcepoint)-BPM4") {
+ field(DESC, "$(BPM4)")
+ field(ASG, "READONLY")
+ field(VAL, "$(BPM4)")
+ field(PINI, "YES")
+}
+
+record(ao, "AGEBD-ORBITBUMP:$(sourcepoint)-C4xx") {
+ field(DESC, "Coefficient dx2dx at $(BPM4)")
+ field(ASG, "READONLY")
+ field(EGU, "mm/mm")
+ field(PREC, "3")
+ field(VAL, "$(C4xx)")
+ field(PINI, "YES")
+}
+
+record(ao, "AGEBD-ORBITBUMP:$(sourcepoint)-C4xpx") {
+ field(DESC, "Coefficient dxp2dx at $(BPM4)")
+ field(ASG, "READONLY")
+ field(EGU, "mm/mrad")
+ field(PREC, "3")
+ field(VAL, "$(C4xpx)")
+ field(PINI, "YES")
+}
+
+record(ao, "AGEBD-ORBITBUMP:$(sourcepoint)-C4yy") {
+ field(DESC, "Coefficient dy2dy at $(BPM4)")
+ field(ASG, "READONLY")
+ field(EGU, "mm/mm")
+ field(PREC, "3")
+ field(VAL, "$(C4yy)")
+ field(PINI, "YES")
+}
+
+record(ao, "AGEBD-ORBITBUMP:$(sourcepoint)-C4ypy") {
+ field(DESC, "Coefficient dyp2dy at $(BPM4)")
+ field(ASG, "READONLY")
+ field(EGU, "mm/mrad")
+ field(PREC, "3")
+ field(VAL, "$(C4ypy)")
+ field(PINI, "YES")
+}
+
+record(calcout, "AGEBD-ORBITBUMP:$(sourcepoint)-DELTAX-BPM4") {
+ field(DESC, "Hor. change for $(BPM4)")
+ field(ASG, "READONLY")
+ field(SCAN, "Passive")
+ field(PREC, "3")
+ field(CALC, "A*B/1000 + C*D/1000")
+ field(INPA, "AGEBD-ORBITBUMP:$(sourcepoint)-C4xx")
+ field(INPB, "AGEBD-ORBITBUMP:$(sourcepoint)-OFFSET-X-TOTAL")
+ field(INPC, "AGEBD-ORBITBUMP:$(sourcepoint)-C4xpx")
+ field(INPD, "AGEBD-ORBITBUMP:$(sourcepoint)-OFFSET-XP-TOTAL")
+ field(INPE, "$(sourcepoint)-ORBITBUMP:OFFSET-X")
+ field(INPF, "$(sourcepoint)-ORBITBUMP:OFFSET-XP")
+ field(OOPT, "On Change")
+ field(DOPT, "Use CALC")
+ field(OUT, "$(BPM4):X-B-REF-OP")
+}
+
+record(calcout, "AGEBD-ORBITBUMP:$(sourcepoint)-DELTAY-BPM4") {
+ field(DESC, "Hor. change for $(BPM4)")
+ field(ASG, "READONLY")
+ field(SCAN, "Passive")
+ field(PREC, "3")
+ field(CALC, "A*B/1000 + C*D/1000")
+ field(INPA, "AGEBD-ORBITBUMP:$(sourcepoint)-C4yy")
+ field(INPB, "AGEBD-ORBITBUMP:$(sourcepoint)-OFFSET-Y-TOTAL")
+ field(INPC, "AGEBD-ORBITBUMP:$(sourcepoint)-C4ypy")
+ field(INPD, "AGEBD-ORBITBUMP:$(sourcepoint)-OFFSET-YP-TOTAL")
+ field(OOPT, "On Change")
+ field(DOPT, "Use CALC")
+ field(OUT, "$(BPM4):Y-B-REF-OP")
+}
\ No newline at end of file
diff --git a/services/orbitbump/current/ioc/README.md b/services/orbitbump/current/ioc/README.md
new file mode 100644
index 0000000..9a0741c
--- /dev/null
+++ b/services/orbitbump/current/ioc/README.md
@@ -0,0 +1 @@
+# TODO: dev/prod templating
diff --git a/services/orbitbump/current/ioc/startup.script b/services/orbitbump/current/ioc/startup.script
new file mode 100644
index 0000000..0fa52ff
--- /dev/null
+++ b/services/orbitbump/current/ioc/startup.script
@@ -0,0 +1 @@
+epicsEnvSet("ENGINEER", "armborst")
diff --git a/services/orbitbump/current/qt/A_BD_OrbitBump.ui b/services/orbitbump/current/qt/A_BD_OrbitBump.ui
new file mode 100644
index 0000000..fcc9232
--- /dev/null
+++ b/services/orbitbump/current/qt/A_BD_OrbitBump.ui
@@ -0,0 +1,409 @@
+
+
+ MainWindow
+
+
+
+ 0
+ 0
+ 770
+ 990
+
+
+
+ MainWindow
+
+
+
+
+
+ 10
+ 220
+ 750
+ 346
+
+
+
+ sourcepoint=X01DA,beamline=Debye;sourcepoint=X02DA,beamline=S-TOMCAT;sourcepoint=X03DA,beamline=PEARL;sourcepoint=X04DB,beamline=VUV;sourcepoint=X05DA,beamline=Optics;sourcepoint=X06DA,beamline=PXIII;sourcepoint=X07DB,beamline=nanoXAS;sourcepoint=X07DA,beamline=PolLux;sourcepoint=X10DA,beamline=SuperXAS
+
+
+ A_BD_OrbitBump_Operator_inc.ui
+
+
+ 9
+
+
+ 5
+
+
+
+
+
+ 10
+ 80
+ 750
+ 100
+
+
+
+ sourcepoint=X01DD,beamline=NEMO;sourcepoint=X08DB,beamline=DISCO;sourcepoint=X10DG,beamline=X11HEAT
+
+
+ A_BD_OrbitBump_Operator_inc.ui
+
+
+ 3
+
+
+ 5
+
+
+
+
+
+ 10
+ 190
+ 261
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ Dipole Beamlines
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+
+
+ 10
+ 50
+ 291
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ Diagnostic Beamlines
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+
+
+ 10
+ 570
+ 261
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ ID Beamlines
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+
+
+ 10
+ 600
+ 750
+ 541
+
+
+
+ sourcepoint=X02SA,beamline=I-TOMCAT;sourcepoint=X03MA,beamline=ADRESS;sourcepoint=X04SA,beamline=ADDAMS;sourcepoint=X05LA,beamline=QUEST;sourcepoint=X06SA,beamline=PXI;sourcepoint=X07MA,beamline=Phoenix/XTreme;sourcepoint=X08SA,beamline=micro-XAS;sourcepoint=X09LA,beamline=PEARL/XIL-II;sourcepoint=X10SA,beamline=PXII;sourcepoint=X11MA,beamline=SIM;sourcepoint=X12SA,beamline=cSAXS
+
+
+ A_BD_OrbitBump_Operator_inc.ui
+
+
+ 11
+
+
+ 5
+
+
+
+
+
+ 330
+ 50
+ 100
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ X (um)
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 440
+ 50
+ 100
+ 30
+
+
+
+
+ 15
+ 75
+ true
+
+
+
+ X' (urad)
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 550
+ 50
+ 100
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ Y (um)
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 660
+ 50
+ 100
+ 30
+
+
+
+
+ 15
+ 75
+ true
+
+
+
+ Y' (urad)
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 598
+ 4
+ 170
+ 30
+
+
+
+ Expert Panel All
+
+
+
+ 183
+ 157
+ 92
+
+
+
+ Expert Panel All
+
+
+ A_BD_OrbitBump_Expert_all.ui
+
+
+
+
+
+ 2
+ 2
+ 767
+ 33
+
+
+
+
+ Sans Serif
+ 20
+ 75
+ false
+ true
+
+
+
+ Beamline local Bumps
+
+
+ Qt::AlignLeading
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+ 100
+ 100
+ 100
+
+
+
+ caLabel::Static
+
+
+
+
+
+ 800
+ 260
+ 70
+ 20
+
+
+
+ Reload
+
+
+ RELOAD
+
+
+ A
+
+
+ AGEBD-ALH:ORBITBUMP-GUIRELOAD
+
+
+ caCalc::TriggerZeroToOne
+
+
+
+
+
+ 800
+ 320
+ 70
+ 20
+
+
+
+ cainclude
+ cainclude_2
+ calabel
+ calabel_2
+ calabel_3
+ cainclude_3
+ calabel_4
+ calabel_5
+ calabel_6
+ calabel_7
+ calabel_8
+ carelateddisplay
+ cacalc_2
+ wmsignalpropagator
+
+
+
+
+ caRelatedDisplay
+ QWidget
+
+
+
+ caLabel
+ QLabel
+
+
+
+ caInclude
+ QWidget
+
+
+
+ caCalc
+ QLabel
+
+
+
+ wmSignalPropagator
+ QLabel
+
+
+
+
+
+
+ cacalc_2
+ emitSignal(bool)
+ wmsignalpropagator
+ reloadwindow()
+
+
+ 844
+ 271
+
+
+ 847
+ 327
+
+
+
+
+
diff --git a/services/orbitbump/current/qt/A_BD_OrbitBump_Expert.ui b/services/orbitbump/current/qt/A_BD_OrbitBump_Expert.ui
new file mode 100644
index 0000000..328eafb
--- /dev/null
+++ b/services/orbitbump/current/qt/A_BD_OrbitBump_Expert.ui
@@ -0,0 +1,465 @@
+
+
+ MainWindow
+
+
+
+ 0
+ 0
+ 1801
+ 196
+
+
+
+ MainWindow
+
+
+
+
+
+ 10
+ 72
+ 1790
+ 120
+
+
+
+ sourcepoint=$(sourcepoint),beamline=$(beamline)
+
+
+ A_BD_OrbitBump_Expert_inc.ui
+
+
+ 1
+
+
+ 1
+
+
+
+
+
+ 240
+ 42
+ 100
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ X (um)
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 354
+ 42
+ 100
+ 30
+
+
+
+
+ 15
+ 75
+ true
+
+
+
+ X' (urad)
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 462
+ 42
+ 100
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ Y (um)
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 574
+ 42
+ 100
+ 30
+
+
+
+
+ 15
+ 75
+ true
+
+
+
+ Y' (urad)
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 686
+ 42
+ 100
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ BPM 1
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 966
+ 42
+ 100
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ BPM 2
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 1246
+ 42
+ 100
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ BPM 3
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 1526
+ 42
+ 100
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ BPM 4
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 791
+ 42
+ 80
+ 30
+
+
+
+
+ 18
+ 50
+ false
+
+
+
+ dx
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 876
+ 42
+ 80
+ 30
+
+
+
+
+ 18
+ 50
+ false
+
+
+
+ dy
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 1071
+ 42
+ 80
+ 30
+
+
+
+
+ 18
+ 50
+ false
+
+
+
+ dx
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 1156
+ 42
+ 80
+ 30
+
+
+
+
+ 18
+ 50
+ false
+
+
+
+ dy
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 1631
+ 42
+ 80
+ 30
+
+
+
+
+ 18
+ 50
+ false
+
+
+
+ dx
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 1351
+ 42
+ 80
+ 30
+
+
+
+
+ 18
+ 50
+ false
+
+
+
+ dx
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 1716
+ 42
+ 80
+ 30
+
+
+
+
+ 18
+ 50
+ false
+
+
+
+ dy
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 1436
+ 42
+ 80
+ 30
+
+
+
+
+ 18
+ 50
+ false
+
+
+
+ dy
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 0
+ 0
+ 1909
+ 33
+
+
+
+
+ Sans Serif
+ 20
+ 75
+ false
+ true
+
+
+
+ $(sourcepoint) $(beamline)
+
+
+ Qt::AlignLeading
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+ 100
+ 100
+ 100
+
+
+
+ caLabel::Static
+
+
+
+
+
+
+ caLabel
+ QLabel
+
+
+
+ caInclude
+ QWidget
+
+
+
+
+
+
diff --git a/services/orbitbump/current/qt/A_BD_OrbitBump_ExpertBackUp.ui b/services/orbitbump/current/qt/A_BD_OrbitBump_ExpertBackUp.ui
new file mode 100644
index 0000000..780ccbc
--- /dev/null
+++ b/services/orbitbump/current/qt/A_BD_OrbitBump_ExpertBackUp.ui
@@ -0,0 +1,183 @@
+
+
+ MainWindow
+
+
+
+ 0
+ 0
+ 1178
+ 600
+
+
+
+ MainWindow
+
+
+
+
+
+
+
+ 270
+ 340
+ 501
+ 51
+
+
+
+ AGEBD-ORBITBUMP:BEAMLINECALC
+
+
+ caLineEdit::Default
+
+
+ caLineEdit::onBackground
+
+
+ caLineEdit::User
+
+
+
+
+
+ 50
+ 110
+ 501
+ 51
+
+
+
+ AGEBD-ORBITBUMP:BEAMLINETYPE-BEND
+
+
+ caLineEdit::Default
+
+
+ caLineEdit::onBackground
+
+
+ caLineEdit::User
+
+
+
+
+
+ 270
+ 230
+ 501
+ 51
+
+
+
+ AGEBD-ORBITBUMP:BEAMLINETYPE
+
+
+ caLineEdit::Default
+
+
+ caLineEdit::onBackground
+
+
+ caLineEdit::User
+
+
+
+
+
+ 630
+ 110
+ 501
+ 51
+
+
+
+ AGEBD-ORBITBUMP:BEAMLINETYPE-ID
+
+
+ caLineEdit::Default
+
+
+ caLineEdit::onBackground
+
+
+ caLineEdit::User
+
+
+
+
+
+ 260
+ 450
+ 501
+ 51
+
+
+
+ AGEBD-ORBITBUMP:BEAMLINE
+
+
+ caLineEdit::Default
+
+
+ caLineEdit::onBackground
+
+
+ caLineEdit::User
+
+
+
+
+
+
+ caMenu
+ QComboBox
+
+
+
+ caLineEdit
+ QLineEdit
+
+
+
+
+
+
diff --git a/services/orbitbump/current/qt/A_BD_OrbitBump_Expert_all.ui b/services/orbitbump/current/qt/A_BD_OrbitBump_Expert_all.ui
new file mode 100644
index 0000000..b5f2dd1
--- /dev/null
+++ b/services/orbitbump/current/qt/A_BD_OrbitBump_Expert_all.ui
@@ -0,0 +1,1273 @@
+
+
+ MainWindow
+
+
+
+ 0
+ 0
+ 1819
+ 1470
+
+
+
+ MainWindow
+
+
+
+
+
+ 0
+ 2
+ 1837
+ 33
+
+
+
+
+ Sans Serif
+ 20
+ 75
+ false
+ true
+
+
+
+ Beamline local Bumps Expert
+
+
+ Qt::AlignLeading
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+ 100
+ 100
+ 100
+
+
+
+ caLabel::Static
+
+
+
+
+
+ 0
+ 40
+ 1819
+ 1430
+
+
+
+ 0
+
+
+
+ Diagnostic Beamlines
+
+
+
+
+ 570
+ 6
+ 100
+ 30
+
+
+
+
+ 15
+ 75
+ true
+
+
+
+ Y' (urad)
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 1629
+ 6
+ 80
+ 30
+
+
+
+
+ 18
+ 50
+ false
+
+
+
+ dx
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 964
+ 6
+ 100
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ BPM 2
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 240
+ 6
+ 100
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ X (um)
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 1524
+ 6
+ 100
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ BPM 4
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 460
+ 6
+ 100
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ Y (um)
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 10
+ 40
+ 1790
+ 242
+
+
+
+ sourcepoint=X01DD,beamline=NEMO;sourcepoint=X08DB,beamline=DISCO
+
+
+ A_BD_OrbitBump_Expert_inc.ui
+
+
+ 2
+
+
+ 2
+
+
+
+
+
+ 684
+ 6
+ 100
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ BPM 1
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 1349
+ 6
+ 80
+ 30
+
+
+
+
+ 18
+ 50
+ false
+
+
+
+ dx
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 874
+ 6
+ 80
+ 30
+
+
+
+
+ 18
+ 50
+ false
+
+
+
+ dy
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 1069
+ 6
+ 80
+ 30
+
+
+
+
+ 18
+ 50
+ false
+
+
+
+ dx
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 789
+ 6
+ 80
+ 30
+
+
+
+
+ 18
+ 50
+ false
+
+
+
+ dx
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 1434
+ 6
+ 80
+ 30
+
+
+
+
+ 18
+ 50
+ false
+
+
+
+ dy
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 1154
+ 6
+ 80
+ 30
+
+
+
+
+ 18
+ 50
+ false
+
+
+
+ dy
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 1244
+ 6
+ 100
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ BPM 3
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 1714
+ 6
+ 80
+ 30
+
+
+
+
+ 18
+ 50
+ false
+
+
+
+ dy
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 350
+ 6
+ 100
+ 30
+
+
+
+
+ 15
+ 75
+ true
+
+
+
+ X' (urad)
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ Dipole Beamlines
+
+
+
+
+ 1067
+ 6
+ 80
+ 30
+
+
+
+
+ 18
+ 50
+ false
+
+
+
+ dx
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 1242
+ 6
+ 100
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ BPM 3
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 682
+ 6
+ 100
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ BPM 1
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 1432
+ 6
+ 80
+ 30
+
+
+
+
+ 18
+ 50
+ false
+
+
+
+ dy
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 570
+ 6
+ 100
+ 30
+
+
+
+
+ 15
+ 75
+ true
+
+
+
+ Y' (urad)
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 1627
+ 6
+ 80
+ 30
+
+
+
+
+ 18
+ 50
+ false
+
+
+
+ dx
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 240
+ 6
+ 100
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ X (um)
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 350
+ 6
+ 100
+ 30
+
+
+
+
+ 15
+ 75
+ true
+
+
+
+ X' (urad)
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 872
+ 6
+ 80
+ 30
+
+
+
+
+ 18
+ 50
+ false
+
+
+
+ dy
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 1522
+ 6
+ 100
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ BPM 4
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 787
+ 6
+ 80
+ 30
+
+
+
+
+ 18
+ 50
+ false
+
+
+
+ dx
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 962
+ 6
+ 100
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ BPM 2
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 1347
+ 6
+ 80
+ 30
+
+
+
+
+ 18
+ 50
+ false
+
+
+
+ dx
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 1152
+ 6
+ 80
+ 30
+
+
+
+
+ 18
+ 50
+ false
+
+
+
+ dy
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 460
+ 6
+ 100
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ Y (um)
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 1712
+ 6
+ 80
+ 30
+
+
+
+
+ 18
+ 50
+ false
+
+
+
+ dy
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 10
+ 40
+ 1790
+ 1096
+
+
+
+ sourcepoint=X01DA,beamline=Debye;sourcepoint=X02DA,beamline=S-TOMCAT;sourcepoint=X03DA,beamline=PEARL;sourcepoint=X04DB,beamline=VUV;sourcepoint=X05DA,beamline=Optics;sourcepoint=X06DA,beamline=PXIII;sourcepoint=X07DB,beamline=nanoXAS;sourcepoint=X07DA,beamline=PolLux;sourcepoint=X10DA,beamline=SuperXAS
+
+
+ A_BD_OrbitBump_Expert_inc.ui
+
+
+ 9
+
+
+ 2
+
+
+
+
+
+ ID Beamlines
+
+
+
+
+ 10
+ 40
+ 1790
+ 1340
+
+
+
+ sourcepoint=X02SA,beamline=I-TOMCAT;sourcepoint=X03MA,beamline=ADRESS;sourcepoint=X04SA,beamline=ADDAMS;sourcepoint=X05LA,beamline=QUEST;sourcepoint=X06SA,beamline=PXI;sourcepoint=X07MA,beamline=Phoenix/XTreme;sourcepoint=X08SA,beamline=micro-XAS;sourcepoint=X09LA,beamline=PEARL/XIL-II;sourcepoint=X10SA,beamline=PXII;sourcepoint=X11MA,beamline=SIM;sourcepoint=X12SA,beamline=cSAXS
+
+
+ A_BD_OrbitBump_Expert_inc.ui
+
+
+ 11
+
+
+ 2
+
+
+
+
+
+ 872
+ 6
+ 80
+ 30
+
+
+
+
+ 18
+ 50
+ false
+
+
+
+ dy
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 1522
+ 6
+ 100
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ BPM 4
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 1627
+ 6
+ 80
+ 30
+
+
+
+
+ 18
+ 50
+ false
+
+
+
+ dx
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 682
+ 6
+ 100
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ BPM 1
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 1242
+ 6
+ 100
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ BPM 3
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 1432
+ 6
+ 80
+ 30
+
+
+
+
+ 18
+ 50
+ false
+
+
+
+ dy
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 240
+ 6
+ 100
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ X (um)
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 787
+ 6
+ 80
+ 30
+
+
+
+
+ 18
+ 50
+ false
+
+
+
+ dx
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 350
+ 6
+ 100
+ 30
+
+
+
+
+ 15
+ 75
+ true
+
+
+
+ X' (urad)
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 962
+ 6
+ 100
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ BPM 2
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 1067
+ 6
+ 80
+ 30
+
+
+
+
+ 18
+ 50
+ false
+
+
+
+ dx
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 1712
+ 6
+ 80
+ 30
+
+
+
+
+ 18
+ 50
+ false
+
+
+
+ dy
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 1347
+ 6
+ 80
+ 30
+
+
+
+
+ 18
+ 50
+ false
+
+
+
+ dx
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 460
+ 6
+ 100
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ Y (um)
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 570
+ 6
+ 100
+ 30
+
+
+
+
+ 15
+ 75
+ true
+
+
+
+ Y' (urad)
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 1152
+ 6
+ 80
+ 30
+
+
+
+
+ 18
+ 50
+ false
+
+
+
+ dy
+
+
+ Qt::AlignCenter
+
+
+
+
+
+
+
+
+ caLabel
+ QLabel
+
+
+
+ caInclude
+ QWidget
+
+
+
+
+
+
diff --git a/services/orbitbump/current/qt/A_BD_OrbitBump_Expert_inc.ui b/services/orbitbump/current/qt/A_BD_OrbitBump_Expert_inc.ui
new file mode 100644
index 0000000..2aa7420
--- /dev/null
+++ b/services/orbitbump/current/qt/A_BD_OrbitBump_Expert_inc.ui
@@ -0,0 +1,627 @@
+
+
+ MainWindow
+
+
+
+ 0
+ 0
+ 1790
+ 120
+
+
+
+ MainWindow
+
+
+
+
+
+ 779
+ 1
+ 80
+ 30
+
+
+
+ AGEBD-ORBITBUMP:$(sourcepoint)-DELTAX-BPM1
+
+
+
+
+
+ 864
+ 1
+ 80
+ 30
+
+
+
+ AGEBD-ORBITBUMP:$(sourcepoint)-DELTAY-BPM1
+
+
+
+
+
+ 1059
+ 1
+ 80
+ 30
+
+
+
+ AGEBD-ORBITBUMP:$(sourcepoint)-DELTAX-BPM2
+
+
+
+
+
+ 1144
+ 1
+ 80
+ 30
+
+
+
+ AGEBD-ORBITBUMP:$(sourcepoint)-DELTAY-BPM2
+
+
+
+
+
+ 230
+ 1
+ 100
+ 30
+
+
+
+ 3
+
+
+ 0
+
+
+ AGEBD-ORBITBUMP:$(sourcepoint)-OFFSET-X
+
+
+ caSpinbox::Alarm
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 340
+ 1
+ 100
+ 30
+
+
+
+ 3
+
+
+ 0
+
+
+ AGEBD-ORBITBUMP:$(sourcepoint)-OFFSET-XP
+
+
+ caSpinbox::Alarm
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 560
+ 1
+ 100
+ 30
+
+
+
+ 3
+
+
+ 0
+
+
+ AGEBD-ORBITBUMP:$(sourcepoint)-OFFSET-YP
+
+
+ caSpinbox::Alarm
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 450
+ 1
+ 100
+ 30
+
+
+
+ 3
+
+
+ 0
+
+
+ AGEBD-ORBITBUMP:$(sourcepoint)-OFFSET-Y
+
+
+ caSpinbox::Alarm
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 1619
+ 1
+ 80
+ 30
+
+
+
+ AGEBD-ORBITBUMP:$(sourcepoint)-DELTAX-BPM4
+
+
+
+
+
+ 1424
+ 1
+ 80
+ 30
+
+
+
+ AGEBD-ORBITBUMP:$(sourcepoint)-DELTAY-BPM3
+
+
+
+
+
+ 1704
+ 1
+ 80
+ 30
+
+
+
+ AGEBD-ORBITBUMP:$(sourcepoint)-DELTAY-BPM4
+
+
+
+
+
+ 1339
+ 1
+ 80
+ 30
+
+
+
+ AGEBD-ORBITBUMP:$(sourcepoint)-DELTAX-BPM3
+
+
+
+
+
+ 674
+ 1
+ 100
+ 30
+
+
+
+ AGEBD-ORBITBUMP:$(sourcepoint)-BPM1
+
+
+
+
+
+ 954
+ 1
+ 100
+ 30
+
+
+
+ AGEBD-ORBITBUMP:$(sourcepoint)-BPM2
+
+
+
+
+
+ 1234
+ 1
+ 100
+ 30
+
+
+
+ AGEBD-ORBITBUMP:$(sourcepoint)-BPM3
+
+
+
+
+
+ 1514
+ 1
+ 100
+ 30
+
+
+
+ AGEBD-ORBITBUMP:$(sourcepoint)-BPM4
+
+
+
+
+
+ 450
+ 42
+ 100
+ 30
+
+
+
+ 3
+
+
+ 0
+
+
+ $(sourcepoint)-ORBITBUMP:OFFSET-Y
+
+
+ caSpinbox::Alarm
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 230
+ 42
+ 100
+ 30
+
+
+
+ 3
+
+
+ 0
+
+
+ $(sourcepoint)-ORBITBUMP:OFFSET-X
+
+
+ caSpinbox::Alarm
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 560
+ 42
+ 100
+ 30
+
+
+
+ 3
+
+
+ 0
+
+
+ $(sourcepoint)-ORBITBUMP:OFFSET-YP
+
+
+ caSpinbox::Alarm
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 340
+ 42
+ 100
+ 30
+
+
+
+ 3
+
+
+ 0
+
+
+ $(sourcepoint)-ORBITBUMP:OFFSET-XP
+
+
+ caSpinbox::Alarm
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 0
+ 40
+ 225
+ 30
+
+
+
+ Beamline setpoint
+
+
+
+
+
+ 0
+ 0
+ 1790
+ 120
+
+
+
+
+
+
+ 230
+ 80
+ 100
+ 30
+
+
+
+ AGEBD-ORBITBUMP:$(sourcepoint)-OFFSET-X-TOTAL
+
+
+ caLineEdit::Alarm_Default
+
+
+ false
+
+
+ caLineEdit::onBackground
+
+
+
+
+
+ 450
+ 80
+ 100
+ 30
+
+
+
+ AGEBD-ORBITBUMP:$(sourcepoint)-OFFSET-Y-TOTAL
+
+
+ caLineEdit::Alarm_Default
+
+
+ caLineEdit::onBackground
+
+
+
+
+
+ 560
+ 80
+ 100
+ 30
+
+
+
+ AGEBD-ORBITBUMP:$(sourcepoint)-OFFSET-YP-TOTAL
+
+
+ caLineEdit::Alarm_Default
+
+
+ caLineEdit::onBackground
+
+
+
+
+
+ 340
+ 80
+ 100
+ 30
+
+
+
+ AGEBD-ORBITBUMP:$(sourcepoint)-OFFSET-XP-TOTAL
+
+
+ caLineEdit::Alarm_Default
+
+
+ caLineEdit::onBackground
+
+
+
+
+
+ 0
+ 80
+ 225
+ 30
+
+
+
+ Total Bump
+
+
+
+
+
+ 0
+ 2
+ 225
+ 30
+
+
+
+ Machine setpoint
+
+
+ cagraphics
+ calineedit
+ calineedit_2
+ calineedit_3
+ calineedit_4
+ caspinbox_2
+ caspinbox_3
+ caspinbox_4
+ caspinbox_5
+ calineedit_5
+ calineedit_6
+ calineedit_7
+ calineedit_8
+ calineedit_9
+ calineedit_10
+ calineedit_11
+ calineedit_12
+ caspinbox_6
+ caspinbox_7
+ caspinbox_8
+ caspinbox_9
+ calabel_3
+ calineedit_17
+ calineedit_18
+ calineedit_19
+ calineedit_20
+ calabel_5
+ calabel_6
+
+
+
+
+ caSpinbox
+ QFrame
+
+
+
+ caLabel
+ QLabel
+
+
+
+ caGraphics
+ QWidget
+
+
+
+ caLineEdit
+ QLineEdit
+
+
+
+
+
+
diff --git a/services/orbitbump/current/qt/A_BD_OrbitBump_Operator.ui b/services/orbitbump/current/qt/A_BD_OrbitBump_Operator.ui
new file mode 100644
index 0000000..0a66761
--- /dev/null
+++ b/services/orbitbump/current/qt/A_BD_OrbitBump_Operator.ui
@@ -0,0 +1,291 @@
+
+
+ MainWindow
+
+
+
+ 0
+ 0
+ 770
+ 950
+
+
+
+ MainWindow
+
+
+
+
+
+ 10
+ 190
+ 750
+ 346
+
+
+
+ sourcepoint=X01DA,beamline=Debye;sourcepoint=X02DA,beamline=S-TOMCAT;sourcepoint=X03DA,beamline=PEARL;sourcepoint=X04DB,beamline=VUV;sourcepoint=X05DA,beamline=Optics;sourcepoint=X06DA,beamline=PXIII;sourcepoint=X07DB,beamline=nanoXAS;sourcepoint=X07DA,beamline=PolLux;sourcepoint=X10DA,beamline=SuperXAS
+
+
+ A_BD_OrbitBump_Operator_inc.ui
+
+
+ 9
+
+
+ 5
+
+
+
+
+
+ 10
+ 80
+ 750
+ 80
+
+
+
+ sourcepoint=X01DD,beamline=NEMO;sourcepoint=X08DB,beamline=DISCO
+
+
+ A_BD_OrbitBump_Operator_inc.ui
+
+
+ 2
+
+
+ 5
+
+
+
+
+
+ 10
+ 160
+ 261
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ Dipole Beamlines
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+
+
+ 10
+ 50
+ 291
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ Diagnostic Beamlines
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+
+
+ 10
+ 530
+ 261
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ ID Beamlines
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+
+
+ 10
+ 560
+ 750
+ 541
+
+
+
+ sourcepoint=X02SA,beamline=I-TOMCAT;sourcepoint=X03MA,beamline=ADRESS;sourcepoint=X04SA,beamline=ADDAMS;sourcepoint=X05LA,beamline=QUEST;sourcepoint=X06SA,beamline=PXI;sourcepoint=X07MA,beamline=Phoenix/XTreme;sourcepoint=X08SA,beamline=micro-XAS;sourcepoint=X09LA,beamline=PEARL/XIL-II;sourcepoint=X10SA,beamline=PXII;sourcepoint=X11MA,beamline=SIM;sourcepoint=X12SA,beamline=cSAXS
+
+
+ A_BD_OrbitBump_Operator_inc.ui
+
+
+ 11
+
+
+ 5
+
+
+
+
+
+ 330
+ 50
+ 100
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ X (um)
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 440
+ 50
+ 100
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ X' (urad)
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 550
+ 50
+ 100
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ Y (um)
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 660
+ 50
+ 100
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ Y' (urad)
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 590
+ 10
+ 170
+ 30
+
+
+
+ Expert Panel
+
+
+
+ 183
+ 157
+ 92
+
+
+
+ Expert Panel
+
+
+ A_BD_OrbitBump_Expert.ui
+
+
+
+
+
+
+ caRelatedDisplay
+ QWidget
+
+
+
+ caLabel
+ QLabel
+
+
+
+ caInclude
+ QWidget
+
+
+
+
+
+
diff --git a/services/orbitbump/current/qt/A_BD_OrbitBump_Operator_inc.ui b/services/orbitbump/current/qt/A_BD_OrbitBump_Operator_inc.ui
new file mode 100644
index 0000000..2845c39
--- /dev/null
+++ b/services/orbitbump/current/qt/A_BD_OrbitBump_Operator_inc.ui
@@ -0,0 +1,159 @@
+
+
+ MainWindow
+
+
+
+ 0
+ 0
+ 750
+ 30
+
+
+
+ MainWindow
+
+
+
+
+
+ 160
+ 0
+ 150
+ 30
+
+
+
+ $(beamline)
+
+
+
+
+
+ 320
+ 0
+ 100
+ 30
+
+
+
+ AGEBD-ORBITBUMP:$(sourcepoint)-OFFSET-X-TOTAL
+
+
+ caLineEdit::Alarm_Default
+
+
+ false
+
+
+ caLineEdit::onBackground
+
+
+
+
+
+ 430
+ 0
+ 100
+ 30
+
+
+
+ AGEBD-ORBITBUMP:$(sourcepoint)-OFFSET-XP-TOTAL
+
+
+ caLineEdit::Alarm_Default
+
+
+ caLineEdit::onBackground
+
+
+
+
+
+ 540
+ 0
+ 100
+ 30
+
+
+
+ AGEBD-ORBITBUMP:$(sourcepoint)-OFFSET-Y-TOTAL
+
+
+ caLineEdit::Alarm_Default
+
+
+ caLineEdit::onBackground
+
+
+
+
+
+ 650
+ 0
+ 100
+ 30
+
+
+
+ AGEBD-ORBITBUMP:$(sourcepoint)-OFFSET-YP-TOTAL
+
+
+ caLineEdit::Alarm_Default
+
+
+ caLineEdit::onBackground
+
+
+
+
+
+ 0
+ 0
+ 150
+ 30
+
+
+
+ -$(sourcepoint) Expert
+
+
+
+ 183
+ 157
+ 92
+
+
+
+ $(sourcepoint) Expert
+
+
+ A_BD_OrbitBump_Expert.ui
+
+
+ sourcepoint=$(sourcepoint),beamline=$(beamline)
+
+
+
+
+
+
+ caRelatedDisplay
+ QWidget
+
+
+
+ caLabel
+ QLabel
+
+
+
+ caLineEdit
+ QLineEdit
+
+
+
+
+
+
diff --git a/services/orbitbump/current/systemd/AGEBD-SERVICE-ORBITBUMP.service b/services/orbitbump/current/systemd/AGEBD-SERVICE-ORBITBUMP.service
new file mode 100644
index 0000000..4358d12
--- /dev/null
+++ b/services/orbitbump/current/systemd/AGEBD-SERVICE-ORBITBUMP.service
@@ -0,0 +1,16 @@
+[Unit]
+Description=AGEBD-SERVICE-ORBITBUMP
+After=network.target
+
+[Service]
+Environment=AGEBD_ENV={{ agebd_env }}
+ExecStart=/sls/bd/hla/{{ agebd_env }}/bin/start_service.sh ORBITBUMP
+Restart=no
+
+[Install]
+WantedBy=default.target
+
+# https://www.freedesktop.org/software/systemd/man/latest/systemd.service.html
+# systemctl --user daemon-reload
+# systemctl --user enable /sls/bd/bin/systemd/AGEBD-SERVICE-ORBITBUMP.service
+# systemctl --user start AGEBD-SERVICE-ORBITBUMP
diff --git a/services/plots/current/app/pyproject.toml b/services/plots/current/app/pyproject.toml
new file mode 100644
index 0000000..40449a1
--- /dev/null
+++ b/services/plots/current/app/pyproject.toml
@@ -0,0 +1,50 @@
+[project]
+name = "agebd-plots"
+version = "0.1.0"
+description = "AGEBD-PLOTS Service"
+requires-python = "==3.10.*"
+dependencies = [
+ "agebd",
+ "matplotlib>=3.10.9",
+ "urllib3>=2.7.0",
+]
+# TODO: elog
+
+[dependency-groups]
+dev = [
+ "pyepics>=3.5.8",
+ "pytest>=8.4.2",
+ "ruff>=0.15.20",
+]
+
+[tool.uv.sources]
+# Path is relative to where agebd package is deployed on hla
+# machines (see CI/CD in .gitea/workflows)
+agebd = { path = "../../../../packages/agebd", editable = true }
+
+[build-system]
+requires = ["hatchling"]
+build-backend = "hatchling.build"
+
+[tool.uv]
+package = true
+
+[tool.pytest.ini_options]
+pythonpath = ["src"]
+env = [
+ "AGEBD_ENV=local",
+]
+
+[tool.ruff]
+include = [
+ "src/**/*.py",
+ "tests/**/*.py",
+]
+line-length = 100
+
+[tool.ruff.lint]
+# use isort to sort imports
+extend-select = ["I"]
+
+[tool.ruff.lint.isort]
+known-first-party = ["agebd"]
diff --git a/services/plots/current/app/src/agebd_plots/__init__.py b/services/plots/current/app/src/agebd_plots/__init__.py
new file mode 100644
index 0000000..1800c27
--- /dev/null
+++ b/services/plots/current/app/src/agebd_plots/__init__.py
@@ -0,0 +1 @@
+from .service import PVs, Service
diff --git a/services/plots/current/app/src/agebd_plots/main.py b/services/plots/current/app/src/agebd_plots/main.py
new file mode 100644
index 0000000..317cce2
--- /dev/null
+++ b/services/plots/current/app/src/agebd_plots/main.py
@@ -0,0 +1,31 @@
+import typer
+
+from agebd.enums import LogLevel
+from agebd.runner import PeriodicRunner
+from agebd.utils import init_logging
+from agebd_plots import PVs, Service
+
+# TODO: remove: cicd test 10
+
+
+def main(
+ log_level: LogLevel = typer.Option(
+ LogLevel.INFO,
+ "--log-level",
+ "-l",
+ # Looks at the OS env variable first. If empty, falls back to "INFO"
+ envvar="AGEBD_LOG_LEVEL",
+ # help="Set log level: DEBUG, INFO, WARNING, ERROR, CRITICAL",
+ case_sensitive=False,
+ ),
+):
+ init_logging(log_level)
+ service_name = "PLOTS"
+ pvs = PVs(service_name=service_name)
+ service = Service(name=service_name, pvs=pvs)
+ runner = PeriodicRunner(service=service)
+ runner.start()
+
+
+if __name__ == "__main__":
+ typer.run(main)
diff --git a/services/plots/current/app/src/agebd_plots/service.py b/services/plots/current/app/src/agebd_plots/service.py
new file mode 100644
index 0000000..5fa7646
--- /dev/null
+++ b/services/plots/current/app/src/agebd_plots/service.py
@@ -0,0 +1,286 @@
+import time
+
+import urllib3
+
+urllib3.disable_warnings()
+from datetime import datetime
+from time import sleep, strftime, time
+
+import elog
+import matplotlib.pyplot as plt
+import numpy as np
+from epics import PV
+from matplotlib.dates import DateFormatter, HourLocator
+
+from agebd.h5 import h5save
+from agebd.pv import get_pv_class, get_pv_external_class
+from agebd.service.base import BaseService
+from agebd.service.pvs import BasePVs
+from agebd.utils import printgetversion
+
+__version__ = printgetversion(__file__)
+
+PV = get_pv_class()
+PV_EXTERNAL = get_pv_external_class()
+
+plt.switch_backend("agg")
+plt.rcParams.update({"font.size": 18})
+plt.rcParams["axes.facecolor"] = "white"
+plt.rcParams["figure.facecolor"] = "white"
+plt.rcParams["lines.markersize"] = 1
+plt.rcParams["lines.linewidth"] = 0.2
+plt.rcParams["agg.path.chunksize"] = 20000
+
+
+class PVs(BasePVs):
+ light_delivery = PV_EXTERNAL("AGEOP-STATUS:LIGHT-DELIVERY.VAL")
+ shift_type = PV_EXTERNAL("AGEOP-STATUS:DUO-SHIFT-TYPE.VAL")
+
+ # fmt: off
+ buffers_shift = {
+ 'ARS07-DPCT-0000:CURR' : PV('AGEBD-PLOTS:CURRENT-PCT-9h-BUFFER'),
+ 'AGEBD-DBPM3CURR:CURRENT-AVG' : PV('AGEBD-PLOTS:CURRENT-BPM-9h-BUFFER'),
+ 'AGEBD-PARAMS:CURRENT' : PV('AGEBD-PLOTS:CURRENT-9h-BUFFER'),
+ 'AGEBD-PARAMS:INJECTION-RATE' : PV('AGEBD-PLOTS:INJECTION-RATE-9h-BUFFER'),
+ 'AGEBD-PARAMS:TRANSMISSION' : PV('AGEBD-PLOTS:TRANSMISSION-9h-BUFFER'),
+ 'AGEBD-PARAMS:LIFETIME' : PV('AGEBD-PLOTS:LIFETIME-9h-BUFFER'),
+ 'ARIVA-VMAVE:PRESS-AVE' : PV('AGEBD-PLOTS:MAVAC-AVG-9h-BUFFER'),
+ 'ARIVA-VMAVE:PRESS-MAX' : PV('AGEBD-PLOTS:MAVAC-MAX-9h-BUFFER'),
+ 'ARIVA-VMAVE-FE:PRESS-AVE' : PV('AGEBD-PLOTS:FEVAC-AVG-9h-BUFFER'),
+ 'ARIVA-VMAVE-FE:PRESS-MAX' : PV('AGEBD-PLOTS:FEVAC-MAX-9h-BUFFER'),
+ 'ABRTL-DDRM-0670:FET1_BIAS_DOSE' : PV('AGEBD-PLOTS:ABRTL-DDRM-0670-9h-BUFFER'),
+ 'ABRTL-DDRM-0950:FET1_BIAS_DOSE' : PV('AGEBD-PLOTS:ABRTL-DDRM-0950-9h-BUFFER'),
+ 'X05LA-DDRM-0330:FET1_BIAS_DOSE' : PV('AGEBD-PLOTS:X05LA-DDRM-0330-9h-BUFFER'),
+ 'X05LA-DDRM-0650:FET1_BIAS_DOSE' : PV('AGEBD-PLOTS:X05LA-DDRM-0650-9h-BUFFER'),
+ 'X09LA-DDRM-0330:FET1_BIAS_DOSE' : PV('AGEBD-PLOTS:X09LA-DDRM-0330-9h-BUFFER'),
+ 'X09LA-DDRM-0790:FET1_BIAS_DOSE' : PV('AGEBD-PLOTS:X09LA-DDRM-0790-9h-BUFFER'),
+ 'ARS01-DDRM-0375:FET1_BIAS_DOSE' : PV('AGEBD-PLOTS:ARS01-DDRM-0375-9h-BUFFER'),
+ 'ARS01-DDRM-1530:FET1_BIAS_DOSE' : PV('AGEBD-PLOTS:ARS01-DDRM-1530-9h-BUFFER'),
+ 'ARS05-DDRM-1530:FET1_BIAS_DOSE' : PV('AGEBD-PLOTS:ARS05-DDRM-1530-9h-BUFFER'),
+ 'ARS05-DDRM-3500:FET1_BIAS_DOSE' : PV('AGEBD-PLOTS:ARS05-DDRM-3500-9h-BUFFER'),
+ 'ARS09-DDRM-1530:FET1_BIAS_DOSE' : PV('AGEBD-PLOTS:ARS09-DDRM-1530-9h-BUFFER'),
+ 'ARS09-DDRM-3500:FET1_BIAS_DOSE' : PV('AGEBD-PLOTS:ARS09-DDRM-3500-9h-BUFFER'),
+ 'ARS12-DDRM-1530:FET1_BIAS_DOSE' : PV('AGEBD-PLOTS:ARS12-DDRM-1530-9h-BUFFER'),
+ 'ARS12-DDRM-3500:FET1_BIAS_DOSE' : PV('AGEBD-PLOTS:ARS12-DDRM-3500-9h-BUFFER'),
+ 'ARS12-DDRM-4400:FET1_BIAS_DOSE' : PV('AGEBD-PLOTS:ARS12-DDRM-4400-9h-BUFFER'),
+ 'ARS12-DDRM-5480:FET1_BIAS_DOSE' : PV('AGEBD-PLOTS:ARS12-DDRM-5480-9h-BUFFER'),
+ 'X04SA-UIND:GAP-READ' : PV('AGEBD-PLOTS:X04SA-UIND-GAP-9h-BUFFER'),
+ 'X10SA-UIND:GAP-READ' : PV('AGEBD-PLOTS:X10SA-UIND-GAP-9h-BUFFER'),
+ 'X12SA-UIND:GAP-READ' : PV('AGEBD-PLOTS:X12SA-UIND-GAP-9h-BUFFER'),
+ }
+
+ buffers_week = {
+ 'AGEBD-DBPM3CURR:CURRENT-AVG' : PV('AGEBD-PLOTS:CURRENT-BPM-168h-BUFFER'),
+ 'ARS07-DPCT-0000:CURR' : PV('AGEBD-PLOTS:CURRENT-PCT-168h-BUFFER'),
+ 'AGEBD-TAUBPM:TAU' : PV('AGEBD-PLOTS:TAU-BPM-168h-BUFFER'),
+ 'AGEBD-TAUPCT:TAU' : PV('AGEBD-PLOTS:TAU-PCT-168h-BUFFER'),
+ 'AGEBD-SCRUBBING:TOPUP-TAU' : PV('AGEBD-PLOTS:TAU-TOPUP-168h-BUFFER'),
+ 'AGEBD-TAUBPM:INJRATE' : PV('AGEBD-PLOTS:INJRATE-BPM-168h-BUFFER'),
+ 'AGEBD-TAUPCT:INJRATE' : PV('AGEBD-PLOTS:INJRATE-PCT-168h-BUFFER'),
+ 'ARIVA-VMAVE:PRESS-AVE' : PV('AGEBD-PLOTS:MAVAC-AVG-168h-BUFFER'),
+ 'ARIVA-VMAVE:PRESS-MAX' : PV('AGEBD-PLOTS:MAVAC-MAX-168h-BUFFER'),
+ 'ARIVA-VMAVE-FE:PRESS-AVE' : PV('AGEBD-PLOTS:FEVAC-AVG-168h-BUFFER'),
+ 'ARIVA-VMAVE-FE:PRESS-MAX' : PV('AGEBD-PLOTS:FEVAC-MAX-168h-BUFFER'),
+ }
+ # fmt: on
+
+ def __init__(self, service_name: str, pv_factory=PV):
+ super().__init__(service_name, pv_factory)
+
+
+class Service(BaseService[PVs]):
+ def __init__(
+ self,
+ name: str,
+ pvs: PVs,
+ version: str = __version__,
+ sleep_interval: float = 0.01,
+ ):
+ super().__init__(name, pvs, version, sleep_interval)
+
+ self.path_shift = "/sls/op/data/applications/plots_shift/"
+ self.path_weekly = "/sls/op/data/applications/plots_weekly/"
+ self.lastshiftplot = -1
+ self.lastweekplot = -1
+ self.logbook = elog.open(
+ "https://elog-gfa.psi.ch/SLS/",
+ user="robot",
+ password="robot",
+ use_ssl=True,
+ )
+
+ def update(self):
+ pvs = self.pvs
+
+ dtn = datetime.now()
+ minute = dtn.minute
+ hour = dtn.hour
+ weekday = dtn.weekday()
+ day = dtn.day
+ shift_type = pvs.shift_type.get()
+
+ # shift plots
+ if hour in [6, 14, 22] and minute == 30 and hour != self.lastshiftplot:
+ self.lastshiftplot = hour
+
+ print("Preparing shift plots...")
+ print(" ... fetching data")
+
+ data = {pv: pvs.buffers_shift[pv].get() for pv in pvs.buffers_shift}
+ Npts = len(data["ARS07-DPCT-0000:CURR"])
+ tf = int(pvs.buffers_shift["ARS07-DPCT-0000:CURR"].timestamp)
+ timevec = np.array(
+ [datetime.fromtimestamp(t) for t in np.linspace(tf - Npts - 1, tf, Npts)]
+ )
+ data.update({"time": np.array([np.datetime64(t) for t in timevec], dtype="S30")})
+
+ print(" ...saving data")
+ h5save(self.path_shift + "ShiftPlotSLS", data)
+ print(" ...data saved")
+
+ print(" ...preparing plots")
+ Nplots = 1
+ fig = plt.figure(figsize=(16, 9 * Nplots), constrained_layout=True)
+
+ ax = fig.add_subplot(Nplots, 1, 1)
+ ax.plot(timevec, data["ARS07-DPCT-0000:CURR"], "-xg", label="ARS07-DPCT-0000:CURR")
+ ax.tick_params(axis="y", colors="g", which="both")
+ lgnd = ax.legend(loc="lower left", bbox_to_anchor=(0.07, 1))
+ for handle in lgnd.legendHandles:
+ handle._markersize = 7
+ handle._linewidth = 2
+ ax.set_ylabel("Beam current / mA", color="g")
+ ax.set_ylim([-1, 410])
+ ax.set_xlim([timevec[0], timevec[-1]])
+
+ ax = ax.twinx()
+ ax.plot(
+ timevec,
+ data["AGEBD-PARAMS:LIFETIME"],
+ "-xb",
+ label="AGEBD-PARAMS:LIFETIME",
+ alpha=0.5,
+ )
+ ax.tick_params(axis="y", colors="b", which="both")
+ lgnd = ax.legend(loc="lower right", bbox_to_anchor=(0.93, 1))
+ for handle in lgnd.legendHandles:
+ handle._markersize = 7
+ handle._linewidth = 2
+ ax.set_ylabel("Beam lifetime / hours", color="b")
+ ax.set_ylim([-0.1, 41])
+ ax.set_xlim([timevec[0], timevec[-1]])
+ ax.set_xlabel("Time")
+ # Set major ticks every hour and format as HH:MM
+ ax.xaxis.set_major_locator(HourLocator())
+ ax.xaxis.set_major_formatter(DateFormatter("%H:%M"))
+ ax.grid(axis="both")
+
+ print(" ...saving plots")
+ file1 = self.path_shift + strftime("%Y%m%d%H%M%S") + "_ShiftPlotSLS.png"
+ fig.savefig(file1, dpi=192, bbox_inches="tight")
+ plt.close(fig)
+ print(" ...saved")
+
+ if shift_type > 0:
+ print(" ...preparing elog entry...")
+ dict_of_attributes = {
+ "Wann": time(),
+ "Autor": "Plots Logger",
+ "Eintrag": "Status",
+ "Titel": "Plots for last shift",
+ "Encoding": "html",
+ }
+ self.msg_id = self.logbook.post(
+ "",
+ attributes=dict_of_attributes,
+ attachments=[file1],
+ suppress_email_notification=True,
+ attribute_as_param="value",
+ )
+ print(" ...elog entry submitted...")
+
+ # weekly plots
+ if weekday == 2 and hour == 7 and day != self.lastweekplot:
+ self.lastweekplot = day
+
+ print("Preparing weekly plots...")
+ print(" ... fetching data")
+
+ data = {pv: pvs.buffers_week[pv].get() for pv in pvs.buffers_week}
+ Npts = len(data["AGEBD-DBPM3CURR:CURRENT-AVG"])
+ tf = int(pvs.buffers_week["AGEBD-DBPM3CURR:CURRENT-AVG"].timestamp)
+ timevec = np.array(
+ [datetime.fromtimestamp(t) for t in np.linspace(tf - Npts - 1, tf, Npts)]
+ )
+ data.update({"time": np.array([np.datetime64(t) for t in timevec], dtype="S30")})
+
+ print(" ...saving data")
+ h5save(self.path_weekly + "WeeklyPlotSLS", data)
+ print(" ...data saved")
+
+ print(" ...preparing plots")
+ Nplots = 1
+ fig = plt.figure(figsize=(16, 9 * Nplots), constrained_layout=True)
+
+ ax = fig.add_subplot(Nplots, 1, 1)
+ ax.plot(timevec, data["ARS07-DPCT-0000:CURR"], "-xg", label="ARS07-DPCT-0000:CURR")
+ ax.tick_params(axis="y", colors="g", which="both")
+ lgnd = ax.legend(loc="lower left", bbox_to_anchor=(0.07, 1))
+ for handle in lgnd.legendHandles:
+ handle._markersize = 7
+ handle._linewidth = 2
+ ax.set_ylabel("Beam current / mA", color="g")
+ ax.set_ylim([-1, 410])
+ ax.set_xlim([timevec[0], timevec[-1]])
+
+ ax = ax.twinx()
+ ax.plot(timevec, data["AGEBD-TAUBPM:TAU"], "-xb", label="AGEBD-TAUBPM:TAU", alpha=0.5)
+ ax.tick_params(axis="y", colors="b", which="both")
+ lgnd = ax.legend(loc="lower right", bbox_to_anchor=(0.93, 1))
+ for handle in lgnd.legendHandles:
+ handle._markersize = 7
+ handle._linewidth = 2
+ ax.set_ylabel("Beam lifetime / hours", color="b")
+ ax.set_ylim([-0.1, 41])
+ ax.set_xlim([timevec[0], timevec[-1]])
+ ax.xaxis.set_major_locator(HourLocator(byhour=12))
+ ax.xaxis.set_major_formatter(DateFormatter("%a %H:%M"))
+ ax.set_xlabel("Time")
+ ax.grid(axis="both")
+
+ print(" ...saving plots")
+ file2 = self.path_weekly + strftime("%Y%m%d%H%M%S") + "_WeeklyPlotSLS.png"
+ fig.savefig(file2, dpi=192, bbox_inches="tight")
+ plt.close(fig)
+ print(" ...finished")
+
+ if shift_type > 0:
+ print(" ...preparing elog entry...")
+ dict_of_attributes = {
+ "Wann": time(),
+ "Autor": "Plots Logger",
+ "Eintrag": "Status",
+ "Titel": "Plots for last week",
+ "Encoding": "html",
+ }
+
+ print(" ...posting elog entry...")
+ try:
+ self.msg_id = self.logbook.post(
+ "",
+ attributes=dict_of_attributes,
+ attachments=[file2],
+ suppress_email_notification=True,
+ attribute_as_param="value",
+ )
+ print(" ...elog entry submitted...")
+ except:
+ print(" ...elog failed...")
+
+ else:
+ print(" ...no elog entry during shutdown.")
+
+ print(" ...setting all beamlines to offline")
+ pvs.light_delivery.put(1)
+ sleep(0.1)
+ pvs.light_delivery.put(0)
diff --git a/services/plots/current/app/tests/test_app.py b/services/plots/current/app/tests/test_app.py
new file mode 100644
index 0000000..842d66f
--- /dev/null
+++ b/services/plots/current/app/tests/test_app.py
@@ -0,0 +1,9 @@
+from agebd_plots import PVs, Service
+
+
+def test_app():
+ service_name = "DUMMY"
+ pvs = PVs(service_name=service_name)
+ service = Service(name=service_name, pvs=pvs)
+ service.CallbackFired = 1
+ service.update()
diff --git a/services/plots/current/app/uv.lock b/services/plots/current/app/uv.lock
new file mode 100644
index 0000000..ecd97cf
--- /dev/null
+++ b/services/plots/current/app/uv.lock
@@ -0,0 +1,454 @@
+version = 1
+revision = 3
+requires-python = "==3.10.*"
+
+[[package]]
+name = "agebd"
+version = "0.1.0"
+source = { editable = "../../../../packages/agebd" }
+dependencies = [
+ { name = "h5py" },
+ { name = "typer" },
+]
+
+[package.metadata]
+requires-dist = [
+ { name = "h5py", specifier = ">=3.16.0" },
+ { name = "typer", specifier = ">=0.23.2" },
+]
+
+[package.metadata.requires-dev]
+dev = [
+ { name = "pyright", specifier = ">=1.1.410" },
+ { name = "pytest", specifier = ">=8.4.2" },
+ { name = "ruff", specifier = ">=0.15.19" },
+]
+
+[[package]]
+name = "agebd-plots"
+version = "0.1.0"
+source = { editable = "." }
+dependencies = [
+ { name = "agebd" },
+ { name = "matplotlib" },
+ { name = "urllib3" },
+]
+
+[package.dev-dependencies]
+dev = [
+ { name = "pyepics" },
+ { name = "pytest" },
+ { name = "ruff" },
+]
+
+[package.metadata]
+requires-dist = [
+ { name = "agebd", editable = "../../../../packages/agebd" },
+ { name = "matplotlib", specifier = ">=3.10.9" },
+ { name = "urllib3", specifier = ">=2.7.0" },
+]
+
+[package.metadata.requires-dev]
+dev = [
+ { name = "pyepics", specifier = ">=3.5.8" },
+ { name = "pytest", specifier = ">=8.4.2" },
+ { name = "ruff", specifier = ">=0.15.20" },
+]
+
+[[package]]
+name = "annotated-doc"
+version = "0.0.4"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/57/ba/046ceea27344560984e26a590f90bc7f4a75b06701f653222458922b558c/annotated_doc-0.0.4.tar.gz", hash = "sha256:fbcda96e87e9c92ad167c2e53839e57503ecfda18804ea28102353485033faa4", size = 7288, upload-time = "2025-11-10T22:07:42.062Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl", hash = "sha256:571ac1dc6991c450b25a9c2d84a3705e2ae7a53467b5d111c24fa8baabbed320", size = 5303, upload-time = "2025-11-10T22:07:40.673Z" },
+]
+
+[[package]]
+name = "colorama"
+version = "0.4.6"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" },
+]
+
+[[package]]
+name = "contourpy"
+version = "1.3.2"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "numpy" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/66/54/eb9bfc647b19f2009dd5c7f5ec51c4e6ca831725f1aea7a993034f483147/contourpy-1.3.2.tar.gz", hash = "sha256:b6945942715a034c671b7fc54f9588126b0b8bf23db2696e3ca8328f3ff0ab54", size = 13466130, upload-time = "2025-04-15T17:47:53.79Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/12/a3/da4153ec8fe25d263aa48c1a4cbde7f49b59af86f0b6f7862788c60da737/contourpy-1.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ba38e3f9f330af820c4b27ceb4b9c7feee5fe0493ea53a8720f4792667465934", size = 268551, upload-time = "2025-04-15T17:34:46.581Z" },
+ { url = "https://files.pythonhosted.org/packages/2f/6c/330de89ae1087eb622bfca0177d32a7ece50c3ef07b28002de4757d9d875/contourpy-1.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:dc41ba0714aa2968d1f8674ec97504a8f7e334f48eeacebcaa6256213acb0989", size = 253399, upload-time = "2025-04-15T17:34:51.427Z" },
+ { url = "https://files.pythonhosted.org/packages/c1/bd/20c6726b1b7f81a8bee5271bed5c165f0a8e1f572578a9d27e2ccb763cb2/contourpy-1.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9be002b31c558d1ddf1b9b415b162c603405414bacd6932d031c5b5a8b757f0d", size = 312061, upload-time = "2025-04-15T17:34:55.961Z" },
+ { url = "https://files.pythonhosted.org/packages/22/fc/a9665c88f8a2473f823cf1ec601de9e5375050f1958cbb356cdf06ef1ab6/contourpy-1.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8d2e74acbcba3bfdb6d9d8384cdc4f9260cae86ed9beee8bd5f54fee49a430b9", size = 351956, upload-time = "2025-04-15T17:35:00.992Z" },
+ { url = "https://files.pythonhosted.org/packages/25/eb/9f0a0238f305ad8fb7ef42481020d6e20cf15e46be99a1fcf939546a177e/contourpy-1.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e259bced5549ac64410162adc973c5e2fb77f04df4a439d00b478e57a0e65512", size = 320872, upload-time = "2025-04-15T17:35:06.177Z" },
+ { url = "https://files.pythonhosted.org/packages/32/5c/1ee32d1c7956923202f00cf8d2a14a62ed7517bdc0ee1e55301227fc273c/contourpy-1.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad687a04bc802cbe8b9c399c07162a3c35e227e2daccf1668eb1f278cb698631", size = 325027, upload-time = "2025-04-15T17:35:11.244Z" },
+ { url = "https://files.pythonhosted.org/packages/83/bf/9baed89785ba743ef329c2b07fd0611d12bfecbedbdd3eeecf929d8d3b52/contourpy-1.3.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:cdd22595308f53ef2f891040ab2b93d79192513ffccbd7fe19be7aa773a5e09f", size = 1306641, upload-time = "2025-04-15T17:35:26.701Z" },
+ { url = "https://files.pythonhosted.org/packages/d4/cc/74e5e83d1e35de2d28bd97033426b450bc4fd96e092a1f7a63dc7369b55d/contourpy-1.3.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b4f54d6a2defe9f257327b0f243612dd051cc43825587520b1bf74a31e2f6ef2", size = 1374075, upload-time = "2025-04-15T17:35:43.204Z" },
+ { url = "https://files.pythonhosted.org/packages/0c/42/17f3b798fd5e033b46a16f8d9fcb39f1aba051307f5ebf441bad1ecf78f8/contourpy-1.3.2-cp310-cp310-win32.whl", hash = "sha256:f939a054192ddc596e031e50bb13b657ce318cf13d264f095ce9db7dc6ae81c0", size = 177534, upload-time = "2025-04-15T17:35:46.554Z" },
+ { url = "https://files.pythonhosted.org/packages/54/ec/5162b8582f2c994721018d0c9ece9dc6ff769d298a8ac6b6a652c307e7df/contourpy-1.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:c440093bbc8fc21c637c03bafcbef95ccd963bc6e0514ad887932c18ca2a759a", size = 221188, upload-time = "2025-04-15T17:35:50.064Z" },
+ { url = "https://files.pythonhosted.org/packages/33/05/b26e3c6ecc05f349ee0013f0bb850a761016d89cec528a98193a48c34033/contourpy-1.3.2-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:fd93cc7f3139b6dd7aab2f26a90dde0aa9fc264dbf70f6740d498a70b860b82c", size = 265681, upload-time = "2025-04-15T17:44:59.314Z" },
+ { url = "https://files.pythonhosted.org/packages/2b/25/ac07d6ad12affa7d1ffed11b77417d0a6308170f44ff20fa1d5aa6333f03/contourpy-1.3.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:107ba8a6a7eec58bb475329e6d3b95deba9440667c4d62b9b6063942b61d7f16", size = 315101, upload-time = "2025-04-15T17:45:04.165Z" },
+ { url = "https://files.pythonhosted.org/packages/8f/4d/5bb3192bbe9d3f27e3061a6a8e7733c9120e203cb8515767d30973f71030/contourpy-1.3.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:ded1706ed0c1049224531b81128efbd5084598f18d8a2d9efae833edbd2b40ad", size = 220599, upload-time = "2025-04-15T17:45:08.456Z" },
+]
+
+[[package]]
+name = "cycler"
+version = "0.12.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/a9/95/a3dbbb5028f35eafb79008e7522a75244477d2838f38cbb722248dabc2a8/cycler-0.12.1.tar.gz", hash = "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c", size = 7615, upload-time = "2023-10-07T05:32:18.335Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30", size = 8321, upload-time = "2023-10-07T05:32:16.783Z" },
+]
+
+[[package]]
+name = "exceptiongroup"
+version = "1.3.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "typing-extensions" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" },
+]
+
+[[package]]
+name = "fonttools"
+version = "4.63.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/84/69/c97f2c18e0db87d2c7b15da1974dace76ae938f1cfa22e2727a648b7ed43/fonttools-4.63.0.tar.gz", hash = "sha256:caeb583deeb5168e694b65cda8b4ee62abedfa66cf88488734466f2366b9c4e0", size = 3597189, upload-time = "2026-05-14T12:04:30.958Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/f2/c9/4141c90a90db20f807c7e10bfd689fe53eb8f7f4caff58ee4d4dfe46919f/fonttools-4.63.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e3297a6a4059b4acc3a1e9a8b04741f240a80044eef08ebd32e8b5bcdddce75b", size = 2884632, upload-time = "2026-05-14T12:02:38.56Z" },
+ { url = "https://files.pythonhosted.org/packages/b8/46/ad12b5c10eae602d7ef814b02afa08aacbf89da917fed5b071282b7eadc2/fonttools-4.63.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b1cd75a03ad8cb5bc40c90bfde68c0c47de423aa19e5c0f362b43520645eea94", size = 2429441, upload-time = "2026-05-14T12:02:41.162Z" },
+ { url = "https://files.pythonhosted.org/packages/90/8f/bdca24a84c81d56fffed052229cdcff368f6e05882e526f4558891481f65/fonttools-4.63.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c0425b277a59cff3d80ca42162a8de360f318438a2ac83570842a678d826d579", size = 4946346, upload-time = "2026-05-14T12:02:43.41Z" },
+ { url = "https://files.pythonhosted.org/packages/04/59/a639c0e136441ee91a65b56fdf89e5d075927e7a09c559d1b0f5276577db/fonttools-4.63.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d7e5c9973aa04c95650c96e5f5ad865fbf42d62079163ecfab1e01cbc2504c22", size = 4903184, upload-time = "2026-05-14T12:02:45.742Z" },
+ { url = "https://files.pythonhosted.org/packages/e6/53/91b7e0cb45b536f3da1b29ba8cbab89f27e8b986809e0b1982303a3f4eca/fonttools-4.63.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:cb014d58140a38135f16064c74c652ed57aa0b75cbf8bb59cac821f7edb5334e", size = 4922967, upload-time = "2026-05-14T12:02:48.386Z" },
+ { url = "https://files.pythonhosted.org/packages/c7/b7/87439bf44e6b97c5538cd29d0b7e366a5b8ce2cc132a4134fb67fa3f2fa2/fonttools-4.63.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:032038247a96c1690f9f31e377c389383c902531b085aa4e4dabd6f57f870e69", size = 5042799, upload-time = "2026-05-14T12:02:50.424Z" },
+ { url = "https://files.pythonhosted.org/packages/ad/7c/8b96c3263b89ef99cded544c0f0636686f85dbd3c211c4dceef0231fca23/fonttools-4.63.0-cp310-cp310-win32.whl", hash = "sha256:a8b33a82979e0a6a34ff435cc81317be1f95ec1ebb7a3a2d1c8a6a54f02ae44e", size = 1519704, upload-time = "2026-05-14T12:02:52.523Z" },
+ { url = "https://files.pythonhosted.org/packages/e5/4d/2c2f0069970b6907de8fb5b05c5c0193cc22f717df151d1c7aef1c738f58/fonttools-4.63.0-cp310-cp310-win_amd64.whl", hash = "sha256:0c18358a155d75034911c5ee397a5b44cd19dd325dbb8b35fb60bf421d6a72ac", size = 1568666, upload-time = "2026-05-14T12:02:54.917Z" },
+ { url = "https://files.pythonhosted.org/packages/2c/47/c99d5268f354002ce80f8d029cd9d7d872969da1de8b93d32de4dc56d6f4/fonttools-4.63.0-py3-none-any.whl", hash = "sha256:445af2eab030a16b9171ea8bdda7ebf7d96bda2df88ee182a464252f6e05e20d", size = 1164562, upload-time = "2026-05-14T12:04:29.092Z" },
+]
+
+[[package]]
+name = "h5py"
+version = "3.16.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "numpy" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/db/33/acd0ce6863b6c0d7735007df01815403f5589a21ff8c2e1ee2587a38f548/h5py-3.16.0.tar.gz", hash = "sha256:a0dbaad796840ccaa67a4c144a0d0c8080073c34c76d5a6941d6818678ef2738", size = 446526, upload-time = "2026-03-06T13:49:08.07Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/3a/6b/231413e58a787a89b316bb0d1777da3c62257e4797e09afd8d17ad3549dc/h5py-3.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e06f864bedb2c8e7c1358e6c73af48519e317457c444d6f3d332bb4e8fa6d7d9", size = 3724137, upload-time = "2026-03-06T13:47:35.242Z" },
+ { url = "https://files.pythonhosted.org/packages/74/f9/557ce3aad0fe8471fb5279bab0fc56ea473858a022c4ce8a0b8f303d64e9/h5py-3.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ec86d4fffd87a0f4cb3d5796ceb5a50123a2a6d99b43e616e5504e66a953eca3", size = 3090112, upload-time = "2026-03-06T13:47:37.634Z" },
+ { url = "https://files.pythonhosted.org/packages/7a/f5/e15b3d0dc8a18e56409a839e6468d6fb589bc5207c917399c2e0706eeb44/h5py-3.16.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:86385ea895508220b8a7e45efa428aeafaa586bd737c7af9ee04661d8d84a10d", size = 4844847, upload-time = "2026-03-06T13:47:39.811Z" },
+ { url = "https://files.pythonhosted.org/packages/cb/92/a8851d936547efe30cc0ce5245feac01f3ec6171f7899bc3f775c72030b3/h5py-3.16.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:8975273c2c5921c25700193b408e28d6bdd0111c37468b2d4e25dcec4cd1d84d", size = 5065352, upload-time = "2026-03-06T13:47:41.489Z" },
+ { url = "https://files.pythonhosted.org/packages/2b/ae/f2adc5d0ca9626db3277a3d87516e124cbc5d0eea0bd79bc085702d04f2c/h5py-3.16.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:1677ad48b703f44efc9ea0c3ab284527f81bc4f318386aaaebc5fede6bbae56f", size = 4839173, upload-time = "2026-03-06T13:47:43.586Z" },
+ { url = "https://files.pythonhosted.org/packages/64/0b/e0c8c69da1d8838da023a50cd3080eae5d475691f7636b35eff20bb6ef20/h5py-3.16.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7c4dd4cf5f0a4e36083f73172f6cfc25a5710789269547f132a20975bfe2434c", size = 5076216, upload-time = "2026-03-06T13:47:45.315Z" },
+ { url = "https://files.pythonhosted.org/packages/66/35/d88fd6718832133c885004c61ceeeb24dbd6397ef877dbed6b3a64d6a286/h5py-3.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:bdef06507725b455fccba9c16529121a5e1fbf56aa375f7d9713d9e8ff42454d", size = 3183639, upload-time = "2026-03-06T13:47:47.041Z" },
+]
+
+[[package]]
+name = "iniconfig"
+version = "2.3.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" },
+]
+
+[[package]]
+name = "kiwisolver"
+version = "1.5.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d0/67/9c61eccb13f0bdca9307614e782fec49ffdde0f7a2314935d489fa93cd9c/kiwisolver-1.5.0.tar.gz", hash = "sha256:d4193f3d9dc3f6f79aaed0e5637f45d98850ebf01f7ca20e69457f3e8946b66a", size = 103482, upload-time = "2026-03-09T13:15:53.382Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/ac/f8/06549565caa026e540b7e7bab5c5a90eb7ca986015f4c48dace243cd24d9/kiwisolver-1.5.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:32cc0a5365239a6ea0c6ed461e8838d053b57e397443c0ca894dcc8e388d4374", size = 122802, upload-time = "2026-03-09T13:12:37.515Z" },
+ { url = "https://files.pythonhosted.org/packages/84/eb/8476a0818850c563ff343ea7c9c05dcdcbd689a38e01aa31657df01f91fa/kiwisolver-1.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:cc0b66c1eec9021353a4b4483afb12dfd50e3669ffbb9152d6842eb34c7e29fd", size = 66216, upload-time = "2026-03-09T13:12:38.812Z" },
+ { url = "https://files.pythonhosted.org/packages/f3/c4/f9c8a6b4c21aed4198566e45923512986d6cef530e7263b3a5f823546561/kiwisolver-1.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:86e0287879f75621ae85197b0877ed2f8b7aa57b511c7331dce2eb6f4de7d476", size = 63917, upload-time = "2026-03-09T13:12:40.053Z" },
+ { url = "https://files.pythonhosted.org/packages/f1/0e/ba4ae25d03722f64de8b2c13e80d82ab537a06b30fc7065183c6439357e3/kiwisolver-1.5.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:62f59da443c4f4849f73a51a193b1d9d258dcad0c41bc4d1b8fb2bcc04bfeb22", size = 1628776, upload-time = "2026-03-09T13:12:41.976Z" },
+ { url = "https://files.pythonhosted.org/packages/8a/e4/3f43a011bc8a0860d1c96f84d32fa87439d3feedf66e672fef03bf5e8bac/kiwisolver-1.5.0-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9190426b7aa26c5229501fa297b8d0653cfd3f5a36f7990c264e157cbf886b3b", size = 1228164, upload-time = "2026-03-09T13:12:44.002Z" },
+ { url = "https://files.pythonhosted.org/packages/4b/34/3a901559a1e0c218404f9a61a93be82d45cb8f44453ba43088644980f033/kiwisolver-1.5.0-cp310-cp310-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c8277104ded0a51e699c8c3aff63ce2c56d4ed5519a5f73e0fd7057f959a2b9e", size = 1246656, upload-time = "2026-03-09T13:12:45.557Z" },
+ { url = "https://files.pythonhosted.org/packages/87/9e/f78c466ea20527822b95ad38f141f2de1dcd7f23fb8716b002b0d91bbe59/kiwisolver-1.5.0-cp310-cp310-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8f9baf6f0a6e7571c45c8863010b45e837c3ee1c2c77fcd6ef423be91b21fedb", size = 1295562, upload-time = "2026-03-09T13:12:47.562Z" },
+ { url = "https://files.pythonhosted.org/packages/0a/66/fd0e4a612e3a286c24e6d6f3a5428d11258ed1909bc530ba3b59807fd980/kiwisolver-1.5.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:cff8e5383db4989311f99e814feeb90c4723eb4edca425b9d5d9c3fefcdd9537", size = 2178473, upload-time = "2026-03-09T13:12:50.254Z" },
+ { url = "https://files.pythonhosted.org/packages/dc/8e/6cac929e0049539e5ee25c1ee937556f379ba5204840d03008363ced662d/kiwisolver-1.5.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:ebae99ed6764f2b5771c522477b311be313e8841d2e0376db2b10922daebbba4", size = 2274035, upload-time = "2026-03-09T13:12:51.785Z" },
+ { url = "https://files.pythonhosted.org/packages/ca/d3/9d0c18f1b52ea8074b792452cf17f1f5a56bd0302a85191f405cfbf9da16/kiwisolver-1.5.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:d5cd5189fc2b6a538b75ae45433140c4823463918f7b1617c31e68b085c0022c", size = 2443217, upload-time = "2026-03-09T13:12:53.329Z" },
+ { url = "https://files.pythonhosted.org/packages/45/2a/6e19368803a038b2a90857bf4ee9e3c7b667216d045866bf22d3439fd75e/kiwisolver-1.5.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f42c23db5d1521218a3276bb08666dcb662896a0be7347cba864eca45ff64ede", size = 2249196, upload-time = "2026-03-09T13:12:55.057Z" },
+ { url = "https://files.pythonhosted.org/packages/75/2b/3f641dfcbe72e222175d626bacf2f72c3b34312afec949dd1c50afa400f5/kiwisolver-1.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:94eff26096eb5395136634622515b234ecb6c9979824c1f5004c6e3c3c85ccd2", size = 73389, upload-time = "2026-03-09T13:12:56.496Z" },
+ { url = "https://files.pythonhosted.org/packages/da/88/299b137b9e0025d8982e03d2d52c123b0a2b159e84b0ef1501ef446339cf/kiwisolver-1.5.0-cp310-cp310-win_arm64.whl", hash = "sha256:dd952e03bfbb096cfe2dd35cd9e00f269969b67536cb4370994afc20ff2d0875", size = 64782, upload-time = "2026-03-09T13:12:57.609Z" },
+ { url = "https://files.pythonhosted.org/packages/17/6f/6fd4f690a40c2582fa34b97d2678f718acf3706b91d270c65ecb455d0a06/kiwisolver-1.5.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:295d9ffe712caa9f8a3081de8d32fc60191b4b51c76f02f951fd8407253528f4", size = 59606, upload-time = "2026-03-09T13:15:40.81Z" },
+ { url = "https://files.pythonhosted.org/packages/82/a0/2355d5e3b338f13ce63f361abb181e3b6ea5fffdb73f739b3e80efa76159/kiwisolver-1.5.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:51e8c4084897de9f05898c2c2a39af6318044ae969d46ff7a34ed3f96274adca", size = 57537, upload-time = "2026-03-09T13:15:42.071Z" },
+ { url = "https://files.pythonhosted.org/packages/c8/b9/1d50e610ecadebe205b71d6728fd224ce0e0ca6aba7b9cbe1da049203ac5/kiwisolver-1.5.0-pp310-pypy310_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b83af57bdddef03c01a9138034c6ff03181a3028d9a1003b301eb1a55e161a3f", size = 79888, upload-time = "2026-03-09T13:15:43.317Z" },
+ { url = "https://files.pythonhosted.org/packages/cd/ee/b85ffcd75afed0357d74f0e6fc02a4507da441165de1ca4760b9f496390d/kiwisolver-1.5.0-pp310-pypy310_pp73-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bf4679a3d71012a7c2bf360e5cd878fbd5e4fcac0896b56393dec239d81529ed", size = 77584, upload-time = "2026-03-09T13:15:44.605Z" },
+ { url = "https://files.pythonhosted.org/packages/6b/dd/644d0dde6010a8583b4cd66dd41c5f83f5325464d15c4f490b3340ab73b4/kiwisolver-1.5.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:41024ed50e44ab1a60d3fe0a9d15a4ccc9f5f2b1d814ff283c8d01134d5b81bc", size = 73390, upload-time = "2026-03-09T13:15:45.832Z" },
+]
+
+[[package]]
+name = "markdown-it-py"
+version = "4.2.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "mdurl" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/06/ff/7841249c247aa650a76b9ee4bbaeae59370dc8bfd2f6c01f3630c35eb134/markdown_it_py-4.2.0.tar.gz", hash = "sha256:04a21681d6fbb623de53f6f364d352309d4094dd4194040a10fd51833e418d49", size = 82454, upload-time = "2026-05-07T12:08:28.36Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl", hash = "sha256:9f7ebbcd14fe59494226453aed97c1070d83f8d24b6fc3a3bcf9a38092641c4a", size = 91687, upload-time = "2026-05-07T12:08:27.182Z" },
+]
+
+[[package]]
+name = "matplotlib"
+version = "3.10.9"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "contourpy" },
+ { name = "cycler" },
+ { name = "fonttools" },
+ { name = "kiwisolver" },
+ { name = "numpy" },
+ { name = "packaging" },
+ { name = "pillow" },
+ { name = "pyparsing" },
+ { name = "python-dateutil" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/63/1b/4be5be87d43d327a0cf4de1a56e86f7f84c89312452406cf122efe2839e6/matplotlib-3.10.9.tar.gz", hash = "sha256:fd66508e8c6877d98e586654b608a0456db8d7e8a546eb1e2600efd957302358", size = 34811233, upload-time = "2026-04-24T00:14:13.539Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/18/6f/340b04986e67aac6f66c5145ce68bf72c64bed30f92c8913499a6e6b8f99/matplotlib-3.10.9-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:77210dce9cb8153dffc967efaae990543392563d5a376d4dd8539bebcb0ed217", size = 8296625, upload-time = "2026-04-24T00:11:43.376Z" },
+ { url = "https://files.pythonhosted.org/packages/bb/2f/127081eb83162053ebb9678ceac64220b93a663e0167432566e9c7c82aab/matplotlib-3.10.9-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1e7698ac9868428e84d2c967424803b2472ff7167d9d6590d4204ed775343c3b", size = 8188790, upload-time = "2026-04-24T00:11:46.556Z" },
+ { url = "https://files.pythonhosted.org/packages/fc/b7/d8bcec2626c35f96972bff656299fef4578113ea6193c8fdad324710410c/matplotlib-3.10.9-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1aa972116abb4c9d201bf245620b433726cb6856f3bef6a78f776a00f5c92d37", size = 8769389, upload-time = "2026-04-24T00:11:48.959Z" },
+ { url = "https://files.pythonhosted.org/packages/12/49/b78e214a527ea732033b7f4d37f7afb504d74ba9d134bd47938230dfb8b1/matplotlib-3.10.9-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ae2f11957b27ce53497dd4d7b235c4d4f1faf383dfb39d0c5beb833bff883294", size = 9589657, upload-time = "2026-04-24T00:11:51.915Z" },
+ { url = "https://files.pythonhosted.org/packages/5f/15/5246f7b43beae19c74dfee651d58d6cc8112e06f77adb4e88cc04f2e3a23/matplotlib-3.10.9-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b049278ddce116aaa1c1377ebf58adea909132dfce0281cf7e3a1ea9fc2e2c65", size = 9651983, upload-time = "2026-04-24T00:11:54.766Z" },
+ { url = "https://files.pythonhosted.org/packages/75/77/5acecfe672ba0fa1b8c0454f69ce155d1e6fc5852fa7206bf9afaf767121/matplotlib-3.10.9-cp310-cp310-win_amd64.whl", hash = "sha256:82834c3c292d24d3a8aae77cd2d20019de69d692a34a970e4fdb8d33e2ea3dda", size = 8199701, upload-time = "2026-04-24T00:11:58.389Z" },
+ { url = "https://files.pythonhosted.org/packages/2c/2b/0e92ad0ac446633f928a1563db4aa8add407e1924faf0ded5b95b35afb27/matplotlib-3.10.9-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:1872fb212a05b729e649754a72d5da61d03e0554d76e80303b6f83d1d2c0552b", size = 8293058, upload-time = "2026-04-24T00:13:56.339Z" },
+ { url = "https://files.pythonhosted.org/packages/4b/23/74682fd369f5299ceda438fea2a0662e6383b85c9383fb9cdfcf04713e07/matplotlib-3.10.9-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:985f2238880e2e69093f588f5fe2e46771747febf0649f3cf7f7b7480875317f", size = 8186627, upload-time = "2026-04-24T00:13:58.623Z" },
+ { url = "https://files.pythonhosted.org/packages/ca/e8/368aab88f3c4cd8992800f31abfe0670c3e47540ba20a97e9fdbcde594b3/matplotlib-3.10.9-pp310-pypy310_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:6640f75af2c6148293caa0a2b39dd806a492dd66c8a8b04035813e33d0fd2585", size = 8764117, upload-time = "2026-04-24T00:14:01.684Z" },
+]
+
+[[package]]
+name = "mdurl"
+version = "0.1.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" },
+]
+
+[[package]]
+name = "numpy"
+version = "2.2.6"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/76/21/7d2a95e4bba9dc13d043ee156a356c0a8f0c6309dff6b21b4d71a073b8a8/numpy-2.2.6.tar.gz", hash = "sha256:e29554e2bef54a90aa5cc07da6ce955accb83f21ab5de01a62c8478897b264fd", size = 20276440, upload-time = "2025-05-17T22:38:04.611Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/9a/3e/ed6db5be21ce87955c0cbd3009f2803f59fa08df21b5df06862e2d8e2bdd/numpy-2.2.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b412caa66f72040e6d268491a59f2c43bf03eb6c96dd8f0307829feb7fa2b6fb", size = 21165245, upload-time = "2025-05-17T21:27:58.555Z" },
+ { url = "https://files.pythonhosted.org/packages/22/c2/4b9221495b2a132cc9d2eb862e21d42a009f5a60e45fc44b00118c174bff/numpy-2.2.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e41fd67c52b86603a91c1a505ebaef50b3314de0213461c7a6e99c9a3beff90", size = 14360048, upload-time = "2025-05-17T21:28:21.406Z" },
+ { url = "https://files.pythonhosted.org/packages/fd/77/dc2fcfc66943c6410e2bf598062f5959372735ffda175b39906d54f02349/numpy-2.2.6-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:37e990a01ae6ec7fe7fa1c26c55ecb672dd98b19c3d0e1d1f326fa13cb38d163", size = 5340542, upload-time = "2025-05-17T21:28:30.931Z" },
+ { url = "https://files.pythonhosted.org/packages/7a/4f/1cb5fdc353a5f5cc7feb692db9b8ec2c3d6405453f982435efc52561df58/numpy-2.2.6-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:5a6429d4be8ca66d889b7cf70f536a397dc45ba6faeb5f8c5427935d9592e9cf", size = 6878301, upload-time = "2025-05-17T21:28:41.613Z" },
+ { url = "https://files.pythonhosted.org/packages/eb/17/96a3acd228cec142fcb8723bd3cc39c2a474f7dcf0a5d16731980bcafa95/numpy-2.2.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:efd28d4e9cd7d7a8d39074a4d44c63eda73401580c5c76acda2ce969e0a38e83", size = 14297320, upload-time = "2025-05-17T21:29:02.78Z" },
+ { url = "https://files.pythonhosted.org/packages/b4/63/3de6a34ad7ad6646ac7d2f55ebc6ad439dbbf9c4370017c50cf403fb19b5/numpy-2.2.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc7b73d02efb0e18c000e9ad8b83480dfcd5dfd11065997ed4c6747470ae8915", size = 16801050, upload-time = "2025-05-17T21:29:27.675Z" },
+ { url = "https://files.pythonhosted.org/packages/07/b6/89d837eddef52b3d0cec5c6ba0456c1bf1b9ef6a6672fc2b7873c3ec4e2e/numpy-2.2.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:74d4531beb257d2c3f4b261bfb0fc09e0f9ebb8842d82a7b4209415896adc680", size = 15807034, upload-time = "2025-05-17T21:29:51.102Z" },
+ { url = "https://files.pythonhosted.org/packages/01/c8/dc6ae86e3c61cfec1f178e5c9f7858584049b6093f843bca541f94120920/numpy-2.2.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8fc377d995680230e83241d8a96def29f204b5782f371c532579b4f20607a289", size = 18614185, upload-time = "2025-05-17T21:30:18.703Z" },
+ { url = "https://files.pythonhosted.org/packages/5b/c5/0064b1b7e7c89137b471ccec1fd2282fceaae0ab3a9550f2568782d80357/numpy-2.2.6-cp310-cp310-win32.whl", hash = "sha256:b093dd74e50a8cba3e873868d9e93a85b78e0daf2e98c6797566ad8044e8363d", size = 6527149, upload-time = "2025-05-17T21:30:29.788Z" },
+ { url = "https://files.pythonhosted.org/packages/a3/dd/4b822569d6b96c39d1215dbae0582fd99954dcbcf0c1a13c61783feaca3f/numpy-2.2.6-cp310-cp310-win_amd64.whl", hash = "sha256:f0fd6321b839904e15c46e0d257fdd101dd7f530fe03fd6359c1ea63738703f3", size = 12904620, upload-time = "2025-05-17T21:30:48.994Z" },
+ { url = "https://files.pythonhosted.org/packages/9e/3b/d94a75f4dbf1ef5d321523ecac21ef23a3cd2ac8b78ae2aac40873590229/numpy-2.2.6-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0b605b275d7bd0c640cad4e5d30fa701a8d59302e127e5f79138ad62762c3e3d", size = 21040391, upload-time = "2025-05-17T21:44:35.948Z" },
+ { url = "https://files.pythonhosted.org/packages/17/f4/09b2fa1b58f0fb4f7c7963a1649c64c4d315752240377ed74d9cd878f7b5/numpy-2.2.6-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:7befc596a7dc9da8a337f79802ee8adb30a552a94f792b9c9d18c840055907db", size = 6786754, upload-time = "2025-05-17T21:44:47.446Z" },
+ { url = "https://files.pythonhosted.org/packages/af/30/feba75f143bdc868a1cc3f44ccfa6c4b9ec522b36458e738cd00f67b573f/numpy-2.2.6-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce47521a4754c8f4593837384bd3424880629f718d87c5d44f8ed763edd63543", size = 16643476, upload-time = "2025-05-17T21:45:11.871Z" },
+ { url = "https://files.pythonhosted.org/packages/37/48/ac2a9584402fb6c0cd5b5d1a91dcf176b15760130dd386bbafdbfe3640bf/numpy-2.2.6-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d042d24c90c41b54fd506da306759e06e568864df8ec17ccc17e9e884634fd00", size = 12812666, upload-time = "2025-05-17T21:45:31.426Z" },
+]
+
+[[package]]
+name = "packaging"
+version = "26.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d7/f1/e7a6dd94a8d4a5626c03e4e99c87f241ba9e350cd9e6d75123f992427270/packaging-26.2.tar.gz", hash = "sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661", size = 228134, upload-time = "2026-04-24T20:15:23.917Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/df/b2/87e62e8c3e2f4b32e5fe99e0b86d576da1312593b39f47d8ceef365e95ed/packaging-26.2-py3-none-any.whl", hash = "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e", size = 100195, upload-time = "2026-04-24T20:15:22.081Z" },
+]
+
+[[package]]
+name = "pillow"
+version = "12.3.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/1c/3d/bb7fca845737cf9d7dbde16ed1843984665ff2e0a518f5db43e77ec540b9/pillow-12.3.0.tar.gz", hash = "sha256:3b8182a766685eaa002637e28b4ec8d6b18819a0c71f579bf0dbaa5830297cce", size = 47025035, upload-time = "2026-07-01T11:56:38.965Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/25/c2/669d88644cddb1485bd9534e63e8cf476c8e51cb3c3a1297677023505c0e/pillow-12.3.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:6c0016e7b354317c4e9e525b937ac8596c38d2d232b419529b9cd7a1cd46e39a", size = 5392418, upload-time = "2026-07-01T11:53:27.808Z" },
+ { url = "https://files.pythonhosted.org/packages/6b/ba/3762f376a2948e3036488d773a146e0ae6ecc2ca03ac20e2615bd0b2ba02/pillow-12.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:bcc33feacfaefce60c12fd500a277533bdc02b10a19f7f6d348763d8140bbba7", size = 4785287, upload-time = "2026-07-01T11:53:29.761Z" },
+ { url = "https://files.pythonhosted.org/packages/07/50/b5d688cc9c52d4482f3d5bcab6ce20bc2a74a85d2343841c907444a3be2c/pillow-12.3.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5594fc43d548a7ed94949d139aa1341b270f1863f11cfd37f5a6c8b778a6b67f", size = 6253754, upload-time = "2026-07-01T11:53:32.298Z" },
+ { url = "https://files.pythonhosted.org/packages/4e/89/36f4cd76cf4baf05c50ababb976249153f18c959171c7f6ba09a6f217260/pillow-12.3.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f0606c8bf2cdefea14a43530f7657cbbb7ecf1c4222512492ef4a4434a9501ec", size = 6925605, upload-time = "2026-07-01T11:53:34.487Z" },
+ { url = "https://files.pythonhosted.org/packages/eb/c0/4de58cf6633b9e3a6061ef4be6fb91fc3c90b812ece886f531e3c523d777/pillow-12.3.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:85f998ea1848bc6757289e739cfbdda3a04adfd58b02fc018ce54d754a5ce468", size = 6327788, upload-time = "2026-07-01T11:53:36.433Z" },
+ { url = "https://files.pythonhosted.org/packages/87/3c/14d53682a19550dbbaf3b598f807d5457646c510805a44c7d7891cd1cd1a/pillow-12.3.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:25b9b82bb22e6e2b3cd07b39c68b7b862001226cb3dff7130d1cb914121b39ed", size = 7036288, upload-time = "2026-07-01T11:53:38.712Z" },
+ { url = "https://files.pythonhosted.org/packages/38/1d/36279e3c77efe034e4cc2b0393ee74ffdb5a62391dacbf9b916154f5f0b8/pillow-12.3.0-cp310-cp310-win32.whl", hash = "sha256:37dc8f7bbb66efe481bb60defacef820c950c24713fb44962ed6aa2a50966de1", size = 6472396, upload-time = "2026-07-01T11:53:40.781Z" },
+ { url = "https://files.pythonhosted.org/packages/48/7c/8fa0039574c476d7c6fa57dd7c32a130436877c6ec1e5ce1cc8ec44878c1/pillow-12.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:300557495eb45ebb8aec96c2da9c4be642fbf7cd937278b4013ba894ea8eb0eb", size = 7226887, upload-time = "2026-07-01T11:53:42.764Z" },
+ { url = "https://files.pythonhosted.org/packages/fa/17/e324be141d173c1c919428066c3259f21c1b8982e564e01a4a81e96dbdcf/pillow-12.3.0-cp310-cp310-win_arm64.whl", hash = "sha256:514435a37670e3e5e08f3945b68718b6ed329bb84367777e16f9f4dfe1e61a0f", size = 2568039, upload-time = "2026-07-01T11:53:45.372Z" },
+]
+
+[[package]]
+name = "pluggy"
+version = "1.6.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" },
+]
+
+[[package]]
+name = "pyepics"
+version = "3.5.10"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "numpy" },
+ { name = "pyparsing" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/69/57/29e1e9ef11ba2a3419f489946ae1d8190025a1e4f4e1c1686758bb2b6e0a/pyepics-3.5.10.tar.gz", hash = "sha256:f390cf9be40aba757b9528888114bc14d8db01086d0c93914720b1772460375b", size = 6150481, upload-time = "2026-05-20T18:44:36.336Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d6/36/e517fd83bd97d6bfe4105e0c6b322070c5cc36fb56a8fab2866e319f8804/pyepics-3.5.10-py3-none-any.whl", hash = "sha256:c9fac2c54f2b595268e66fc348cf5ec24e63718e7dbd07d73d1b37d4da6bfee1", size = 5332376, upload-time = "2026-05-20T18:44:34.242Z" },
+]
+
+[[package]]
+name = "pygments"
+version = "2.20.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" },
+]
+
+[[package]]
+name = "pyparsing"
+version = "3.3.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f3/91/9c6ee907786a473bf81c5f53cf703ba0957b23ab84c264080fb5a450416f/pyparsing-3.3.2.tar.gz", hash = "sha256:c777f4d763f140633dcb6d8a3eda953bf7a214dc4eff598413c070bcdc117cbc", size = 6851574, upload-time = "2026-01-21T03:57:59.36Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl", hash = "sha256:850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d", size = 122781, upload-time = "2026-01-21T03:57:55.912Z" },
+]
+
+[[package]]
+name = "pytest"
+version = "9.1.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "colorama", marker = "sys_platform == 'win32'" },
+ { name = "exceptiongroup" },
+ { name = "iniconfig" },
+ { name = "packaging" },
+ { name = "pluggy" },
+ { name = "pygments" },
+ { name = "tomli" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/e4/47/b9efed96c114afcfa3c9d3fe98a76a1d14c74a9e266d397cf6eb64be5e01/pytest-9.1.1.tar.gz", hash = "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313", size = 1636369, upload-time = "2026-06-19T10:58:32.857Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/24/25/1de2678b631f5a49215c6c96fff41ba892b0a34df68d6d80292b1b48aa7f/pytest-9.1.1-py3-none-any.whl", hash = "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c", size = 386536, upload-time = "2026-06-19T10:58:31.347Z" },
+]
+
+[[package]]
+name = "python-dateutil"
+version = "2.9.0.post0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "six" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" },
+]
+
+[[package]]
+name = "rich"
+version = "15.0.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "markdown-it-py" },
+ { name = "pygments" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/c0/8f/0722ca900cc807c13a6a0c696dacf35430f72e0ec571c4275d2371fca3e9/rich-15.0.0.tar.gz", hash = "sha256:edd07a4824c6b40189fb7ac9bc4c52536e9780fbbfbddf6f1e2502c31b068c36", size = 230680, upload-time = "2026-04-12T08:24:00.75Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl", hash = "sha256:33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb", size = 310654, upload-time = "2026-04-12T08:24:02.83Z" },
+]
+
+[[package]]
+name = "ruff"
+version = "0.15.21"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/0f/36/6f65aa9989acdec45d417192d8f4e7921931d8a6cf87ac74bce3eed98a8e/ruff-0.15.21.tar.gz", hash = "sha256:d0cfc841c572283c36548f82664a54ce6565567f1b0d5b4cf2caac693d8b7500", size = 4769401, upload-time = "2026-07-09T20:01:34.005Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d0/c6/ede15cac6839f3dbce52565c8f5164a8210e669c7bc4decb03e5bdf47d0d/ruff-0.15.21-py3-none-linux_armv6l.whl", hash = "sha256:63ea0e965e5d73c90e95b2434beeafc70820536717f561b32ab6e777cb9bdf5d", size = 10854342, upload-time = "2026-07-09T20:00:53.998Z" },
+ { url = "https://files.pythonhosted.org/packages/28/9d/d825b07ee7ea9e2d61df92a860033c94e06e7300d50a1c2653aac27d24fe/ruff-0.15.21-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:0f212c5d7d54c01bbfe6dcab02b724a39300f3e34ed7acbe995ccb320a2c58bd", size = 11139539, upload-time = "2026-07-09T20:00:57.809Z" },
+ { url = "https://files.pythonhosted.org/packages/f5/de/3b107712e642f063c7a9e0887c427b22cb44097de5aab36c05f2e280670c/ruff-0.15.21-py3-none-macosx_11_0_arm64.whl", hash = "sha256:e6312e41bc96791299614995ea3a977c5857c3b5662b1ecef6755b02b87cb646", size = 10595437, upload-time = "2026-07-09T20:01:00.006Z" },
+ { url = "https://files.pythonhosted.org/packages/9a/6f/b4523cc90ba239ede441447a19d0c968846a3012e5a0b0c5b62831a3d5e3/ruff-0.15.21-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01d65b4831c6b2a4ba8ee6faa84049d44d982b7a706e622c4094c509e51673be", size = 10990053, upload-time = "2026-07-09T20:01:02.187Z" },
+ { url = "https://files.pythonhosted.org/packages/92/cc/c6a9872a5375f0628875481cf2f66b13d7d865bf3ca2e57f91c7e762d976/ruff-0.15.21-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2c5a913a589120ce67933d5d05fd6ddbcc2481c6a054980ee767f7414c72b4fd", size = 10666096, upload-time = "2026-07-09T20:01:04.299Z" },
+ { url = "https://files.pythonhosted.org/packages/ab/97/c621f7a17e097f1790fa3af6374138823b330b2d03fc38337945daca212c/ruff-0.15.21-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ef04b681d02ad4dc9620f00f83ac5c22f652d0e9a9cfe431d219b16ad5ccc41", size = 11537011, upload-time = "2026-07-09T20:01:06.771Z" },
+ { url = "https://files.pythonhosted.org/packages/ea/51/d928727e476e25ccc57c6f449ffd80241a651a973ad949d39cfb2a771d28/ruff-0.15.21-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:16d090c0740916594157e75b80d666eab8e78083b39b3b0e1d698f4670a17b86", size = 12347101, upload-time = "2026-07-09T20:01:08.859Z" },
+ { url = "https://files.pythonhosted.org/packages/1e/88/8cd62026802b16018ad06931d87997cf795ba2a6239ab659606c87d96bf0/ruff-0.15.21-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3a10e74757dd65004d779b73e2f3c5210156d9980b41224d50d2ebcf1db51e67", size = 11572001, upload-time = "2026-07-09T20:01:11.092Z" },
+ { url = "https://files.pythonhosted.org/packages/b2/97/f63084cf55444fc110e8cb985ebfcc592af47f597d44453d778cb81bc156/ruff-0.15.21-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bab0905d2f29e0d9fbc3c373ed23db0095edaa3f71f1f4f519ec15134d9e85c8", size = 11549239, upload-time = "2026-07-09T20:01:13.27Z" },
+ { url = "https://files.pythonhosted.org/packages/9d/77/f107da4a2874b7715914b03f09ba9c54424de3ff8a1cc5d015d3ee2ce0ac/ruff-0.15.21-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:00eca240af5789fec6fe7df74c088cc1f9644ed83027113468efba7c92b94075", size = 11535340, upload-time = "2026-07-09T20:01:15.206Z" },
+ { url = "https://files.pythonhosted.org/packages/d5/e9/601deb322d3303a7bf212b0100ead6f2ee3f6a044d89c30f2f92bf83c731/ruff-0.15.21-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:262ab31557a75141325e32d3357f3597645a7f084e732b6b054dde428ecd9341", size = 10964048, upload-time = "2026-07-09T20:01:17.723Z" },
+ { url = "https://files.pythonhosted.org/packages/ea/2e/0f2176d1e99c15192caea19c8c3a0a955246b4cb4de795042eeb616345cd/ruff-0.15.21-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:659c4e7a4212f83306045ec7c5e5a356d16d9a6ef4ae0c7a4d872914fc655d9d", size = 10667055, upload-time = "2026-07-09T20:01:19.73Z" },
+ { url = "https://files.pythonhosted.org/packages/48/60/abd74a02e0c4214f12a68becfd30af7165cfdcb0e661ecdc60bbb949c09a/ruff-0.15.21-py3-none-musllinux_1_2_i686.whl", hash = "sha256:9e866eab611a5f959d36df2d10e446973a3610bc42b0c15b31dc27977d59c233", size = 11242043, upload-time = "2026-07-09T20:01:21.947Z" },
+ { url = "https://files.pythonhosted.org/packages/b2/c6/583075d8ccabb4b229345edcaf1545eb3d8d6be90f686a479d7e94088bbf/ruff-0.15.21-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e89bc93c0d3803ba870b55c29671bad9dc6d94bb1eb181b056b52eb05b52854f", size = 11648064, upload-time = "2026-07-09T20:01:24.023Z" },
+ { url = "https://files.pythonhosted.org/packages/3a/3c/37d0ecb729a7cc2d393ea7dce316fc585680f35d93b8d62139d7d0a3700c/ruff-0.15.21-py3-none-win32.whl", hash = "sha256:01f8d5be84823c172b389e123174f781f9daf86d6c58719d603f941932195cdd", size = 10896555, upload-time = "2026-07-09T20:01:26.941Z" },
+ { url = "https://files.pythonhosted.org/packages/c0/b8/e43466b2a6067ce91e669068f6e28d6c719a920f014b070d5c8731725de3/ruff-0.15.21-py3-none-win_amd64.whl", hash = "sha256:d4b8d9a2f0f12b816b50447f6eccb9f4bb01a6b82c86b50fb3b5354b458dc6d3", size = 12038772, upload-time = "2026-07-09T20:01:29.497Z" },
+ { url = "https://files.pythonhosted.org/packages/dd/75/e90ab9aeece218a9fc5a5bc3ec97d0ee6bb3c4ff95869463c1de58e29a1c/ruff-0.15.21-py3-none-win_arm64.whl", hash = "sha256:6e83115d4b9377c1cbc13abf0e051f069fab0ef815ea0504a8a008cee24dd0a8", size = 11375265, upload-time = "2026-07-09T20:01:31.772Z" },
+]
+
+[[package]]
+name = "shellingham"
+version = "1.5.4"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/58/15/8b3609fd3830ef7b27b655beb4b4e9c62313a4e8da8c676e142cc210d58e/shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de", size = 10310, upload-time = "2023-10-24T04:13:40.426Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755, upload-time = "2023-10-24T04:13:38.866Z" },
+]
+
+[[package]]
+name = "six"
+version = "1.17.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" },
+]
+
+[[package]]
+name = "tomli"
+version = "2.4.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/22/de/48c59722572767841493b26183a0d1cc411d54fd759c5607c4590b6563a6/tomli-2.4.1.tar.gz", hash = "sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f", size = 17543, upload-time = "2026-03-25T20:22:03.828Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/7b/61/cceae43728b7de99d9b847560c262873a1f6c98202171fd5ed62640b494b/tomli-2.4.1-py3-none-any.whl", hash = "sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe", size = 14583, upload-time = "2026-03-25T20:22:03.012Z" },
+]
+
+[[package]]
+name = "typer"
+version = "0.27.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "annotated-doc" },
+ { name = "colorama", marker = "sys_platform == 'win32'" },
+ { name = "rich" },
+ { name = "shellingham" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/37/78/fda3361b56efc27944f24225f6ecd13d96d6fcfe37bd0eb34e2f4c63f9fc/typer-0.27.0.tar.gz", hash = "sha256:629bd12ea5d13a17148125d9a264f949eb171fb3f120f9b04d85873cab054fa5", size = 203430, upload-time = "2026-07-15T19:21:07.007Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/40/03/26a383c9e58c213199d1aad1c3d353cfc22d4444ec6d2c0bf8ad02523843/typer-0.27.0-py3-none-any.whl", hash = "sha256:6f4b27631e47f077871b7dc30e933ec0131c1390fbe0e387ea5574b5bac9ccf1", size = 122716, upload-time = "2026-07-15T19:21:05.553Z" },
+]
+
+[[package]]
+name = "typing-extensions"
+version = "4.16.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f6/cc/6253133b5bb138fc3306cebfbda2c520f545d36b5be2c7255cc528bb45d6/typing_extensions-4.16.0.tar.gz", hash = "sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5", size = 113555, upload-time = "2026-07-02T08:40:05.92Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/49/d3/b8441a820a491ddfc024b0b0cf0393375b75ea13866d9c66727e54c2fc80/typing_extensions-4.16.0-py3-none-any.whl", hash = "sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8", size = 45571, upload-time = "2026-07-02T08:40:04.659Z" },
+]
+
+[[package]]
+name = "urllib3"
+version = "2.7.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/53/0c/06f8b233b8fd13b9e5ee11424ef85419ba0d8ba0b3138bf360be2ff56953/urllib3-2.7.0.tar.gz", hash = "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c", size = 433602, upload-time = "2026-05-07T16:13:18.596Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/7f/3e/5db95bcf282c52709639744ca2a8b149baccf648e39c8cc87553df9eae0c/urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897", size = 131087, upload-time = "2026-05-07T16:13:17.151Z" },
+]
diff --git a/services/plots/current/ioc/AGEBD-CPCL-PLOTS_main.subs b/services/plots/current/ioc/AGEBD-CPCL-PLOTS_main.subs
new file mode 100644
index 0000000..250d28c
--- /dev/null
+++ b/services/plots/current/ioc/AGEBD-CPCL-PLOTS_main.subs
@@ -0,0 +1,64 @@
+file PLOTS_timeaxis.template {
+ pattern
+ { DEVICE }
+ { AGEBD-PLOTS{{ agebd_env }} }
+}
+
+
+file PLOTS_9h.template {
+ pattern
+ { DEVICE, NAME, INP }
+ { AGEBD-PLOTS{{ agebd_env }}, CURRENT, AGEBD-PARAMS:CURRENT }
+ { AGEBD-PLOTS{{ agebd_env }}, CURRENT-BPM, AGEBD-DBPM3CURR:CURRENT-AVG }
+ { AGEBD-PLOTS{{ agebd_env }}, CURRENT-PCT, ARS07-DPCT-0000:CURR }
+ { AGEBD-PLOTS{{ agebd_env }}, INJECTION-RATE, AGEBD-PARAMS:INJECTION-RATE }
+ { AGEBD-PLOTS{{ agebd_env }}, TRANSMISSION, AGEBD-PARAMS:TRANSMISSION }
+ { AGEBD-PLOTS{{ agebd_env }}, LIFETIME, AGEBD-PARAMS:LIFETIME }
+ { AGEBD-PLOTS{{ agebd_env }}, MAVAC-AVG, ARIVA-VMAVE:PRESS-AVE }
+ { AGEBD-PLOTS{{ agebd_env }}, MAVAC-MAX, ARIVA-VMAVE:PRESS-MAX }
+ { AGEBD-PLOTS{{ agebd_env }}, FEVAC-AVG, ARIVA-VMAVE-FE:PRESS-AVE }
+ { AGEBD-PLOTS{{ agebd_env }}, FEVAC-MAX, ARIVA-VMAVE-FE:PRESS-MAX }
+ { AGEBD-PLOTS{{ agebd_env }}, ABRTL-DDRM-0670, ABRTL-DDRM-0670:FET1_BIAS_DOSE}
+ { AGEBD-PLOTS{{ agebd_env }}, ABRTL-DDRM-0950, ABRTL-DDRM-0950:FET1_DOSE}
+ { AGEBD-PLOTS{{ agebd_env }}, X05LA-DDRM-0330, X05LA-DDRM-0330:FET1_BIAS_DOSE}
+ { AGEBD-PLOTS{{ agebd_env }}, X05LA-DDRM-0650, X05LA-DDRM-0650:FET1_BIAS_DOSE}
+ { AGEBD-PLOTS{{ agebd_env }}, X09LA-DDRM-0330, X09LA-DDRM-0330:FET1_BIAS_DOSE}
+ { AGEBD-PLOTS{{ agebd_env }}, X09LA-DDRM-0790, X09LA-DDRM-0790:FET1_BIAS_DOSE}
+ { AGEBD-PLOTS{{ agebd_env }}, ARS01-DDRM-0375, ARS01-DDRM-0375:FET1_DOSE}
+ { AGEBD-PLOTS{{ agebd_env }}, ARS01-DDRM-1530, ARS01-DDRM-1530:FET1_BIAS_DOSE}
+ { AGEBD-PLOTS{{ agebd_env }}, ARS05-DDRM-1530, ARS05-DDRM-1530:FET1_BIAS_DOSE}
+ { AGEBD-PLOTS{{ agebd_env }}, ARS05-DDRM-3500, ARS05-DDRM-3500:FET1_BIAS_DOSE}
+ { AGEBD-PLOTS{{ agebd_env }}, ARS09-DDRM-1530, ARS09-DDRM-1530:FET1_BIAS_DOSE}
+ { AGEBD-PLOTS{{ agebd_env }}, ARS09-DDRM-3500, ARS09-DDRM-3500:FET2_BIAS_DOSE}
+ { AGEBD-PLOTS{{ agebd_env }}, ARS12-DDRM-1530, ARS12-DDRM-1530:FET1_BIAS_DOSE}
+ { AGEBD-PLOTS{{ agebd_env }}, ARS12-DDRM-3500, ARS12-DDRM-3500:FET1_BIAS_DOSE}
+ { AGEBD-PLOTS{{ agebd_env }}, ARS12-DDRM-4400, ARS12-DDRM-4400:FET1_BIAS_DOSE}
+ { AGEBD-PLOTS{{ agebd_env }}, ARS12-DDRM-5480, ARS12-DDRM-5480:FET1_BIAS_DOSE}
+ { AGEBD-PLOTS{{ agebd_env }}, X02SA-UIND-GAP, AGEOP-STATUS:X02SA-UIND-GAP} # Soft Blue #A0C4FF
+ # { AGEBD-PLOTS{{ agebd_env }}, X03MA-UIND-GAP, AGEOP-STATUS:X03MA-UIND-GAP} # Warm Orange #FFD6A5
+ { AGEBD-PLOTS{{ agebd_env }}, X04SA-UIND-GAP, AGEOP-STATUS:X04SA-UIND-GAP} # Light Green #CAFFBF
+ # { AGEBD-PLOTS{{ agebd_env }}, X05LA-UIND-GAP, AGEOP-STATUS:X05LA-UIND-GAP} # Coral Red #FFADAD
+ { AGEBD-PLOTS{{ agebd_env }}, X06SA-UIND-GAP, AGEOP-STATUS:X06SA-UIND-GAP} # Lavender #CDB4DB
+ # { AGEBD-PLOTS{{ agebd_env }}, X07MA-UIND-GAP, AGEOP-STATUS:X07MA-UIND-GAP} # Desert Tan #DDB892
+ # { AGEBD-PLOTS{{ agebd_env }}, X08SA-UIND-GAP, AGEOP-STATUS:X08SA-UIND-GAP} # Peach Pink #FFB5A7
+ { AGEBD-PLOTS{{ agebd_env }}, X09LB-UIND-GAP, AGEOP-STATUS:X09LB-UIND-GAP} # Aqua Blue #9BF6FF
+ { AGEBD-PLOTS{{ agebd_env }}, X10SA-UIND-GAP, AGEOP-STATUS:X10SA-UIND-GAP} # Pale Yellow #FDFFB6
+ { AGEBD-PLOTS{{ agebd_env }}, X11MA-UIND2-GAP, AGEOP-STATUS:X11MA-UIND2-GAP} # Periwinkle #BDB2FF
+ { AGEBD-PLOTS{{ agebd_env }}, X12SA-UIND-GAP, AGEOP-STATUS:X12SA-UIND-GAP} # Mint Green #B0F2C2
+}
+
+file PLOTS_week.template {
+ pattern
+ { DEVICE, NAME, INP }
+ { AGEBD-PLOTS{{ agebd_env }}, CURRENT-BPM, AGEBD-DBPM3CURR:CURRENT-AVG }
+ { AGEBD-PLOTS{{ agebd_env }}, CURRENT-PCT, ARS07-DPCT-0000:CURR }
+ { AGEBD-PLOTS{{ agebd_env }}, TAU-BPM, AGEBD-TAUBPM:TAU }
+ { AGEBD-PLOTS{{ agebd_env }}, TAU-PCT, AGEBD-TAUPCT:TAU }
+ { AGEBD-PLOTS{{ agebd_env }}, TAU-TOPUP, AGEBD-SCRUBBING:TOPUP-TAU }
+ { AGEBD-PLOTS{{ agebd_env }}, INJRATE-BPM, AGEBD-TAUBPM:INJRATE }
+ { AGEBD-PLOTS{{ agebd_env }}, INJRATE-PCT, AGEBD-TAUPCT:INJRATE }
+ { AGEBD-PLOTS{{ agebd_env }}, MAVAC-AVG, ARIVA-VMAVE:PRESS-AVE }
+ { AGEBD-PLOTS{{ agebd_env }}, MAVAC-MAX, ARIVA-VMAVE:PRESS-MAX }
+ { AGEBD-PLOTS{{ agebd_env }}, FEVAC-AVG, ARIVA-VMAVE-FE:PRESS-AVE }
+ { AGEBD-PLOTS{{ agebd_env }}, FEVAC-MAX, ARIVA-VMAVE-FE:PRESS-MAX }
+}
diff --git a/services/plots/current/ioc/AGEBD-CPCL-PLOTS_parameters.yaml b/services/plots/current/ioc/AGEBD-CPCL-PLOTS_parameters.yaml
new file mode 100644
index 0000000..ff8e70f
--- /dev/null
+++ b/services/plots/current/ioc/AGEBD-CPCL-PLOTS_parameters.yaml
@@ -0,0 +1,6 @@
+cpu_architecture: x86_64
+epics_version: 7.0.8
+ioc_host: sls-vserv-bd-01{{ agebd_env }}
+ioc_port: {{ ioc_port }}
+os: RHEL8
+os_id: rhel
diff --git a/services/plots/current/ioc/PLOTS_9h.template b/services/plots/current/ioc/PLOTS_9h.template
new file mode 100644
index 0000000..707d073
--- /dev/null
+++ b/services/plots/current/ioc/PLOTS_9h.template
@@ -0,0 +1,8 @@
+## 9 Hour Plots
+record(compress, "$(DEVICE):$(NAME)-9h-BUFFER") {
+ field(DESC, "9h Buffer for SLS Status Panel")
+ field(SCAN, "1 second")
+ field(INP, "$(INP)")
+ field(ALG, "Circular Buffer")
+ field(NSAM, "32400")
+}
diff --git a/services/plots/current/ioc/PLOTS_timeaxis.template b/services/plots/current/ioc/PLOTS_timeaxis.template
new file mode 100644
index 0000000..974d670
--- /dev/null
+++ b/services/plots/current/ioc/PLOTS_timeaxis.template
@@ -0,0 +1,23 @@
+# 9 Hour Plots
+record(waveform, "$(DEVICE):PAST-9-HOURS") {
+ field(DESC, "Time axis for 9h buffer")
+ field(EGU, "h")
+ field(FTVL, "FLOAT")
+ field(DTYP, "sequence")
+ field(NELM, "32400")
+ field(LOPR, "-9.0")
+ field(HOPR, "0.0")
+ field(PINI, "YES")
+}
+
+# 1 Week Plot
+record(waveform, "$(DEVICE):PAST-168-HOURS") {
+ field(DESC, "Time axis for 1 week buffer")
+ field(EGU, "h")
+ field(FTVL, "FLOAT")
+ field(DTYP, "sequence")
+ field(NELM, "604800")
+ field(LOPR, "-168.0")
+ field(HOPR, "0.0")
+ field(PINI, "YES")
+}
\ No newline at end of file
diff --git a/services/plots/current/ioc/PLOTS_week.template b/services/plots/current/ioc/PLOTS_week.template
new file mode 100644
index 0000000..cd5e692
--- /dev/null
+++ b/services/plots/current/ioc/PLOTS_week.template
@@ -0,0 +1,8 @@
+## 1 Week Plot
+record(compress, "$(DEVICE):$(NAME)-168h-BUFFER") {
+ field(DESC, "1 Week Buffer for SLS Status Panel")
+ field(SCAN, "1 second")
+ field(INP, "$(INP)")
+ field(ALG, "Circular Buffer")
+ field(NSAM, "604800")
+}
diff --git a/services/plots/current/ioc/README.md b/services/plots/current/ioc/README.md
new file mode 100644
index 0000000..13b004e
--- /dev/null
+++ b/services/plots/current/ioc/README.md
@@ -0,0 +1,28 @@
+# Contact
+:envelope: [Felix Armborst](mailto:felix.armborst@psi.ch)
+:envelope: [Stefan Mäder](mailto:stefan.maeder@psi.ch)
+
+**The relevant panels are:**
+- 9h Plots for Panels (SLS status / Scrubbing)
+
+:pushpin:
+ Some useful tools/commands
+
+```
+ ## ssh to you local clone of this repo on sls-lca
+ # (re-)install this ioc
+ ioc install -V --ioc AGEBD-CPCL-PLOTS
+
+ # connect to ioc shell of running ioc and resart via ctrl+x to restart with made changes
+ ioc shell AGEBD-CPCL-PLOTS
+
+ ## useful debugging commands
+ # get the most important variables,softioc server port etc
+ ioc boots AGEBD-CPCL-PLOTS
+ ioc records -f SLS --sort name --ioc AGEBD-CPCL-PLOTS >ioc_records.txt
+ ioc duplicates -f SLS
+
+ # make a clean test installation
+ mkdir -p ./TTT; ioc install --instbase ./TTT --clean --ioc AGEBD-CPCL-PLOTS
+ meld ./TTT/AGEBD-CPCL-PLOTS /ioc/AGEBD-CPCL-PLOTS
+ ```
diff --git a/services/plots/current/ioc/startup.script b/services/plots/current/ioc/startup.script
new file mode 100644
index 0000000..4da8df1
--- /dev/null
+++ b/services/plots/current/ioc/startup.script
@@ -0,0 +1,4 @@
+epicsEnvSet("ENGINEER", "Operation")
+require array
+require SynApps
+addScan 300
diff --git a/services/plots/current/qt/A_BD_Plots.ui b/services/plots/current/qt/A_BD_Plots.ui
new file mode 100644
index 0000000..0fa9278
--- /dev/null
+++ b/services/plots/current/qt/A_BD_Plots.ui
@@ -0,0 +1,103 @@
+
+
+ MainWindow
+
+
+
+ 0
+ 0
+ 800
+ 600
+
+
+
+ MainWindow
+
+
+
+
+
+ 0
+ 60
+ 100
+ 50
+
+
+
+ 1
+
+
+ 0
+
+
+ AGEBD-PLOTS-DEV:AO
+
+
+ 9.000000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 0
+ 0
+ 601
+ 22
+
+
+
+ Toggle AGEBD-ALH-DEV:PLOTS-ONOFF
+
+
+ AGEBD-ALH-DEV:PLOTS-ONOFF
+
+
+
+
+
+ 6
+ 34
+ 401
+ 21
+
+
+
+
+ 13
+
+
+
+ Value of AGEBD-PLOTS-DEV:AO
+
+
+
+
+
+
+
+
+ caNumeric
+ QFrame
+
+
+
+ caToggleButton
+ QCheckBox
+
+
+
+
+
+
diff --git a/services/plots/current/systemd/AGEBD-SERVICE-PLOTS.service b/services/plots/current/systemd/AGEBD-SERVICE-PLOTS.service
new file mode 100644
index 0000000..a1b82cd
--- /dev/null
+++ b/services/plots/current/systemd/AGEBD-SERVICE-PLOTS.service
@@ -0,0 +1,16 @@
+[Unit]
+Description=AGEBD-SERVICE-PLOTS
+After=network.target
+
+[Service]
+Environment=AGEBD_ENV={{ agebd_env }}
+ExecStart=/sls/bd/hla/{{ agebd_env }}/bin/start_service.sh PLOTS
+Restart=no
+
+[Install]
+WantedBy=default.target
+
+# https://www.freedesktop.org/software/systemd/man/latest/systemd.service.html
+# systemctl --user daemon-reload
+# systemctl --user enable /sls/bd/bin/systemd/AGEBD-SERVICE-PLOTS.service
+# systemctl --user start AGEBD-SERVICE-PLOTS
diff --git a/services/postmortemlog/current/app/pyproject.toml b/services/postmortemlog/current/app/pyproject.toml
new file mode 100644
index 0000000..d2dc249
--- /dev/null
+++ b/services/postmortemlog/current/app/pyproject.toml
@@ -0,0 +1,50 @@
+[project]
+name = "agebd-postmortemlog"
+version = "0.1.0"
+description = "AGEBD-POSTMORTEMLOG Service"
+requires-python = "==3.10.*"
+dependencies = [
+ "agebd",
+ "matplotlib>=3.10.9",
+ "numpy>=2.0.2",
+ "urllib3>=2.7.0",
+]
+
+[dependency-groups]
+dev = [
+ "pyepics>=3.5.8",
+ "pytest>=8.4.2",
+ "ruff>=0.15.20",
+]
+
+[tool.uv.sources]
+# Path is relative to where agebd package is deployed on hla
+# machines (see CI/CD in .gitea/workflows)
+agebd = { path = "../../../../packages/agebd", editable = true }
+
+[build-system]
+requires = ["hatchling"]
+build-backend = "hatchling.build"
+
+[tool.uv]
+package = true
+
+[tool.pytest.ini_options]
+pythonpath = ["src"]
+env = [
+ "AGEBD_ENV=local",
+]
+
+[tool.ruff]
+include = [
+ "src/**/*.py",
+ "tests/**/*.py",
+]
+line-length = 100
+
+[tool.ruff.lint]
+# use isort to sort imports
+extend-select = ["I"]
+
+[tool.ruff.lint.isort]
+known-first-party = ["agebd"]
diff --git a/services/postmortemlog/current/app/src/agebd_postmortemlog/__init__.py b/services/postmortemlog/current/app/src/agebd_postmortemlog/__init__.py
new file mode 100644
index 0000000..1800c27
--- /dev/null
+++ b/services/postmortemlog/current/app/src/agebd_postmortemlog/__init__.py
@@ -0,0 +1 @@
+from .service import PVs, Service
diff --git a/services/postmortemlog/current/app/src/agebd_postmortemlog/main.py b/services/postmortemlog/current/app/src/agebd_postmortemlog/main.py
new file mode 100644
index 0000000..0c762eb
--- /dev/null
+++ b/services/postmortemlog/current/app/src/agebd_postmortemlog/main.py
@@ -0,0 +1,31 @@
+import typer
+
+from agebd.enums import LogLevel
+from agebd.runner import CallbackRunner
+from agebd.utils import init_logging
+from agebd_postmortemlog import PVs, Service
+
+
+# TODO: remove: cicd test 10
+
+def main(
+ log_level: LogLevel = typer.Option(
+ LogLevel.INFO,
+ "--log-level",
+ "-l",
+ # Looks at the OS env variable first. If empty, falls back to "INFO"
+ envvar="AGEBD_LOG_LEVEL",
+ # help="Set log level: DEBUG, INFO, WARNING, ERROR, CRITICAL",
+ case_sensitive=False,
+ ),
+):
+ init_logging(log_level)
+ service_name = "POSTMORTEMLOG"
+ pvs = PVs(service_name=service_name)
+ service = Service(name=service_name, pvs=pvs)
+ runner = CallbackRunner(service=service)
+ runner.start()
+
+
+if __name__ == "__main__":
+ typer.run(main)
diff --git a/services/postmortemlog/current/app/src/agebd_postmortemlog/service.py b/services/postmortemlog/current/app/src/agebd_postmortemlog/service.py
new file mode 100644
index 0000000..5c05f25
--- /dev/null
+++ b/services/postmortemlog/current/app/src/agebd_postmortemlog/service.py
@@ -0,0 +1,1739 @@
+import time
+
+# https://urllib3.readthedocs.io/en/1.26.x/advanced-usage.html#ssl-warnings
+import urllib3
+
+urllib3.disable_warnings()
+import socket
+from datetime import datetime
+from time import perf_counter, sleep, time
+
+import elog
+import matplotlib.pyplot as plt
+import numpy as np
+from epics import poll
+
+from agebd.h5 import h5save
+from agebd.pv import get_pv_class
+from agebd.service.base import BaseService
+from agebd.service.pvs import BasePVs
+from agebd.utils import printgetversion
+
+__version__ = printgetversion(__file__)
+
+PV = get_pv_class()
+
+plt.switch_backend("agg")
+plt.rcParams.update({"font.size": 18})
+plt.rcParams["axes.facecolor"] = "white"
+plt.rcParams["figure.facecolor"] = "white"
+plt.rcParams["lines.markersize"] = 1
+plt.rcParams["lines.linewidth"] = 0.2
+
+EpicsTimestampStr2FileTimestampStr = lambda ts: datetime.strptime(
+ ts, "%Y-%m-%d %H:%M:%S.%f"
+).strftime("%Y%m%d_%H%M%S")
+
+
+class PVs(BasePVs):
+ # # Generic Service Control PV
+ test = PV("AGEBD-POSTMORTEMLOG:TEST")
+ postdelay = PV("AGEBD-POSTMORTEMLOG:BEAM-ABORT-EVT.ODLY")
+
+ # Potential Service Callback PVs
+ bdcinputsum = PV("AGESA-SBDC-0000:SUM_INPUT_NOT_OK.VAL", auto_monitor=True)
+ bdcinputsum_latched = PV("AGESA-SBDC-0000:SUM_INPUT_NOT_OK_LATCHED.VAL", auto_monitor=True)
+
+ # Minimum current condition
+ pctmaster = PV("ARS07-DPCT-0000:CURR.VAL")
+
+ # Service Input PVs (Post Mortem Information)
+ bdc_interlocks = [
+ PV("AGESA-SBDC-0000:CH{:02.0f}-INPUT_OK_LATCHED.VAL".format(i)) for i in range(21)
+ ]
+ bdc_delays = [PV("AGESA-SBDC-0000:CH{:02.0f}-DELAY.VAL".format(i)) for i in range(21)]
+
+ pmioc_time = PV("ARS01-MKIK-0050-1:TRIG-CNT.VAL")
+
+ vcs_alarmlist = PV("ARS00-VCS:PLC_AlarmList.VAL")
+ mis_alarmlist = PV("ARS00-MIS-PLC-01:AlarmList.VAL")
+ misfe_alarmlist = PV("ARS00-MIS-PLC-01:AlarmList_Frontends.VAL")
+
+ # Counters
+ counter_bdc = PV("AGESA-SBDC-0000:INT-COUNTER.VAL", auto_monitor=True)
+ counter_dumpkicker = PV("ARS01-MKIK-0050-1:TRIG-CNT.VAL")
+ counter_tmaster_beamdump = PV("AGETI-CVME-MASTER-TMA:Evt-Beam-Dump-EVRCount-I.VAL")
+ counter_tmaster_postmortem = PV("AGETI-CVME-MASTER-TMA:Evt-PM-Rec-EVRCount-I.VAL")
+
+ # Post Mortem Data as dict for easier access
+ PostMortemLinks = [
+ ## BLMs
+ # IOC: ABODI-DFBL
+ PV("ABODI-DFBL:SigPm.A"),
+ PV("ABODI-DFBL:SigPm.B"),
+ PV("ABODI-DFBL:SigPm.C"),
+ PV("ABODI-DFBL:SigPm.D"),
+ # IOC: ARS01-DFBL
+ PV("ARS01-DFBL:SigPm.A"),
+ PV("ARS01-DFBL:SigPm.B"),
+ PV("ARS01-DFBL:SigPm.C"),
+ PV("ARS01-DFBL:SigPm.D"),
+ # IOC: ARS02-DFBL
+ PV("ARS02-DFBL:SigPm.A"),
+ PV("ARS02-DFBL:SigPm.B"),
+ PV("ARS02-DFBL:SigPm.C"),
+ PV("ARS02-DFBL:SigPm.D"),
+ # IOC: ARS06-DFBL
+ PV("ARS06-DFBL:SigPm.A"),
+ PV("ARS06-DFBL:SigPm.B"),
+ PV("ARS06-DFBL:SigPm.C"),
+ PV("ARS06-DFBL:SigPm.D"),
+ # IOC: ARS09-DFBL
+ PV("ARS09-DFBL:SigPm.A"),
+ PV("ARS09-DFBL:SigPm.B"),
+ PV("ARS09-DFBL:SigPm.C"),
+ PV("ARS09-DFBL:SigPm.D"),
+ ## 4 Kicker Bump
+ PV("ARS01-MKIK-0140:TIME-AXIS.VAL"),
+ PV("ARS01-MKIK-0140:CURRENT-WF.VAL"),
+ PV("ARS01-MKIK-0220:TIME-AXIS.VAL"),
+ PV("ARS01-MKIK-0220:CURRENT-WF.VAL"),
+ PV("ARS01-MKIK-0850:TIME-AXIS.VAL"),
+ PV("ARS01-MKIK-0850:CURRENT-WF.VAL"),
+ PV("ARS01-MKIK-0940:TIME-AXIS.VAL"),
+ PV("ARS01-MKIK-0940:CURRENT-WF.VAL"),
+ ## Beam Dump Kicker
+ PV("ARS01-MKIK-0050-1:TIME-AXIS.VAL"),
+ PV("ARS01-MKIK-0050-1:CURRENT-WF.VAL"),
+ PV("ARS01-MKIK-0050-2:TIME-AXIS.VAL"),
+ PV("ARS01-MKIK-0050-2:CURRENT-WF.VAL"),
+ PV("ARS01-MKIK-0050-3:TIME-AXIS.VAL"),
+ PV("ARS01-MKIK-0050-3:CURRENT-WF.VAL"),
+ PV("ARS01-MKIK-0050-4:TIME-AXIS.VAL"),
+ PV("ARS01-MKIK-0050-4:CURRENT-WF.VAL"),
+ ## Beam Dump Post Mortem Digitizer
+ PV("ARF-LPD64:X-AXIS-CH1.VAL"),
+ PV("ARF-LPD64:CH1-DATA.VAL"),
+ PV("ARF-LPD64:X-AXIS-CH2.VAL"),
+ PV("ARF-LPD64:CH2-DATA.VAL"),
+ PV("ARF-LPD64:X-AXIS-CH3.VAL"),
+ PV("ARF-LPD64:CH3-DATA.VAL"),
+ PV("ARF-LPD64:X-AXIS-CH4.VAL"),
+ PV("ARF-LPD64:CH4-DATA.VAL"),
+ PV("AGESA-SBDC-0000:BUNCH0_MAGNET_RAMP_DELAY.VAL"),
+ # ---------- FILLING PATTERN --------------
+ PV("AGEBD-POSTMORTEMLOG:BUFFER-FILLPATTERN-APD.VAL"),
+ ]
+ # ---------- BPM Post Mortem Data --------------
+ bpmnames = [
+ "ARS01-DBPM-0390:",
+ "ARS01-DBPM-0760:",
+ "ARS01-DBPM-1080:",
+ "ARS01-DBPM-1460:",
+ "ARS01-DBPM-1900:",
+ "ARS01-DBPM-2410:",
+ "ARS01-DBPM-2910:",
+ "ARS01-DBPM-4220:",
+ "ARS01-DBPM-4720:",
+ "ARS01-DBPM-5250:",
+ "ARS01-DBPM-5530:",
+ "ARS01-DBPM-5880:",
+ "ARS02-DBPM-1080:",
+ "ARS02-DBPM-1460:",
+ "ARS02-DBPM-1900:",
+ "ARS02-DBPM-2410:",
+ "ARS02-DBPM-2910:",
+ "ARS02-DBPM-4220:",
+ "ARS02-DBPM-4720:",
+ "ARS02-DBPM-5250:",
+ "ARS02-DBPM-5530:",
+ "ARS02-DBPM-5880:",
+ "ARS03-DBPM-0810:",
+ "ARS03-DBPM-1080:",
+ "ARS03-DBPM-1460:",
+ "ARS03-DBPM-1900:",
+ "ARS03-DBPM-2410:",
+ "ARS03-DBPM-2910:",
+ "ARS03-DBPM-4220:",
+ "ARS03-DBPM-4720:",
+ "ARS03-DBPM-5250:",
+ "ARS03-DBPM-5530:",
+ "ARS03-DBPM-5880:",
+ "ARS04-DBPM-0090:",
+ "ARS04-DBPM-0900:",
+ "ARS04-DBPM-1080:",
+ "ARS04-DBPM-1460:",
+ "ARS04-DBPM-1900:",
+ "ARS04-DBPM-2410:",
+ "ARS04-DBPM-2910:",
+ "ARS04-DBPM-4220:",
+ "ARS04-DBPM-4720:",
+ "ARS04-DBPM-5250:",
+ "ARS04-DBPM-5530:",
+ "ARS04-DBPM-5880:",
+ "ARS05-DBPM-0410:",
+ "ARS05-DBPM-1080:",
+ "ARS05-DBPM-1460:",
+ "ARS05-DBPM-1900:",
+ "ARS05-DBPM-2410:",
+ "ARS05-DBPM-2910:",
+ "ARS05-DBPM-4220:",
+ "ARS05-DBPM-4720:",
+ "ARS05-DBPM-5250:",
+ "ARS05-DBPM-5530:",
+ "ARS05-DBPM-5880:",
+ "ARS06-DBPM-1080:",
+ "ARS06-DBPM-1460:",
+ "ARS06-DBPM-1900:",
+ "ARS06-DBPM-2410:",
+ "ARS06-DBPM-2910:",
+ "ARS06-DBPM-4220:",
+ "ARS06-DBPM-4720:",
+ "ARS06-DBPM-5250:",
+ "ARS06-DBPM-5530:",
+ "ARS06-DBPM-5880:",
+ "ARS07-DBPM-0810:",
+ "ARS07-DBPM-0840:",
+ "ARS07-DBPM-1080:",
+ "ARS07-DBPM-1460:",
+ "ARS07-DBPM-1900:",
+ "ARS07-DBPM-2410:",
+ "ARS07-DBPM-2910:",
+ "ARS07-DBPM-4220:",
+ "ARS07-DBPM-4720:",
+ "ARS07-DBPM-5250:",
+ "ARS07-DBPM-5530:",
+ "ARS07-DBPM-5880:",
+ "ARS08-DBPM-1080:",
+ "ARS08-DBPM-1460:",
+ "ARS08-DBPM-1900:",
+ "ARS08-DBPM-2410:",
+ "ARS08-DBPM-2910:",
+ "ARS08-DBPM-4220:",
+ "ARS08-DBPM-4720:",
+ "ARS08-DBPM-5250:",
+ "ARS08-DBPM-5530:",
+ "ARS08-DBPM-5880:",
+ "ARS09-DBPM-0570:",
+ "ARS09-DBPM-1080:",
+ "ARS09-DBPM-1460:",
+ "ARS09-DBPM-1900:",
+ "ARS09-DBPM-2410:",
+ "ARS09-DBPM-2910:",
+ "ARS09-DBPM-4220:",
+ "ARS09-DBPM-4720:",
+ "ARS09-DBPM-5250:",
+ "ARS09-DBPM-5530:",
+ "ARS09-DBPM-5880:",
+ "ARS10-DBPM-1080:",
+ "ARS10-DBPM-1460:",
+ "ARS10-DBPM-1900:",
+ "ARS10-DBPM-2410:",
+ "ARS10-DBPM-2910:",
+ "ARS10-DBPM-4220:",
+ "ARS10-DBPM-4720:",
+ "ARS10-DBPM-5250:",
+ "ARS10-DBPM-5530:",
+ "ARS10-DBPM-5880:",
+ "ARS11-DBPM-0850:",
+ "ARS11-DBPM-1080:",
+ "ARS11-DBPM-1460:",
+ "ARS11-DBPM-1900:",
+ "ARS11-DBPM-2410:",
+ "ARS11-DBPM-2910:",
+ "ARS11-DBPM-4220:",
+ "ARS11-DBPM-4720:",
+ "ARS11-DBPM-5250:",
+ "ARS11-DBPM-5530:",
+ "ARS11-DBPM-5880:",
+ "ARS12-DBPM-1080:",
+ "ARS12-DBPM-1460:",
+ "ARS12-DBPM-1900:",
+ "ARS12-DBPM-2410:",
+ "ARS12-DBPM-2910:",
+ "ARS12-DBPM-4220:",
+ "ARS12-DBPM-4720:",
+ "ARS12-DBPM-5250:",
+ "ARS12-DBPM-5530:",
+ "ARS12-DBPM-5880:",
+ ]
+ for bpm in bpmnames:
+ for q in ["X", "Y", "Q"]:
+ bpmpvname = bpm + "PM-DATA-BEAM-" + q
+ PostMortemLinks.append(PV(bpmpvname))
+
+ # MBFB modes
+ # state of injection, state of pulsed magnets
+
+ ## CIRCULAR BUFFER Records from POST MORTEM IOC
+ names_circ_buffer_ioc = [
+ # ---------- BEAM CURRENT --------------
+ "CURRPCT",
+ "CURRBPM",
+ # ---------- BEAM LIFETIME --------------
+ "TAUBPM",
+ "TAUPCT",
+ # ---------- TUNES --------------
+ "QX",
+ "QY",
+ "QZ",
+ # ---------- BEAM SIZE --------------
+ "X01DD-SIGX",
+ "X01DD-SIGY",
+ "X08DB-SIGX",
+ "X08DB-SIGY",
+ # ---------- RF --------------
+ "MASTERFREQ-GET",
+ "MASTERFREQ-SET",
+ "RFPOW-0140-INP",
+ "RFPOW-0060-INP",
+ "RFPOW-0230-INP",
+ "RFPOW-0310-INP",
+ "RFPOW-0060-REF",
+ "RFPOW-0140-REF",
+ "RFPOW-0230-REF",
+ "RFPOW-0310-REF",
+ # ---------- RADFETS --------------
+ "ARS01-DDRM-0375", # Directly downstream of beam dump
+ "ABRTL-DDRM-0670", # ABRTL upstream of thick septum (also downstream of beam dump)
+ "ABRTL-DDRM-0950", # ABRTL downstream of thick septum
+ "ARS01-DDRM-1530", # End of matching section downstream of X01 (injection straight)
+ "X05LA-DDRM-0330", # Directly downstream of collimators 5
+ "ARS05-DDRM-1530", # End of matching section downstream of X05 (main RF and collimators 5)
+ "ARS05-DDRM-3500", # Center dipole of arc 5
+ "X09LA-DDRM-0330",
+ "ARS05-VMCC-0210",
+ "ARS05-VMCC-0215",
+ "ARS05-VMCC-0310",
+ "ARS05-VMCC-0315", # Directly downstream of collimators 9
+ "ARS09-DDRM-1530", # End of matching section downstream of X09 (3HC and collimators 9)
+ "ARS09-DDRM-3500", # Center dipole of arc 9
+ "ARS12-DDRM-1530", # End of matching section downstream of X12 (beginning of last arc)
+ "ARS12-DDRM-3500", # Center dipole of arc 12
+ "ARS12-DDRM-4400", # Fifth dipole of arc 12
+ "ARS12-DDRM-5480", # Start of matching section upstream of X01 (end of last arc)
+ # ---------- VACUUM --------------
+ "VACMAX",
+ "VACMAXFE",
+ "ARS01-VMCC-0110",
+ "ARS01-VMCC-0210",
+ "ARS01-VMCC-0225",
+ "ARS01-VMCC-0310",
+ "ARS01-VMCC-1550",
+ "ARS01-VMCC-3510",
+ "ARS01-VMCC-5460",
+ "ARS02-VMCC-0110",
+ "ARS02-VMCC-0210",
+ "ARS02-VMCC-0310",
+ "ARS02-VMCC-1550",
+ "ARS02-VMCC-3510",
+ "ARS02-VMCC-5460",
+ "ARS03-VMCC-0110",
+ "ARS03-VMCC-0320",
+ "ARS03-VMCC-1550",
+ "ARS03-VMCC-3510",
+ "ARS03-VMCC-5460",
+ "ARS04-VMCC-0110",
+ "ARS04-VMCC-1550",
+ "ARS04-VMCC-3510",
+ "ARS04-VMCC-5460",
+ "ARS05-VMCC-0110",
+ "ARS05-VMCC-0115",
+ "ARS05-VMCC-0210",
+ "ARS05-VMCC-0215",
+ "ARS05-VMCC-0310",
+ "ARS05-VMCC-0315",
+ "ARS05-VMCC-0410",
+ "ARS05-VMCC-0415",
+ "ARS05-VMCC-0510",
+ "ARS05-VMCC-0520",
+ "ARS05-VMCC-0530",
+ "ARS05-VMCC-0810",
+ "ARS05-VMCC-1550",
+ "ARS05-VMCC-3510",
+ "ARS05-VMCC-5460",
+ "ARS06-VMCC-0110",
+ "ARS06-VMCC-1550",
+ "ARS06-VMCC-3510",
+ "ARS06-VMCC-5460",
+ "ARS07-VMCC-0010",
+ "ARS07-VMCC-0120",
+ "ARS07-VMCC-0210",
+ "ARS07-VMCC-1550",
+ "ARS09-VMCC-0510",
+ "ARS09-VMCC-0810",
+ "ARS07-VMCC-3510",
+ "ARS07-VMCC-5460",
+ "ARS08-VMCC-0110",
+ "ARS08-VMCC-1550",
+ "ARS08-VMCC-3510",
+ "ARS08-VMCC-5460",
+ "ARS09-VMCC-0110",
+ "ARS09-VMCC-0120",
+ "ARS09-VMCC-0410",
+ "ARS09-VMCC-0510",
+ "ARS09-VMCC-0810",
+ "ARS09-VMCC-1550",
+ "ARS09-VMCC-3510",
+ "ARS09-VMCC-5460",
+ "ARS10-VMCC-0110",
+ "ARS10-VMCC-1550",
+ "ARS10-VMCC-3510",
+ "ARS10-VMCC-5460",
+ "ARS11-VMCC-0110",
+ "ARS11-VMCC-0210",
+ "ARS11-VMCC-0310",
+ "ARS11-VMCC-0410",
+ "ARS11-VMCC-0510",
+ "ARS11-VMCC-1550",
+ "ARS11-VMCC-3510",
+ "ARS11-VMCC-5460",
+ "ARS12-VMCC-0110",
+ "ARS12-VMCC-1550",
+ "ARS12-VMCC-3510",
+ "ARS12-VMCC-5460",
+ ]
+
+ for pvname in names_circ_buffer_ioc:
+ pvname = "AGEBD-POSTMORTEMLOG:BUFFER-" + pvname + "-LAST.VAL"
+ PostMortemLinks.append(PV(pvname))
+
+ # Prepare machine for accumulation
+ master_trig = PV("AGETI-CVME-MASTER-TMA:SR-Inj-Status-Sel.VAL")
+ reset_bucket = PV("AGEBD-TIMING:ZERO-TARGET-BUCKET.VAL")
+ ID_gap_ena = PV("AGEOP-STATUS:LIGHT-DELIVERY.VAL")
+
+ def __init__(self, service_name: str, pv_factory=PV):
+ super().__init__(service_name, pv_factory)
+ PV = pv_factory
+
+ self.CallbackPV = PV("AGESA-SBDC-0000:INT-COUNTER.VAL", auto_monitor=True)
+
+
+class vals:
+ bdc_channels = np.array(
+ [ # see https://git.psi.ch/epics_iocboot_sls/A_MPS/-/blob/main/AGESA-CECL-BDC/AGESA-CECL-BDC_main.subs
+ "Manual EPICS Beam Dump", # 00
+ "LLRF for Storage Ring Cavity 1", # 01
+ "LLRF for Storage Ring Cavity 2", # 02
+ "LLRF for Storage Ring Cavity 3", # 03
+ "LLRF for Storage Ring Cavity 4", # 04
+ "LLRF for Super Conducting 3HC", # 05
+ "Orbit Deviation", # 06
+ "FOFB", # 07
+ "Horizontal Multi Bunch Instability", # 08
+ "Vertical Multi Bunch Instability", # 09
+ "Longitudinal Multi Bunch Instabil", # 10
+ "Filling Patern Deviation", # 11
+ "Quench of Super Conducting Super Bend", # 12
+ "Quench of High Temperature Super Conducting Undulator", # 13
+ "PSYS", # 14
+ "Vacuum", # 15
+ "Machine Interlock System", # 16
+ "Rapid Storage Ring Current Drop", # 17
+ "Beam Dump Kicker", # 18
+ "SLS A/C Power", # 19
+ "Control Room Emergency Dump", # 20
+ ]
+ )
+
+
+def htmltable(data, header=False):
+
+ table = []
+ table.append('
') # overall table design
+
+ if header:
+ header = data[0]
+ table.append('') # header row design
+
+ for cell in header:
+ table.append('| {:} | '.format(cell)) # header cell design
+
+ table.append("
")
+ data = data[1:]
+
+ for i, row in enumerate(data):
+ if i % 2 == 0:
+ table.append('') # even row design
+ else:
+ table.append('
') # odd row design
+
+ for cell in row:
+ table.append('| {:} | '.format(cell)) # data cell design
+
+ table.append("
")
+
+ table.append("
")
+
+ return "".join(table)
+
+
+def mysleep(seconds):
+
+ t0 = perf_counter()
+ wait = True
+
+ while wait:
+ wait = perf_counter() - t0 < seconds
+
+
+def get_scopetime():
+
+ # scope address
+ scope = "LPD64-B031482.psi.ch"
+ port = 4000
+
+ # cmd for timestamp retrieval
+ cmd = "HORizontal:FASTframe:TIMEStamp:ALL?\n"
+
+ # Create a TCP socket
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ sock.settimeout(5) # Timeout in seconds
+
+ try:
+ sock.connect((scope, port))
+ sock.sendall(cmd.encode())
+
+ # Read the response
+ response = sock.recv(1024).decode().strip()
+
+ except Exception as e:
+ response = f"Error: {e:}"
+ finally:
+ sock.close()
+
+ # get time string by truncating response from index of fastfframe and quotation marks
+ date_str = response[4:-1]
+ # truncate useless nanoseconds to be compaticble with datetime
+ date_str = date_str[:-6]
+ # creat datetimeobject
+ date_obj = datetime.strptime(date_str, "%d.%m.%Y.%H:%M:%S.%f")
+ return date_obj.strftime("%Y-%m-%d %H:%M:%S.%f")
+
+
+class Service(BaseService[PVs]):
+ def __init__(
+ self,
+ name: str,
+ pvs: PVs,
+ version: str = __version__,
+ sleep_interval: float = 0.1,
+ ):
+ super().__init__(name, pvs, version, sleep_interval)
+
+ self.logbook = elog.open(
+ "https://elog-gfa.psi.ch/SLS/",
+ user="robot",
+ password="robot",
+ use_ssl=True,
+ )
+
+ # Counters
+ self.counter_bdc_last = pvs.counter_bdc.get()
+ self.counter_dumpkicker_last = pvs.counter_dumpkicker.get()
+ self.counter_tmaster_beamdump_last = pvs.counter_tmaster_beamdump.get()
+ self.counter_tmaster_postmortem_last = pvs.counter_tmaster_postmortem.get()
+
+ self.curr = np.zeros(10)
+ self.Tshift = pvs.postdelay.get()
+
+ def update(self):
+ pvs = self.pvs
+
+ curr = pvs.pctmaster.get()
+
+ if curr != self.curr[-1]:
+ self.curr[:-1] = self.curr[1:]
+ self.curr[-1] = curr
+
+ if pvs.test.get():
+ self.test = True
+ else:
+ self.test = False
+
+ # when callback fired and threshold current exceeded, write elog entry
+ if self.CallbackFired and np.nanmax(self.curr) > 3 or self.test:
+ # start stop watch
+ t0 = perf_counter()
+
+ # get timestamps
+ self.t0_hla = str(datetime.fromtimestamp(time()))
+
+ # prepare elog config and perform some machine actions depending on real or test interlock
+ if self.test:
+ self.suppress_email_notification = True
+ pvs.test.put(0)
+ print("Post mortem test request detected...")
+ else:
+ pvs.master_trig.put(0)
+ pvs.ID_gap_ena.put(1)
+ pvs.reset_bucket.put(1)
+ self.suppress_email_notification = False
+ print("Interlock beam dump detected...")
+
+ # wait for BDC latch to show interlocks
+ print(" ...waiting for BDC...")
+ while not pvs.bdcinputsum_latched.get() > 0 and perf_counter() - t0 < self.Tshift:
+ self.alive()
+ poll(evt=1.0e-5, iot=0.1)
+
+ # get BDC data
+ self.interlocks = np.array([interlock.get() for interlock in pvs.bdc_interlocks])
+ self.delays = np.array([delay.get() for delay in pvs.bdc_delays])
+
+ # get PLC alarm lists
+ self.vcs_alarmlist = pvs.vcs_alarmlist.get(as_string=True).split("\n")
+ self.mis_alarmlist = pvs.mis_alarmlist.get(as_string=True).split("\n")
+ self.misfe_alarmlist = pvs.misfe_alarmlist.get(as_string=True).split("\n")
+
+ # wait for BDC to get reset or posttrigger time tshift to pass
+ print(" ...waiting for all interlocks...")
+ while pvs.bdcinputsum_latched.get() > 0 and perf_counter() - t0 < self.Tshift:
+ self.alive()
+
+ # check for additional interlock requests to BDC
+ interlocks = np.array([interlock.get() for interlock in pvs.bdc_interlocks])
+ delays = np.array([delay.get() for delay in pvs.bdc_delays])
+ if len(np.flatnonzero(interlocks)) > len(np.flatnonzero(self.interlocks)):
+ self.interlocks = interlocks
+ self.delays = delays
+
+ # check for additional alarms in PLC alarm lists
+ vcs_alarmlist = pvs.vcs_alarmlist.get(as_string=True).split("\n")
+ if len(vcs_alarmlist) > len(self.vcs_alarmlist):
+ self.vcs_alarmlist = vcs_alarmlist
+ mis_alarmlist = pvs.mis_alarmlist.get(as_string=True).split("\n")
+ if len(mis_alarmlist) > len(self.mis_alarmlist):
+ self.mis_alarmlist = mis_alarmlist
+ misfe_alarmlist = pvs.misfe_alarmlist.get(as_string=True).split("\n")
+ if len(misfe_alarmlist) > len(self.misfe_alarmlist):
+ self.misfe_alarmlist = misfe_alarmlist
+
+ sleep(0.1)
+
+ # make sure that post trigger delay time has passed
+ while perf_counter() - t0 < self.Tshift:
+ self.alive()
+ # wait for time to pass
+ mysleep(0.01)
+ mysleep(1)
+ self.alive()
+
+ # get EPICS post mortem data including postdelay data after dump
+ self.PMD = {}
+ for pv in pvs.PostMortemLinks:
+ pvname = pv.pvname.removesuffix(".VAL")
+ pvname = pvname.removesuffix("-LAST")
+ if not pv.connected:
+ self.PMD[pvname] = np.ones(2) * np.nan
+ print(" pv not connected: {:}".format(pvname))
+ else:
+ if pvname == "AGEBD-POSTMORTEMLOG:BUFFER-FILLPATTERN-APD":
+ self.PMD[pvname] = np.reshape(pv.get(), (int(432000 / 480), 480))
+ else:
+ self.PMD[pvname] = pv.get()
+ self.PMD[pvname + ".timestamp"] = str(datetime.fromtimestamp(pv.timestamp))
+ self.t0_pmioc = self.PMD["AGEBD-POSTMORTEMLOG:BUFFER-CURRPCT.timestamp"]
+ self.t0_pmlpd64 = get_scopetime()
+
+ # if PM IOC is running since at least 15 minutes: NSAM = 9000, SCAN = 0.1
+ Npts = len(self.PMD["AGEBD-POSTMORTEMLOG:BUFFER-CURRPCT"])
+ dt = 0.1
+ T = Npts * dt
+ self.t = np.linspace(-T + self.Tshift, -dt + self.Tshift, Npts)
+
+ Npts = len(self.PMD["AGEBD-POSTMORTEMLOG:BUFFER-FILLPATTERN-APD"])
+ dt = 1
+ T = Npts * dt
+ self.t2 = np.linspace(-T + self.Tshift, -dt + self.Tshift, Npts)
+
+ self.counter_bdc = pvs.counter_bdc.get()
+ self.t0_bdc = str(datetime.fromtimestamp(pvs.counter_bdc.timestamp))
+ self.counter_dumpkicker = pvs.counter_dumpkicker.get()
+ self.counter_tmaster_beamdump = pvs.counter_tmaster_beamdump.get()
+ self.counter_tmaster_postmortem = pvs.counter_tmaster_postmortem.get()
+
+ Npost = int(self.Tshift / 0.1)
+ self.DRMs = {
+ pvname[27:]: value
+ for pvname, value in self.PMD.items()
+ if "-DDRM-" in pvname and not ".timestamp" in pvname
+ }
+ self.DRMs_i = {
+ DRM: np.nanmin(DRMarray[-Npost - 15 : -Npost - 5])
+ for DRM, DRMarray in self.DRMs.items()
+ }
+ self.DRMs_f = {
+ DRM: np.nanmax(DRMarray[-Npost - 5 :]) for DRM, DRMarray in self.DRMs.items()
+ }
+ self.DRMs_d = {
+ DRM: np.nanmax(np.array([0, self.DRMs_f[DRM] - self.DRMs_i[DRM]]))
+ for DRM in self.DRMs
+ } # difference with negative values mapped to 0
+ self.DRMs_sum = np.nansum(np.array([self.DRMs_d[DRM] for DRM in self.DRMs]))
+ self.DRMs_p = {DRM: 100 * self.DRMs_d[DRM] / self.DRMs_sum for DRM in self.DRMs}
+
+ self.logtxt = []
+
+ # Beam Dump Controller Log
+ print("self.interlocks, ", self.interlocks)
+ print("self.delays, ", self.delays)
+ self.index1 = np.flatnonzero(self.interlocks)
+ print("self.index1", self.index1)
+ self.index2 = np.argsort(self.delays[self.index1])
+ print("self.index2", self.index2)
+
+ if self.test:
+ self.firstinterlock = "Test"
+ elif len(self.index1) == 0:
+ self.firstinterlock = "BDC Readout Issue"
+ else:
+ self.firstinterlock = vals.bdc_channels[self.index1][
+ self.index2[0]
+ ] # This lines often crashes
+
+ print(" ...interlock triggered by {:}...".format(self.firstinterlock))
+
+ self.bdc_delays = [
+ "{:.2f} µs".format(self.delays[self.index1][i]) for i in self.index2
+ ]
+ self.bdc_channel_description = [
+ "{:}".format(vals.bdc_channels[self.index1][i]) for i in self.index2
+ ]
+ self.bdc_channel_nr = ["{:02}".format(self.index1[i]) for i in self.index2]
+
+ self.logtxt.append("Beam Dump Controller
")
+ self.logtxt.append(
+ htmltable(
+ [["Delay", "Description", "Channel Nr."]]
+ + [
+ [
+ "{:.2f} µs".format(self.delays[self.index1][i]),
+ "{:}".format(vals.bdc_channels[self.index1][i]),
+ "{:02}".format(self.index1[i]),
+ ]
+ for i in self.index2
+ ],
+ header=True,
+ )
+ )
+
+ self.alive()
+
+ # VCS Alarm List
+ self.logtxt.append("VCS
")
+ self.logtxt.append(self.vcs_alarmlist[0])
+ (
+ self.vcs_alarmlist_alarmindex,
+ self.vcs_alarmlist_timestamps,
+ self.vcs_alarmlist_descriptions,
+ ) = self.GascheLines2HTMLtable(self.vcs_alarmlist[2:])
+
+ self.alive()
+
+ # MIS Alarm List
+ self.logtxt.append("MIS
")
+ self.logtxt.append(self.mis_alarmlist[0])
+ (
+ self.mis_alarmlist_alarmindex,
+ self.mis_alarmlist_timestamps,
+ self.mis_alarmlist_descriptions,
+ ) = self.GascheLines2HTMLtable(self.mis_alarmlist[2:])
+
+ self.alive()
+
+ # MIS-FE Alarm List
+ self.logtxt.append("MIS-FE
")
+ self.logtxt.append(self.misfe_alarmlist[0])
+ (
+ self.misfe_alarmlist_alarmindex,
+ self.misfe_alarmlist_timestamps,
+ self.misfe_alarmlist_descriptions,
+ ) = self.GascheLines2HTMLtable(self.misfe_alarmlist[2:])
+
+ self.alive()
+
+ # RadFETs
+ drmdat = lambda DRM: [
+ "{:.4f}".format(self.DRMs_i[DRM]),
+ "{:.4f}".format(self.DRMs_f[DRM]),
+ "{:.4f}".format(self.DRMs_d[DRM]),
+ "{:.2f}".format(self.DRMs_p[DRM]),
+ ]
+ self.logtxt.append("RadFETs
")
+ self.logtxt.append(
+ htmltable(
+ [
+ [
+ "PV",
+ "Description",
+ "Before Dump / Gy",
+ "After Dump / Gy",
+ "Delta / Gy",
+ "Distribution / %",
+ ],
+ ["ARS01-DDRM-0375", "Directly downstream of beam dump"]
+ + drmdat("ARS01-DDRM-0375"),
+ [
+ "ABRTL-DDRM-0670",
+ "ABRTL upstream of thick septum (also downstream of beam dump)",
+ ]
+ + drmdat("ABRTL-DDRM-0670"),
+ ["ABRTL-DDRM-0950", "ABRTL downstream of thick septum"]
+ + drmdat("ABRTL-DDRM-0950"),
+ [
+ "ARS01-DDRM-1530",
+ "End of matching section downstream of X01 (injection straight)",
+ ]
+ + drmdat("ARS01-DDRM-1530"),
+ ["X05LA-DDRM-0330", "Directly downstream of collimators 5"]
+ + drmdat("X05LA-DDRM-0330"),
+ [
+ "ARS05-DDRM-1530",
+ "End of matching section downstream of X05 (main RF and collimators 5)",
+ ]
+ + drmdat("ARS05-DDRM-1530"),
+ ["ARS05-DDRM-3500", "Center dipole of arc 5"] + drmdat("ARS05-DDRM-3500"),
+ ["X09LA-DDRM-0330", "Directly downstream of collimators 9"]
+ + drmdat("X09LA-DDRM-0330"),
+ [
+ "ARS09-DDRM-1530",
+ "End of matching section downstream of X09 (3HC and collimators 9)",
+ ]
+ + drmdat("ARS09-DDRM-1530"),
+ ["ARS09-DDRM-3500", "Center dipole of arc 9 "] + drmdat("ARS09-DDRM-3500"),
+ [
+ "ARS12-DDRM-1530",
+ "End of matching section downstream of X12 (beginning of last arc)",
+ ]
+ + drmdat("ARS12-DDRM-1530"),
+ ["ARS12-DDRM-3500", "Center dipole of arc 12"] + drmdat("ARS12-DDRM-3500"),
+ ["ARS12-DDRM-4400", "Fifth dipole of arc 12"] + drmdat("ARS12-DDRM-4400"),
+ [
+ "ARS12-DDRM-5480",
+ "Start of matching section upstream of X01 (end of last arc)",
+ ]
+ + drmdat("ARS12-DDRM-5480"),
+ ],
+ header=True,
+ )
+ )
+
+ self.alive()
+
+ # Timestamps
+ self.logtxt.append("Timestamps
")
+ self.logtxt.append(
+ htmltable(
+ [
+ ["BDC Timestamp", "{:}".format(str(self.t0_bdc)[:-3])],
+ ["HLA Timestamp", "{:}".format(str(self.t0_hla)[:-3])],
+ ["PM IOC Timestamp", "{:}".format(str(self.t0_pmioc)[:-3])],
+ ["PM Scope LPD64", "{:}".format(str(self.t0_pmlpd64)[:-3])],
+ ],
+ header=False,
+ )
+ )
+
+ # Counters
+ self.logtxt.append("Counters
")
+ self.logtxt.append(
+ htmltable(
+ [
+ ["Counter", "Value", "Last Value", "Delta"],
+ [
+ "BDC Dump Counter",
+ "{:.0f}".format(self.counter_bdc),
+ "{:.0f}".format(self.counter_bdc_last),
+ "{:.0f}".format(self.counter_bdc - self.counter_bdc_last),
+ ],
+ [
+ "Beam Dump Kicker Counter",
+ "{:.0f}".format(self.counter_dumpkicker),
+ "{:.0f}".format(self.counter_dumpkicker_last),
+ "{:.0f}".format(self.counter_dumpkicker - self.counter_dumpkicker_last),
+ ],
+ [
+ "Beam Dump Event Counter",
+ "{:.0f}".format(self.counter_tmaster_beamdump),
+ "{:.0f}".format(self.counter_tmaster_beamdump_last),
+ "{:.0f}".format(
+ self.counter_tmaster_beamdump - self.counter_tmaster_beamdump_last
+ ),
+ ],
+ [
+ "Post Mortem Event Counter",
+ "{:.0f}".format(self.counter_tmaster_postmortem),
+ "{:.0f}".format(self.counter_tmaster_postmortem_last),
+ "{:.0f}".format(
+ self.counter_tmaster_postmortem
+ - self.counter_tmaster_postmortem_last
+ ),
+ ],
+ ],
+ header=True,
+ )
+ )
+
+ self.counter_bdc_last = self.counter_bdc
+ self.counter_dumpkicker_last = self.counter_dumpkicker
+ self.counter_tmaster_beamdump_last = self.counter_tmaster_beamdump
+ self.counter_tmaster_postmortem_last = self.counter_tmaster_postmortem
+
+ self.alive()
+
+ # assign dump to system
+ if self.firstinterlock in [
+ "LLRF for Storage Ring Cavity 1",
+ "LLRF for Storage Ring Cavity 2",
+ "LLRF for Storage Ring Cavity 3",
+ "LLRF for Storage Ring Cavity 4",
+ "LLRF for Super Conducting 3HC",
+ ]:
+ system = "HF"
+ elif self.firstinterlock in ["Orbit Deviation"]:
+ system = "BPMs"
+ elif self.firstinterlock in [
+ "FOFB",
+ "Horizontal Multi Bunch Instability",
+ "Vertical Multi Bunch Instability",
+ "Longitudinal Multi Bunch Instabil",
+ "Filling Patern Deviation",
+ ]:
+ system = "Feedbacks"
+ elif self.firstinterlock in ["Vacuum"]:
+ system = "Vakuum"
+ elif self.firstinterlock in ["PSYS"]:
+ system = "PSYS"
+ elif self.firstinterlock in ["Machine Interlock System"]:
+ system = "MachineInterlockSystem"
+ elif self.firstinterlock in ["Test"]:
+ system = "Test"
+ else:
+ system = "Unbekannt"
+
+ # prepare plots for attachment
+ fig1 = self.makeplots()
+
+ self.alive()
+
+ try:
+ fig2 = self.lpd64plot()
+ file2 = "/sls/op/data/applications/postmortem/{:}_BeamDumpLPD64.png".format(
+ EpicsTimestampStr2FileTimestampStr(self.t0_hla)
+ )
+ fig2.savefig(file2, dpi=192, bbox_inches="tight")
+ file2 = [file2]
+ plt.close(fig2)
+ except:
+ file2 = []
+ print("LPD64 plot failed")
+
+ self.alive()
+
+ file1 = "/sls/op/data/applications/postmortem/{:}_PostMortem.png".format(
+ EpicsTimestampStr2FileTimestampStr(self.t0_hla)
+ )
+ fig1.savefig(file1, dpi=192, bbox_inches="tight")
+ self.list_of_attachments = file2 + [file1]
+ plt.close(fig1)
+
+ self.alive()
+
+ # prepare data file
+ if self.test:
+ file3 = "/sls/op/data/applications/postmortem/{:}_PostMortem_Test.h5".format(
+ EpicsTimestampStr2FileTimestampStr(self.t0_hla)
+ )
+ else:
+ file3 = "/sls/op/data/applications/postmortem/{:}_PostMortem.h5".format(
+ EpicsTimestampStr2FileTimestampStr(self.t0_hla)
+ )
+ data = {
+ "t0_hla": self.t0_hla,
+ "t0_pmioc": self.t0_pmioc,
+ "t0_bdc": self.t0_bdc,
+ "t0_lpd64": self.t0_pmlpd64,
+ "t": self.t,
+ "t2": self.t2,
+ "bdc_delays": self.bdc_delays,
+ "bdc_channel_description": self.bdc_channel_description,
+ "bdc_channel_nr": self.bdc_channel_nr,
+ "counter_bdc": self.counter_bdc,
+ "counter_dumpkicker": self.counter_dumpkicker,
+ "counter_tmaster_beamdump": self.counter_tmaster_beamdump,
+ "counter_tmaster_postmortem": self.counter_tmaster_postmortem,
+ "vcs_alarmlist_infostring": self.vcs_alarmlist[0],
+ "vcs_alarmlist_alarmindex": self.vcs_alarmlist_alarmindex,
+ "vcs_alarmlist_timestamps": self.vcs_alarmlist_timestamps,
+ "vcs_alarmlist_descriptions": self.vcs_alarmlist_descriptions,
+ "mis_alarmlist_infostring": self.mis_alarmlist[0],
+ "mis_alarmlist_alarmindex": self.mis_alarmlist_alarmindex,
+ "mis_alarmlist_timestamps": self.mis_alarmlist_timestamps,
+ "mis_alarmlist_descriptions": self.mis_alarmlist_descriptions,
+ "misfe_alarmlist_infostring": self.misfe_alarmlist[0],
+ "misfe_alarmlist_alarmindex": self.misfe_alarmlist_alarmindex,
+ "misfe_alarmlist_timestamps": self.misfe_alarmlist_timestamps,
+ "misfe_alarmlist_descriptions": self.misfe_alarmlist_descriptions,
+ }
+ data.update(self.PMD)
+
+ self.alive()
+
+ # Write to elog
+ self.logtxt = "".join(self.logtxt)
+
+ self.dict_of_attributes = {
+ "Wann": time(),
+ "Autor": "Post Mortem Logger",
+ "Eintrag": "Post Mortem",
+ "Effekt": "Downtime",
+ "System": "{:}".format(system),
+ "Titel": "Interlock Beam Dump {:.0f}, {:.0f} mA".format(
+ self.counter_bdc, np.nanmax(self.curr)
+ ),
+ "Encoding": "html",
+ }
+
+ self.alive()
+
+ print(" ...elog entry prepared...")
+
+ self.msg_id = self.logbook.post(
+ self.logtxt,
+ attributes=self.dict_of_attributes,
+ attachments=self.list_of_attachments,
+ suppress_email_notification=self.suppress_email_notification,
+ attribute_as_param="value",
+ )
+ print(" ...elog entry submitted...")
+
+ self.alive()
+
+ h5save(file3, data, timestamp=False)
+ print(" {:}".format(file3))
+ print(" ...post mortem data saved")
+
+ self.CallbackFired = 0
+
+ elif self.CallbackFired:
+ print("Beam dump below threshold current detected.")
+ # upate counters for beamdumps from below threshold beam current
+ self.counter_bdc_last = pvs.counter_bdc.get()
+ self.counter_dumpkicker_last = pvs.counter_dumpkicker.get()
+ self.counter_tmaster_beamdump_last = pvs.counter_tmaster_beamdump.get()
+ self.counter_tmaster_postmortem_last = pvs.counter_tmaster_postmortem.get()
+ self.CallbackFired = 0
+
+ def alive(self):
+ # inform watchdog(s) for service run/main state
+ self.pvs.running.put(0)
+ self.pvs.alive.put(0)
+
+ def GascheLines2HTMLtable(self, lines):
+
+ timestamps = [
+ (
+ datetime.strptime(line[6:30], "%Y-%m-%d %H:%M:%S.%f") - datetime(1970, 1, 1)
+ ).total_seconds()
+ for line in lines
+ ]
+ sortindex = np.argsort(timestamps)
+
+ alarmindex = [lines[i][1:4] for i in sortindex]
+ timestamps = [lines[i][6:30] for i in sortindex]
+ descriptions = [lines[i][33:] for i in sortindex]
+
+ self.logtxt.append(
+ htmltable(
+ [["Alarm", "Timestamp", "Description"]]
+ + [[lines[i][1:4], lines[i][6:30], lines[i][33:]] for i in sortindex],
+ header=True,
+ )
+ )
+
+ return alarmindex, timestamps, descriptions
+
+ def makeplots(self):
+
+ # prepare figure
+ Nplotrows = 14
+ Nplotcols = 1
+ bbox = (1.1, 1)
+ fig = plt.figure(figsize=(20, 6 * (Nplotrows + 4)), constrained_layout=True)
+ height_ratios = np.ones(Nplotrows)
+ height_ratios[4] = 3
+ height_ratios[5] = 3
+ GS = fig.add_gridspec(Nplotrows, Nplotcols, height_ratios=list(height_ratios))
+
+ self.alive()
+ # Beam Current and Lifetime
+ index = 0
+ ax = fig.add_subplot(GS[index])
+ ax.plot(
+ self.t,
+ self.PMD["AGEBD-POSTMORTEMLOG:BUFFER-CURRBPM"],
+ "-xg",
+ label="AGEBD-DBPM3CURR:CURRENT-AVG",
+ )
+ ax.plot(
+ self.t,
+ self.PMD["AGEBD-POSTMORTEMLOG:BUFFER-CURRPCT"],
+ "-x",
+ color="lawngreen",
+ label="ARS07-DPCT-0000:CURR",
+ )
+ ax.tick_params(axis="y", colors="g", which="both")
+ ax.set_ylabel("Beam current / mA", color="g")
+ ax.set_xlim([self.t[0], self.t[-1]])
+
+ ax2 = ax.twinx()
+ ax2.plot(self.t, self.PMD["AGEBD-POSTMORTEMLOG:BUFFER-TAUBPM"], "-xb", label="TAUBPM")
+ ax2.plot(
+ self.t,
+ self.PMD["AGEBD-POSTMORTEMLOG:BUFFER-TAUPCT"],
+ "-x",
+ color="cornflowerblue",
+ label="TAUPCT",
+ )
+ ax2.tick_params(axis="y", colors="b", which="both")
+ lines, labels = ax.get_legend_handles_labels()
+ lines2, labels2 = ax2.get_legend_handles_labels()
+ lgnd = ax2.legend(lines + lines2, labels + labels2, loc="upper left", bbox_to_anchor=bbox)
+ for handle in lgnd.legendHandles:
+ handle._markersize = 7
+ handle._linewidth = 2
+ ax2.set_ylabel("Beam lifetime / hours", color="b")
+ ax2.set_xlim([self.t[0], self.t[-1]])
+ ax2.set_ylim([0, 25])
+
+ self.alive()
+ # Tunes
+ index += 1
+ ax = fig.add_subplot(GS[index])
+ ax.plot(
+ self.t,
+ self.PMD["AGEBD-POSTMORTEMLOG:BUFFER-QX"],
+ "-x",
+ color="#2A63E4",
+ label="AGEBD-TUNEBUMP:QX",
+ )
+ ax.plot(
+ self.t,
+ self.PMD["AGEBD-POSTMORTEMLOG:BUFFER-QY"],
+ "-x",
+ color="#8B1A96",
+ label="AGEBD-TUNEBUMP:QY",
+ )
+ ax.set_ylabel("Transverse Tunes")
+ ax.set_xlim([self.t[0], self.t[-1]])
+ ax2 = ax.twinx()
+ ax2.plot(
+ self.t,
+ self.PMD["AGEBD-POSTMORTEMLOG:BUFFER-QZ"],
+ "-x",
+ color="#cd6100",
+ label="GEBD-TUNEBUMP:QZ",
+ )
+ ax2.set_ylabel("Synchrotron Tune")
+ lines, labels = ax.get_legend_handles_labels()
+ lines2, labels2 = ax2.get_legend_handles_labels()
+ lgnd = ax2.legend(lines + lines2, labels + labels2, loc="upper left", bbox_to_anchor=bbox)
+ for handle in lgnd.legendHandles:
+ handle._markersize = 7
+ handle._linewidth = 2
+
+ self.alive()
+ # Beam Size X01DD
+ index += 1
+ ax = fig.add_subplot(GS[index])
+ ax.plot(
+ self.t,
+ self.PMD["AGEBD-POSTMORTEMLOG:BUFFER-X01DD-SIGY"],
+ "-x",
+ color="#8B1A96",
+ label="$\langle\sigma_y\\rangle$={:.1f} µm".format(
+ np.nanmean(self.PMD["AGEBD-POSTMORTEMLOG:BUFFER-X01DD-SIGY"])
+ ),
+ )
+ ax.plot(
+ self.t,
+ self.PMD["AGEBD-POSTMORTEMLOG:BUFFER-X01DD-SIGX"],
+ "-x",
+ color="#2A63E4",
+ label="$\langle\sigma_x\\rangle$={:.1f} µm".format(
+ np.nanmean(self.PMD["AGEBD-POSTMORTEMLOG:BUFFER-X01DD-SIGX"])
+ ),
+ )
+ lines, labels = ax.get_legend_handles_labels()
+ lgnd = ax.legend(lines, labels, loc="upper left", bbox_to_anchor=bbox)
+ for handle in lgnd.legendHandles:
+ handle._markersize = 7
+ handle._linewidth = 2
+ ax.set_ylabel("FZP beam size X01DD / µm")
+ ax.set_xlim([self.t[0], self.t[-1]])
+ ax.set_ylim([0, 30])
+
+ self.alive()
+ # Beam Size X08DB
+ index += 1
+ ax = fig.add_subplot(GS[index])
+ ax.plot(
+ self.t,
+ self.PMD["AGEBD-POSTMORTEMLOG:BUFFER-X08DB-SIGY"],
+ "-x",
+ color="#8B1A96",
+ label="$\langle\sigma_y\\rangle$={:.1f} µm".format(
+ np.nanmean(self.PMD["AGEBD-POSTMORTEMLOG:BUFFER-X08DB-SIGY"])
+ ),
+ )
+ ax.plot(
+ self.t,
+ self.PMD["AGEBD-POSTMORTEMLOG:BUFFER-X08DB-SIGX"],
+ "-x",
+ color="#2A63E4",
+ label="$\langle\sigma_x\\rangle$={:.1f} µm".format(
+ np.nanmean(self.PMD["AGEBD-POSTMORTEMLOG:BUFFER-X08DB-SIGX"])
+ ),
+ )
+ lines, labels = ax.get_legend_handles_labels()
+ lgnd = ax.legend(lines, labels, loc="upper left", bbox_to_anchor=bbox)
+ for handle in lgnd.legendHandles:
+ handle._markersize = 7
+ handle._linewidth = 2
+ ax.set_ylabel("FZP beam size X08DB / µm")
+ ax.set_xlim([self.t[0], self.t[-1]])
+ ax.set_ylim([0, 30])
+
+ self.alive()
+ # Highest Vacuum Pressure for Machine and Frontend
+ index += 1
+ ax = fig.add_subplot(GS[index])
+ ax.plot(
+ self.t,
+ self.PMD["AGEBD-POSTMORTEMLOG:BUFFER-VACMAX"],
+ "-xy",
+ label="ARIVA-VMAVE:PRESS-MAX",
+ )
+ ax.tick_params(axis="y", colors="y", which="both")
+ ax.set_ylabel("Vacuum pressure / mbar", color="y")
+ ax.set_xlim([self.t[0], self.t[-1]])
+
+ ax2 = ax.twinx()
+ ax2.plot(
+ self.t,
+ self.PMD["AGEBD-POSTMORTEMLOG:BUFFER-VACMAXFE"],
+ "-x",
+ color="orange",
+ label="ARIVA-VMAVE-FE:PRESS-MAX",
+ )
+ ax2.tick_params(axis="y", colors="orange", which="both")
+ lines, labels = ax.get_legend_handles_labels()
+ lines2, labels2 = ax2.get_legend_handles_labels()
+ lgnd = ax2.legend(lines + lines2, labels + labels2, loc="upper left", bbox_to_anchor=bbox)
+ for handle in lgnd.legendHandles:
+ handle._markersize = 7
+ handle._linewidth = 2
+ ax2.set_ylabel("Vacuum pressure / mbar", color="orange")
+ ax2.set_xlim([self.t[0], self.t[-1]])
+
+ self.alive()
+ # Absolute Machine Vacuum Peaks
+ index += 1
+ ax = fig.add_subplot(GS[index])
+
+ names_macvac = [key for key in self.PMD if "-VMCC-" in key and not ".timestamp" in key]
+ ranking = np.zeros(len(names_macvac))
+
+ for i, pvname in enumerate(names_macvac):
+ ranking[i] = np.nanmax(self.PMD[pvname])
+
+ for i in np.argsort(ranking)[::-1]:
+ pvname = names_macvac[i]
+ ax.semilogy(
+ self.t,
+ self.PMD[pvname],
+ label="{:}, $p_{{max}}=$ {:.1e}".format(pvname[27:], ranking[i]),
+ )
+
+ ax.set_ylabel("Sorted machine vacuum pressure")
+ ax.set_xlim([self.t[0], self.t[-1]])
+ ax.legend(loc="upper left", bbox_to_anchor=bbox, ncol=2)
+
+ self.alive()
+ # Relative Machine Vacuum Peaks
+ index += 1
+ ax = fig.add_subplot(GS[index])
+
+ datarel = {}
+ ranking = np.zeros(len(names_macvac))
+
+ for i, pvname in enumerate(names_macvac):
+ datarel[pvname] = self.PMD[pvname] / np.nanmin(self.PMD[pvname])
+ ranking[i] = np.nanmax(datarel[pvname])
+
+ for i in np.argsort(ranking)[::-1]:
+ pvname = names_macvac[i]
+ ax.plot(
+ self.t,
+ datarel[pvname],
+ label="{:}, $\delta_{{max}}=$ {:.1f}".format(pvname[27:], ranking[i]),
+ )
+
+ ax.set_ylabel("Sorted relative vacuum pressure change, $\delta_{{max}}=max(p/p_{{min}})$ ")
+ ax.set_ylim([1, np.nanmax(ranking)])
+ ax.set_xlim([self.t[0], self.t[-1]])
+ ax.legend(loc="upper left", bbox_to_anchor=bbox, ncol=2)
+
+ self.alive()
+ # RF Master Oscillator Frequency
+ rf_ref = 499652000
+ index += 1
+ ax = fig.add_subplot(GS[index])
+ ax.plot(
+ self.t,
+ rf_ref - self.PMD["AGEBD-POSTMORTEMLOG:BUFFER-MASTERFREQ-SET"],
+ "-xr",
+ label="AGERF-MO01:FREQ-SET",
+ )
+ ax.plot(
+ self.t,
+ rf_ref - self.PMD["AGEBD-POSTMORTEMLOG:BUFFER-MASTERFREQ-GET"],
+ "-xm",
+ label="AGERF-MO01:FREQ-GET",
+ )
+ ax.tick_params(axis="y", colors="m", which="both")
+ ax.get_yaxis().get_major_formatter().set_scientific(False)
+ ax.get_yaxis().get_major_formatter().set_useOffset(False)
+ lgnd = ax.legend(loc="upper left", bbox_to_anchor=bbox)
+ for handle in lgnd.legendHandles:
+ handle._markersize = 7
+ handle._linewidth = 2
+ ax.set_ylabel(
+ "Master oscillator frequency offset to {:.0f} kHz / Hz".format(rf_ref / 1000), color="m"
+ )
+ ax.set_xlim([self.t[0], self.t[-1]])
+
+ self.alive()
+ # RF Power In/Reflected
+ index += 1
+ c = "m"
+ ax = fig.add_subplot(GS[index])
+ ax.plot(
+ self.t,
+ self.PMD["AGEBD-POSTMORTEMLOG:BUFFER-RFPOW-0060-INP"],
+ "-x",
+ color=c,
+ label="$\\Sigma$ ARS05-RCAV-0060:CO1i-POWER-MAX",
+ )
+ ax.plot(
+ self.t,
+ self.PMD["AGEBD-POSTMORTEMLOG:BUFFER-RFPOW-0140-INP"],
+ "-x",
+ color=c,
+ label="$\\Sigma$ ARS05-RCAV-0140:CO1i-POWER-MAX",
+ )
+ ax.plot(
+ self.t,
+ self.PMD["AGEBD-POSTMORTEMLOG:BUFFER-RFPOW-0230-INP"],
+ "-x",
+ color=c,
+ label="$\\Sigma$ ARS05-RCAV-0230:CO1i-POWER-MAX",
+ )
+ ax.plot(
+ self.t,
+ self.PMD["AGEBD-POSTMORTEMLOG:BUFFER-RFPOW-0310-INP"],
+ "-x",
+ color=c,
+ label="$\\Sigma$ ARS05-RCAV-0310:CO1i-POWER-MAX",
+ )
+ ax.tick_params(axis="y", colors=c, which="both")
+ ax.set_ylabel("Total main RF forward power / kW", color=c)
+ ax.set_xlabel("Time since beam dump / s")
+ ax.set_xlim([self.t[0], self.t[-1]])
+
+ ax2, c = ax.twinx(), "r"
+ ax2.plot(
+ self.t,
+ self.PMD["AGEBD-POSTMORTEMLOG:BUFFER-RFPOW-0060-REF"],
+ "-x",
+ color=c,
+ label="$\\Sigma$ ARS05-RCAV-0060:CO1r-POWER-MAX",
+ )
+ ax2.plot(
+ self.t,
+ self.PMD["AGEBD-POSTMORTEMLOG:BUFFER-RFPOW-0140-REF"],
+ "-x",
+ color=c,
+ label="$\\Sigma$ ARS05-RCAV-0140:CO1r-POWER-MAX",
+ )
+ ax2.plot(
+ self.t,
+ self.PMD["AGEBD-POSTMORTEMLOG:BUFFER-RFPOW-0230-REF"],
+ "-x",
+ color=c,
+ label="$\\Sigma$ ARS05-RCAV-0230:CO1r-POWER-MAX",
+ )
+ ax2.plot(
+ self.t,
+ self.PMD["AGEBD-POSTMORTEMLOG:BUFFER-RFPOW-0310-REF"],
+ "-x",
+ color=c,
+ label="$\\Sigma$ ARS05-RCAV-0310:CO1r-POWER-MAX",
+ )
+ ax2.tick_params(axis="y", colors=c, which="both")
+ lines, labels = ax.get_legend_handles_labels()
+ lines2, labels2 = ax2.get_legend_handles_labels()
+ lgnd = ax2.legend(lines + lines2, labels + labels2, loc="upper left", bbox_to_anchor=bbox)
+ for handle in lgnd.legendHandles:
+ handle._markersize = 7
+ handle._linewidth = 2
+ ax2.set_ylabel("Total main RF reflected power / kW", color=c)
+ ax2.set_xlim([self.t[0], self.t[-1]])
+
+ self.alive()
+ # 4 Kicker Bump
+ index += 1
+ ax = fig.add_subplot(GS[index])
+ ax.plot(
+ self.PMD["ARS01-MKIK-0140:TIME-AXIS"],
+ self.PMD["ARS01-MKIK-0140:CURRENT-WF"],
+ "-x",
+ label="Kicker 1, " + self.PMD["ARS01-MKIK-0140:CURRENT-WF.timestamp"][:-5],
+ )
+ ax.plot(
+ self.PMD["ARS01-MKIK-0220:TIME-AXIS"],
+ self.PMD["ARS01-MKIK-0220:CURRENT-WF"],
+ "-x",
+ label="Kicker 2, " + self.PMD["ARS01-MKIK-0220:CURRENT-WF.timestamp"][:-5],
+ )
+ ax.plot(
+ self.PMD["ARS01-MKIK-0850:TIME-AXIS"],
+ self.PMD["ARS01-MKIK-0850:CURRENT-WF"],
+ "-x",
+ label="Kicker 3, " + self.PMD["ARS01-MKIK-0850:CURRENT-WF.timestamp"][:-5],
+ )
+ ax.plot(
+ self.PMD["ARS01-MKIK-0940:TIME-AXIS"],
+ self.PMD["ARS01-MKIK-0940:CURRENT-WF"],
+ "-x",
+ label="Kicker 4, " + self.PMD["ARS01-MKIK-0940:CURRENT-WF.timestamp"][:-5],
+ )
+ lgnd = ax.legend(loc="upper left", bbox_to_anchor=bbox)
+ for handle in lgnd.legendHandles:
+ handle._markersize = 7
+ handle._linewidth = 2
+ ax.set_ylabel("4-kicker bump kicker current / A")
+ ax.set_xlabel("Time since trigger / us")
+ ax.set_xlim(
+ [self.PMD["ARS01-MKIK-0140:TIME-AXIS"][0], self.PMD["ARS01-MKIK-0140:TIME-AXIS"][-1]]
+ )
+
+ self.alive()
+ # Beam Dump Kicker
+ index += 1
+ ax = fig.add_subplot(GS[index])
+ ax.plot(
+ self.PMD["ARS01-MKIK-0050-1:TIME-AXIS"],
+ self.PMD["ARS01-MKIK-0050-1:CURRENT-WF"],
+ "-x",
+ label="Stage 1, " + self.PMD["ARS01-MKIK-0050-1:CURRENT-WF.timestamp"][:-5],
+ )
+ ax.plot(
+ self.PMD["ARS01-MKIK-0050-2:TIME-AXIS"],
+ self.PMD["ARS01-MKIK-0050-2:CURRENT-WF"],
+ "-x",
+ label="Stage 2, " + self.PMD["ARS01-MKIK-0050-2:CURRENT-WF.timestamp"][:-5],
+ )
+ ax.plot(
+ self.PMD["ARS01-MKIK-0050-3:TIME-AXIS"],
+ self.PMD["ARS01-MKIK-0050-3:CURRENT-WF"],
+ "-x",
+ label="Stage 3, " + self.PMD["ARS01-MKIK-0050-3:CURRENT-WF.timestamp"][:-5],
+ )
+ ax.plot(
+ self.PMD["ARS01-MKIK-0050-4:TIME-AXIS"],
+ self.PMD["ARS01-MKIK-0050-4:CURRENT-WF"],
+ "-x",
+ label="Stage 4, " + self.PMD["ARS01-MKIK-0050-4:CURRENT-WF.timestamp"][:-5],
+ )
+ lgnd = ax.legend(loc="upper left", bbox_to_anchor=bbox)
+ for handle in lgnd.legendHandles:
+ handle._markersize = 7
+ handle._linewidth = 2
+ ax.set_ylabel("Beam dump kicker current / A")
+ ax.set_xlabel("Time since trigger / us")
+ ax.set_xlim(
+ [
+ self.PMD["ARS01-MKIK-0050-1:TIME-AXIS"][0],
+ self.PMD["ARS01-MKIK-0050-1:TIME-AXIS"][-1],
+ ]
+ )
+
+ self.alive()
+ # Libera BLMs 1
+ index += 1
+ ax = fig.add_subplot(GS[index])
+ ax.plot(
+ self.PMD["ABODI-DFBL:SigPm.A"],
+ "-x",
+ label="ABODI-DFBL:SigPm.A, " + self.PMD["ABODI-DFBL:SigPm.A.timestamp"][:-5],
+ )
+ ax.plot(
+ self.PMD["ABODI-DFBL:SigPm.B"],
+ "-x",
+ label="ABODI-DFBL:SigPm.B, " + self.PMD["ABODI-DFBL:SigPm.B.timestamp"][:-5],
+ )
+ ax.plot(
+ self.PMD["ABODI-DFBL:SigPm.C"],
+ "-x",
+ label="ABODI-DFBL:SigPm.C, " + self.PMD["ABODI-DFBL:SigPm.C.timestamp"][:-5],
+ )
+ ax.plot(
+ self.PMD["ABODI-DFBL:SigPm.D"],
+ "-x",
+ label="ABODI-DFBL:SigPm.D, " + self.PMD["ABODI-DFBL:SigPm.D.timestamp"][:-5],
+ )
+ ax.plot(
+ self.PMD["ARS01-DFBL:SigPm.A"],
+ "-x",
+ label="ARS01-DFBL:SigPm.A, " + self.PMD["ARS01-DFBL:SigPm.A.timestamp"][:-5],
+ )
+ ax.plot(
+ self.PMD["ARS01-DFBL:SigPm.B"],
+ "-x",
+ label="ARS01-DFBL:SigPm.B, " + self.PMD["ARS01-DFBL:SigPm.B.timestamp"][:-5],
+ )
+ ax.plot(
+ self.PMD["ARS01-DFBL:SigPm.C"],
+ "-x",
+ label="ARS01-DFBL:SigPm.C, " + self.PMD["ARS01-DFBL:SigPm.C.timestamp"][:-5],
+ )
+ ax.plot(
+ self.PMD["ARS01-DFBL:SigPm.D"],
+ "-x",
+ label="ARS01-DFBL:SigPm.D, " + self.PMD["ARS01-DFBL:SigPm.D.timestamp"][:-5],
+ )
+ ax.plot(
+ self.PMD["ARS02-DFBL:SigPm.A"],
+ "-x",
+ label="ARS02-DFBL:SigPm.A, " + self.PMD["ARS02-DFBL:SigPm.A.timestamp"][:-5],
+ )
+ ax.plot(
+ self.PMD["ARS02-DFBL:SigPm.B"],
+ "-x",
+ label="ARS02-DFBL:SigPm.B, " + self.PMD["ARS02-DFBL:SigPm.B.timestamp"][:-5],
+ )
+ lgnd = ax.legend(loc="upper left", bbox_to_anchor=bbox)
+ for handle in lgnd.legendHandles:
+ handle._markersize = 7
+ handle._linewidth = 2
+ ax.set_ylabel("Libera BLM SUM signal Post Mortem Buffer / (a.u.)")
+ ax.set_xlabel("Turns")
+
+ self.alive()
+ # Libera BLMs 2
+ index += 1
+ ax = fig.add_subplot(GS[index])
+ ax.plot(
+ self.PMD["ARS02-DFBL:SigPm.C"],
+ "-x",
+ label="ARS02-DFBL:SigPm.C, " + self.PMD["ARS02-DFBL:SigPm.C.timestamp"][:-5],
+ )
+ ax.plot(
+ self.PMD["ARS02-DFBL:SigPm.D"],
+ "-x",
+ label="ARS02-DFBL:SigPm.D, " + self.PMD["ARS02-DFBL:SigPm.D.timestamp"][:-5],
+ )
+ ax.plot(
+ self.PMD["ARS06-DFBL:SigPm.A"],
+ "-x",
+ label="ARS06-DFBL:SigPm.A, " + self.PMD["ARS06-DFBL:SigPm.A.timestamp"][:-5],
+ )
+ ax.plot(
+ self.PMD["ARS06-DFBL:SigPm.B"],
+ "-x",
+ label="ARS06-DFBL:SigPm.B, " + self.PMD["ARS06-DFBL:SigPm.B.timestamp"][:-5],
+ )
+ ax.plot(
+ self.PMD["ARS06-DFBL:SigPm.C"],
+ "-x",
+ label="ARS06-DFBL:SigPm.C, " + self.PMD["ARS06-DFBL:SigPm.C.timestamp"][:-5],
+ )
+ ax.plot(
+ self.PMD["ARS06-DFBL:SigPm.D"],
+ "-x",
+ label="ARS06-DFBL:SigPm.D, " + self.PMD["ARS06-DFBL:SigPm.D.timestamp"][:-5],
+ )
+ ax.plot(
+ self.PMD["ARS09-DFBL:SigPm.A"],
+ "-x",
+ label="ARS09-DFBL:SigPm.A, " + self.PMD["ARS09-DFBL:SigPm.A.timestamp"][:-5],
+ )
+ ax.plot(
+ self.PMD["ARS09-DFBL:SigPm.B"],
+ "-x",
+ label="ARS09-DFBL:SigPm.B, " + self.PMD["ARS09-DFBL:SigPm.B.timestamp"][:-5],
+ )
+ ax.plot(
+ self.PMD["ARS09-DFBL:SigPm.C"],
+ "-x",
+ label="ARS09-DFBL:SigPm.C, " + self.PMD["ARS09-DFBL:SigPm.C.timestamp"][:-5],
+ )
+ ax.plot(
+ self.PMD["ARS09-DFBL:SigPm.D"],
+ "-x",
+ label="ARS09-DFBL:SigPm.D, " + self.PMD["ARS09-DFBL:SigPm.D.timestamp"][:-5],
+ )
+ lgnd = ax.legend(loc="upper left", bbox_to_anchor=bbox)
+ for handle in lgnd.legendHandles:
+ handle._markersize = 7
+ handle._linewidth = 2
+ ax.set_ylabel("Libera BLM SUM signal Post Mortem Buffer / (a.u.)")
+ ax.set_xlabel("Turns")
+
+ self.alive()
+ # Filling Pattern
+ index += 1
+ ax = fig.add_subplot(GS[index], projection="3d")
+ # X-AXIS is for the bucket nr.
+ X_bucket = np.arange(480) + 1
+ # Y-AXIS is for the filled charge (the first dataset is the newest)
+ Ndat = len(self.PMD["AGEBD-POSTMORTEMLOG:BUFFER-FILLPATTERN-APD"])
+ # Z-AXIS is for the individual plots, i.e., the time before the dump
+ Z_Nplots = self.t2
+ # Color-AXIS is duplicate of the Z and time axis for easier visual
+ N = 5
+ colors = np.tile(plt.cm.get_cmap("hsv", Ndat / N)(np.linspace(0, 1, int(Ndat / N))), (N, 1))
+
+ def plot2din3d(x, y, z, c):
+ ax.plot(x, y, zs=z, zdir="z", color=c)
+ col_obj = ax.fill_between(x, 0, y, step="pre", color=c, alpha=0.1)
+ ax.add_collection3d(col_obj, zs=z, zdir="z")
+
+ for y, z, c in zip(
+ self.PMD["AGEBD-POSTMORTEMLOG:BUFFER-FILLPATTERN-APD"], Z_Nplots, colors
+ ):
+ plot2din3d(X_bucket, y, z, c)
+
+ ax.set_xlabel("Bucket nr.")
+ ax.set_ylabel("Charge / nC")
+ ax.set_zlabel("Time since beam dump / s")
+ ax.view_init(elev=40.0, azim=80)
+ ax.set_box_aspect((16, 9, 5), zoom=1.2)
+
+ return fig
+
+ def lpd64plot(self):
+
+ fig, (axu, axl) = plt.subplots(
+ 2,
+ 1,
+ figsize=(20, 9),
+ sharex=True,
+ tight_layout=True,
+ gridspec_kw={"height_ratios": [1, 3], "hspace": 0},
+ )
+
+ (l4,) = axu.plot(
+ self.PMD["ARF-LPD64:X-AXIS-CH1"] / 1e3,
+ self.PMD["ARF-LPD64:CH1-DATA"],
+ "y+-",
+ label="Filling Pattern BPM ARS01-DBPM-0530",
+ lw=1,
+ )
+ axu.set_ylabel("BPM Sum / V")
+ axu.set_ylim([-80, 80])
+ axu.set_xlim(
+ [
+ np.nanmin(self.PMD["ARF-LPD64:X-AXIS-CH4"]) / 1e3,
+ np.nanmax(self.PMD["ARF-LPD64:X-AXIS-CH4"]) / 1e3,
+ ]
+ )
+
+ (l1,) = axl.plot(
+ self.PMD["ARF-LPD64:X-AXIS-CH4"] / 1e3,
+ self.PMD["ARF-LPD64:CH4-DATA"] / 1e3,
+ "g+-",
+ label="Beam Dump Kicker Magnet, BDC delay = {:.0f} ns".format(
+ self.PMD["AGESA-SBDC-0000:BUNCH0_MAGNET_RAMP_DELAY"]
+ ),
+ lw=1,
+ )
+ axl.set_ylabel("Beam Dump Kicker Pulse / V")
+ axl.set_xlabel("Time relative to dump kick / µs")
+ axl.set_ylim([-0.09, 1.85])
+ axl.set_xlim(
+ [
+ np.nanmin(self.PMD["ARF-LPD64:X-AXIS-CH4"]) / 1e3,
+ np.nanmax(self.PMD["ARF-LPD64:X-AXIS-CH4"]) / 1e3,
+ ]
+ )
+ axl.xaxis.set_ticks(np.arange(-1400 / 1e3, 1401 / 1e3, 200 / 1e3))
+ axl.xaxis.grid()
+
+ axt = axl.twinx()
+
+ i1 = np.where(
+ np.abs(self.PMD["ARF-LPD64:CH3-DATA"]) > np.nanmax(self.PMD["ARF-LPD64:CH3-DATA"]) / 4
+ )[0][0]
+ i2 = np.where(
+ np.abs(self.PMD["ARF-LPD64:CH3-DATA"]) > np.nanmax(self.PMD["ARF-LPD64:CH3-DATA"]) / 4
+ )[0][-1]
+ dt1 = self.PMD["ARF-LPD64:X-AXIS-CH3"][i2] - self.PMD["ARF-LPD64:X-AXIS-CH3"][i1]
+ axt.axvspan(
+ self.PMD["ARF-LPD64:X-AXIS-CH3"][i1] / 1e3,
+ self.PMD["ARF-LPD64:X-AXIS-CH3"][i2] / 1e3,
+ color="red",
+ alpha=0.1,
+ )
+ (l2,) = axt.plot(
+ self.PMD["ARF-LPD64:X-AXIS-CH3"] / 1e3,
+ np.abs(self.PMD["ARF-LPD64:CH3-DATA"]),
+ "r-",
+ label="Beam Dump Cherenkov Fiber, Δt={:.1f} ns".format(dt1),
+ lw=1,
+ )
+
+ i1 = np.where(
+ np.abs(self.PMD["ARF-LPD64:CH2-DATA"]) > np.nanmax(self.PMD["ARF-LPD64:CH2-DATA"]) / 4
+ )[0][0]
+ i2 = np.where(
+ np.abs(self.PMD["ARF-LPD64:CH2-DATA"]) > np.nanmax(self.PMD["ARF-LPD64:CH2-DATA"]) / 4
+ )[0][-1]
+ dt2 = self.PMD["ARF-LPD64:X-AXIS-CH2"][i2] - self.PMD["ARF-LPD64:X-AXIS-CH2"][i1]
+ axt.axvspan(
+ self.PMD["ARF-LPD64:X-AXIS-CH2"][i1] / 1e3,
+ self.PMD["ARF-LPD64:X-AXIS-CH2"][i2] / 1e3,
+ color="blue",
+ alpha=0.1,
+ )
+ (l3,) = axt.plot(
+ self.PMD["ARF-LPD64:X-AXIS-CH2"] / 1e3,
+ np.abs(self.PMD["ARF-LPD64:CH2-DATA"]),
+ "b-",
+ label="Septa Cherenkov Fiber, Δt={:.1f} ns".format(dt2),
+ lw=1,
+ )
+ axt.set_ylabel("Photomultiplier / mV")
+ axt.set_ylim([0, 1500])
+ axt.set_xlim(
+ [
+ np.nanmin(self.PMD["ARF-LPD64:X-AXIS-CH4"]) / 1e3,
+ np.nanmax(self.PMD["ARF-LPD64:X-AXIS-CH4"]) / 1e3,
+ ]
+ )
+ axt.grid()
+
+ leg = axt.legend(
+ handles=[l4, l1, l2, l3],
+ loc="upper left",
+ frameon=True,
+ facecolor="white",
+ framealpha=1,
+ title="Post Mortem Scope, " + self.t0_pmlpd64,
+ )
+ fig.subplots_adjust(hspace=0)
+
+ return fig
diff --git a/services/postmortemlog/current/app/tests/test_app.py b/services/postmortemlog/current/app/tests/test_app.py
new file mode 100644
index 0000000..3da58c5
--- /dev/null
+++ b/services/postmortemlog/current/app/tests/test_app.py
@@ -0,0 +1,9 @@
+from agebd_postmortemlog import PVs, Service
+
+
+def test_app():
+ service_name = "DUMMY"
+ pvs = PVs(service_name=service_name)
+ service = Service(name=service_name, pvs=pvs)
+ service.CallbackFired = 1
+ service.update()
diff --git a/services/postmortemlog/current/app/uv.lock b/services/postmortemlog/current/app/uv.lock
new file mode 100644
index 0000000..284dc68
--- /dev/null
+++ b/services/postmortemlog/current/app/uv.lock
@@ -0,0 +1,456 @@
+version = 1
+revision = 3
+requires-python = "==3.10.*"
+
+[[package]]
+name = "agebd"
+version = "0.1.0"
+source = { editable = "../../../../packages/agebd" }
+dependencies = [
+ { name = "h5py" },
+ { name = "typer" },
+]
+
+[package.metadata]
+requires-dist = [
+ { name = "h5py", specifier = ">=3.16.0" },
+ { name = "typer", specifier = ">=0.23.2" },
+]
+
+[package.metadata.requires-dev]
+dev = [
+ { name = "pyright", specifier = ">=1.1.410" },
+ { name = "pytest", specifier = ">=8.4.2" },
+ { name = "ruff", specifier = ">=0.15.19" },
+]
+
+[[package]]
+name = "agebd-postmortemlog"
+version = "0.1.0"
+source = { editable = "." }
+dependencies = [
+ { name = "agebd" },
+ { name = "matplotlib" },
+ { name = "numpy" },
+ { name = "urllib3" },
+]
+
+[package.dev-dependencies]
+dev = [
+ { name = "pyepics" },
+ { name = "pytest" },
+ { name = "ruff" },
+]
+
+[package.metadata]
+requires-dist = [
+ { name = "agebd", editable = "../../../../packages/agebd" },
+ { name = "matplotlib", specifier = ">=3.10.9" },
+ { name = "numpy", specifier = ">=2.0.2" },
+ { name = "urllib3", specifier = ">=2.7.0" },
+]
+
+[package.metadata.requires-dev]
+dev = [
+ { name = "pyepics", specifier = ">=3.5.8" },
+ { name = "pytest", specifier = ">=8.4.2" },
+ { name = "ruff", specifier = ">=0.15.20" },
+]
+
+[[package]]
+name = "annotated-doc"
+version = "0.0.4"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/57/ba/046ceea27344560984e26a590f90bc7f4a75b06701f653222458922b558c/annotated_doc-0.0.4.tar.gz", hash = "sha256:fbcda96e87e9c92ad167c2e53839e57503ecfda18804ea28102353485033faa4", size = 7288, upload-time = "2025-11-10T22:07:42.062Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl", hash = "sha256:571ac1dc6991c450b25a9c2d84a3705e2ae7a53467b5d111c24fa8baabbed320", size = 5303, upload-time = "2025-11-10T22:07:40.673Z" },
+]
+
+[[package]]
+name = "colorama"
+version = "0.4.6"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" },
+]
+
+[[package]]
+name = "contourpy"
+version = "1.3.2"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "numpy" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/66/54/eb9bfc647b19f2009dd5c7f5ec51c4e6ca831725f1aea7a993034f483147/contourpy-1.3.2.tar.gz", hash = "sha256:b6945942715a034c671b7fc54f9588126b0b8bf23db2696e3ca8328f3ff0ab54", size = 13466130, upload-time = "2025-04-15T17:47:53.79Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/12/a3/da4153ec8fe25d263aa48c1a4cbde7f49b59af86f0b6f7862788c60da737/contourpy-1.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ba38e3f9f330af820c4b27ceb4b9c7feee5fe0493ea53a8720f4792667465934", size = 268551, upload-time = "2025-04-15T17:34:46.581Z" },
+ { url = "https://files.pythonhosted.org/packages/2f/6c/330de89ae1087eb622bfca0177d32a7ece50c3ef07b28002de4757d9d875/contourpy-1.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:dc41ba0714aa2968d1f8674ec97504a8f7e334f48eeacebcaa6256213acb0989", size = 253399, upload-time = "2025-04-15T17:34:51.427Z" },
+ { url = "https://files.pythonhosted.org/packages/c1/bd/20c6726b1b7f81a8bee5271bed5c165f0a8e1f572578a9d27e2ccb763cb2/contourpy-1.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9be002b31c558d1ddf1b9b415b162c603405414bacd6932d031c5b5a8b757f0d", size = 312061, upload-time = "2025-04-15T17:34:55.961Z" },
+ { url = "https://files.pythonhosted.org/packages/22/fc/a9665c88f8a2473f823cf1ec601de9e5375050f1958cbb356cdf06ef1ab6/contourpy-1.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8d2e74acbcba3bfdb6d9d8384cdc4f9260cae86ed9beee8bd5f54fee49a430b9", size = 351956, upload-time = "2025-04-15T17:35:00.992Z" },
+ { url = "https://files.pythonhosted.org/packages/25/eb/9f0a0238f305ad8fb7ef42481020d6e20cf15e46be99a1fcf939546a177e/contourpy-1.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e259bced5549ac64410162adc973c5e2fb77f04df4a439d00b478e57a0e65512", size = 320872, upload-time = "2025-04-15T17:35:06.177Z" },
+ { url = "https://files.pythonhosted.org/packages/32/5c/1ee32d1c7956923202f00cf8d2a14a62ed7517bdc0ee1e55301227fc273c/contourpy-1.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad687a04bc802cbe8b9c399c07162a3c35e227e2daccf1668eb1f278cb698631", size = 325027, upload-time = "2025-04-15T17:35:11.244Z" },
+ { url = "https://files.pythonhosted.org/packages/83/bf/9baed89785ba743ef329c2b07fd0611d12bfecbedbdd3eeecf929d8d3b52/contourpy-1.3.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:cdd22595308f53ef2f891040ab2b93d79192513ffccbd7fe19be7aa773a5e09f", size = 1306641, upload-time = "2025-04-15T17:35:26.701Z" },
+ { url = "https://files.pythonhosted.org/packages/d4/cc/74e5e83d1e35de2d28bd97033426b450bc4fd96e092a1f7a63dc7369b55d/contourpy-1.3.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b4f54d6a2defe9f257327b0f243612dd051cc43825587520b1bf74a31e2f6ef2", size = 1374075, upload-time = "2025-04-15T17:35:43.204Z" },
+ { url = "https://files.pythonhosted.org/packages/0c/42/17f3b798fd5e033b46a16f8d9fcb39f1aba051307f5ebf441bad1ecf78f8/contourpy-1.3.2-cp310-cp310-win32.whl", hash = "sha256:f939a054192ddc596e031e50bb13b657ce318cf13d264f095ce9db7dc6ae81c0", size = 177534, upload-time = "2025-04-15T17:35:46.554Z" },
+ { url = "https://files.pythonhosted.org/packages/54/ec/5162b8582f2c994721018d0c9ece9dc6ff769d298a8ac6b6a652c307e7df/contourpy-1.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:c440093bbc8fc21c637c03bafcbef95ccd963bc6e0514ad887932c18ca2a759a", size = 221188, upload-time = "2025-04-15T17:35:50.064Z" },
+ { url = "https://files.pythonhosted.org/packages/33/05/b26e3c6ecc05f349ee0013f0bb850a761016d89cec528a98193a48c34033/contourpy-1.3.2-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:fd93cc7f3139b6dd7aab2f26a90dde0aa9fc264dbf70f6740d498a70b860b82c", size = 265681, upload-time = "2025-04-15T17:44:59.314Z" },
+ { url = "https://files.pythonhosted.org/packages/2b/25/ac07d6ad12affa7d1ffed11b77417d0a6308170f44ff20fa1d5aa6333f03/contourpy-1.3.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:107ba8a6a7eec58bb475329e6d3b95deba9440667c4d62b9b6063942b61d7f16", size = 315101, upload-time = "2025-04-15T17:45:04.165Z" },
+ { url = "https://files.pythonhosted.org/packages/8f/4d/5bb3192bbe9d3f27e3061a6a8e7733c9120e203cb8515767d30973f71030/contourpy-1.3.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:ded1706ed0c1049224531b81128efbd5084598f18d8a2d9efae833edbd2b40ad", size = 220599, upload-time = "2025-04-15T17:45:08.456Z" },
+]
+
+[[package]]
+name = "cycler"
+version = "0.12.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/a9/95/a3dbbb5028f35eafb79008e7522a75244477d2838f38cbb722248dabc2a8/cycler-0.12.1.tar.gz", hash = "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c", size = 7615, upload-time = "2023-10-07T05:32:18.335Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30", size = 8321, upload-time = "2023-10-07T05:32:16.783Z" },
+]
+
+[[package]]
+name = "exceptiongroup"
+version = "1.3.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "typing-extensions" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" },
+]
+
+[[package]]
+name = "fonttools"
+version = "4.63.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/84/69/c97f2c18e0db87d2c7b15da1974dace76ae938f1cfa22e2727a648b7ed43/fonttools-4.63.0.tar.gz", hash = "sha256:caeb583deeb5168e694b65cda8b4ee62abedfa66cf88488734466f2366b9c4e0", size = 3597189, upload-time = "2026-05-14T12:04:30.958Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/f2/c9/4141c90a90db20f807c7e10bfd689fe53eb8f7f4caff58ee4d4dfe46919f/fonttools-4.63.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e3297a6a4059b4acc3a1e9a8b04741f240a80044eef08ebd32e8b5bcdddce75b", size = 2884632, upload-time = "2026-05-14T12:02:38.56Z" },
+ { url = "https://files.pythonhosted.org/packages/b8/46/ad12b5c10eae602d7ef814b02afa08aacbf89da917fed5b071282b7eadc2/fonttools-4.63.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b1cd75a03ad8cb5bc40c90bfde68c0c47de423aa19e5c0f362b43520645eea94", size = 2429441, upload-time = "2026-05-14T12:02:41.162Z" },
+ { url = "https://files.pythonhosted.org/packages/90/8f/bdca24a84c81d56fffed052229cdcff368f6e05882e526f4558891481f65/fonttools-4.63.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c0425b277a59cff3d80ca42162a8de360f318438a2ac83570842a678d826d579", size = 4946346, upload-time = "2026-05-14T12:02:43.41Z" },
+ { url = "https://files.pythonhosted.org/packages/04/59/a639c0e136441ee91a65b56fdf89e5d075927e7a09c559d1b0f5276577db/fonttools-4.63.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d7e5c9973aa04c95650c96e5f5ad865fbf42d62079163ecfab1e01cbc2504c22", size = 4903184, upload-time = "2026-05-14T12:02:45.742Z" },
+ { url = "https://files.pythonhosted.org/packages/e6/53/91b7e0cb45b536f3da1b29ba8cbab89f27e8b986809e0b1982303a3f4eca/fonttools-4.63.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:cb014d58140a38135f16064c74c652ed57aa0b75cbf8bb59cac821f7edb5334e", size = 4922967, upload-time = "2026-05-14T12:02:48.386Z" },
+ { url = "https://files.pythonhosted.org/packages/c7/b7/87439bf44e6b97c5538cd29d0b7e366a5b8ce2cc132a4134fb67fa3f2fa2/fonttools-4.63.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:032038247a96c1690f9f31e377c389383c902531b085aa4e4dabd6f57f870e69", size = 5042799, upload-time = "2026-05-14T12:02:50.424Z" },
+ { url = "https://files.pythonhosted.org/packages/ad/7c/8b96c3263b89ef99cded544c0f0636686f85dbd3c211c4dceef0231fca23/fonttools-4.63.0-cp310-cp310-win32.whl", hash = "sha256:a8b33a82979e0a6a34ff435cc81317be1f95ec1ebb7a3a2d1c8a6a54f02ae44e", size = 1519704, upload-time = "2026-05-14T12:02:52.523Z" },
+ { url = "https://files.pythonhosted.org/packages/e5/4d/2c2f0069970b6907de8fb5b05c5c0193cc22f717df151d1c7aef1c738f58/fonttools-4.63.0-cp310-cp310-win_amd64.whl", hash = "sha256:0c18358a155d75034911c5ee397a5b44cd19dd325dbb8b35fb60bf421d6a72ac", size = 1568666, upload-time = "2026-05-14T12:02:54.917Z" },
+ { url = "https://files.pythonhosted.org/packages/2c/47/c99d5268f354002ce80f8d029cd9d7d872969da1de8b93d32de4dc56d6f4/fonttools-4.63.0-py3-none-any.whl", hash = "sha256:445af2eab030a16b9171ea8bdda7ebf7d96bda2df88ee182a464252f6e05e20d", size = 1164562, upload-time = "2026-05-14T12:04:29.092Z" },
+]
+
+[[package]]
+name = "h5py"
+version = "3.16.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "numpy" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/db/33/acd0ce6863b6c0d7735007df01815403f5589a21ff8c2e1ee2587a38f548/h5py-3.16.0.tar.gz", hash = "sha256:a0dbaad796840ccaa67a4c144a0d0c8080073c34c76d5a6941d6818678ef2738", size = 446526, upload-time = "2026-03-06T13:49:08.07Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/3a/6b/231413e58a787a89b316bb0d1777da3c62257e4797e09afd8d17ad3549dc/h5py-3.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e06f864bedb2c8e7c1358e6c73af48519e317457c444d6f3d332bb4e8fa6d7d9", size = 3724137, upload-time = "2026-03-06T13:47:35.242Z" },
+ { url = "https://files.pythonhosted.org/packages/74/f9/557ce3aad0fe8471fb5279bab0fc56ea473858a022c4ce8a0b8f303d64e9/h5py-3.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ec86d4fffd87a0f4cb3d5796ceb5a50123a2a6d99b43e616e5504e66a953eca3", size = 3090112, upload-time = "2026-03-06T13:47:37.634Z" },
+ { url = "https://files.pythonhosted.org/packages/7a/f5/e15b3d0dc8a18e56409a839e6468d6fb589bc5207c917399c2e0706eeb44/h5py-3.16.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:86385ea895508220b8a7e45efa428aeafaa586bd737c7af9ee04661d8d84a10d", size = 4844847, upload-time = "2026-03-06T13:47:39.811Z" },
+ { url = "https://files.pythonhosted.org/packages/cb/92/a8851d936547efe30cc0ce5245feac01f3ec6171f7899bc3f775c72030b3/h5py-3.16.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:8975273c2c5921c25700193b408e28d6bdd0111c37468b2d4e25dcec4cd1d84d", size = 5065352, upload-time = "2026-03-06T13:47:41.489Z" },
+ { url = "https://files.pythonhosted.org/packages/2b/ae/f2adc5d0ca9626db3277a3d87516e124cbc5d0eea0bd79bc085702d04f2c/h5py-3.16.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:1677ad48b703f44efc9ea0c3ab284527f81bc4f318386aaaebc5fede6bbae56f", size = 4839173, upload-time = "2026-03-06T13:47:43.586Z" },
+ { url = "https://files.pythonhosted.org/packages/64/0b/e0c8c69da1d8838da023a50cd3080eae5d475691f7636b35eff20bb6ef20/h5py-3.16.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7c4dd4cf5f0a4e36083f73172f6cfc25a5710789269547f132a20975bfe2434c", size = 5076216, upload-time = "2026-03-06T13:47:45.315Z" },
+ { url = "https://files.pythonhosted.org/packages/66/35/d88fd6718832133c885004c61ceeeb24dbd6397ef877dbed6b3a64d6a286/h5py-3.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:bdef06507725b455fccba9c16529121a5e1fbf56aa375f7d9713d9e8ff42454d", size = 3183639, upload-time = "2026-03-06T13:47:47.041Z" },
+]
+
+[[package]]
+name = "iniconfig"
+version = "2.3.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" },
+]
+
+[[package]]
+name = "kiwisolver"
+version = "1.5.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d0/67/9c61eccb13f0bdca9307614e782fec49ffdde0f7a2314935d489fa93cd9c/kiwisolver-1.5.0.tar.gz", hash = "sha256:d4193f3d9dc3f6f79aaed0e5637f45d98850ebf01f7ca20e69457f3e8946b66a", size = 103482, upload-time = "2026-03-09T13:15:53.382Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/ac/f8/06549565caa026e540b7e7bab5c5a90eb7ca986015f4c48dace243cd24d9/kiwisolver-1.5.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:32cc0a5365239a6ea0c6ed461e8838d053b57e397443c0ca894dcc8e388d4374", size = 122802, upload-time = "2026-03-09T13:12:37.515Z" },
+ { url = "https://files.pythonhosted.org/packages/84/eb/8476a0818850c563ff343ea7c9c05dcdcbd689a38e01aa31657df01f91fa/kiwisolver-1.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:cc0b66c1eec9021353a4b4483afb12dfd50e3669ffbb9152d6842eb34c7e29fd", size = 66216, upload-time = "2026-03-09T13:12:38.812Z" },
+ { url = "https://files.pythonhosted.org/packages/f3/c4/f9c8a6b4c21aed4198566e45923512986d6cef530e7263b3a5f823546561/kiwisolver-1.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:86e0287879f75621ae85197b0877ed2f8b7aa57b511c7331dce2eb6f4de7d476", size = 63917, upload-time = "2026-03-09T13:12:40.053Z" },
+ { url = "https://files.pythonhosted.org/packages/f1/0e/ba4ae25d03722f64de8b2c13e80d82ab537a06b30fc7065183c6439357e3/kiwisolver-1.5.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:62f59da443c4f4849f73a51a193b1d9d258dcad0c41bc4d1b8fb2bcc04bfeb22", size = 1628776, upload-time = "2026-03-09T13:12:41.976Z" },
+ { url = "https://files.pythonhosted.org/packages/8a/e4/3f43a011bc8a0860d1c96f84d32fa87439d3feedf66e672fef03bf5e8bac/kiwisolver-1.5.0-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9190426b7aa26c5229501fa297b8d0653cfd3f5a36f7990c264e157cbf886b3b", size = 1228164, upload-time = "2026-03-09T13:12:44.002Z" },
+ { url = "https://files.pythonhosted.org/packages/4b/34/3a901559a1e0c218404f9a61a93be82d45cb8f44453ba43088644980f033/kiwisolver-1.5.0-cp310-cp310-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c8277104ded0a51e699c8c3aff63ce2c56d4ed5519a5f73e0fd7057f959a2b9e", size = 1246656, upload-time = "2026-03-09T13:12:45.557Z" },
+ { url = "https://files.pythonhosted.org/packages/87/9e/f78c466ea20527822b95ad38f141f2de1dcd7f23fb8716b002b0d91bbe59/kiwisolver-1.5.0-cp310-cp310-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8f9baf6f0a6e7571c45c8863010b45e837c3ee1c2c77fcd6ef423be91b21fedb", size = 1295562, upload-time = "2026-03-09T13:12:47.562Z" },
+ { url = "https://files.pythonhosted.org/packages/0a/66/fd0e4a612e3a286c24e6d6f3a5428d11258ed1909bc530ba3b59807fd980/kiwisolver-1.5.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:cff8e5383db4989311f99e814feeb90c4723eb4edca425b9d5d9c3fefcdd9537", size = 2178473, upload-time = "2026-03-09T13:12:50.254Z" },
+ { url = "https://files.pythonhosted.org/packages/dc/8e/6cac929e0049539e5ee25c1ee937556f379ba5204840d03008363ced662d/kiwisolver-1.5.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:ebae99ed6764f2b5771c522477b311be313e8841d2e0376db2b10922daebbba4", size = 2274035, upload-time = "2026-03-09T13:12:51.785Z" },
+ { url = "https://files.pythonhosted.org/packages/ca/d3/9d0c18f1b52ea8074b792452cf17f1f5a56bd0302a85191f405cfbf9da16/kiwisolver-1.5.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:d5cd5189fc2b6a538b75ae45433140c4823463918f7b1617c31e68b085c0022c", size = 2443217, upload-time = "2026-03-09T13:12:53.329Z" },
+ { url = "https://files.pythonhosted.org/packages/45/2a/6e19368803a038b2a90857bf4ee9e3c7b667216d045866bf22d3439fd75e/kiwisolver-1.5.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f42c23db5d1521218a3276bb08666dcb662896a0be7347cba864eca45ff64ede", size = 2249196, upload-time = "2026-03-09T13:12:55.057Z" },
+ { url = "https://files.pythonhosted.org/packages/75/2b/3f641dfcbe72e222175d626bacf2f72c3b34312afec949dd1c50afa400f5/kiwisolver-1.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:94eff26096eb5395136634622515b234ecb6c9979824c1f5004c6e3c3c85ccd2", size = 73389, upload-time = "2026-03-09T13:12:56.496Z" },
+ { url = "https://files.pythonhosted.org/packages/da/88/299b137b9e0025d8982e03d2d52c123b0a2b159e84b0ef1501ef446339cf/kiwisolver-1.5.0-cp310-cp310-win_arm64.whl", hash = "sha256:dd952e03bfbb096cfe2dd35cd9e00f269969b67536cb4370994afc20ff2d0875", size = 64782, upload-time = "2026-03-09T13:12:57.609Z" },
+ { url = "https://files.pythonhosted.org/packages/17/6f/6fd4f690a40c2582fa34b97d2678f718acf3706b91d270c65ecb455d0a06/kiwisolver-1.5.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:295d9ffe712caa9f8a3081de8d32fc60191b4b51c76f02f951fd8407253528f4", size = 59606, upload-time = "2026-03-09T13:15:40.81Z" },
+ { url = "https://files.pythonhosted.org/packages/82/a0/2355d5e3b338f13ce63f361abb181e3b6ea5fffdb73f739b3e80efa76159/kiwisolver-1.5.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:51e8c4084897de9f05898c2c2a39af6318044ae969d46ff7a34ed3f96274adca", size = 57537, upload-time = "2026-03-09T13:15:42.071Z" },
+ { url = "https://files.pythonhosted.org/packages/c8/b9/1d50e610ecadebe205b71d6728fd224ce0e0ca6aba7b9cbe1da049203ac5/kiwisolver-1.5.0-pp310-pypy310_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b83af57bdddef03c01a9138034c6ff03181a3028d9a1003b301eb1a55e161a3f", size = 79888, upload-time = "2026-03-09T13:15:43.317Z" },
+ { url = "https://files.pythonhosted.org/packages/cd/ee/b85ffcd75afed0357d74f0e6fc02a4507da441165de1ca4760b9f496390d/kiwisolver-1.5.0-pp310-pypy310_pp73-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bf4679a3d71012a7c2bf360e5cd878fbd5e4fcac0896b56393dec239d81529ed", size = 77584, upload-time = "2026-03-09T13:15:44.605Z" },
+ { url = "https://files.pythonhosted.org/packages/6b/dd/644d0dde6010a8583b4cd66dd41c5f83f5325464d15c4f490b3340ab73b4/kiwisolver-1.5.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:41024ed50e44ab1a60d3fe0a9d15a4ccc9f5f2b1d814ff283c8d01134d5b81bc", size = 73390, upload-time = "2026-03-09T13:15:45.832Z" },
+]
+
+[[package]]
+name = "markdown-it-py"
+version = "4.2.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "mdurl" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/06/ff/7841249c247aa650a76b9ee4bbaeae59370dc8bfd2f6c01f3630c35eb134/markdown_it_py-4.2.0.tar.gz", hash = "sha256:04a21681d6fbb623de53f6f364d352309d4094dd4194040a10fd51833e418d49", size = 82454, upload-time = "2026-05-07T12:08:28.36Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl", hash = "sha256:9f7ebbcd14fe59494226453aed97c1070d83f8d24b6fc3a3bcf9a38092641c4a", size = 91687, upload-time = "2026-05-07T12:08:27.182Z" },
+]
+
+[[package]]
+name = "matplotlib"
+version = "3.10.9"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "contourpy" },
+ { name = "cycler" },
+ { name = "fonttools" },
+ { name = "kiwisolver" },
+ { name = "numpy" },
+ { name = "packaging" },
+ { name = "pillow" },
+ { name = "pyparsing" },
+ { name = "python-dateutil" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/63/1b/4be5be87d43d327a0cf4de1a56e86f7f84c89312452406cf122efe2839e6/matplotlib-3.10.9.tar.gz", hash = "sha256:fd66508e8c6877d98e586654b608a0456db8d7e8a546eb1e2600efd957302358", size = 34811233, upload-time = "2026-04-24T00:14:13.539Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/18/6f/340b04986e67aac6f66c5145ce68bf72c64bed30f92c8913499a6e6b8f99/matplotlib-3.10.9-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:77210dce9cb8153dffc967efaae990543392563d5a376d4dd8539bebcb0ed217", size = 8296625, upload-time = "2026-04-24T00:11:43.376Z" },
+ { url = "https://files.pythonhosted.org/packages/bb/2f/127081eb83162053ebb9678ceac64220b93a663e0167432566e9c7c82aab/matplotlib-3.10.9-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1e7698ac9868428e84d2c967424803b2472ff7167d9d6590d4204ed775343c3b", size = 8188790, upload-time = "2026-04-24T00:11:46.556Z" },
+ { url = "https://files.pythonhosted.org/packages/fc/b7/d8bcec2626c35f96972bff656299fef4578113ea6193c8fdad324710410c/matplotlib-3.10.9-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1aa972116abb4c9d201bf245620b433726cb6856f3bef6a78f776a00f5c92d37", size = 8769389, upload-time = "2026-04-24T00:11:48.959Z" },
+ { url = "https://files.pythonhosted.org/packages/12/49/b78e214a527ea732033b7f4d37f7afb504d74ba9d134bd47938230dfb8b1/matplotlib-3.10.9-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ae2f11957b27ce53497dd4d7b235c4d4f1faf383dfb39d0c5beb833bff883294", size = 9589657, upload-time = "2026-04-24T00:11:51.915Z" },
+ { url = "https://files.pythonhosted.org/packages/5f/15/5246f7b43beae19c74dfee651d58d6cc8112e06f77adb4e88cc04f2e3a23/matplotlib-3.10.9-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b049278ddce116aaa1c1377ebf58adea909132dfce0281cf7e3a1ea9fc2e2c65", size = 9651983, upload-time = "2026-04-24T00:11:54.766Z" },
+ { url = "https://files.pythonhosted.org/packages/75/77/5acecfe672ba0fa1b8c0454f69ce155d1e6fc5852fa7206bf9afaf767121/matplotlib-3.10.9-cp310-cp310-win_amd64.whl", hash = "sha256:82834c3c292d24d3a8aae77cd2d20019de69d692a34a970e4fdb8d33e2ea3dda", size = 8199701, upload-time = "2026-04-24T00:11:58.389Z" },
+ { url = "https://files.pythonhosted.org/packages/2c/2b/0e92ad0ac446633f928a1563db4aa8add407e1924faf0ded5b95b35afb27/matplotlib-3.10.9-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:1872fb212a05b729e649754a72d5da61d03e0554d76e80303b6f83d1d2c0552b", size = 8293058, upload-time = "2026-04-24T00:13:56.339Z" },
+ { url = "https://files.pythonhosted.org/packages/4b/23/74682fd369f5299ceda438fea2a0662e6383b85c9383fb9cdfcf04713e07/matplotlib-3.10.9-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:985f2238880e2e69093f588f5fe2e46771747febf0649f3cf7f7b7480875317f", size = 8186627, upload-time = "2026-04-24T00:13:58.623Z" },
+ { url = "https://files.pythonhosted.org/packages/ca/e8/368aab88f3c4cd8992800f31abfe0670c3e47540ba20a97e9fdbcde594b3/matplotlib-3.10.9-pp310-pypy310_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:6640f75af2c6148293caa0a2b39dd806a492dd66c8a8b04035813e33d0fd2585", size = 8764117, upload-time = "2026-04-24T00:14:01.684Z" },
+]
+
+[[package]]
+name = "mdurl"
+version = "0.1.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" },
+]
+
+[[package]]
+name = "numpy"
+version = "2.2.6"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/76/21/7d2a95e4bba9dc13d043ee156a356c0a8f0c6309dff6b21b4d71a073b8a8/numpy-2.2.6.tar.gz", hash = "sha256:e29554e2bef54a90aa5cc07da6ce955accb83f21ab5de01a62c8478897b264fd", size = 20276440, upload-time = "2025-05-17T22:38:04.611Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/9a/3e/ed6db5be21ce87955c0cbd3009f2803f59fa08df21b5df06862e2d8e2bdd/numpy-2.2.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b412caa66f72040e6d268491a59f2c43bf03eb6c96dd8f0307829feb7fa2b6fb", size = 21165245, upload-time = "2025-05-17T21:27:58.555Z" },
+ { url = "https://files.pythonhosted.org/packages/22/c2/4b9221495b2a132cc9d2eb862e21d42a009f5a60e45fc44b00118c174bff/numpy-2.2.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e41fd67c52b86603a91c1a505ebaef50b3314de0213461c7a6e99c9a3beff90", size = 14360048, upload-time = "2025-05-17T21:28:21.406Z" },
+ { url = "https://files.pythonhosted.org/packages/fd/77/dc2fcfc66943c6410e2bf598062f5959372735ffda175b39906d54f02349/numpy-2.2.6-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:37e990a01ae6ec7fe7fa1c26c55ecb672dd98b19c3d0e1d1f326fa13cb38d163", size = 5340542, upload-time = "2025-05-17T21:28:30.931Z" },
+ { url = "https://files.pythonhosted.org/packages/7a/4f/1cb5fdc353a5f5cc7feb692db9b8ec2c3d6405453f982435efc52561df58/numpy-2.2.6-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:5a6429d4be8ca66d889b7cf70f536a397dc45ba6faeb5f8c5427935d9592e9cf", size = 6878301, upload-time = "2025-05-17T21:28:41.613Z" },
+ { url = "https://files.pythonhosted.org/packages/eb/17/96a3acd228cec142fcb8723bd3cc39c2a474f7dcf0a5d16731980bcafa95/numpy-2.2.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:efd28d4e9cd7d7a8d39074a4d44c63eda73401580c5c76acda2ce969e0a38e83", size = 14297320, upload-time = "2025-05-17T21:29:02.78Z" },
+ { url = "https://files.pythonhosted.org/packages/b4/63/3de6a34ad7ad6646ac7d2f55ebc6ad439dbbf9c4370017c50cf403fb19b5/numpy-2.2.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc7b73d02efb0e18c000e9ad8b83480dfcd5dfd11065997ed4c6747470ae8915", size = 16801050, upload-time = "2025-05-17T21:29:27.675Z" },
+ { url = "https://files.pythonhosted.org/packages/07/b6/89d837eddef52b3d0cec5c6ba0456c1bf1b9ef6a6672fc2b7873c3ec4e2e/numpy-2.2.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:74d4531beb257d2c3f4b261bfb0fc09e0f9ebb8842d82a7b4209415896adc680", size = 15807034, upload-time = "2025-05-17T21:29:51.102Z" },
+ { url = "https://files.pythonhosted.org/packages/01/c8/dc6ae86e3c61cfec1f178e5c9f7858584049b6093f843bca541f94120920/numpy-2.2.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8fc377d995680230e83241d8a96def29f204b5782f371c532579b4f20607a289", size = 18614185, upload-time = "2025-05-17T21:30:18.703Z" },
+ { url = "https://files.pythonhosted.org/packages/5b/c5/0064b1b7e7c89137b471ccec1fd2282fceaae0ab3a9550f2568782d80357/numpy-2.2.6-cp310-cp310-win32.whl", hash = "sha256:b093dd74e50a8cba3e873868d9e93a85b78e0daf2e98c6797566ad8044e8363d", size = 6527149, upload-time = "2025-05-17T21:30:29.788Z" },
+ { url = "https://files.pythonhosted.org/packages/a3/dd/4b822569d6b96c39d1215dbae0582fd99954dcbcf0c1a13c61783feaca3f/numpy-2.2.6-cp310-cp310-win_amd64.whl", hash = "sha256:f0fd6321b839904e15c46e0d257fdd101dd7f530fe03fd6359c1ea63738703f3", size = 12904620, upload-time = "2025-05-17T21:30:48.994Z" },
+ { url = "https://files.pythonhosted.org/packages/9e/3b/d94a75f4dbf1ef5d321523ecac21ef23a3cd2ac8b78ae2aac40873590229/numpy-2.2.6-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0b605b275d7bd0c640cad4e5d30fa701a8d59302e127e5f79138ad62762c3e3d", size = 21040391, upload-time = "2025-05-17T21:44:35.948Z" },
+ { url = "https://files.pythonhosted.org/packages/17/f4/09b2fa1b58f0fb4f7c7963a1649c64c4d315752240377ed74d9cd878f7b5/numpy-2.2.6-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:7befc596a7dc9da8a337f79802ee8adb30a552a94f792b9c9d18c840055907db", size = 6786754, upload-time = "2025-05-17T21:44:47.446Z" },
+ { url = "https://files.pythonhosted.org/packages/af/30/feba75f143bdc868a1cc3f44ccfa6c4b9ec522b36458e738cd00f67b573f/numpy-2.2.6-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce47521a4754c8f4593837384bd3424880629f718d87c5d44f8ed763edd63543", size = 16643476, upload-time = "2025-05-17T21:45:11.871Z" },
+ { url = "https://files.pythonhosted.org/packages/37/48/ac2a9584402fb6c0cd5b5d1a91dcf176b15760130dd386bbafdbfe3640bf/numpy-2.2.6-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d042d24c90c41b54fd506da306759e06e568864df8ec17ccc17e9e884634fd00", size = 12812666, upload-time = "2025-05-17T21:45:31.426Z" },
+]
+
+[[package]]
+name = "packaging"
+version = "26.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d7/f1/e7a6dd94a8d4a5626c03e4e99c87f241ba9e350cd9e6d75123f992427270/packaging-26.2.tar.gz", hash = "sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661", size = 228134, upload-time = "2026-04-24T20:15:23.917Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/df/b2/87e62e8c3e2f4b32e5fe99e0b86d576da1312593b39f47d8ceef365e95ed/packaging-26.2-py3-none-any.whl", hash = "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e", size = 100195, upload-time = "2026-04-24T20:15:22.081Z" },
+]
+
+[[package]]
+name = "pillow"
+version = "12.3.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/1c/3d/bb7fca845737cf9d7dbde16ed1843984665ff2e0a518f5db43e77ec540b9/pillow-12.3.0.tar.gz", hash = "sha256:3b8182a766685eaa002637e28b4ec8d6b18819a0c71f579bf0dbaa5830297cce", size = 47025035, upload-time = "2026-07-01T11:56:38.965Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/25/c2/669d88644cddb1485bd9534e63e8cf476c8e51cb3c3a1297677023505c0e/pillow-12.3.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:6c0016e7b354317c4e9e525b937ac8596c38d2d232b419529b9cd7a1cd46e39a", size = 5392418, upload-time = "2026-07-01T11:53:27.808Z" },
+ { url = "https://files.pythonhosted.org/packages/6b/ba/3762f376a2948e3036488d773a146e0ae6ecc2ca03ac20e2615bd0b2ba02/pillow-12.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:bcc33feacfaefce60c12fd500a277533bdc02b10a19f7f6d348763d8140bbba7", size = 4785287, upload-time = "2026-07-01T11:53:29.761Z" },
+ { url = "https://files.pythonhosted.org/packages/07/50/b5d688cc9c52d4482f3d5bcab6ce20bc2a74a85d2343841c907444a3be2c/pillow-12.3.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5594fc43d548a7ed94949d139aa1341b270f1863f11cfd37f5a6c8b778a6b67f", size = 6253754, upload-time = "2026-07-01T11:53:32.298Z" },
+ { url = "https://files.pythonhosted.org/packages/4e/89/36f4cd76cf4baf05c50ababb976249153f18c959171c7f6ba09a6f217260/pillow-12.3.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f0606c8bf2cdefea14a43530f7657cbbb7ecf1c4222512492ef4a4434a9501ec", size = 6925605, upload-time = "2026-07-01T11:53:34.487Z" },
+ { url = "https://files.pythonhosted.org/packages/eb/c0/4de58cf6633b9e3a6061ef4be6fb91fc3c90b812ece886f531e3c523d777/pillow-12.3.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:85f998ea1848bc6757289e739cfbdda3a04adfd58b02fc018ce54d754a5ce468", size = 6327788, upload-time = "2026-07-01T11:53:36.433Z" },
+ { url = "https://files.pythonhosted.org/packages/87/3c/14d53682a19550dbbaf3b598f807d5457646c510805a44c7d7891cd1cd1a/pillow-12.3.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:25b9b82bb22e6e2b3cd07b39c68b7b862001226cb3dff7130d1cb914121b39ed", size = 7036288, upload-time = "2026-07-01T11:53:38.712Z" },
+ { url = "https://files.pythonhosted.org/packages/38/1d/36279e3c77efe034e4cc2b0393ee74ffdb5a62391dacbf9b916154f5f0b8/pillow-12.3.0-cp310-cp310-win32.whl", hash = "sha256:37dc8f7bbb66efe481bb60defacef820c950c24713fb44962ed6aa2a50966de1", size = 6472396, upload-time = "2026-07-01T11:53:40.781Z" },
+ { url = "https://files.pythonhosted.org/packages/48/7c/8fa0039574c476d7c6fa57dd7c32a130436877c6ec1e5ce1cc8ec44878c1/pillow-12.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:300557495eb45ebb8aec96c2da9c4be642fbf7cd937278b4013ba894ea8eb0eb", size = 7226887, upload-time = "2026-07-01T11:53:42.764Z" },
+ { url = "https://files.pythonhosted.org/packages/fa/17/e324be141d173c1c919428066c3259f21c1b8982e564e01a4a81e96dbdcf/pillow-12.3.0-cp310-cp310-win_arm64.whl", hash = "sha256:514435a37670e3e5e08f3945b68718b6ed329bb84367777e16f9f4dfe1e61a0f", size = 2568039, upload-time = "2026-07-01T11:53:45.372Z" },
+]
+
+[[package]]
+name = "pluggy"
+version = "1.6.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" },
+]
+
+[[package]]
+name = "pyepics"
+version = "3.5.10"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "numpy" },
+ { name = "pyparsing" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/69/57/29e1e9ef11ba2a3419f489946ae1d8190025a1e4f4e1c1686758bb2b6e0a/pyepics-3.5.10.tar.gz", hash = "sha256:f390cf9be40aba757b9528888114bc14d8db01086d0c93914720b1772460375b", size = 6150481, upload-time = "2026-05-20T18:44:36.336Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d6/36/e517fd83bd97d6bfe4105e0c6b322070c5cc36fb56a8fab2866e319f8804/pyepics-3.5.10-py3-none-any.whl", hash = "sha256:c9fac2c54f2b595268e66fc348cf5ec24e63718e7dbd07d73d1b37d4da6bfee1", size = 5332376, upload-time = "2026-05-20T18:44:34.242Z" },
+]
+
+[[package]]
+name = "pygments"
+version = "2.20.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" },
+]
+
+[[package]]
+name = "pyparsing"
+version = "3.3.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f3/91/9c6ee907786a473bf81c5f53cf703ba0957b23ab84c264080fb5a450416f/pyparsing-3.3.2.tar.gz", hash = "sha256:c777f4d763f140633dcb6d8a3eda953bf7a214dc4eff598413c070bcdc117cbc", size = 6851574, upload-time = "2026-01-21T03:57:59.36Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl", hash = "sha256:850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d", size = 122781, upload-time = "2026-01-21T03:57:55.912Z" },
+]
+
+[[package]]
+name = "pytest"
+version = "9.1.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "colorama", marker = "sys_platform == 'win32'" },
+ { name = "exceptiongroup" },
+ { name = "iniconfig" },
+ { name = "packaging" },
+ { name = "pluggy" },
+ { name = "pygments" },
+ { name = "tomli" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/e4/47/b9efed96c114afcfa3c9d3fe98a76a1d14c74a9e266d397cf6eb64be5e01/pytest-9.1.1.tar.gz", hash = "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313", size = 1636369, upload-time = "2026-06-19T10:58:32.857Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/24/25/1de2678b631f5a49215c6c96fff41ba892b0a34df68d6d80292b1b48aa7f/pytest-9.1.1-py3-none-any.whl", hash = "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c", size = 386536, upload-time = "2026-06-19T10:58:31.347Z" },
+]
+
+[[package]]
+name = "python-dateutil"
+version = "2.9.0.post0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "six" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" },
+]
+
+[[package]]
+name = "rich"
+version = "15.0.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "markdown-it-py" },
+ { name = "pygments" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/c0/8f/0722ca900cc807c13a6a0c696dacf35430f72e0ec571c4275d2371fca3e9/rich-15.0.0.tar.gz", hash = "sha256:edd07a4824c6b40189fb7ac9bc4c52536e9780fbbfbddf6f1e2502c31b068c36", size = 230680, upload-time = "2026-04-12T08:24:00.75Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl", hash = "sha256:33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb", size = 310654, upload-time = "2026-04-12T08:24:02.83Z" },
+]
+
+[[package]]
+name = "ruff"
+version = "0.15.21"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/0f/36/6f65aa9989acdec45d417192d8f4e7921931d8a6cf87ac74bce3eed98a8e/ruff-0.15.21.tar.gz", hash = "sha256:d0cfc841c572283c36548f82664a54ce6565567f1b0d5b4cf2caac693d8b7500", size = 4769401, upload-time = "2026-07-09T20:01:34.005Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d0/c6/ede15cac6839f3dbce52565c8f5164a8210e669c7bc4decb03e5bdf47d0d/ruff-0.15.21-py3-none-linux_armv6l.whl", hash = "sha256:63ea0e965e5d73c90e95b2434beeafc70820536717f561b32ab6e777cb9bdf5d", size = 10854342, upload-time = "2026-07-09T20:00:53.998Z" },
+ { url = "https://files.pythonhosted.org/packages/28/9d/d825b07ee7ea9e2d61df92a860033c94e06e7300d50a1c2653aac27d24fe/ruff-0.15.21-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:0f212c5d7d54c01bbfe6dcab02b724a39300f3e34ed7acbe995ccb320a2c58bd", size = 11139539, upload-time = "2026-07-09T20:00:57.809Z" },
+ { url = "https://files.pythonhosted.org/packages/f5/de/3b107712e642f063c7a9e0887c427b22cb44097de5aab36c05f2e280670c/ruff-0.15.21-py3-none-macosx_11_0_arm64.whl", hash = "sha256:e6312e41bc96791299614995ea3a977c5857c3b5662b1ecef6755b02b87cb646", size = 10595437, upload-time = "2026-07-09T20:01:00.006Z" },
+ { url = "https://files.pythonhosted.org/packages/9a/6f/b4523cc90ba239ede441447a19d0c968846a3012e5a0b0c5b62831a3d5e3/ruff-0.15.21-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01d65b4831c6b2a4ba8ee6faa84049d44d982b7a706e622c4094c509e51673be", size = 10990053, upload-time = "2026-07-09T20:01:02.187Z" },
+ { url = "https://files.pythonhosted.org/packages/92/cc/c6a9872a5375f0628875481cf2f66b13d7d865bf3ca2e57f91c7e762d976/ruff-0.15.21-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2c5a913a589120ce67933d5d05fd6ddbcc2481c6a054980ee767f7414c72b4fd", size = 10666096, upload-time = "2026-07-09T20:01:04.299Z" },
+ { url = "https://files.pythonhosted.org/packages/ab/97/c621f7a17e097f1790fa3af6374138823b330b2d03fc38337945daca212c/ruff-0.15.21-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ef04b681d02ad4dc9620f00f83ac5c22f652d0e9a9cfe431d219b16ad5ccc41", size = 11537011, upload-time = "2026-07-09T20:01:06.771Z" },
+ { url = "https://files.pythonhosted.org/packages/ea/51/d928727e476e25ccc57c6f449ffd80241a651a973ad949d39cfb2a771d28/ruff-0.15.21-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:16d090c0740916594157e75b80d666eab8e78083b39b3b0e1d698f4670a17b86", size = 12347101, upload-time = "2026-07-09T20:01:08.859Z" },
+ { url = "https://files.pythonhosted.org/packages/1e/88/8cd62026802b16018ad06931d87997cf795ba2a6239ab659606c87d96bf0/ruff-0.15.21-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3a10e74757dd65004d779b73e2f3c5210156d9980b41224d50d2ebcf1db51e67", size = 11572001, upload-time = "2026-07-09T20:01:11.092Z" },
+ { url = "https://files.pythonhosted.org/packages/b2/97/f63084cf55444fc110e8cb985ebfcc592af47f597d44453d778cb81bc156/ruff-0.15.21-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bab0905d2f29e0d9fbc3c373ed23db0095edaa3f71f1f4f519ec15134d9e85c8", size = 11549239, upload-time = "2026-07-09T20:01:13.27Z" },
+ { url = "https://files.pythonhosted.org/packages/9d/77/f107da4a2874b7715914b03f09ba9c54424de3ff8a1cc5d015d3ee2ce0ac/ruff-0.15.21-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:00eca240af5789fec6fe7df74c088cc1f9644ed83027113468efba7c92b94075", size = 11535340, upload-time = "2026-07-09T20:01:15.206Z" },
+ { url = "https://files.pythonhosted.org/packages/d5/e9/601deb322d3303a7bf212b0100ead6f2ee3f6a044d89c30f2f92bf83c731/ruff-0.15.21-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:262ab31557a75141325e32d3357f3597645a7f084e732b6b054dde428ecd9341", size = 10964048, upload-time = "2026-07-09T20:01:17.723Z" },
+ { url = "https://files.pythonhosted.org/packages/ea/2e/0f2176d1e99c15192caea19c8c3a0a955246b4cb4de795042eeb616345cd/ruff-0.15.21-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:659c4e7a4212f83306045ec7c5e5a356d16d9a6ef4ae0c7a4d872914fc655d9d", size = 10667055, upload-time = "2026-07-09T20:01:19.73Z" },
+ { url = "https://files.pythonhosted.org/packages/48/60/abd74a02e0c4214f12a68becfd30af7165cfdcb0e661ecdc60bbb949c09a/ruff-0.15.21-py3-none-musllinux_1_2_i686.whl", hash = "sha256:9e866eab611a5f959d36df2d10e446973a3610bc42b0c15b31dc27977d59c233", size = 11242043, upload-time = "2026-07-09T20:01:21.947Z" },
+ { url = "https://files.pythonhosted.org/packages/b2/c6/583075d8ccabb4b229345edcaf1545eb3d8d6be90f686a479d7e94088bbf/ruff-0.15.21-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e89bc93c0d3803ba870b55c29671bad9dc6d94bb1eb181b056b52eb05b52854f", size = 11648064, upload-time = "2026-07-09T20:01:24.023Z" },
+ { url = "https://files.pythonhosted.org/packages/3a/3c/37d0ecb729a7cc2d393ea7dce316fc585680f35d93b8d62139d7d0a3700c/ruff-0.15.21-py3-none-win32.whl", hash = "sha256:01f8d5be84823c172b389e123174f781f9daf86d6c58719d603f941932195cdd", size = 10896555, upload-time = "2026-07-09T20:01:26.941Z" },
+ { url = "https://files.pythonhosted.org/packages/c0/b8/e43466b2a6067ce91e669068f6e28d6c719a920f014b070d5c8731725de3/ruff-0.15.21-py3-none-win_amd64.whl", hash = "sha256:d4b8d9a2f0f12b816b50447f6eccb9f4bb01a6b82c86b50fb3b5354b458dc6d3", size = 12038772, upload-time = "2026-07-09T20:01:29.497Z" },
+ { url = "https://files.pythonhosted.org/packages/dd/75/e90ab9aeece218a9fc5a5bc3ec97d0ee6bb3c4ff95869463c1de58e29a1c/ruff-0.15.21-py3-none-win_arm64.whl", hash = "sha256:6e83115d4b9377c1cbc13abf0e051f069fab0ef815ea0504a8a008cee24dd0a8", size = 11375265, upload-time = "2026-07-09T20:01:31.772Z" },
+]
+
+[[package]]
+name = "shellingham"
+version = "1.5.4"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/58/15/8b3609fd3830ef7b27b655beb4b4e9c62313a4e8da8c676e142cc210d58e/shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de", size = 10310, upload-time = "2023-10-24T04:13:40.426Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755, upload-time = "2023-10-24T04:13:38.866Z" },
+]
+
+[[package]]
+name = "six"
+version = "1.17.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" },
+]
+
+[[package]]
+name = "tomli"
+version = "2.4.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/22/de/48c59722572767841493b26183a0d1cc411d54fd759c5607c4590b6563a6/tomli-2.4.1.tar.gz", hash = "sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f", size = 17543, upload-time = "2026-03-25T20:22:03.828Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/7b/61/cceae43728b7de99d9b847560c262873a1f6c98202171fd5ed62640b494b/tomli-2.4.1-py3-none-any.whl", hash = "sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe", size = 14583, upload-time = "2026-03-25T20:22:03.012Z" },
+]
+
+[[package]]
+name = "typer"
+version = "0.27.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "annotated-doc" },
+ { name = "colorama", marker = "sys_platform == 'win32'" },
+ { name = "rich" },
+ { name = "shellingham" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/37/78/fda3361b56efc27944f24225f6ecd13d96d6fcfe37bd0eb34e2f4c63f9fc/typer-0.27.0.tar.gz", hash = "sha256:629bd12ea5d13a17148125d9a264f949eb171fb3f120f9b04d85873cab054fa5", size = 203430, upload-time = "2026-07-15T19:21:07.007Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/40/03/26a383c9e58c213199d1aad1c3d353cfc22d4444ec6d2c0bf8ad02523843/typer-0.27.0-py3-none-any.whl", hash = "sha256:6f4b27631e47f077871b7dc30e933ec0131c1390fbe0e387ea5574b5bac9ccf1", size = 122716, upload-time = "2026-07-15T19:21:05.553Z" },
+]
+
+[[package]]
+name = "typing-extensions"
+version = "4.16.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f6/cc/6253133b5bb138fc3306cebfbda2c520f545d36b5be2c7255cc528bb45d6/typing_extensions-4.16.0.tar.gz", hash = "sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5", size = 113555, upload-time = "2026-07-02T08:40:05.92Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/49/d3/b8441a820a491ddfc024b0b0cf0393375b75ea13866d9c66727e54c2fc80/typing_extensions-4.16.0-py3-none-any.whl", hash = "sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8", size = 45571, upload-time = "2026-07-02T08:40:04.659Z" },
+]
+
+[[package]]
+name = "urllib3"
+version = "2.7.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/53/0c/06f8b233b8fd13b9e5ee11424ef85419ba0d8ba0b3138bf360be2ff56953/urllib3-2.7.0.tar.gz", hash = "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c", size = 433602, upload-time = "2026-05-07T16:13:18.596Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/7f/3e/5db95bcf282c52709639744ca2a8b149baccf648e39c8cc87553df9eae0c/urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897", size = 131087, upload-time = "2026-05-07T16:13:17.151Z" },
+]
diff --git a/services/postmortemlog/current/ioc/AGEBD-CPCL-POSTMORTEMLOG_main.subs b/services/postmortemlog/current/ioc/AGEBD-CPCL-POSTMORTEMLOG_main.subs
new file mode 100644
index 0000000..628ba75
--- /dev/null
+++ b/services/postmortemlog/current/ioc/AGEBD-CPCL-POSTMORTEMLOG_main.subs
@@ -0,0 +1,129 @@
+file POSTMORTEMLOG.template {
+ pattern
+ { DEVICE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env}} }
+}
+
+file POSTMORTEMLOG_15min10Hz.template {
+ pattern
+ { DEVICE NAME INP}
+ # ---------- BEAM CURRENT --------------
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} CURRBPM AGEBD-DBPM3CURR:CURRENT-AVG }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} CURRPCT ARS07-DPCT-0000:CURR }
+ # ---------- BEAM LIFETIME --------------
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} TAUBPM AGEBD-TAUBPM:TAU }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} TAUPCT AGEBD-TAUPCT:TAU }
+ # ---------- TUNES --------------
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} QX AGEBD-TUNEBUMP:QX }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} QY AGEBD-TUNEBUMP:QY }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} QZ AGEBD-TUNEBUMP:QZ }
+ # ---------- LOSSES --------------
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS01-DDRM-0375 ARS01-DDRM-0375:FET1_DOSE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ABRTL-DDRM-0670 ABRTL-DDRM-0670:FET1_BIAS_DOSE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ABRTL-DDRM-0950 ABRTL-DDRM-0950:FET1_DOSE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS01-DDRM-1530 ARS01-DDRM-1530:FET1_BIAS_DOSE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} X05LA-DDRM-0330 X05LA-DDRM-0330:FET1_BIAS_DOSE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS05-DDRM-1530 ARS05-DDRM-1530:FET1_BIAS_DOSE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS05-DDRM-3500 ARS05-DDRM-3500:FET1_BIAS_DOSE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} X09LA-DDRM-0330 X09LA-DDRM-0330:FET1_BIAS_DOSE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS09-DDRM-1530 ARS09-DDRM-1530:FET1_BIAS_DOSE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS09-DDRM-3500 ARS09-DDRM-3500:FET2_BIAS_DOSE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS12-DDRM-1530 ARS12-DDRM-1530:FET1_BIAS_DOSE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS12-DDRM-3500 ARS12-DDRM-3500:FET2_BIAS_DOSE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS12-DDRM-4400 ARS12-DDRM-4400:FET2_BIAS_DOSE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS12-DDRM-5480 ARS12-DDRM-5480:FET1_BIAS_DOSE }
+ # ---------- RF --------------
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} MASTERFREQ-SET AGERF-MO01:FREQ-SET }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} MASTERFREQ-GET AGERF-MO01:FREQ-GET }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} RFPOW-0140-INP ARS05-RCAV-0140:CO1i-POWER-MAX }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} RFPOW-0060-INP ARS05-RCAV-0060:CO1i-POWER-MAX }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} RFPOW-0230-INP ARS05-RCAV-0230:CO1i-POWER-MAX }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} RFPOW-0310-INP ARS05-RCAV-0310:CO1i-POWER-MAX }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} RFPOW-0060-REF ARS05-RCAV-0060:CO1r-POWER-MAX }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} RFPOW-0140-REF ARS05-RCAV-0140:CO1r-POWER-MAX }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} RFPOW-0230-REF ARS05-RCAV-0230:CO1r-POWER-MAX }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} RFPOW-0310-REF ARS05-RCAV-0310:CO1r-POWER-MAX }
+ # ---------- BEAM SIZE --------------
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} X01DD-SIGX X01DD-FE-CAM1:SIG-X }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} X01DD-SIGY X01DD-FE-CAM1:SIG-Y }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} X08DB-SIGX X08DB-FE-CAM1:SIG-X }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} X08DB-SIGY X08DB-FE-CAM1:SIG-Y }
+ # ---------- VACUUM --------------
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} VACMAX ARIVA-VMAVE:PRESS-MAX }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} VACMAXFE ARIVA-VMAVE-FE:PRESS-MAX }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS01-VMCC-0110 ARS01-VMCC-0110:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS01-VMCC-0210 ARS01-VMCC-0210:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS01-VMCC-0225 ARS01-VMCC-0225:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS01-VMCC-0310 ARS01-VMCC-0310:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS01-VMCC-1550 ARS01-VMCC-1550:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS01-VMCC-3510 ARS01-VMCC-3510:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS01-VMCC-5460 ARS01-VMCC-5460:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS02-VMCC-0110 ARS02-VMCC-0110:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS02-VMCC-0210 ARS02-VMCC-0210:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS02-VMCC-0310 ARS02-VMCC-0310:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS02-VMCC-1550 ARS02-VMCC-1550:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS02-VMCC-3510 ARS02-VMCC-3510:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS02-VMCC-5460 ARS02-VMCC-5460:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS03-VMCC-0110 ARS03-VMCC-0110:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS03-VMCC-0320 ARS03-VMCC-0320:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS03-VMCC-1550 ARS03-VMCC-1550:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS03-VMCC-3510 ARS03-VMCC-3510:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS03-VMCC-5460 ARS03-VMCC-5460:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS04-VMCC-0110 ARS04-VMCC-0110:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS04-VMCC-1550 ARS04-VMCC-1550:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS04-VMCC-3510 ARS04-VMCC-3510:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS04-VMCC-5460 ARS04-VMCC-5460:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS05-VMCC-0110 ARS05-VMCC-0110:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS05-VMCC-0115 ARS05-VMCC-0115:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS05-VMCC-0210 ARS05-VMCC-0210:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS05-VMCC-0215 ARS05-VMCC-0215:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS05-VMCC-0310 ARS05-VMCC-0310:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS05-VMCC-0315 ARS05-VMCC-0315:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS05-VMCC-0410 ARS05-VMCC-0410:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS05-VMCC-0415 ARS05-VMCC-0415:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS05-VMCC-0510 ARS05-VMCC-0510:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS05-VMCC-0520 ARS05-VMCC-0520:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS05-VMCC-0530 ARS05-VMCC-0530:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS05-VMCC-0810 ARS05-VMCC-0810:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS05-VMCC-1550 ARS05-VMCC-1550:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS05-VMCC-3510 ARS05-VMCC-3510:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS05-VMCC-5460 ARS05-VMCC-5460:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS06-VMCC-0110 ARS06-VMCC-0110:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS06-VMCC-1550 ARS06-VMCC-1550:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS06-VMCC-3510 ARS06-VMCC-3510:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS06-VMCC-5460 ARS06-VMCC-5460:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS07-VMCC-0010 ARS07-VMCC-0010:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS07-VMCC-0120 ARS07-VMCC-0120:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS07-VMCC-0210 ARS07-VMCC-0210:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS07-VMCC-1550 ARS07-VMCC-1550:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS07-VMCC-3510 ARS07-VMCC-3510:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS07-VMCC-5460 ARS07-VMCC-5460:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS08-VMCC-0110 ARS08-VMCC-0110:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS08-VMCC-1550 ARS08-VMCC-1550:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS08-VMCC-3510 ARS08-VMCC-3510:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS08-VMCC-5460 ARS08-VMCC-5460:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS09-VMCC-0110 ARS09-VMCC-0110:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS09-VMCC-0120 ARS09-VMCC-0120:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS09-VMCC-0410 ARS09-VMCC-0410:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS09-VMCC-0510 ARS09-VMCC-0510:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS09-VMCC-0810 ARS09-VMCC-0810:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS09-VMCC-1550 ARS09-VMCC-1550:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS09-VMCC-3510 ARS09-VMCC-3510:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS09-VMCC-5460 ARS09-VMCC-5460:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS10-VMCC-0110 ARS10-VMCC-0110:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS10-VMCC-1550 ARS10-VMCC-1550:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS10-VMCC-3510 ARS10-VMCC-3510:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS10-VMCC-5460 ARS10-VMCC-5460:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS11-VMCC-0110 ARS11-VMCC-0110:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS11-VMCC-0210 ARS11-VMCC-0210:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS11-VMCC-0310 ARS11-VMCC-0310:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS11-VMCC-0410 ARS11-VMCC-0410:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS11-VMCC-0510 ARS11-VMCC-0510:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS11-VMCC-1550 ARS11-VMCC-1550:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS11-VMCC-3510 ARS11-VMCC-3510:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS11-VMCC-5460 ARS11-VMCC-5460:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS12-VMCC-0110 ARS12-VMCC-0110:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS12-VMCC-1550 ARS12-VMCC-1550:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS12-VMCC-3510 ARS12-VMCC-3510:PRESSURE }
+ { AGEBD-POSTMORTEMLOG{{ agebd_env }} ARS12-VMCC-5460 ARS12-VMCC-5460:PRESSURE }
+}
diff --git a/services/postmortemlog/current/ioc/AGEBD-CPCL-POSTMORTEMLOG_parameters.yaml b/services/postmortemlog/current/ioc/AGEBD-CPCL-POSTMORTEMLOG_parameters.yaml
new file mode 100644
index 0000000..ff8e70f
--- /dev/null
+++ b/services/postmortemlog/current/ioc/AGEBD-CPCL-POSTMORTEMLOG_parameters.yaml
@@ -0,0 +1,6 @@
+cpu_architecture: x86_64
+epics_version: 7.0.8
+ioc_host: sls-vserv-bd-01{{ agebd_env }}
+ioc_port: {{ ioc_port }}
+os: RHEL8
+os_id: rhel
diff --git a/services/postmortemlog/current/ioc/POSTMORTEMLOG.template b/services/postmortemlog/current/ioc/POSTMORTEMLOG.template
new file mode 100644
index 0000000..857d84a
--- /dev/null
+++ b/services/postmortemlog/current/ioc/POSTMORTEMLOG.template
@@ -0,0 +1,37 @@
+# This is a template for preaparing an IOC providing BD Service specific PVs
+# Access Security Groups:
+# DEFAULT - logt wenn EGU oder so veraendert werden
+# LOG - logt wenn neuer wert geschrieben wird
+# PROTECTED - verhindert versuchte caputs auf alle fields ausser VAL
+# READONLY - verhindert versuchte caputs und aktiviert caputlog
+# Input links can specify CA, CP, or CPP.
+# If the input link specifies CA, it will be forced to be a Channel Access link.
+# If the input link specifies CP, it will also be forced to be a Channel Access link; in addition, it will cause the record containing the input link to process whenever a monitor is posted, no matter what the record's SCAN field specifies.
+# If the input link specifies CPP, it means the same thing as CP, except that the record will be processed if and only if the record itself specifies passive in its SCAN field. Output links can specify CA, which will simply cause them to be Channel Access links.
+#
+
+record(ao, "$(DEVICE):AO") {
+ field(DESC, "Analog Output Record (ao)")
+ field(ASG, "PROTECTED")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(bo, "$(DEVICE):BO") {
+ field(DESC, "Binary Output Record (bo)")
+ field(ASG, "READONLY")
+ field(ZSV, "MINOR")
+ field(OSV, "NO_ALARM")
+ field(VAL, "1")
+ field(PINI, "YES")
+}
+
+# TODO: ok?
+record(bo, "$(DEVICE):CALLBACK") {
+ field(DESC, "Callback PV to listen to for changes")
+ field(ASG, "READONLY")
+ field(ZSV, "MINOR")
+ field(OSV, "NO_ALARM")
+ field(VAL, "1")
+ field(PINI, "YES")
+}
\ No newline at end of file
diff --git a/services/postmortemlog/current/ioc/POSTMORTEMLOG_15min10Hz.template b/services/postmortemlog/current/ioc/POSTMORTEMLOG_15min10Hz.template
new file mode 100644
index 0000000..c287ae4
--- /dev/null
+++ b/services/postmortemlog/current/ioc/POSTMORTEMLOG_15min10Hz.template
@@ -0,0 +1,30 @@
+# Circular Buffer Record for Live Copy of desired PVs
+record (compress, "$(DEVICE):BUFFER-$(NAME)") {
+ field(DESC, "15min 10Hz buffer for post mortem")
+ field(ASG, "READONLY")
+ field(SCAN, ".1 second")
+ field(INP, "$(INP)")
+ field(ALG, "Circular Buffer")
+ field(NSAM, "9000")
+}
+
+# Records for automatically copying EPICS circular buffer Records after beam abort
+record (waveform, "$(DEVICE):BUFFER-$(NAME)-LAST"){
+ field(DESC, "Copy of post mortem buffer")
+ field(ASG, "READONLY")
+ field(FTVL, "FLOAT")
+ field(NELM, "9000")
+ field(INP, "$(DEVICE):BUFFER-$(NAME) VAL")
+ field(SCAN, "Event") # Process on event
+ field(EVNT, "1") # Event number to trigger
+}
+
+# Records for writing to from HLA when viewing beam abort data history
+record (waveform, "$(DEVICE):BUFFER-$(NAME)-HLA"){
+ field(DESC, "Post mortem buffer filled by HLA")
+ field(ASG, "PROTECTED")
+ field(FTVL, "FLOAT")
+ field(NELM, "9000")
+}
+
+
diff --git a/services/postmortemlog/current/ioc/startup.script b/services/postmortemlog/current/ioc/startup.script
new file mode 100644
index 0000000..b62221c
--- /dev/null
+++ b/services/postmortemlog/current/ioc/startup.script
@@ -0,0 +1,2 @@
+epicsEnvSet("ENGINEER", "armborst")
+require array
diff --git a/services/postmortemlog/current/qt/A_BD_PostMortemLog.ui b/services/postmortemlog/current/qt/A_BD_PostMortemLog.ui
new file mode 100644
index 0000000..0d48d96
--- /dev/null
+++ b/services/postmortemlog/current/qt/A_BD_PostMortemLog.ui
@@ -0,0 +1,1197 @@
+
+
+ MainWindow
+
+
+ Qt::WindowModal
+
+
+
+ 0
+ 0
+ 1200
+ 1275
+
+
+
+ MainWindow
+
+
+ false
+
+
+
+
+
+
+
+
+ 1460
+ 210
+ 70
+ 20
+
+
+
+
+
+
+ 1460
+ 150
+ 70
+ 20
+
+
+
+ Reload
+
+
+ RELOAD
+
+
+ A
+
+
+ AGEBD-ALH:POSTMORTEMLOG-GUIRELOAD
+
+
+ caCalc::TriggerZeroToOne
+
+
+
+
+
+ 1450
+ 260
+ 91
+ 21
+
+
+
+ 99999
+
+
+ true
+
+
+ AGEBD-MASTER:LOG
+
+
+
+
+
+ 5
+ 5
+ 1190
+ 1265
+
+
+
+ 3
+
+
+
+ Live
+
+
+
+
+ 5
+ 415
+ 1175
+ 200
+
+
+
+ Horizontal Tune (nominal: Qx = 39.37)
+
+
+ AGEBD-POSTMORTEMLOG:BUFFER-TIME;AGEBD-POSTMORTEMLOG:BUFFER-QX
+
+
+
+ 42
+ 99
+ 228
+
+
+
+
+
+
+ caCartesianPlot::Sticks
+
+
+ caCartesianPlot::NoSymbol
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+ 42
+ 99
+ 228
+
+
+
+ caCartesianPlot::User
+
+
+ caCartesianPlot::Auto
+
+
+ -870;30
+
+
+
+
+
+ true
+
+
+ false
+
+
+ 9
+
+
+ caCartesianPlot::linear
+
+
+
+
+
+ 5
+ 620
+ 1175
+ 200
+
+
+
+ Vertival Tune (nominal: Qy = 15.22)
+
+
+ AGEBD-POSTMORTEMLOG:BUFFER-TIME;AGEBD-POSTMORTEMLOG:BUFFER-QY
+
+
+
+ 139
+ 26
+ 150
+
+
+
+
+
+
+ caCartesianPlot::Sticks
+
+
+ caCartesianPlot::NoSymbol
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+ 139
+ 26
+ 150
+
+
+
+ caCartesianPlot::User
+
+
+ caCartesianPlot::Auto
+
+
+ -870;30
+
+
+
+
+
+ true
+
+
+ false
+
+
+ 9
+
+
+ caCartesianPlot::linear
+
+
+
+
+
+ 5
+ 1030
+ 1175
+ 200
+
+
+
+ Vertival Beam Size (nominal: Sig_y = 10)
+
+
+ AGEBD-POSTMORTEMLOG:BUFFER-TIME;AGEBD-POSTMORTEMLOG:BUFFER-X01DD-SIGY
+
+
+
+ 118
+ 23
+ 130
+
+
+
+ AGEBD-POSTMORTEMLOG:BUFFER-TIME;AGEBD-POSTMORTEMLOG:BUFFER-X08DB-SIGY
+
+
+ caCartesianPlot::Lines
+
+
+ caCartesianPlot::NoSymbol
+
+
+
+ 154
+ 30
+ 170
+
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+ 139
+ 26
+ 150
+
+
+
+ caCartesianPlot::User
+
+
+ caCartesianPlot::Auto
+
+
+ -870;30
+
+
+
+
+
+ true
+
+
+ false
+
+
+ 9
+
+
+ caCartesianPlot::linear
+
+
+
+
+
+ 5
+ 825
+ 1175
+ 200
+
+
+
+ Horizontal Beam Size (nominal: Sig_x = 9)
+
+
+ AGEBD-POSTMORTEMLOG:BUFFER-TIME;AGEBD-POSTMORTEMLOG:BUFFER-X01DD-SIGX
+
+
+
+ 38
+ 92
+ 208
+
+
+
+ AGEBD-POSTMORTEMLOG:BUFFER-TIME;AGEBD-POSTMORTEMLOG:BUFFER-X08DB-SIGX
+
+
+ caCartesianPlot::Lines
+
+
+ caCartesianPlot::NoSymbol
+
+
+
+ 46
+ 113
+ 248
+
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+ 42
+ 99
+ 228
+
+
+
+ caCartesianPlot::User
+
+
+ caCartesianPlot::Auto
+
+
+ -870;30
+
+
+
+
+
+ true
+
+
+ false
+
+
+ 9
+
+
+ caCartesianPlot::linear
+
+
+
+
+
+ 5
+ 5
+ 1175
+ 200
+
+
+
+ Stored Beam Current
+
+
+ AGEBD-POSTMORTEMLOG:BUFFER-TIME;AGEBD-POSTMORTEMLOG:BUFFER-CURRPCT
+
+
+
+ 0
+ 255
+ 0
+
+
+
+ AGEBD-POSTMORTEMLOG:BUFFER-TIME;AGEBD-POSTMORTEMLOG:BUFFER-CURRBPM
+
+
+ caCartesianPlot::Lines
+
+
+ caCartesianPlot::NoSymbol
+
+
+
+ 0
+ 200
+ 0
+
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+ 0
+ 200
+ 0
+
+
+
+ caCartesianPlot::User
+
+
+ caCartesianPlot::Auto
+
+
+ -870;30
+
+
+
+
+
+ true
+
+
+ false
+
+
+ 9
+
+
+ caCartesianPlot::linear
+
+
+
+
+
+ 5
+ 210
+ 1175
+ 200
+
+
+
+ Beam Lifetime
+
+
+ AGEBD-POSTMORTEMLOG:BUFFER-TIME;AGEBD-POSTMORTEMLOG:BUFFER-TAUBPM
+
+
+ caCartesianPlot::FatDots
+
+
+
+ 38
+ 92
+ 208
+
+
+
+ AGEBD-POSTMORTEMLOG:BUFFER-TIME;AGEBD-POSTMORTEMLOG:BUFFER-TAUPCT
+
+
+ caCartesianPlot::FatDots
+
+
+ caCartesianPlot::NoSymbol
+
+
+
+ 46
+ 113
+ 248
+
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+ 42
+ 99
+ 228
+
+
+
+ caCartesianPlot::User
+
+
+ caCartesianPlot::User
+
+
+ -870;30
+
+
+ 0;15
+
+
+ true
+
+
+ false
+
+
+ 9
+
+
+ caCartesianPlot::linear
+
+
+
+
+
+ Last
+
+
+
+
+ 5
+ 1030
+ 1175
+ 200
+
+
+
+ Vertival Beam Size (nominal: Sig_y = 10)
+
+
+ AGEBD-POSTMORTEMLOG:BUFFER-TIME;AGEBD-POSTMORTEMLOG:BUFFER-X01DD-SIGY-LAST
+
+
+
+ 118
+ 23
+ 130
+
+
+
+ AGEBD-POSTMORTEMLOG:BUFFER-TIME;AGEBD-POSTMORTEMLOG:BUFFER-X08DB-SIGY-LAST
+
+
+ caCartesianPlot::Lines
+
+
+ caCartesianPlot::NoSymbol
+
+
+
+ 154
+ 30
+ 170
+
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+ 139
+ 26
+ 150
+
+
+
+ caCartesianPlot::User
+
+
+ caCartesianPlot::Auto
+
+
+ -870;30
+
+
+
+
+
+ true
+
+
+ false
+
+
+ 9
+
+
+ caCartesianPlot::linear
+
+
+
+
+
+ 5
+ 5
+ 1175
+ 200
+
+
+
+ Stored Beam Current
+
+
+ AGEBD-POSTMORTEMLOG:BUFFER-TIME;AGEBD-POSTMORTEMLOG:BUFFER-CURRPCT-LAST
+
+
+
+ 0
+ 255
+ 0
+
+
+
+ AGEBD-POSTMORTEMLOG:BUFFER-TIME;AGEBD-POSTMORTEMLOG:BUFFER-CURRBPM-LAST
+
+
+ caCartesianPlot::Lines
+
+
+ caCartesianPlot::NoSymbol
+
+
+
+ 0
+ 200
+ 0
+
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+ 0
+ 200
+ 0
+
+
+
+ caCartesianPlot::User
+
+
+ caCartesianPlot::Auto
+
+
+ -870;30
+
+
+
+
+
+ true
+
+
+ false
+
+
+ 9
+
+
+ caCartesianPlot::linear
+
+
+
+
+
+ 5
+ 415
+ 1175
+ 200
+
+
+
+ Horizontal Tune (nominal: Qx = 39.37)
+
+
+ AGEBD-POSTMORTEMLOG:BUFFER-TIME;AGEBD-POSTMORTEMLOG:BUFFER-QX-LAST
+
+
+
+ 42
+ 99
+ 228
+
+
+
+
+
+
+ caCartesianPlot::Sticks
+
+
+ caCartesianPlot::NoSymbol
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+ 42
+ 99
+ 228
+
+
+
+ caCartesianPlot::User
+
+
+ caCartesianPlot::Auto
+
+
+ -870;30
+
+
+
+
+
+ true
+
+
+ false
+
+
+ 9
+
+
+ caCartesianPlot::linear
+
+
+
+
+
+ 5
+ 825
+ 1175
+ 200
+
+
+
+ Horizontal Beam Size (nominal: Sig_x = 9)
+
+
+ AGEBD-POSTMORTEMLOG:BUFFER-TIME;AGEBD-POSTMORTEMLOG:BUFFER-X01DD-SIGX-LAST
+
+
+
+ 38
+ 92
+ 208
+
+
+
+ AGEBD-POSTMORTEMLOG:BUFFER-TIME;AGEBD-POSTMORTEMLOG:BUFFER-X08DB-SIGX-LAST
+
+
+ caCartesianPlot::Lines
+
+
+ caCartesianPlot::NoSymbol
+
+
+
+ 46
+ 113
+ 248
+
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+ 42
+ 99
+ 228
+
+
+
+ caCartesianPlot::User
+
+
+ caCartesianPlot::Auto
+
+
+ -870;30
+
+
+
+
+
+ true
+
+
+ false
+
+
+ 9
+
+
+ caCartesianPlot::linear
+
+
+
+
+
+ 5
+ 620
+ 1175
+ 200
+
+
+
+ Vertival Tune (nominal: Qy = 15.22)
+
+
+ AGEBD-POSTMORTEMLOG:BUFFER-TIME;AGEBD-POSTMORTEMLOG:BUFFER-QY-LAST
+
+
+
+ 139
+ 26
+ 150
+
+
+
+
+
+
+ caCartesianPlot::Sticks
+
+
+ caCartesianPlot::NoSymbol
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+ 139
+ 26
+ 150
+
+
+
+ caCartesianPlot::User
+
+
+ caCartesianPlot::Auto
+
+
+ -870;30
+
+
+
+
+
+ true
+
+
+ false
+
+
+ 9
+
+
+ caCartesianPlot::linear
+
+
+
+
+
+ 5
+ 210
+ 1175
+ 200
+
+
+
+ Beam Lifetime
+
+
+ AGEBD-POSTMORTEMLOG:BUFFER-TIME;AGEBD-POSTMORTEMLOG:BUFFER-TAUBPM-LAST
+
+
+ caCartesianPlot::FatDots
+
+
+
+ 38
+ 92
+ 208
+
+
+
+ AGEBD-POSTMORTEMLOG:BUFFER-TIME;AGEBD-POSTMORTEMLOG:BUFFER-TAUPCT-LAST
+
+
+ caCartesianPlot::FatDots
+
+
+ caCartesianPlot::NoSymbol
+
+
+
+ 46
+ 113
+ 248
+
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+ 42
+ 99
+ 228
+
+
+
+ caCartesianPlot::User
+
+
+ caCartesianPlot::User
+
+
+ -870;30
+
+
+ 0;15
+
+
+ true
+
+
+ false
+
+
+ 9
+
+
+ caCartesianPlot::linear
+
+
+
+
+
+ Historic
+
+
+
+
+ Debug
+
+
+
+
+ 0
+ 40
+ 1187
+ 1200
+
+
+
+ QTextEdit::NoWrap
+
+
+
+
+
+ 250
+ 5
+ 241
+ 30
+
+
+
+ Update Logs
+
+
+ AGEBD-MASTER:POSTMORTEMLOG-LOGS-REQ
+
+
+ Update Logs
+
+
+
+ 160
+ 160
+ 160
+
+
+
+
+
+
+ 1
+
+
+
+
+
+ 0
+ 5
+ 241
+ 30
+
+
+
+ Test Trigger Post Mortem
+
+
+ AGEBD-POSTMORTEMLOG:TEST
+
+
+ Test Trigger Post Mortem
+
+
+
+ 160
+ 160
+ 160
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+ caMessageButton
+ QPushButton
+
+
+
+ caLineEdit
+ QLineEdit
+
+
+
+ caCartesianPlot
+ QwtPlot
+
+
+
+ caCalc
+ QLabel
+
+
+
+ wmSignalPropagator
+ QLabel
+
+
+
+ QwtPlot
+ QFrame
+
+
+
+
+
+
+ cacalc_2
+ emitSignal(bool)
+ wmsignalpropagator
+ reloadwindow()
+
+
+ 1460
+ 159
+
+
+ 1460
+ 222
+
+
+
+
+ calineedit
+ textChanged(QString)
+ textBrowser
+ setHtml(QString)
+
+
+ 1495
+ 270
+
+
+ 600
+ 671
+
+
+
+
+
diff --git a/services/postmortemlog/current/systemd/AGEBD-SERVICE-POSTMORTEMLOG.service b/services/postmortemlog/current/systemd/AGEBD-SERVICE-POSTMORTEMLOG.service
new file mode 100644
index 0000000..eb0ff43
--- /dev/null
+++ b/services/postmortemlog/current/systemd/AGEBD-SERVICE-POSTMORTEMLOG.service
@@ -0,0 +1,16 @@
+[Unit]
+Description=AGEBD-SERVICE-POSTMORTEMLOG
+After=network.target
+
+[Service]
+Environment=AGEBD_ENV={{ agebd_env }}
+ExecStart=/sls/bd/hla/{{ agebd_env }}/bin/start_service.sh POSTMORTEMLOG
+Restart=no
+
+[Install]
+WantedBy=default.target
+
+# https://www.freedesktop.org/software/systemd/man/latest/systemd.service.html
+# systemctl --user daemon-reload
+# systemctl --user enable /sls/bd/bin/systemd/AGEBD-SERVICE-POSTMORTEMLOG.service
+# systemctl --user start AGEBD-SERVICE-POSTMORTEMLOG
diff --git a/services/scrubbing/current/app/pyproject.toml b/services/scrubbing/current/app/pyproject.toml
new file mode 100644
index 0000000..b81a822
--- /dev/null
+++ b/services/scrubbing/current/app/pyproject.toml
@@ -0,0 +1,48 @@
+[project]
+name = "agebd-scrubbing"
+version = "0.1.0"
+description = "AGEBD-SCRUBBING Service"
+requires-python = "==3.10.*"
+dependencies = [
+ "agebd",
+ "numpy>=2.2.6",
+]
+
+[dependency-groups]
+dev = [
+ "pyepics>=3.5.8",
+ "pytest>=8.4.2",
+ "ruff>=0.15.20",
+]
+
+[tool.uv.sources]
+# Path is relative to where agebd package is deployed on hla
+# machines (see CI/CD in .gitea/workflows)
+agebd = { path = "../../../../packages/agebd", editable = true }
+
+[build-system]
+requires = ["hatchling"]
+build-backend = "hatchling.build"
+
+[tool.uv]
+package = true
+
+[tool.pytest.ini_options]
+pythonpath = ["src"]
+env = [
+ "AGEBD_ENV=local",
+]
+
+[tool.ruff]
+include = [
+ "src/**/*.py",
+ "tests/**/*.py",
+]
+line-length = 100
+
+[tool.ruff.lint]
+# use isort to sort imports
+extend-select = ["I"]
+
+[tool.ruff.lint.isort]
+known-first-party = ["agebd"]
diff --git a/services/scrubbing/current/app/src/agebd_scrubbing/__init__.py b/services/scrubbing/current/app/src/agebd_scrubbing/__init__.py
new file mode 100644
index 0000000..1800c27
--- /dev/null
+++ b/services/scrubbing/current/app/src/agebd_scrubbing/__init__.py
@@ -0,0 +1 @@
+from .service import PVs, Service
diff --git a/services/scrubbing/current/app/src/agebd_scrubbing/main.py b/services/scrubbing/current/app/src/agebd_scrubbing/main.py
new file mode 100644
index 0000000..73085b9
--- /dev/null
+++ b/services/scrubbing/current/app/src/agebd_scrubbing/main.py
@@ -0,0 +1,35 @@
+import typer
+
+from agebd.enums import LogLevel
+from agebd.utils import init_logging
+from agebd_scrubbing import PVs, Service
+from agebd_scrubbing.runner import Runner
+
+# TODO: remove: cicd test 10
+
+
+def main(
+ log_level: LogLevel = typer.Option(
+ LogLevel.INFO,
+ "--log-level",
+ "-l",
+ # Looks at the OS env variable first. If empty, falls back to "INFO"
+ envvar="AGEBD_LOG_LEVEL",
+ # help="Set log level: DEBUG, INFO, WARNING, ERROR, CRITICAL",
+ case_sensitive=False,
+ ),
+):
+ """
+ Uses custom/old Runner because migrating to the agebd Runner would be quite
+ complex.
+ """
+ init_logging(log_level)
+ service_name = "SCRUBBING"
+ pvs = PVs(service_name=service_name)
+ service = Service(pvs=pvs)
+ runner = Runner(svc=service)
+ runner.start()
+
+
+if __name__ == "__main__":
+ typer.run(main)
diff --git a/services/scrubbing/current/app/src/agebd_scrubbing/runner.py b/services/scrubbing/current/app/src/agebd_scrubbing/runner.py
new file mode 100644
index 0000000..2ad2058
--- /dev/null
+++ b/services/scrubbing/current/app/src/agebd_scrubbing/runner.py
@@ -0,0 +1,280 @@
+import traceback
+from time import perf_counter, sleep
+
+import numpy as np
+from epics import poll
+
+from agebd_scrubbing.service import Service
+
+
+class Runner:
+ def __init__(self, svc: Service) -> None:
+ self.svc = svc
+
+ def start(self):
+ svc = self.svc
+ pvs = self.svc.pvs
+
+ while not pvs.abort.get():
+ if pvs.onoff.get() == 1:
+ # add callback for triggering the loop
+ if not svc.CallbackActive:
+ pvs.status.put("running")
+ pvs.CallbackPV.add_callback(callback=svc.InjectionCallback, index=1, svc=svc)
+ svc.CallbackActive = 1
+
+ if svc.ChangeTrue or perf_counter() > svc.tl + 0.1:
+ # start time for next loop firing, if no vacuum changes
+ svc.tl = perf_counter()
+
+ # reload control PVs
+ svc.update()
+
+ # check stop/abort conitions if injection is active
+ if svc.injection:
+ # ensure disabled scrubbing during injection
+ svc.pause_scrubbing()
+
+ # ensure correct injector settings
+ if svc.cur > pvs.current_threshold.get():
+ pvs.gun_grid.put(svc.grid_fpfb)
+ else:
+ pvs.gun_grid.put(svc.grid_accum)
+
+ # abort injection when limits exceeded
+ if svc.conditions_abort_injection:
+ # disable injection when upper limit reached
+ svc.stop_injection()
+ print("injection aborted")
+
+ if not svc.abort:
+ svc.abort = 1
+ svc.abort_t0 = perf_counter()
+
+ svc.set_status(svc.states["abort"], wait=60)
+
+ elif svc.conditions_stop_injection:
+ # disable injection when upper limit reached
+ svc.stop_injection()
+ print("injection stopped")
+
+ # start scrubbing if activated
+ if svc.scrubbi > 0:
+ sleep(0.1)
+ svc.start_scrubbing()
+
+ svc.set_status(svc.states["decay + scrub"])
+
+ else:
+ svc.set_status(svc.states["decay - scrub"])
+
+ elif svc.info != svc.states["inject"]:
+ svc.set_status(svc.states["inject"])
+
+ # stop injection and info if master trigger missing
+ elif not svc.trig_master:
+ svc.stop_injection()
+ svc.set_status(svc.states["wait 4 master"])
+
+ # stop injection and info if master mode is not set to manual
+ elif not svc.master_mode == 2:
+ svc.stop_injection()
+ svc.set_status(svc.states["wait 4 manual"])
+
+ # stop injection and wait for 60s if injection was aborted
+ elif svc.abort:
+ svc.stop_injection()
+ dt = perf_counter() - svc.abort_t0
+
+ if dt > 60:
+ svc.abort = 0
+
+ else:
+ svc.set_status(svc.states["abort"], wait=60 - dt)
+
+ sleep(0.1)
+
+ # start warmup cycling if conditions for starting injection are fulfilled
+ elif svc.conditions_start_injection and svc.info not in [
+ svc.states["inject"],
+ svc.states["warmup"],
+ ]:
+ svc.set_status(svc.states["warmup"])
+
+ # disable pingers for injection
+ svc.pause_scrubbing()
+
+ # make sure that injection bump and pinger not both fired
+ sleep(0.1)
+
+ # check setpoints for required amount of warmup cycles
+ svc.cycles_BOIN_sp = pvs.cycles_BOIN_sp.get()
+ svc.cycles_BOMB_sp = pvs.cycles_BOMB_sp.get()
+ svc.cycles_BOME_sp = pvs.cycles_BOME_sp.get()
+ svc.cycles_BOEX_sp = pvs.cycles_BOEX_sp.get()
+ svc.cycles_SRIN_sp = pvs.cycles_SRIN_sp.get()
+
+ # set readback of warmup cycle counters to setpoint
+ pvs.cycles_BOIN_rb.put(svc.cycles_BOIN_sp)
+ pvs.cycles_BOMB_rb.put(svc.cycles_BOMB_sp)
+ pvs.cycles_BOME_rb.put(svc.cycles_BOME_sp)
+ pvs.cycles_BOEX_rb.put(svc.cycles_BOEX_sp)
+ pvs.cycles_SRIN_rb.put(svc.cycles_SRIN_sp)
+ svc.cycles_BOIN_rb = svc.cycles_BOIN_sp
+ svc.cycles_BOMB_rb = svc.cycles_BOMB_sp
+ svc.cycles_BOME_rb = svc.cycles_BOME_sp
+ svc.cycles_BOEX_rb = svc.cycles_BOEX_sp
+ svc.cycles_SRIN_rb = svc.cycles_SRIN_sp
+
+ # calculate highest amount of total required warmup cycles
+ svc.cycles_max = np.nanmax(
+ [
+ svc.cycles_BOIN_sp,
+ svc.cycles_BOMB_sp,
+ svc.cycles_BOME_sp,
+ svc.cycles_BOEX_sp,
+ svc.cycles_SRIN_sp,
+ ]
+ )
+
+ # calculate highest amount of remaining warmup cycles
+ svc.cycles_rem = svc.cycles_max
+
+ # remove default callback for warmup (secretly since svc.CallbackActive = 0)
+ pvs.CallbackPV.remove_callback(index=1)
+
+ # activate warmup callbacks
+ pvs.cycles_BOIN_cnt.add_callback(
+ callback=svc.WarmupCallback, index=2, svc=svc
+ )
+ pvs.cycles_BOMB_cnt.add_callback(
+ callback=svc.WarmupCallback, index=3, svc=svc
+ )
+ pvs.cycles_BOME_cnt.add_callback(
+ callback=svc.WarmupCallback, index=4, svc=svc
+ )
+ pvs.cycles_BOEX_cnt.add_callback(
+ callback=svc.WarmupCallback, index=5, svc=svc
+ )
+ pvs.cycles_SRIN_cnt.add_callback(
+ callback=svc.WarmupCallback, index=6, svc=svc
+ )
+ # pvs.cycles_ALL_cnt.add_callback(callback=InjectionCallback, index=7, svc=svc)
+
+ # set callback warmup cycle counters to 0
+ svc.wait4warm = {
+ "AGETI-CVME-MASTER-TMA:Evt-BO-Inj-EVRCount-I.VAL": 0,
+ "AGETI-CVME-MASTER-TMA:Evt-BO-MA-B-EVRCount-I.VAL": 0,
+ "AGETI-CVME-MASTER-TMA:Evt-BO-Ramp-EVRCount-I.VAL": 0,
+ "AGETI-CVME-MASTER-TMA:Evt-BO-Ext-EVRCount-I.VAL": 0,
+ "AGETI-CVME-MASTER-TMA:Evt-SR-Inj-EVRCount-I.VAL": 0,
+ }
+
+ svc.tp = perf_counter()
+
+ # do top up analysis
+ svc.topup_dt = (svc.tp - svc.topup_t0) / 60
+ svc.topup_dI = svc.topup_I0 - svc.cur
+ pvs.topup_dt.put(svc.topup_dt)
+ pvs.topup_dI.put(svc.topup_dI)
+ if svc.topup_I0 > 0:
+ if svc.topup_dI / svc.topup_I0 < 1:
+ pvs.topup_tau.put(
+ (-svc.topup_dt / 60) / np.log(1 - svc.topup_dI / svc.topup_I0)
+ )
+
+ elif svc.info == svc.states["warmup"]:
+ if svc.cycles_rem < 1:
+ # start injection
+ svc.start_injection()
+
+ # reactivate default callback by notifying mainloop of its deactivation
+ svc.CallbackActive = 0
+
+ # disable warmup callbacks
+ pvs.cycles_BOIN_cnt.remove_callback(index=2)
+ pvs.cycles_BOMB_cnt.remove_callback(index=3)
+ pvs.cycles_BOME_cnt.remove_callback(index=4)
+ pvs.cycles_BOEX_cnt.remove_callback(index=5)
+ pvs.cycles_SRIN_cnt.remove_callback(index=6)
+ pvs.cycles_ALL_cnt.remove_callback(index=7)
+
+ svc.set_status(svc.states["inject"])
+
+ else:
+ svc.prepare_injection()
+
+ elif svc.info in [svc.states["pause"], svc.states["wait 4 master"]]:
+ if svc.injection:
+ svc.set_status(svc.states["inject"])
+ else:
+ if pvs.trig_pinger_h.get() and pvs.trig_pinger_v.get():
+ svc.set_status(svc.states["decay + scrub"])
+ else:
+ svc.set_status(svc.states["decay - scrub"])
+
+ # stop scrubbing when deactivated
+ elif svc.scrubbi == 0 and svc.scrubbilast > 0:
+ svc.stop_scrubbing()
+ svc.set_status(svc.states["decay - scrub"])
+
+ # if scrubbing activated and lifetime drops below 1 hour --> stop scrubbing
+ elif svc.scrubbi > 0 and svc.tau < 1:
+ svc.pause_scrubbing()
+ svc.set_status(svc.states["decay - scrub"])
+ print("Scrubbing aborted, tau < 1")
+
+ svc.ChangeTrue = 0
+
+ # inform watchdog(s)
+ pvs.running.put(0)
+
+ # wait for callback to fire
+ poll(evt=1.0e-5, iot=0.1)
+
+ else:
+ # WHILE PAUSED REBOOT OF THE SCRUBBING IOC SHOULD NOT DISTURB THE SERVICE
+
+ if svc.CallbackActive:
+ # remove callback
+ pvs.CallbackPV.remove_callback(index=1)
+ svc.CallbackActive = 0
+
+ # reload control PVs
+ svc.update()
+
+ # disable injection and pingers when first paused
+ if svc.info != svc.states["pause"]:
+ svc.stop_injection()
+ svc.pause_scrubbing()
+
+ svc.set_status(svc.states["pause"])
+ pvs.status.put("paused")
+
+ sleep(0.1)
+
+ # sleep and inform watchdog(s)
+ pvs.alive.put(0)
+
+ if pvs.abort.get():
+ # confirm clean abort
+ pvs.status.put("killed")
+ print("Got Killed by Master Service!")
+ pvs.abortreq.put(0)
+
+ # elif svc.crashed:
+
+ # # confirm crash
+ # pvs.status.put('crashed')
+ # print('Service crashed on exception!')
+ # print('----- svc.exception.__traceback__ -----')
+ # print(svc.exception.__traceback__)
+ # print()
+ # print('----- traceback.format_exc() -----')
+ # print(traceback.format_exc())
+
+ else:
+ # confirm unknown exit
+ pvs.status.put("unknown crash")
+ print("Service crashed without exception!")
+ print(traceback.format_exc())
diff --git a/services/scrubbing/current/app/src/agebd_scrubbing/service.py b/services/scrubbing/current/app/src/agebd_scrubbing/service.py
new file mode 100644
index 0000000..3be0bc5
--- /dev/null
+++ b/services/scrubbing/current/app/src/agebd_scrubbing/service.py
@@ -0,0 +1,507 @@
+from datetime import datetime
+from time import perf_counter, sleep
+
+import numpy as np
+from epics import PV
+
+from agebd.pv import get_pv_class
+from agebd.service.pvs import BasePVs
+from agebd.utils import printgetversion
+
+__version__ = printgetversion(__file__)
+
+PV = get_pv_class()
+
+
+class PVs(BasePVs):
+ cycles_BOIN_sp = PV("AGEBD-SCRUBBING:WARMUPCYCLES-BOIN-SP.VAL")
+ cycles_BOIN_rb = PV("AGEBD-SCRUBBING:WARMUPCYCLES-BOIN-RB.VAL")
+ cycles_BOIN_cnt = PV("AGETI-CVME-MASTER-TMA:Evt-BO-Inj-EVRCount-I.VAL", auto_monitor=True)
+ cycles_BOMB_sp = PV("AGEBD-SCRUBBING:WARMUPCYCLES-BOMB-SP.VAL")
+ cycles_BOMB_rb = PV("AGEBD-SCRUBBING:WARMUPCYCLES-BOMB-RB.VAL")
+ cycles_BOMB_cnt = PV("AGETI-CVME-MASTER-TMA:Evt-BO-MA-B-EVRCount-I.VAL", auto_monitor=True)
+ cycles_BOME_sp = PV("AGEBD-SCRUBBING:WARMUPCYCLES-BOME-SP.VAL")
+ cycles_BOME_rb = PV("AGEBD-SCRUBBING:WARMUPCYCLES-BOME-RB.VAL")
+ cycles_BOME_cnt = PV("AGETI-CVME-MASTER-TMA:Evt-BO-Ramp-EVRCount-I.VAL", auto_monitor=True)
+ cycles_BOEX_sp = PV("AGEBD-SCRUBBING:WARMUPCYCLES-BOEX-SP.VAL")
+ cycles_BOEX_rb = PV("AGEBD-SCRUBBING:WARMUPCYCLES-BOEX-RB.VAL")
+ cycles_BOEX_cnt = PV("AGETI-CVME-MASTER-TMA:Evt-BO-Ext-EVRCount-I.VAL", auto_monitor=True)
+ cycles_SRIN_sp = PV("AGEBD-SCRUBBING:WARMUPCYCLES-SRIN-SP.VAL")
+ cycles_SRIN_rb = PV("AGEBD-SCRUBBING:WARMUPCYCLES-SRIN-RB.VAL")
+ cycles_SRIN_cnt = PV("AGETI-CVME-MASTER-TMA:Evt-SR-Inj-EVRCount-I.VAL", auto_monitor=True)
+ cycles_ALL_cnt = PV("AGETI-CVME-MASTER-TMA:Event-Seq-Cnt-I.VAL", auto_monitor=True)
+
+ ## Control PVs
+ # top-up control mode
+ # topumod = PV('.VAL')
+ # top-up mode vacuum limits
+ vac_max = PV("AGEBD-SCRUBBING:CONTROL-VACUUM-MAX.VAL")
+ vac_min = PV("AGEBD-SCRUBBING:CONTROL-VACUUM-MIN.VAL")
+ # top-up mode current limits
+ cur_max = PV("AGEBD-SCRUBBING:CONTROL-CURRENT-MAX.VAL")
+ cur_min = PV("AGEBD-SCRUBBING:CONTROL-CURRENT-MIN.VAL")
+ # top-up mode time limits for injection and decay (periodic refill)
+ tim_inj = PV("AGEBD-SCRUBBING:CONTROL-TIME-MAX.VAL")
+ tim_dec = PV("AGEBD-SCRUBBING:CONTROL-TIME-MIN.VAL")
+ # mbfb gain setpoints for scrubbing
+ mbfbx_gain_sp = PV("AGEBD-SCRUBBING:MBFBX-GAIN-SP.VAL")
+ mbfby_gain_sp = PV("AGEBD-SCRUBBING:MBFBY-GAIN-SP.VAL")
+ mbfbx_gain = PV("ARSGE-CECL-MBFB:MBFB-T-X-DDS-GAIN.VAL")
+ mbfby_gain = PV("ARSGE-CECL-MBFB:MBFB-T-Y-DDS-GAIN.VAL")
+
+ # RDP Scan
+ # pause : set gain to 0 as normal, get current sweep freq, stop sweep, set initial freq of sweep to current freq
+ # start : set gain to sp (i.e., 100) as normal, start sweep
+ mbfby_freq_sp = PV("ARSGE-CECL-MBFB:MBFB-T-Y-DDS-FRQ.VAL")
+ mbfby_sweep_onoff = PV("ARSGE-CECL-MBFB:MBFB-T-Y-DDS-SWEEP-EN.VAL")
+ mbfby_sweepfreq_start = PV("ARSGE-CECL-MBFB:MBFB-T-Y-DDS-SWEEP-FREQ-START.VAL")
+ mbfby_sweepfreq_rb = PV("ARSGE-CECL-MBFB:MBFB-T-Y-DDS-SWEEP-FRQ-RB-REG.VAL")
+
+ vac_dyn = PV("AGEBD-SCRUBBING:CONTROL-VACUUM-DYN.VAL")
+ vac_dyn_frac = PV("AGEBD-SCRUBBING:CONTROL-VACUUM-DYN-FRAC.VAL")
+
+ # grd_max = PV('AGEBD-SCRUBBING:CONTROL-GUNGRID-MAX.VAL')
+ grid_accum = PV("AGEBD-SCRUBBING:CONTROL-GUNGRID-ACCUM.VAL")
+ grid_fpfb = PV("AGEBD-SCRUBBING:CONTROL-GUNGRID-FPFB.VAL")
+ # current above which the feedback mode is started
+ current_threshold = PV("AGEBD-TIMING:CURRENT-THRESHOLD.VAL")
+
+ scrubbing = PV("AGEBD-SCRUBBING:CONTROL-SCRUB.VAL")
+
+ # Input PVs
+ vacs = [
+ # PV('ARIVA-VMAVE:PRESS-MAX.VAL'), # VCS gauges in the Arcs + Straights
+ # PV('ARIVA-VMAVE-FE:PRESS-MAX.VAL'), # VCS gauges in the ring to always the first one after the FE-Valve
+ # PV('ARIVA-VMAVE-ALL:PRESS-MAX.VAL'), # Max of the two above
+ # PV('ARIVA-VMAVE-PSH:PRESS-MAX.VAL'), # VCS gauges in the Photon Shutters/Beam Stoppers of the existing beamlines
+ PV("ARIVA-VMAVE-ALL:PRESS-MAX.VAL"), # Max of three signals: Ring/FE/PSH
+ PV("ARS07-VMCC-0120:PRESSURE.VAL"),
+ ]
+ vac_all = PV("ARIVA-VMAVE-ALL:PRESS-MAX.VAL")
+ vac_acc = [
+ PV("ARIVA-VMAVE:PRESS-MAX.VAL"),
+ PV("ARS07-VMCC-0120:PRESSURE.VAL"),
+ ]
+ # vac_fe = PV('ARIVA-VMAVE-FE:PRESS-MAX.VAL')
+ # cur = PV('AGEBD-DBPM3CURR:CURRENT-AVG.VAL')
+ cur = PV("ARS07-DPCT-0000:CURR.VAL")
+ # cur1 = PV('ARS07-CECL-DPCT:BDC-DPCT100-SCALED')
+ # cur2 = PV('ARS07-CECL-DPCT2:BDC-DPCT200-SCALED')
+ # curuse = PV('ARS07-DPCT-0000:CHOICE-RB')
+
+ injguard = PV("AGEBD-INJECTIONGUARD:CHECK-SUM.VAL")
+
+ injactive = PV("AGEBD-PARAMS:INJECTION-ACTIVE")
+
+ tau = PV("AGEBD-PARAMS:LIFETIME.VAL")
+
+ # Regulated PVs
+ trig_firego = PV("AGEBD-TIMING:GO.VAL")
+ trig_master = PV("AGETI-CVME-MASTER-TMA:SR-Inj-Status-Sel.VAL")
+ master_mode = PV("AGETI-CVME-MASTER-TMA:FP-Mode-Sel.VAL")
+ trig_secret = PV("AGEBD-INJECTIONGUARD:STATUS-SECRET-MASTER.VAL")
+ # trig_guntxb = PV('ALIRF-VME-A-GUN:CH1-MODE.VAL')
+ # AGETI-CVME-MASTER-TMA:Evt-LI-Gun-Ena-Sel
+ # trig_gunevt = PV('AGETI-CVME-MASTER-TMA:Evt-LI-Gun-Ena-Sel.VAL')
+ # AGETI-CVME-MASTER-TMA:Evt-BO-Inj-Ena-Sel
+ trig_booinj = PV("AGETI-CVME-MASTER-TMA:Evt-BO-Inj-Ena-Sel.VAL")
+ # AGETI-CVME-MASTER-TMA:Evt-BO-MA-B-Ena-Sel
+ # trig_boormp = PV('AGETI-CVME-MASTER-TMA:Evt-Old-BO-HW-Ena-Sel.VAL')
+ trig_bormp1 = PV("AGETI-CVME-MASTER-TMA:Evt-BO-MA-B-Ena-Sel.VAL")
+ # AGETI-CVME-MASTER-TMA:Evt-BO-Ramp-Ena-Sel
+ trig_bormp2 = PV("AGETI-CVME-MASTER-TMA:Evt-BO-Ramp-Ena-Sel.VAL")
+ trig_booext = PV(
+ "AGETI-CVME-MASTER-TMA:Evt-BO-Ext-Ena-Sel.VAL"
+ ) # Alias AGETI-CVME-MASTER-TMA:Evt-10
+ trig_rininj = PV(
+ "AGETI-CVME-MASTER-TMA:Evt-SR-Inj-Ena-Sel.VAL"
+ ) # Alias AGETI-CVME-MASTER-TMA:Evt-26
+ trig_pinger_h = PV(
+ "AGETI-CVME-MASTER-TMA:Evt-SR-Pinger-H-Ena-Sel.VAL"
+ ) # Alias AGETI-CVME-MASTER-TMA:Evt-14-Ena-Sel
+ trig_pinger_v = PV(
+ "AGETI-CVME-MASTER-TMA:Evt-SR-Pinger-V-Ena-Sel.VAL"
+ ) # Alias AGETI-CVME-MASTER-TMA:Evt-14-Ena-Sel
+
+ # # injection follow bucket workaround for linac (https://elog-gfa.psi.ch/SLS/64299)
+ # # Before making injection, disable the LLRF phase feedback ...
+ # linac_llrf_phaseFB1 = PV('ALIRF-A1-LLE-DSP:PHASE-FB-SWITCH.VAL')
+ # linac_llrf_phaseFB2 = PV('ALIRF-A2-LLE-DSP:PHASE-FB-SWITCH.VAL')
+ # # ... and disable the phase alarm by setting the phase limits
+ # linac_llrf_phaseFB_PBU_HIHI = PV('ALIRF-PBU:Ph-COMP.HIHI')
+ # linac_llrf_phaseFB_FBU_HIHI = PV('ALIRF-FBU:Ph-COMP.HIHI')
+ # linac_llrf_phaseFB_MOD1_HIHI = PV('ALIRF-AS-1:Ph-COMP.HIHI')
+ # linac_llrf_phaseFB_MOD2_HIHI = PV('ALIRF-AS-2:Ph-COMP.HIHI')
+ # linac_llrf_phaseFB_PBU_LOLO = PV('ALIRF-PBU:Ph-COMP.LOLO')
+ # linac_llrf_phaseFB_FBU_LOLO = PV('ALIRF-FBU:Ph-COMP.LOLO')
+ # linac_llrf_phaseFB_MOD1_LOLO = PV('ALIRF-AS-1:Ph-COMP.LOLO')
+ # linac_llrf_phaseFB_MOD2_LOLO = PV('ALIRF-AS-2:Ph-COMP.LOLO')
+
+ gun_grid = PV("ALIRF-GUN-GRID:V-SET.VAL")
+ # pinger_v = PV('ARS01-MKIK-0320:CTRL-ON-OFF.VAL')
+ # pinger_h = PV('ARS01-MKIK-0290:CTRL-ON-OFF.VAL')
+
+ topup_dt = PV("AGEBD-SCRUBBING:TOPUP-DELTAT.VAL")
+ topup_dI = PV("AGEBD-SCRUBBING:TOPUP-DELTAI.VAL")
+ topup_tau = PV("AGEBD-SCRUBBING:TOPUP-TAU.VAL")
+
+ def __init__(self, service_name: str, pv_factory=PV):
+ super().__init__(service_name, pv_factory)
+ PV = pv_factory
+
+ # Service Callback PVs
+ self.CallbackPV = PV("AGETI-CVME-MASTER-TMA:Evt-Old-BO-SYN.VALA", auto_monitor=True)
+
+
+class Service:
+ def __init__(self, pvs: PVs):
+ self.pvs = pvs
+
+ self.pvs.started.put(str(datetime.now())[:-7])
+ self.pvs.version.put(__version__)
+ self.pvs.info.put("initialized")
+
+ self.cycles_BOIN_sp = pvs.cycles_BOIN_sp.get()
+ self.cycles_BOIN_rb = pvs.cycles_BOIN_rb.get()
+ self.cycles_BOIN_cnt = pvs.cycles_BOIN_cnt.get()
+ self.cycles_BOMB_sp = pvs.cycles_BOMB_sp.get()
+ self.cycles_BOMB_rb = pvs.cycles_BOMB_rb.get()
+ self.cycles_BOMB_cnt = pvs.cycles_BOMB_cnt.get()
+ self.cycles_BOME_sp = pvs.cycles_BOME_sp.get()
+ self.cycles_BOME_rb = pvs.cycles_BOME_rb.get()
+ self.cycles_BOME_cnt = pvs.cycles_BOME_cnt.get()
+ self.cycles_BOEX_sp = pvs.cycles_BOEX_sp.get()
+ self.cycles_BOEX_rb = pvs.cycles_BOEX_rb.get()
+ self.cycles_BOEX_cnt = pvs.cycles_BOEX_cnt.get()
+ self.cycles_SRIN_sp = pvs.cycles_SRIN_sp.get()
+ self.cycles_SRIN_rb = pvs.cycles_SRIN_rb.get()
+ self.cycles_SRIN_cnt = pvs.cycles_SRIN_cnt.get()
+ self.timerthreadready = 1
+
+ self.cycles_max = np.nanmax(
+ [
+ self.cycles_BOIN_sp,
+ self.cycles_BOMB_sp,
+ self.cycles_BOME_sp,
+ self.cycles_BOEX_sp,
+ self.cycles_SRIN_sp,
+ ]
+ )
+
+ self.cycles_rem = self.cycles_max
+
+ self.wait4warm = {
+ "AGETI-CVME-MASTER-TMA:Evt-BO-Inj-EVRCount-I.VAL": 0,
+ "AGETI-CVME-MASTER-TMA:Evt-BO-MA-B-EVRCount-I.VAL": 0,
+ "AGETI-CVME-MASTER-TMA:Evt-BO-Ramp-EVRCount-I.VAL": 0,
+ "AGETI-CVME-MASTER-TMA:Evt-BO-Ext-EVRCount-I.VAL": 0,
+ "AGETI-CVME-MASTER-TMA:Evt-SR-Inj-EVRCount-I.VAL": 0,
+ }
+
+ self.vac = np.max([pv.get() for pv in pvs.vacs])
+ # self.vac_acc = pvs.vac_acc.get()
+ self.vac_acc = np.max([pv.get() for pv in pvs.vac_acc])
+ # self.vac = pvs.vac_fe.get()
+ self.vac_array = np.repeat(self.vac_acc, 10)
+ self.vac_dyn = self.vac * pvs.vac_dyn_frac.get()
+ pvs.vac_dyn.put(self.vac_dyn * 1e9)
+ self.cur = 420
+ self.scrubbi = pvs.scrubbing.get()
+ self.scrubbilast = self.scrubbi
+
+ self.mbfbx_sp = int(pvs.mbfbx_gain_sp.get())
+ self.mbfby_sp = int(pvs.mbfby_gain_sp.get())
+ self.mbfby_sweepfreq_rb = np.round(pvs.mbfby_sweepfreq_rb.get())
+
+ self.topup_t0 = perf_counter()
+ self.topup_I0 = pvs.cur_min.get()
+ self.topup_dI = 0.0
+ self.topup_dt = 0.0
+
+ def getcurr(self):
+ pvs = self.pvs
+
+ self.cur = pvs.cur.get()
+
+ # def start_linac_phasefeedback(self):
+
+ # # injection follow bucket workaround for linac (https://elog-gfa.psi.ch/SLS/64299)
+ # # Before making injection, disable the LLRF phase alarms and feedback ...
+ # pvs.linac_llrf_phaseFB1.put(1)
+ # pvs.linac_llrf_phaseFB2.put(1)
+
+ # pvs.linac_llrf_phaseFB_PBU_HIHI.put(10)
+ # pvs.linac_llrf_phaseFB_FBU_HIHI.put(10)
+ # pvs.linac_llrf_phaseFB_MOD1_HIHI.put(10)
+ # pvs.linac_llrf_phaseFB_MOD2_HIHI.put(10)
+ # pvs.linac_llrf_phaseFB_PBU_LOLO.put(-10)
+ # pvs.linac_llrf_phaseFB_FBU_LOLO.put(-10)
+ # pvs.linac_llrf_phaseFB_MOD1_LOLO.put(-10)
+ # pvs.linac_llrf_phaseFB_MOD2_LOLO.put(-10)
+ # print('phaseFB ON')
+
+ def update(self):
+ pvs = self.pvs
+
+ # (re-)load input PVs
+ self.injection = pvs.injactive.get()
+ self.vac = np.max([pv.get() for pv in pvs.vacs])
+ self.vac_acc = np.max([pv.get() for pv in pvs.vac_acc])
+
+ self.getcurr()
+
+ self.trig_master = pvs.trig_master.get() and pvs.trig_secret.get()
+ self.master_mode = pvs.master_mode.get()
+ self.injguard = pvs.injguard.get()
+ self.info = pvs.info.get().split(",")[0]
+ self.tau = pvs.tau.get()
+
+ # (re-)load control PVs
+ self.vac_max = pvs.vac_max.get() * 1e-9
+ self.vac_dyn = np.max(self.vac_array[:5]) * pvs.vac_dyn_frac.get()
+ pvs.vac_dyn.put(self.vac_dyn * 1e9)
+
+ # roll oldest value arr[0] to end, i.e., arr[-1]
+ self.vac_array = np.roll(self.vac_array, -2)
+ # replace oldest value with new value
+ self.vac_array[-2:] = self.vac_acc
+
+ self.mbfbx_sp = int(pvs.mbfbx_gain_sp.get())
+ self.mbfby_sp = int(pvs.mbfby_gain_sp.get())
+
+ self.vac_min = pvs.vac_min.get() * 1e-9
+ self.cur_max = pvs.cur_max.get()
+ self.cur_min = pvs.cur_min.get()
+ self.grid_accum = pvs.grid_accum.get()
+ self.grid_fpfb = pvs.grid_fpfb.get()
+ self.scrubbilast = self.scrubbi
+ self.scrubbi = pvs.scrubbing.get()
+
+ self.conditions_start_injection = ( # is any lower limit reached?
+ self.vac <= self.vac_min or self.cur <= self.cur_min
+ ) and ( # is no upper limit exceeded ?
+ self.cur <= self.cur_max and self.vac <= self.vac_max and self.vac_acc <= self.vac_dyn
+ )
+
+ self.conditions_stop_injection = (
+ # is upper current limit reached/exceeded?
+ self.cur >= self.cur_max or self.vac >= self.vac_max
+ )
+
+ self.conditions_abort_injection = (
+ # is any upper limit reached/exceeded?
+ self.vac_acc >= self.vac_dyn or self.cur > self.cur_max * 1.02
+ # or self.injguard != 1
+ )
+
+ def stop_injection(self):
+ pvs = self.pvs
+
+ # disable super duper master fire trigger
+ pvs.trig_firego.put(0)
+
+ # stop injection events
+ pvs.trig_booinj.put(0)
+ pvs.trig_bormp1.put(0)
+ pvs.trig_bormp2.put(0)
+ pvs.trig_booext.put(0)
+ pvs.trig_rininj.put(0)
+
+ self.injection = 0
+
+ # prepare top-up analysis
+ self.topup_I0 = self.cur
+ self.topup_t0 = perf_counter()
+
+ # # create thread that restarts phase feedback after 2 seconds
+ # if self.timerthreadready:
+
+ # tt = threading.Timer(10, self.start_linac_phasefeedback)
+ # tt.start()
+ # print('threadtimer started....')
+ # self.timerthreadready = 0
+
+ def start_injection(self):
+ pvs = self.pvs
+
+ # # injection follow bucket workaround for linac (https://elog-gfa.psi.ch/SLS/64299)
+ # # Before making injection, disable the LLRF phase alarms and feedback ...
+ # pvs.linac_llrf_phaseFB_PBU_HIHI.put(360)
+ # pvs.linac_llrf_phaseFB_FBU_HIHI.put(360)
+ # pvs.linac_llrf_phaseFB_MOD1_HIHI.put(360)
+ # pvs.linac_llrf_phaseFB_MOD2_HIHI.put(360)
+ # pvs.linac_llrf_phaseFB_PBU_LOLO.put(-360)
+ # pvs.linac_llrf_phaseFB_FBU_LOLO.put(-360)
+ # pvs.linac_llrf_phaseFB_MOD1_LOLO.put(-360)
+ # pvs.linac_llrf_phaseFB_MOD2_LOLO.put(-360)
+ # pvs.linac_llrf_phaseFB1.put(0)
+ # pvs.linac_llrf_phaseFB2.put(0)
+ # print('phaseFB OFF')
+ # self.timerthreadready = 1
+ # sleep(0.5)
+
+ # enable super duper master fire trigger
+ pvs.trig_firego.put(1)
+
+ def prepare_injection(self):
+ pvs = self.pvs
+
+ # ensure correct injector settings
+ if self.cur > pvs.current_threshold.get():
+ pvs.gun_grid.put(self.grid_fpfb)
+ else:
+ pvs.gun_grid.put(self.grid_accum)
+
+ self.cycles_BOIN_rb = (
+ self.cycles_BOIN_sp - self.wait4warm["AGETI-CVME-MASTER-TMA:Evt-BO-Inj-EVRCount-I.VAL"]
+ )
+ self.cycles_BOMB_rb = (
+ self.cycles_BOMB_sp - self.wait4warm["AGETI-CVME-MASTER-TMA:Evt-BO-MA-B-EVRCount-I.VAL"]
+ )
+ self.cycles_BOME_rb = (
+ self.cycles_BOME_sp - self.wait4warm["AGETI-CVME-MASTER-TMA:Evt-BO-Ramp-EVRCount-I.VAL"]
+ )
+ self.cycles_BOEX_rb = (
+ self.cycles_BOEX_sp - self.wait4warm["AGETI-CVME-MASTER-TMA:Evt-BO-Ext-EVRCount-I.VAL"]
+ )
+ self.cycles_SRIN_rb = (
+ self.cycles_SRIN_sp - self.wait4warm["AGETI-CVME-MASTER-TMA:Evt-SR-Inj-EVRCount-I.VAL"]
+ )
+
+ self.cycles_rem = np.nanmax(
+ [
+ self.cycles_BOIN_rb,
+ self.cycles_BOMB_rb,
+ self.cycles_BOME_rb,
+ self.cycles_BOEX_rb,
+ self.cycles_SRIN_rb,
+ ]
+ )
+
+ if self.cycles_rem == self.cycles_BOIN_sp:
+ pvs.trig_booinj.put(1)
+ if self.cycles_rem == self.cycles_BOMB_sp:
+ pvs.trig_bormp1.put(1)
+ if self.cycles_rem == self.cycles_BOME_sp:
+ pvs.trig_bormp2.put(1)
+ if self.cycles_rem == self.cycles_BOEX_sp:
+ pvs.trig_booext.put(1)
+ if self.cycles_rem == self.cycles_SRIN_sp:
+ pvs.trig_rininj.put(1)
+
+ pvs.cycles_BOIN_rb.put(self.cycles_BOIN_rb)
+ pvs.cycles_BOMB_rb.put(self.cycles_BOMB_rb)
+ pvs.cycles_BOME_rb.put(self.cycles_BOME_rb)
+ pvs.cycles_BOEX_rb.put(self.cycles_BOEX_rb)
+ pvs.cycles_SRIN_rb.put(self.cycles_SRIN_rb)
+
+ def start_scrubbing(self):
+ pvs = self.pvs
+
+ if self.scrubbi == 1:
+ pvs.trig_pinger_v.put(1)
+ elif self.scrubbi == 2:
+ pvs.trig_pinger_h.put(1)
+ elif self.scrubbi == 3:
+ pvs.trig_pinger_v.put(1)
+ pvs.trig_pinger_h.put(1)
+ elif self.scrubbi == 4:
+ for i in range(self.mbfby_sp):
+ pvs.mbfby_gain.put(i + 1)
+ sleep(0.05)
+ elif self.scrubbi == 5:
+ for i in range(self.mbfbx_sp):
+ pvs.mbfbx_gain.put(i + 1)
+ sleep(0.05)
+ elif self.scrubbi == 6:
+ for i in range(self.mbfby_sp):
+ pvs.mbfby_gain.put(i + 1)
+ sleep(0.05)
+ for i in range(self.mbfbx_sp):
+ pvs.mbfbx_gain.put(i + 1)
+ sleep(0.05)
+ elif self.scrubbi == 7:
+ for i in range(self.mbfby_sp):
+ pvs.mbfby_gain.put(i + 1)
+ sleep(0.05)
+ pvs.mbfby_sweep_onoff.put(1)
+
+ print("scrubbing started...")
+
+ def stop_scrubbing(self):
+ pvs = self.pvs
+
+ pvs.mbfbx_gain.put(0)
+ pvs.mbfby_gain.put(0)
+ pvs.trig_pinger_h.put(0)
+ pvs.trig_pinger_v.put(0)
+
+ if self.scrubbi == 7:
+ self.mbfby_sweepfreq_rb = np.round(pvs.mbfby_sweepfreq_rb.get())
+ pvs.mbfby_sweep_onoff.put(0)
+ pvs.mbfby_sweepfreq_start.put(self.mbfby_sweepfreq_rb)
+ pvs.mbfby_freq_sp.put(self.mbfby_sweepfreq_rb)
+
+ def pause_scrubbing(self):
+ pvs = self.pvs
+
+ if self.scrubbi > 0:
+ pvs.mbfbx_gain.put(0)
+ pvs.mbfby_gain.put(0)
+ pvs.trig_pinger_h.put(0)
+ pvs.trig_pinger_v.put(0)
+
+ if self.scrubbi == 7:
+ self.mbfby_sweepfreq_rb = np.round(pvs.mbfby_sweepfreq_rb.get())
+ pvs.mbfby_sweep_onoff.put(0)
+ pvs.mbfby_sweepfreq_start.put(self.mbfby_sweepfreq_rb)
+ pvs.mbfby_freq_sp.put(self.mbfby_sweepfreq_rb)
+
+ def set_status(self, status, wait=0):
+ pvs = self.pvs
+
+ if self.info != status:
+ self.info = status
+
+ if wait == 0:
+ pvs.info.put(status)
+
+ if wait > 0:
+ pvs.info.put(status + ", Wait {:.0f}s".format(wait))
+
+ ## define some "static" class attributes, i.e., persistent over every class call v = vals()
+ # trigger for execution of loop (controlled by PV callback)
+ ChangeTrue = 0
+ # current state of callback
+ CallbackActive = 0
+ # start time for next loop firing, if no vacuum changes
+ tl = perf_counter()
+ # waittime before injection after preparation
+ tp = perf_counter()
+ # status for GUI message
+ status = "Service Restarted"
+ # injection abort status
+ abort = 0
+ # injection abort timer
+ abort_t0 = perf_counter()
+ # states of state machine
+ states = {
+ "abort": "Injection Abort",
+ "decay + scrub": "Decaying Beam, Scrub ON",
+ "decay - scrub": "Decaying Beam, Scrub OFF",
+ "inject": "Injecting",
+ "wait 4 master": "Waiting for Master Trigger",
+ "wait 4 manual": "Master Manual Mode Required",
+ "warmup": "Top Up Save Warmup",
+ "pause": "Service Paused",
+ }
+
+ # define callback function to trigger loop execution on change of corresponding pv change
+ def InjectionCallback(self, pvname=None, value=None, char_value=None, **kw):
+ # trigger execution of loop with actual callback since execution of code here not reliable
+ self.ChangeTrue += 1
+
+ def WarmupCallback(self, pvname=None, value=None, char_value=None, **kw):
+ # trigger execution of loop with actual callback since execution of code here not reliable
+ self.wait4warm[pvname] += 1
+ self.ChangeTrue += 1
diff --git a/services/scrubbing/current/app/tests/test_app.py b/services/scrubbing/current/app/tests/test_app.py
new file mode 100644
index 0000000..693f7c8
--- /dev/null
+++ b/services/scrubbing/current/app/tests/test_app.py
@@ -0,0 +1,8 @@
+from agebd_scrubbing import PVs, Service
+
+
+def test_app():
+ service_name = "DUMMY"
+ pvs = PVs(service_name=service_name)
+ service = Service(pvs=pvs)
+ service.update()
diff --git a/services/scrubbing/current/app/uv.lock b/services/scrubbing/current/app/uv.lock
new file mode 100644
index 0000000..457a790
--- /dev/null
+++ b/services/scrubbing/current/app/uv.lock
@@ -0,0 +1,301 @@
+version = 1
+revision = 3
+requires-python = "==3.10.*"
+
+[[package]]
+name = "agebd"
+version = "0.1.0"
+source = { editable = "../../../../packages/agebd" }
+dependencies = [
+ { name = "h5py" },
+ { name = "typer" },
+]
+
+[package.metadata]
+requires-dist = [
+ { name = "h5py", specifier = ">=3.16.0" },
+ { name = "typer", specifier = ">=0.23.2" },
+]
+
+[package.metadata.requires-dev]
+dev = [
+ { name = "pyright", specifier = ">=1.1.410" },
+ { name = "pytest", specifier = ">=8.4.2" },
+ { name = "ruff", specifier = ">=0.15.19" },
+]
+
+[[package]]
+name = "agebd-scrubbing"
+version = "0.1.0"
+source = { editable = "." }
+dependencies = [
+ { name = "agebd" },
+ { name = "numpy" },
+]
+
+[package.dev-dependencies]
+dev = [
+ { name = "pyepics" },
+ { name = "pytest" },
+ { name = "ruff" },
+]
+
+[package.metadata]
+requires-dist = [
+ { name = "agebd", editable = "../../../../packages/agebd" },
+ { name = "numpy", specifier = ">=2.2.6" },
+]
+
+[package.metadata.requires-dev]
+dev = [
+ { name = "pyepics", specifier = ">=3.5.8" },
+ { name = "pytest", specifier = ">=8.4.2" },
+ { name = "ruff", specifier = ">=0.15.20" },
+]
+
+[[package]]
+name = "annotated-doc"
+version = "0.0.4"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/57/ba/046ceea27344560984e26a590f90bc7f4a75b06701f653222458922b558c/annotated_doc-0.0.4.tar.gz", hash = "sha256:fbcda96e87e9c92ad167c2e53839e57503ecfda18804ea28102353485033faa4", size = 7288, upload-time = "2025-11-10T22:07:42.062Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl", hash = "sha256:571ac1dc6991c450b25a9c2d84a3705e2ae7a53467b5d111c24fa8baabbed320", size = 5303, upload-time = "2025-11-10T22:07:40.673Z" },
+]
+
+[[package]]
+name = "colorama"
+version = "0.4.6"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" },
+]
+
+[[package]]
+name = "exceptiongroup"
+version = "1.3.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "typing-extensions" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" },
+]
+
+[[package]]
+name = "h5py"
+version = "3.16.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "numpy" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/db/33/acd0ce6863b6c0d7735007df01815403f5589a21ff8c2e1ee2587a38f548/h5py-3.16.0.tar.gz", hash = "sha256:a0dbaad796840ccaa67a4c144a0d0c8080073c34c76d5a6941d6818678ef2738", size = 446526, upload-time = "2026-03-06T13:49:08.07Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/3a/6b/231413e58a787a89b316bb0d1777da3c62257e4797e09afd8d17ad3549dc/h5py-3.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e06f864bedb2c8e7c1358e6c73af48519e317457c444d6f3d332bb4e8fa6d7d9", size = 3724137, upload-time = "2026-03-06T13:47:35.242Z" },
+ { url = "https://files.pythonhosted.org/packages/74/f9/557ce3aad0fe8471fb5279bab0fc56ea473858a022c4ce8a0b8f303d64e9/h5py-3.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ec86d4fffd87a0f4cb3d5796ceb5a50123a2a6d99b43e616e5504e66a953eca3", size = 3090112, upload-time = "2026-03-06T13:47:37.634Z" },
+ { url = "https://files.pythonhosted.org/packages/7a/f5/e15b3d0dc8a18e56409a839e6468d6fb589bc5207c917399c2e0706eeb44/h5py-3.16.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:86385ea895508220b8a7e45efa428aeafaa586bd737c7af9ee04661d8d84a10d", size = 4844847, upload-time = "2026-03-06T13:47:39.811Z" },
+ { url = "https://files.pythonhosted.org/packages/cb/92/a8851d936547efe30cc0ce5245feac01f3ec6171f7899bc3f775c72030b3/h5py-3.16.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:8975273c2c5921c25700193b408e28d6bdd0111c37468b2d4e25dcec4cd1d84d", size = 5065352, upload-time = "2026-03-06T13:47:41.489Z" },
+ { url = "https://files.pythonhosted.org/packages/2b/ae/f2adc5d0ca9626db3277a3d87516e124cbc5d0eea0bd79bc085702d04f2c/h5py-3.16.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:1677ad48b703f44efc9ea0c3ab284527f81bc4f318386aaaebc5fede6bbae56f", size = 4839173, upload-time = "2026-03-06T13:47:43.586Z" },
+ { url = "https://files.pythonhosted.org/packages/64/0b/e0c8c69da1d8838da023a50cd3080eae5d475691f7636b35eff20bb6ef20/h5py-3.16.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7c4dd4cf5f0a4e36083f73172f6cfc25a5710789269547f132a20975bfe2434c", size = 5076216, upload-time = "2026-03-06T13:47:45.315Z" },
+ { url = "https://files.pythonhosted.org/packages/66/35/d88fd6718832133c885004c61ceeeb24dbd6397ef877dbed6b3a64d6a286/h5py-3.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:bdef06507725b455fccba9c16529121a5e1fbf56aa375f7d9713d9e8ff42454d", size = 3183639, upload-time = "2026-03-06T13:47:47.041Z" },
+]
+
+[[package]]
+name = "iniconfig"
+version = "2.3.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" },
+]
+
+[[package]]
+name = "markdown-it-py"
+version = "4.2.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "mdurl" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/06/ff/7841249c247aa650a76b9ee4bbaeae59370dc8bfd2f6c01f3630c35eb134/markdown_it_py-4.2.0.tar.gz", hash = "sha256:04a21681d6fbb623de53f6f364d352309d4094dd4194040a10fd51833e418d49", size = 82454, upload-time = "2026-05-07T12:08:28.36Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl", hash = "sha256:9f7ebbcd14fe59494226453aed97c1070d83f8d24b6fc3a3bcf9a38092641c4a", size = 91687, upload-time = "2026-05-07T12:08:27.182Z" },
+]
+
+[[package]]
+name = "mdurl"
+version = "0.1.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" },
+]
+
+[[package]]
+name = "numpy"
+version = "2.2.6"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/76/21/7d2a95e4bba9dc13d043ee156a356c0a8f0c6309dff6b21b4d71a073b8a8/numpy-2.2.6.tar.gz", hash = "sha256:e29554e2bef54a90aa5cc07da6ce955accb83f21ab5de01a62c8478897b264fd", size = 20276440, upload-time = "2025-05-17T22:38:04.611Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/9a/3e/ed6db5be21ce87955c0cbd3009f2803f59fa08df21b5df06862e2d8e2bdd/numpy-2.2.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b412caa66f72040e6d268491a59f2c43bf03eb6c96dd8f0307829feb7fa2b6fb", size = 21165245, upload-time = "2025-05-17T21:27:58.555Z" },
+ { url = "https://files.pythonhosted.org/packages/22/c2/4b9221495b2a132cc9d2eb862e21d42a009f5a60e45fc44b00118c174bff/numpy-2.2.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e41fd67c52b86603a91c1a505ebaef50b3314de0213461c7a6e99c9a3beff90", size = 14360048, upload-time = "2025-05-17T21:28:21.406Z" },
+ { url = "https://files.pythonhosted.org/packages/fd/77/dc2fcfc66943c6410e2bf598062f5959372735ffda175b39906d54f02349/numpy-2.2.6-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:37e990a01ae6ec7fe7fa1c26c55ecb672dd98b19c3d0e1d1f326fa13cb38d163", size = 5340542, upload-time = "2025-05-17T21:28:30.931Z" },
+ { url = "https://files.pythonhosted.org/packages/7a/4f/1cb5fdc353a5f5cc7feb692db9b8ec2c3d6405453f982435efc52561df58/numpy-2.2.6-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:5a6429d4be8ca66d889b7cf70f536a397dc45ba6faeb5f8c5427935d9592e9cf", size = 6878301, upload-time = "2025-05-17T21:28:41.613Z" },
+ { url = "https://files.pythonhosted.org/packages/eb/17/96a3acd228cec142fcb8723bd3cc39c2a474f7dcf0a5d16731980bcafa95/numpy-2.2.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:efd28d4e9cd7d7a8d39074a4d44c63eda73401580c5c76acda2ce969e0a38e83", size = 14297320, upload-time = "2025-05-17T21:29:02.78Z" },
+ { url = "https://files.pythonhosted.org/packages/b4/63/3de6a34ad7ad6646ac7d2f55ebc6ad439dbbf9c4370017c50cf403fb19b5/numpy-2.2.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc7b73d02efb0e18c000e9ad8b83480dfcd5dfd11065997ed4c6747470ae8915", size = 16801050, upload-time = "2025-05-17T21:29:27.675Z" },
+ { url = "https://files.pythonhosted.org/packages/07/b6/89d837eddef52b3d0cec5c6ba0456c1bf1b9ef6a6672fc2b7873c3ec4e2e/numpy-2.2.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:74d4531beb257d2c3f4b261bfb0fc09e0f9ebb8842d82a7b4209415896adc680", size = 15807034, upload-time = "2025-05-17T21:29:51.102Z" },
+ { url = "https://files.pythonhosted.org/packages/01/c8/dc6ae86e3c61cfec1f178e5c9f7858584049b6093f843bca541f94120920/numpy-2.2.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8fc377d995680230e83241d8a96def29f204b5782f371c532579b4f20607a289", size = 18614185, upload-time = "2025-05-17T21:30:18.703Z" },
+ { url = "https://files.pythonhosted.org/packages/5b/c5/0064b1b7e7c89137b471ccec1fd2282fceaae0ab3a9550f2568782d80357/numpy-2.2.6-cp310-cp310-win32.whl", hash = "sha256:b093dd74e50a8cba3e873868d9e93a85b78e0daf2e98c6797566ad8044e8363d", size = 6527149, upload-time = "2025-05-17T21:30:29.788Z" },
+ { url = "https://files.pythonhosted.org/packages/a3/dd/4b822569d6b96c39d1215dbae0582fd99954dcbcf0c1a13c61783feaca3f/numpy-2.2.6-cp310-cp310-win_amd64.whl", hash = "sha256:f0fd6321b839904e15c46e0d257fdd101dd7f530fe03fd6359c1ea63738703f3", size = 12904620, upload-time = "2025-05-17T21:30:48.994Z" },
+ { url = "https://files.pythonhosted.org/packages/9e/3b/d94a75f4dbf1ef5d321523ecac21ef23a3cd2ac8b78ae2aac40873590229/numpy-2.2.6-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0b605b275d7bd0c640cad4e5d30fa701a8d59302e127e5f79138ad62762c3e3d", size = 21040391, upload-time = "2025-05-17T21:44:35.948Z" },
+ { url = "https://files.pythonhosted.org/packages/17/f4/09b2fa1b58f0fb4f7c7963a1649c64c4d315752240377ed74d9cd878f7b5/numpy-2.2.6-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:7befc596a7dc9da8a337f79802ee8adb30a552a94f792b9c9d18c840055907db", size = 6786754, upload-time = "2025-05-17T21:44:47.446Z" },
+ { url = "https://files.pythonhosted.org/packages/af/30/feba75f143bdc868a1cc3f44ccfa6c4b9ec522b36458e738cd00f67b573f/numpy-2.2.6-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce47521a4754c8f4593837384bd3424880629f718d87c5d44f8ed763edd63543", size = 16643476, upload-time = "2025-05-17T21:45:11.871Z" },
+ { url = "https://files.pythonhosted.org/packages/37/48/ac2a9584402fb6c0cd5b5d1a91dcf176b15760130dd386bbafdbfe3640bf/numpy-2.2.6-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d042d24c90c41b54fd506da306759e06e568864df8ec17ccc17e9e884634fd00", size = 12812666, upload-time = "2025-05-17T21:45:31.426Z" },
+]
+
+[[package]]
+name = "packaging"
+version = "26.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d7/f1/e7a6dd94a8d4a5626c03e4e99c87f241ba9e350cd9e6d75123f992427270/packaging-26.2.tar.gz", hash = "sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661", size = 228134, upload-time = "2026-04-24T20:15:23.917Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/df/b2/87e62e8c3e2f4b32e5fe99e0b86d576da1312593b39f47d8ceef365e95ed/packaging-26.2-py3-none-any.whl", hash = "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e", size = 100195, upload-time = "2026-04-24T20:15:22.081Z" },
+]
+
+[[package]]
+name = "pluggy"
+version = "1.6.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" },
+]
+
+[[package]]
+name = "pyepics"
+version = "3.5.10"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "numpy" },
+ { name = "pyparsing" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/69/57/29e1e9ef11ba2a3419f489946ae1d8190025a1e4f4e1c1686758bb2b6e0a/pyepics-3.5.10.tar.gz", hash = "sha256:f390cf9be40aba757b9528888114bc14d8db01086d0c93914720b1772460375b", size = 6150481, upload-time = "2026-05-20T18:44:36.336Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d6/36/e517fd83bd97d6bfe4105e0c6b322070c5cc36fb56a8fab2866e319f8804/pyepics-3.5.10-py3-none-any.whl", hash = "sha256:c9fac2c54f2b595268e66fc348cf5ec24e63718e7dbd07d73d1b37d4da6bfee1", size = 5332376, upload-time = "2026-05-20T18:44:34.242Z" },
+]
+
+[[package]]
+name = "pygments"
+version = "2.20.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" },
+]
+
+[[package]]
+name = "pyparsing"
+version = "3.3.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f3/91/9c6ee907786a473bf81c5f53cf703ba0957b23ab84c264080fb5a450416f/pyparsing-3.3.2.tar.gz", hash = "sha256:c777f4d763f140633dcb6d8a3eda953bf7a214dc4eff598413c070bcdc117cbc", size = 6851574, upload-time = "2026-01-21T03:57:59.36Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl", hash = "sha256:850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d", size = 122781, upload-time = "2026-01-21T03:57:55.912Z" },
+]
+
+[[package]]
+name = "pytest"
+version = "9.1.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "colorama", marker = "sys_platform == 'win32'" },
+ { name = "exceptiongroup" },
+ { name = "iniconfig" },
+ { name = "packaging" },
+ { name = "pluggy" },
+ { name = "pygments" },
+ { name = "tomli" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/e4/47/b9efed96c114afcfa3c9d3fe98a76a1d14c74a9e266d397cf6eb64be5e01/pytest-9.1.1.tar.gz", hash = "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313", size = 1636369, upload-time = "2026-06-19T10:58:32.857Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/24/25/1de2678b631f5a49215c6c96fff41ba892b0a34df68d6d80292b1b48aa7f/pytest-9.1.1-py3-none-any.whl", hash = "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c", size = 386536, upload-time = "2026-06-19T10:58:31.347Z" },
+]
+
+[[package]]
+name = "rich"
+version = "15.0.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "markdown-it-py" },
+ { name = "pygments" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/c0/8f/0722ca900cc807c13a6a0c696dacf35430f72e0ec571c4275d2371fca3e9/rich-15.0.0.tar.gz", hash = "sha256:edd07a4824c6b40189fb7ac9bc4c52536e9780fbbfbddf6f1e2502c31b068c36", size = 230680, upload-time = "2026-04-12T08:24:00.75Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl", hash = "sha256:33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb", size = 310654, upload-time = "2026-04-12T08:24:02.83Z" },
+]
+
+[[package]]
+name = "ruff"
+version = "0.15.21"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/0f/36/6f65aa9989acdec45d417192d8f4e7921931d8a6cf87ac74bce3eed98a8e/ruff-0.15.21.tar.gz", hash = "sha256:d0cfc841c572283c36548f82664a54ce6565567f1b0d5b4cf2caac693d8b7500", size = 4769401, upload-time = "2026-07-09T20:01:34.005Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d0/c6/ede15cac6839f3dbce52565c8f5164a8210e669c7bc4decb03e5bdf47d0d/ruff-0.15.21-py3-none-linux_armv6l.whl", hash = "sha256:63ea0e965e5d73c90e95b2434beeafc70820536717f561b32ab6e777cb9bdf5d", size = 10854342, upload-time = "2026-07-09T20:00:53.998Z" },
+ { url = "https://files.pythonhosted.org/packages/28/9d/d825b07ee7ea9e2d61df92a860033c94e06e7300d50a1c2653aac27d24fe/ruff-0.15.21-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:0f212c5d7d54c01bbfe6dcab02b724a39300f3e34ed7acbe995ccb320a2c58bd", size = 11139539, upload-time = "2026-07-09T20:00:57.809Z" },
+ { url = "https://files.pythonhosted.org/packages/f5/de/3b107712e642f063c7a9e0887c427b22cb44097de5aab36c05f2e280670c/ruff-0.15.21-py3-none-macosx_11_0_arm64.whl", hash = "sha256:e6312e41bc96791299614995ea3a977c5857c3b5662b1ecef6755b02b87cb646", size = 10595437, upload-time = "2026-07-09T20:01:00.006Z" },
+ { url = "https://files.pythonhosted.org/packages/9a/6f/b4523cc90ba239ede441447a19d0c968846a3012e5a0b0c5b62831a3d5e3/ruff-0.15.21-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01d65b4831c6b2a4ba8ee6faa84049d44d982b7a706e622c4094c509e51673be", size = 10990053, upload-time = "2026-07-09T20:01:02.187Z" },
+ { url = "https://files.pythonhosted.org/packages/92/cc/c6a9872a5375f0628875481cf2f66b13d7d865bf3ca2e57f91c7e762d976/ruff-0.15.21-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2c5a913a589120ce67933d5d05fd6ddbcc2481c6a054980ee767f7414c72b4fd", size = 10666096, upload-time = "2026-07-09T20:01:04.299Z" },
+ { url = "https://files.pythonhosted.org/packages/ab/97/c621f7a17e097f1790fa3af6374138823b330b2d03fc38337945daca212c/ruff-0.15.21-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ef04b681d02ad4dc9620f00f83ac5c22f652d0e9a9cfe431d219b16ad5ccc41", size = 11537011, upload-time = "2026-07-09T20:01:06.771Z" },
+ { url = "https://files.pythonhosted.org/packages/ea/51/d928727e476e25ccc57c6f449ffd80241a651a973ad949d39cfb2a771d28/ruff-0.15.21-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:16d090c0740916594157e75b80d666eab8e78083b39b3b0e1d698f4670a17b86", size = 12347101, upload-time = "2026-07-09T20:01:08.859Z" },
+ { url = "https://files.pythonhosted.org/packages/1e/88/8cd62026802b16018ad06931d87997cf795ba2a6239ab659606c87d96bf0/ruff-0.15.21-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3a10e74757dd65004d779b73e2f3c5210156d9980b41224d50d2ebcf1db51e67", size = 11572001, upload-time = "2026-07-09T20:01:11.092Z" },
+ { url = "https://files.pythonhosted.org/packages/b2/97/f63084cf55444fc110e8cb985ebfcc592af47f597d44453d778cb81bc156/ruff-0.15.21-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bab0905d2f29e0d9fbc3c373ed23db0095edaa3f71f1f4f519ec15134d9e85c8", size = 11549239, upload-time = "2026-07-09T20:01:13.27Z" },
+ { url = "https://files.pythonhosted.org/packages/9d/77/f107da4a2874b7715914b03f09ba9c54424de3ff8a1cc5d015d3ee2ce0ac/ruff-0.15.21-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:00eca240af5789fec6fe7df74c088cc1f9644ed83027113468efba7c92b94075", size = 11535340, upload-time = "2026-07-09T20:01:15.206Z" },
+ { url = "https://files.pythonhosted.org/packages/d5/e9/601deb322d3303a7bf212b0100ead6f2ee3f6a044d89c30f2f92bf83c731/ruff-0.15.21-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:262ab31557a75141325e32d3357f3597645a7f084e732b6b054dde428ecd9341", size = 10964048, upload-time = "2026-07-09T20:01:17.723Z" },
+ { url = "https://files.pythonhosted.org/packages/ea/2e/0f2176d1e99c15192caea19c8c3a0a955246b4cb4de795042eeb616345cd/ruff-0.15.21-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:659c4e7a4212f83306045ec7c5e5a356d16d9a6ef4ae0c7a4d872914fc655d9d", size = 10667055, upload-time = "2026-07-09T20:01:19.73Z" },
+ { url = "https://files.pythonhosted.org/packages/48/60/abd74a02e0c4214f12a68becfd30af7165cfdcb0e661ecdc60bbb949c09a/ruff-0.15.21-py3-none-musllinux_1_2_i686.whl", hash = "sha256:9e866eab611a5f959d36df2d10e446973a3610bc42b0c15b31dc27977d59c233", size = 11242043, upload-time = "2026-07-09T20:01:21.947Z" },
+ { url = "https://files.pythonhosted.org/packages/b2/c6/583075d8ccabb4b229345edcaf1545eb3d8d6be90f686a479d7e94088bbf/ruff-0.15.21-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e89bc93c0d3803ba870b55c29671bad9dc6d94bb1eb181b056b52eb05b52854f", size = 11648064, upload-time = "2026-07-09T20:01:24.023Z" },
+ { url = "https://files.pythonhosted.org/packages/3a/3c/37d0ecb729a7cc2d393ea7dce316fc585680f35d93b8d62139d7d0a3700c/ruff-0.15.21-py3-none-win32.whl", hash = "sha256:01f8d5be84823c172b389e123174f781f9daf86d6c58719d603f941932195cdd", size = 10896555, upload-time = "2026-07-09T20:01:26.941Z" },
+ { url = "https://files.pythonhosted.org/packages/c0/b8/e43466b2a6067ce91e669068f6e28d6c719a920f014b070d5c8731725de3/ruff-0.15.21-py3-none-win_amd64.whl", hash = "sha256:d4b8d9a2f0f12b816b50447f6eccb9f4bb01a6b82c86b50fb3b5354b458dc6d3", size = 12038772, upload-time = "2026-07-09T20:01:29.497Z" },
+ { url = "https://files.pythonhosted.org/packages/dd/75/e90ab9aeece218a9fc5a5bc3ec97d0ee6bb3c4ff95869463c1de58e29a1c/ruff-0.15.21-py3-none-win_arm64.whl", hash = "sha256:6e83115d4b9377c1cbc13abf0e051f069fab0ef815ea0504a8a008cee24dd0a8", size = 11375265, upload-time = "2026-07-09T20:01:31.772Z" },
+]
+
+[[package]]
+name = "shellingham"
+version = "1.5.4"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/58/15/8b3609fd3830ef7b27b655beb4b4e9c62313a4e8da8c676e142cc210d58e/shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de", size = 10310, upload-time = "2023-10-24T04:13:40.426Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755, upload-time = "2023-10-24T04:13:38.866Z" },
+]
+
+[[package]]
+name = "tomli"
+version = "2.4.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/22/de/48c59722572767841493b26183a0d1cc411d54fd759c5607c4590b6563a6/tomli-2.4.1.tar.gz", hash = "sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f", size = 17543, upload-time = "2026-03-25T20:22:03.828Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/7b/61/cceae43728b7de99d9b847560c262873a1f6c98202171fd5ed62640b494b/tomli-2.4.1-py3-none-any.whl", hash = "sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe", size = 14583, upload-time = "2026-03-25T20:22:03.012Z" },
+]
+
+[[package]]
+name = "typer"
+version = "0.27.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "annotated-doc" },
+ { name = "colorama", marker = "sys_platform == 'win32'" },
+ { name = "rich" },
+ { name = "shellingham" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/37/78/fda3361b56efc27944f24225f6ecd13d96d6fcfe37bd0eb34e2f4c63f9fc/typer-0.27.0.tar.gz", hash = "sha256:629bd12ea5d13a17148125d9a264f949eb171fb3f120f9b04d85873cab054fa5", size = 203430, upload-time = "2026-07-15T19:21:07.007Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/40/03/26a383c9e58c213199d1aad1c3d353cfc22d4444ec6d2c0bf8ad02523843/typer-0.27.0-py3-none-any.whl", hash = "sha256:6f4b27631e47f077871b7dc30e933ec0131c1390fbe0e387ea5574b5bac9ccf1", size = 122716, upload-time = "2026-07-15T19:21:05.553Z" },
+]
+
+[[package]]
+name = "typing-extensions"
+version = "4.16.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f6/cc/6253133b5bb138fc3306cebfbda2c520f545d36b5be2c7255cc528bb45d6/typing_extensions-4.16.0.tar.gz", hash = "sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5", size = 113555, upload-time = "2026-07-02T08:40:05.92Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/49/d3/b8441a820a491ddfc024b0b0cf0393375b75ea13866d9c66727e54c2fc80/typing_extensions-4.16.0-py3-none-any.whl", hash = "sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8", size = 45571, upload-time = "2026-07-02T08:40:04.659Z" },
+]
diff --git a/services/scrubbing/current/ioc/AGEBD-CPCL-SCRUBBING_main.subs b/services/scrubbing/current/ioc/AGEBD-CPCL-SCRUBBING_main.subs
new file mode 100644
index 0000000..c5f2732
--- /dev/null
+++ b/services/scrubbing/current/ioc/AGEBD-CPCL-SCRUBBING_main.subs
@@ -0,0 +1,4 @@
+file SCRUBBING.template {
+ pattern { DEVICE }
+ { AGEBD-SCRUBBING{{ agebd_env }} }
+}
diff --git a/services/scrubbing/current/ioc/AGEBD-CPCL-SCRUBBING_parameters.yaml b/services/scrubbing/current/ioc/AGEBD-CPCL-SCRUBBING_parameters.yaml
new file mode 100644
index 0000000..ff8e70f
--- /dev/null
+++ b/services/scrubbing/current/ioc/AGEBD-CPCL-SCRUBBING_parameters.yaml
@@ -0,0 +1,6 @@
+cpu_architecture: x86_64
+epics_version: 7.0.8
+ioc_host: sls-vserv-bd-01{{ agebd_env }}
+ioc_port: {{ ioc_port }}
+os: RHEL8
+os_id: rhel
diff --git a/services/scrubbing/current/ioc/SCRUBBING.template b/services/scrubbing/current/ioc/SCRUBBING.template
new file mode 100644
index 0000000..94ad8aa
--- /dev/null
+++ b/services/scrubbing/current/ioc/SCRUBBING.template
@@ -0,0 +1,290 @@
+# HLA Service Control Parameters
+
+record(mbbo, "$(DEVICE):CONTROL-SCRUB") {
+ field(DESC, "Scrubbing Mode")
+ field(ASG, "PROTECTED")
+ field(ZRST, "Off")
+ field(ZRVL, "0")
+ field(ONST, "Vertical Pinger")
+ field(ONVL, "1")
+ field(TWST, "Horizontal Pingers")
+ field(TWVL, "2")
+ field(THST, "Both Pingers")
+ field(THVL, "3")
+ field(FRST, "Vertical MBFB")
+ field(FRVL, "4")
+ field(FVST, "Horizontal MBFB")
+ field(FVVL, "5")
+ field(SXST, "Both MBFBs")
+ field(SXVL, "6")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-VACUUM-MAX") {
+ field(DESC, "Stop injection at this vacuum pressure")
+ field(ASG, "PROTECTED")
+ field(EGU, "1e-9 mbar")
+ field(VAL, "360")
+ field(PREC, "3")
+ field(FLNK, "$(DEVICE):CONTROL-VACUUM-MAX-PLOT")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-VACUUM-DYN") {
+ field(DESC, "Stop injection at this vacuum pressure")
+ field(ASG, "PROTECTED")
+ field(EGU, "1e-9 mbar")
+ field(VAL, "27")
+ field(PREC, "3")
+ field(FLNK, "$(DEVICE):CONTROL-VACUUM-DYN-PLOT")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-VACUUM-DYN-FRAC") {
+ field(DESC, "Fraction defining dynamic pressure ")
+ field(ASG, "PROTECTED")
+ field(VAL, "1.2")
+ field(PREC, "3")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-VACUUM-MIN") {
+ field(DESC, "Start injection at this vacuum pressure")
+ field(ASG, "PROTECTED")
+ field(EGU, "1e-9 mbar")
+ field(VAL, "0")
+ field(PREC, "3")
+ field(FLNK, "$(DEVICE):CONTROL-VACUUM-MIN-PLOT")
+ field(PINI, "YES")
+}
+
+record(calc, "$(DEVICE):CONTROL-VACUUM-MAX-PLOT") {
+ field(DESC, "Stop injection at this vacuum pressure")
+ field(ASG, "READONLY")
+ field(EGU, "mbar")
+ field(PREC, "-5")
+ field(CALC, "A/1e9")
+ field(INPA, "$(DEVICE):CONTROL-VACUUM-MAX")
+}
+
+record(calc, "$(DEVICE):CONTROL-VACUUM-DYN-PLOT") {
+ field(DESC, "Stop injection at this vacuum pressure")
+ field(ASG, "READONLY")
+ field(EGU, "mbar")
+ field(PREC, "-5")
+ field(CALC, "A/1e9")
+ field(INPA, "$(DEVICE):CONTROL-VACUUM-DYN")
+}
+
+record(calc, "$(DEVICE):CONTROL-VACUUM-MIN-PLOT") {
+ field(DESC, "Stop injection at this vacuum pressure")
+ field(ASG, "READONLY")
+ field(EGU, "mbar")
+ field(PREC, "-5")
+ field(CALC, "A/1e9")
+ field(INPA, "$(DEVICE):CONTROL-VACUUM-MIN")
+}
+
+record(ao, "$(DEVICE):CONTROL-CURRENT-MAX") {
+ field(DESC, "Stop injection at this current")
+ field(ASG, "PROTECTED")
+ field(EGU, "mA")
+ field(VAL, "403")
+ field(PREC, "3")
+ field(PINI, "YES")
+ field(DRVH, "425")
+ field(DRVL, "0")
+}
+
+record(ao, "$(DEVICE):CONTROL-CURRENT-MIN") {
+ field(DESC, "Start injection at this current")
+ field(ASG, "PROTECTED")
+ field(EGU, "mA")
+ field(VAL, "400")
+ field(PREC, "3")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-TIME-MAX") {
+ field(DESC, "Stop injection after this time")
+ field(ASG, "PROTECTED")
+ field(EGU, "s")
+ field(VAL, "30")
+ field(PREC, "3")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-TIME-MIN") {
+ field(DESC, "Start injection after this time")
+ field(ASG, "PROTECTED")
+ field(EGU, "s")
+ field(VAL, "300")
+ field(PREC, "3")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):MBFBY-GAIN-SP") {
+ field(DESC, "MBFBy Gain SP for scrubbing")
+ field(ASG, "PROTECTED")
+ field(EGU, "%")
+ field(VAL, "1")
+ field(PREC, "3")
+ field(PINI, "YES")
+ field(DRVH, "100")
+ field(DRVL, "0")
+}
+
+record(ao, "$(DEVICE):MBFBX-GAIN-SP") {
+ field(DESC, "MBFBx Gain SP for scrubbing")
+ field(ASG, "PROTECTED")
+ field(EGU, "%")
+ field(VAL, "1")
+ field(PREC, "3")
+ field(PINI, "YES")
+ field(DRVH, "100")
+ field(DRVL, "0")
+}
+
+record(ao, "$(DEVICE):CONTROL-GUNGRID-ACCUM") {
+ field(DESC, "Gungrid val for accumulation")
+ field(ASG, "PROTECTED")
+ field(EGU, "V")
+ field(VAL, "100")
+ field(PREC, "3")
+ field(PINI, "YES")
+ field(DRVH, "180")
+ field(DRVL, "40")
+}
+
+record(ao, "$(DEVICE):CONTROL-GUNGRID-FPFB") {
+ field(DESC, "Gungrid val for FPFB Injection")
+ field(ASG, "PROTECTED")
+ field(EGU, "V")
+ field(VAL, "160")
+ field(PREC, "3")
+ field(PINI, "YES")
+ field(DRVH, "180")
+ field(DRVL, "40")
+}
+
+# HLA Service Output/Result Parameters
+
+record(ao, "$(DEVICE):TOPUP-TAU") {
+ field(DESC, "Average tau since last top up")
+ field(ASG, "PROTECTED")
+ field(EGU, "h")
+ field(VAL, "100")
+ field(PREC, "3")
+ field(VAL, "-1")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):TOPUP-DELTAT") {
+ field(DESC, "Time since last top up")
+ field(ASG, "PROTECTED")
+ field(EGU, "min")
+ field(VAL, "100")
+ field(PREC, "3")
+ field(VAL, "-1")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):TOPUP-DELTAI") {
+ field(DESC, "Current change since last top up")
+ field(ASG, "PROTECTED")
+ field(EGU, "mA")
+ field(VAL, "100")
+ field(PREC, "3")
+ field(VAL, "-1")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):WARMUPCYCLES-BOIN-SP") {
+ field(DESC, "Warmup cycles for booster injection")
+ field(ASG, "PROTECTED")
+ field(EGU, "")
+ field(VAL, "15")
+ field(PREC, "1")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):WARMUPCYCLES-BOMB-SP") {
+ field(DESC, "Warmup cycles for ABOMA-B")
+ field(ASG, "PROTECTED")
+ field(EGU, "")
+ field(VAL, "5")
+ field(PREC, "1")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):WARMUPCYCLES-BOME-SP") {
+ field(DESC, "Warmup cycles for ABOMA-ELSE")
+ field(ASG, "PROTECTED")
+ field(EGU, "")
+ field(VAL, "15")
+ field(PREC, "1")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):WARMUPCYCLES-BOEX-SP") {
+ field(DESC, "Warmup cycles for booster extraction")
+ field(ASG, "PROTECTED")
+ field(EGU, "")
+ field(VAL, "15")
+ field(PREC, "1")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):WARMUPCYCLES-SRIN-SP") {
+ field(DESC, "Warmup cycles for SR Injection")
+ field(ASG, "PROTECTED")
+ field(EGU, "")
+ field(VAL, "15")
+ field(PREC, "1")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):WARMUPCYCLES-BOIN-RB") {
+ field(DESC, "Warmup cycles for booster injection")
+ field(ASG, "PROTECTED")
+ field(EGU, "")
+ field(VAL, "15")
+ field(PREC, "1")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):WARMUPCYCLES-BOMB-RB") {
+ field(DESC, "Warmup cycles for ABOMA-B")
+ field(ASG, "PROTECTED")
+ field(EGU, "")
+ field(VAL, "5")
+ field(PREC, "1")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):WARMUPCYCLES-BOME-RB") {
+ field(DESC, "Warmup cycles for ABOMA-ELSE")
+ field(ASG, "PROTECTED")
+ field(EGU, "")
+ field(VAL, "15")
+ field(PREC, "1")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):WARMUPCYCLES-BOEX-RB") {
+ field(DESC, "Warmup cycles for booster extraction")
+ field(ASG, "PROTECTED")
+ field(EGU, "")
+ field(VAL, "15")
+ field(PREC, "1")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):WARMUPCYCLES-SRIN-RB") {
+ field(DESC, "Warmup cycles for SR Injection")
+ field(ASG, "PROTECTED")
+ field(EGU, "")
+ field(VAL, "15")
+ field(PREC, "1")
+ field(PINI, "YES")
+}
\ No newline at end of file
diff --git a/services/scrubbing/current/ioc/startup.script b/services/scrubbing/current/ioc/startup.script
new file mode 100644
index 0000000..0fa52ff
--- /dev/null
+++ b/services/scrubbing/current/ioc/startup.script
@@ -0,0 +1 @@
+epicsEnvSet("ENGINEER", "armborst")
diff --git a/services/scrubbing/current/qt/A_BD_Scrubbing.ui b/services/scrubbing/current/qt/A_BD_Scrubbing.ui
new file mode 100644
index 0000000..00f96bd
--- /dev/null
+++ b/services/scrubbing/current/qt/A_BD_Scrubbing.ui
@@ -0,0 +1,5326 @@
+
+
+ MainWindow
+
+
+
+ 0
+ 0
+ 1500
+ 1000
+
+
+
+ MainWindow
+
+
+
+
+
+ 10
+ 10
+ 211
+ 61
+
+
+
+ AGEBD-ALH:SCRUBBING-ONOFF
+
+
+ caChoice::Column
+
+
+ 1
+
+
+
+
+
+ 640
+ 280
+ 861
+ 461
+
+
+
+
+ 10
+ 75
+ true
+
+
+
+ Vakuum (last 60 seconds)
+
+
+
+
+
+
+
+
+ ARIVA-VMAVE:PRESS-MAX;ARIVA-VMAVE-FE:PRESS-MAX;ARIVA-VMAVE-ALL:PRESS-MAX;AGEBD-SCRUBBING:CONTROL-VACUUM-MAX-PLOT;AGEBD-SCRUBBING:CONTROL-VACUUM-MIN-PLOT;AGEBD-SCRUBBING:CONTROL-VACUUM-DYN-PLOT
+
+
+ caStripPlot::Second
+
+
+ 60.000000000000000
+
+
+ caStripPlot::High
+
+
+ caStripPlot::log10
+
+
+ 0.000000410000000
+
+
+ 0.000000001000000
+
+
+ caStripPlot::User
+
+
+ caStripPlot::User
+
+
+
+ 255
+ 255
+ 127
+
+
+
+ 0.000000410000000
+
+
+ 0.000000001000000
+
+
+ caStripPlot::User
+
+
+ caStripPlot::User
+
+
+
+ 252
+ 192
+ 11
+
+
+
+ 0.000000410000000
+
+
+ 0.000000001000000
+
+
+ caStripPlot::User
+
+
+ caStripPlot::User
+
+
+
+ 252
+ 192
+ 11
+
+
+
+ 0.000000410000000
+
+
+ 0.000000001000000
+
+
+ caStripPlot::User
+
+
+ caStripPlot::User
+
+
+
+ 239
+ 41
+ 41
+
+
+
+ 0.000000410000000
+
+
+ 0.000000001000000
+
+
+ caStripPlot::User
+
+
+ caStripPlot::User
+
+
+
+ 239
+ 41
+ 41
+
+
+
+ 0.000000410000000
+
+
+ 0.000000001000000
+
+
+ caStripPlot::User
+
+
+ caStripPlot::User
+
+
+
+ 255
+ 0
+ 255
+
+
+
+ 0.000000100000000
+
+
+ 0.000000001000000
+
+
+
+ 218
+ 218
+ 218
+
+
+
+ true
+
+
+ false
+
+
+
+
+ 260
+ 40
+ 350
+ 50
+
+
+
+
+ Lucida Sans Typewriter
+ 32
+ 75
+ true
+
+
+
+ Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft
+
+
+ ARIVA-VMAVE-ALL:PRESS-MAX
+
+
+
+ 252
+ 192
+ 11
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caLineEdit::Static
+
+
+ 1
+
+
+ caLineEdit::User
+
+
+ caLineEdit::WidthAndHeight
+
+
+ true
+
+
+ caLineEdit::exponential
+
+
+
+
+
+ 260
+ 100
+ 350
+ 50
+
+
+
+
+ Lucida Sans Typewriter
+ 32
+ 75
+ true
+
+
+
+ Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft
+
+
+ ARIVA-VMAVE:PRESS-MAX
+
+
+
+ 255
+ 255
+ 127
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caLineEdit::Static
+
+
+ 1
+
+
+ caLineEdit::User
+
+
+ caLineEdit::WidthAndHeight
+
+
+ true
+
+
+ caLineEdit::exponential
+
+
+
+
+
+ 70
+ 40
+ 190
+ 50
+
+
+
+
+ 31
+ 50
+ false
+
+
+
+ Frontend
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 252
+ 192
+ 11
+
+
+
+
+
+
+ 70
+ 100
+ 230
+ 50
+
+
+
+
+ 31
+ 50
+ false
+
+
+
+ Machine
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 255
+ 255
+ 127
+
+
+
+
+
+
+
+ 1990
+ 540
+ 70
+ 20
+
+
+
+
+
+
+ 1980
+ 360
+ 71
+ 20
+
+
+
+ RELOAD
+
+
+ Qt::AlignCenter
+
+
+ RELOAD
+
+
+ A
+
+
+ AGEBD-ALH:SCRUBBING-GUIRELOAD
+
+
+ caCalc::TriggerOneToZero
+
+
+
+
+
+ 10
+ 80
+ 391
+ 41
+
+
+
+ AGEBD-ALH:SCRUBBING-INFO
+
+
+ caLineEdit::Alarm_Default
+
+
+ caLineEdit::onBackground
+
+
+ caLineEdit::User
+
+
+
+
+
+ 230
+ 40
+ 50
+ 30
+
+
+
+ AGEBD-SCRUBBING:TOPUP-DELTAT
+
+
+ caLineEdit::Default
+
+
+ caLineEdit::onBackground
+
+
+ 2
+
+
+ caLineEdit::User
+
+
+
+
+
+ 349
+ 40
+ 50
+ 30
+
+
+
+ AGEBD-SCRUBBING:TOPUP-TAU
+
+
+ caLineEdit::Default
+
+
+ caLineEdit::onBackground
+
+
+ 2
+
+
+ caLineEdit::User
+
+
+
+
+
+ 350
+ 10
+ 50
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ Tau
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 290
+ 10
+ 50
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ dI
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 230
+ 10
+ 50
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ dt
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 290
+ 40
+ 50
+ 30
+
+
+
+ AGEBD-SCRUBBING:TOPUP-DELTAI
+
+
+ caLineEdit::Default
+
+
+ caLineEdit::onBackground
+
+
+ 2
+
+
+ caLineEdit::User
+
+
+
+
+
+ 5
+ 450
+ 631
+ 291
+
+
+
+ Events, Trigger und Top-Up Save
+
+
+
+
+ 135
+ 173
+ 78
+ 28
+
+
+
+ true
+
+
+
+ 0
+ 0
+ 176
+
+
+
+ caGraphics::Filled
+
+
+ 1
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caGraphics::IfZero
+
+
+ AGETI-CVME-MASTER-TMA:Evt-BO-Ext-Ena-Sel
+
+
+ caGraphics::Rectangle
+
+
+ 22
+
+
+ 180
+
+
+ 0
+
+
+ 90
+
+
+
+
+
+ 215
+ 32
+ 70
+ 20
+
+
+
+ true
+
+
+ Enable
+
+
+ AGETI-CVME-MASTER-TMA:SR-Inj-Status-Sel
+
+
+ Enable
+
+
+
+ 219
+ 212
+ 157
+
+
+
+ 1
+
+
+
+
+
+ 10
+ 31
+ 100
+ 22
+
+
+
+
+ Sans Serif
+ 13
+
+
+
+ true
+
+
+ Master
+
+
+ Qt::AlignAbsolute|Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::Height
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ QFrame::NoFrame
+
+
+
+
+
+ 211
+ 173
+ 78
+ 28
+
+
+
+ true
+
+
+
+ 0
+ 0
+ 176
+
+
+
+ caGraphics::Filled
+
+
+ 1
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caGraphics::Calc
+
+
+ A=1
+
+
+ AGETI-CVME-MASTER-TMA:Evt-BO-Ext-Ena-Sel
+
+
+ caGraphics::Rectangle
+
+
+ 22
+
+
+ 180
+
+
+
+
+
+ 215
+ 177
+ 70
+ 20
+
+
+
+ true
+
+
+ Enable
+
+
+ AGETI-CVME-MASTER-TMA:Evt-BO-Ext-Ena-Sel
+
+
+ Enable
+
+
+
+ 219
+ 212
+ 157
+
+
+
+ 1
+
+
+
+
+
+ 135
+ 28
+ 78
+ 28
+
+
+
+ true
+
+
+
+ 0
+ 0
+ 176
+
+
+
+ caGraphics::Filled
+
+
+ 1
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caGraphics::Calc
+
+
+ A=0
+
+
+ AGETI-CVME-MASTER-TMA:SR-Inj-Status-Sel
+
+
+ caGraphics::Rectangle
+
+
+ 22
+
+
+ 180
+
+
+
+
+
+ 139
+ 177
+ 70
+ 20
+
+
+
+ true
+
+
+ Disable
+
+
+ AGETI-CVME-MASTER-TMA:Evt-BO-Ext-Ena-Sel
+
+
+ Disable
+
+
+
+ 219
+ 212
+ 157
+
+
+
+ 0
+
+
+
+
+
+ 10
+ 176
+ 100
+ 22
+
+
+
+
+ Sans Serif
+ 13
+
+
+
+ true
+
+
+ Booster Ext
+
+
+ Qt::AlignAbsolute|Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::Height
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ QFrame::NoFrame
+
+
+
+
+
+ 211
+ 28
+ 78
+ 28
+
+
+
+ true
+
+
+
+ 0
+ 0
+ 176
+
+
+
+ caGraphics::Filled
+
+
+ 1
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caGraphics::Calc
+
+
+ A=1
+
+
+ AGETI-CVME-MASTER-TMA:SR-Inj-Status-Sel
+
+
+ caGraphics::Rectangle
+
+
+ 22
+
+
+ 180
+
+
+ 0
+
+
+ 90
+
+
+
+
+
+ 139
+ 32
+ 70
+ 20
+
+
+
+ true
+
+
+ Disable
+
+
+ AGETI-CVME-MASTER-TMA:SR-Inj-Status-Sel
+
+
+ Disable
+
+
+
+ 219
+ 212
+ 157
+
+
+
+ 0
+
+
+
+
+
+ 139
+ 119
+ 70
+ 20
+
+
+
+ true
+
+
+ Disable
+
+
+ AGETI-CVME-MASTER-TMA:Evt-BO-MA-B-Ena-Sel
+
+
+ Disable
+
+
+
+ 219
+ 212
+ 157
+
+
+
+ 0
+
+
+
+
+
+ 10
+ 118
+ 121
+ 22
+
+
+
+
+ Sans Serif
+ 13
+
+
+
+ true
+
+
+ ABOMA-B
+
+
+ Qt::AlignAbsolute|Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::Height
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ QFrame::NoFrame
+
+
+
+
+
+ 135
+ 115
+ 78
+ 28
+
+
+
+ true
+
+
+
+ 0
+ 0
+ 176
+
+
+
+ caGraphics::Filled
+
+
+ 1
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caGraphics::IfZero
+
+
+ AGETI-CVME-MASTER-TMA:Evt-BO-MA-B-Ena-Sel
+
+
+ caGraphics::Rectangle
+
+
+ 22
+
+
+ 180
+
+
+ 0
+
+
+ 90
+
+
+
+
+
+ 215
+ 119
+ 70
+ 20
+
+
+
+ true
+
+
+ External
+
+
+ AGETI-CVME-MASTER-TMA:Evt-BO-MA-B-Ena-Sel
+
+
+ External
+
+
+
+ 219
+ 212
+ 157
+
+
+
+ 1
+
+
+
+
+
+ 211
+ 115
+ 78
+ 28
+
+
+
+ true
+
+
+
+ 0
+ 0
+ 176
+
+
+
+ caGraphics::Filled
+
+
+ 1
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caGraphics::Calc
+
+
+ A=1
+
+
+ AGETI-CVME-MASTER-TMA:Evt-BO-MA-B-Ena-Sel
+
+
+ caGraphics::Rectangle
+
+
+ 22
+
+
+ 180
+
+
+
+
+
+ 139
+ 206
+ 70
+ 20
+
+
+
+ true
+
+
+ Disable
+
+
+ AGETI-CVME-MASTER-TMA:Evt-SR-Inj-Ena-Sel
+
+
+ Disable
+
+
+
+ 219
+ 212
+ 157
+
+
+
+ 0
+
+
+
+
+
+ 215
+ 206
+ 70
+ 20
+
+
+
+ true
+
+
+ Enable
+
+
+ AGETI-CVME-MASTER-TMA:Evt-SR-Inj-Ena-Sel
+
+
+ Enable
+
+
+
+ 219
+ 212
+ 157
+
+
+
+ 1
+
+
+
+
+
+ 211
+ 202
+ 78
+ 28
+
+
+
+ true
+
+
+
+ 0
+ 0
+ 176
+
+
+
+ caGraphics::Filled
+
+
+ 1
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caGraphics::Calc
+
+
+ A=1
+
+
+ AGETI-CVME-MASTER-TMA:Evt-SR-Inj-Ena-Sel
+
+
+ caGraphics::Rectangle
+
+
+ 22
+
+
+ 180
+
+
+
+
+
+ 10
+ 205
+ 150
+ 22
+
+
+
+
+ Sans Serif
+ 13
+
+
+
+ true
+
+
+ Qt::LeftToRight
+
+
+ Ring Inj
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ QFrame::NoFrame
+
+
+
+
+
+ 135
+ 202
+ 78
+ 28
+
+
+
+ true
+
+
+
+ 0
+ 0
+ 176
+
+
+
+ caGraphics::Filled
+
+
+ 1
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caGraphics::IfZero
+
+
+ AGETI-CVME-MASTER-TMA:Evt-SR-Inj-Ena-Sel
+
+
+ caGraphics::Rectangle
+
+
+ 22
+
+
+ 180
+
+
+ 0
+
+
+ 90
+
+
+
+
+
+ 211
+ 57
+ 78
+ 28
+
+
+
+ true
+
+
+
+ 0
+ 0
+ 176
+
+
+
+ caGraphics::Filled
+
+
+ 1
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caGraphics::Calc
+
+
+ A=1
+
+
+ AGETI-CVME-MASTER-TMA:Evt-LI-Gun-Ena-Sel
+
+
+ caGraphics::Rectangle
+
+
+ 22
+
+
+ 180
+
+
+
+
+
+ 215
+ 61
+ 70
+ 20
+
+
+
+ true
+
+
+ Enable
+
+
+ AGETI-CVME-MASTER-TMA:Evt-LI-Gun-Ena-Sel
+
+
+ Enable
+
+
+
+ 219
+ 212
+ 157
+
+
+
+ 1
+
+
+
+
+
+ 135
+ 57
+ 78
+ 28
+
+
+
+ true
+
+
+
+ 0
+ 0
+ 176
+
+
+
+ caGraphics::Filled
+
+
+ 1
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caGraphics::IfZero
+
+
+ AGETI-CVME-MASTER-TMA:Evt-LI-Gun-Ena-Sel
+
+
+ caGraphics::Rectangle
+
+
+ 22
+
+
+ 180
+
+
+ 0
+
+
+ 90
+
+
+
+
+
+ 10
+ 60
+ 91
+ 22
+
+
+
+
+ Sans Serif
+ 13
+
+
+
+ true
+
+
+ Qt::LeftToRight
+
+
+ Gun
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ QFrame::NoFrame
+
+
+
+
+
+ 139
+ 61
+ 70
+ 20
+
+
+
+ true
+
+
+ Disable
+
+
+ AGETI-CVME-MASTER-TMA:Evt-LI-Gun-Ena-Sel
+
+
+ Disable
+
+
+
+ 219
+ 212
+ 157
+
+
+
+ 0
+
+
+
+
+
+ 139
+ 90
+ 70
+ 20
+
+
+
+ true
+
+
+ Disable
+
+
+ AGETI-CVME-MASTER-TMA:Evt-BO-Inj-Ena-Sel
+
+
+ Disable
+
+
+
+ 219
+ 212
+ 157
+
+
+
+ 0
+
+
+
+
+
+ 215
+ 90
+ 70
+ 20
+
+
+
+ true
+
+
+ Enable
+
+
+ AGETI-CVME-MASTER-TMA:Evt-BO-Inj-Ena-Sel
+
+
+ Enable
+
+
+
+ 219
+ 212
+ 157
+
+
+
+ 1
+
+
+
+
+
+ 135
+ 86
+ 78
+ 28
+
+
+
+ true
+
+
+
+ 0
+ 0
+ 176
+
+
+
+ caGraphics::Filled
+
+
+ 1
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caGraphics::IfZero
+
+
+ AGETI-CVME-MASTER-TMA:Evt-BO-Inj-Ena-Sel
+
+
+ caGraphics::Rectangle
+
+
+ 22
+
+
+ 180
+
+
+ 0
+
+
+ 90
+
+
+
+
+
+ 211
+ 86
+ 78
+ 28
+
+
+
+ true
+
+
+
+ 0
+ 0
+ 176
+
+
+
+ caGraphics::Filled
+
+
+ 1
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caGraphics::Calc
+
+
+ A=1
+
+
+ AGETI-CVME-MASTER-TMA:Evt-BO-Inj-Ena-Sel
+
+
+ caGraphics::Rectangle
+
+
+ 22
+
+
+ 180
+
+
+
+
+
+ 10
+ 89
+ 111
+ 22
+
+
+
+
+ Sans Serif
+ 13
+
+
+
+ true
+
+
+ Qt::LeftToRight
+
+
+ Booster Inj
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ QFrame::NoFrame
+
+
+
+
+
+ 95
+ 28
+ 28
+ 28
+
+
+
+ true
+
+
+ false
+
+
+ 22
+
+
+ 22
+
+
+ AGEBD-INJECTIONGUARD:STATUS-SECRET-MASTER
+
+
+ caLed::Alarm
+
+
+
+
+
+ 520
+ 28
+ 100
+ 28
+
+
+
+
+ Monospace
+ 13
+ PreferDefault
+
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ true
+
+
+ AGETI-CVME-MASTER-TMA:Event-Seq-Cnt-I
+
+
+
+ 160
+ 160
+ 164
+
+
+
+ caLineEdit::Default
+
+
+ caLineEdit::None
+
+
+
+
+
+ 520
+ 86
+ 100
+ 28
+
+
+
+
+ Monospace
+ 13
+ PreferDefault
+
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ true
+
+
+ AGETI-CVME-MASTER-TMA:Evt-BO-Inj-EVRCount-I
+
+
+
+ 160
+ 160
+ 164
+
+
+
+ caLineEdit::Default
+
+
+ caLineEdit::None
+
+
+
+
+
+ 520
+ 115
+ 100
+ 28
+
+
+
+
+ Monospace
+ 13
+ PreferDefault
+
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ true
+
+
+
+AGETI-CVME-MASTER-TMA:Evt-BO-MA-B-EVRCount-I
+
+
+
+ 160
+ 160
+ 164
+
+
+
+ caLineEdit::Default
+
+
+ caLineEdit::None
+
+
+
+
+
+ 520
+ 173
+ 100
+ 28
+
+
+
+
+ Monospace
+ 13
+ PreferDefault
+
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ true
+
+
+ AGETI-CVME-MASTER-TMA:Evt-BO-Ext-EVRCount-I
+
+
+
+ 160
+ 160
+ 164
+
+
+
+ caLineEdit::Default
+
+
+ caLineEdit::None
+
+
+
+
+
+ 520
+ 202
+ 100
+ 28
+
+
+
+
+ Monospace
+ 13
+ PreferDefault
+
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ true
+
+
+ AGETI-CVME-MASTER-TMA:Evt-SR-Inj-EVRCount-I
+
+
+
+ 160
+ 160
+ 164
+
+
+
+ caLineEdit::Default
+
+
+ caLineEdit::None
+
+
+
+
+
+ 520
+ 231
+ 100
+ 28
+
+
+
+
+ Monospace
+ 13
+ PreferDefault
+
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ true
+
+
+ AGETI-CVME-MASTER-TMA:Evt-SR-Pinger-H-EVRCount-I
+
+
+
+ 160
+ 160
+ 164
+
+
+
+ caLineEdit::Default
+
+
+ caLineEdit::None
+
+
+
+
+
+ 135
+ 231
+ 78
+ 28
+
+
+
+ true
+
+
+
+ 0
+ 0
+ 176
+
+
+
+ caGraphics::Filled
+
+
+ 1
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caGraphics::IfZero
+
+
+ AGETI-CVME-MASTER-TMA:Evt-SR-Pinger-H-Ena-Sel
+
+
+ caGraphics::Rectangle
+
+
+ 22
+
+
+ 180
+
+
+ 0
+
+
+ 90
+
+
+
+
+
+ 139
+ 235
+ 70
+ 20
+
+
+
+ true
+
+
+ Disable
+
+
+ AGETI-CVME-MASTER-TMA:Evt-SR-Pinger-H-Ena-Sel
+
+
+ Disable
+
+
+
+ 219
+ 212
+ 157
+
+
+
+ 0
+
+
+
+
+
+ 211
+ 231
+ 78
+ 28
+
+
+
+ true
+
+
+
+ 0
+ 0
+ 176
+
+
+
+ caGraphics::Filled
+
+
+ 1
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caGraphics::Calc
+
+
+ A=1
+
+
+ AGETI-CVME-MASTER-TMA:Evt-SR-Pinger-H-Ena-Sel
+
+
+ caGraphics::Rectangle
+
+
+ 22
+
+
+ 180
+
+
+
+
+
+ 215
+ 235
+ 70
+ 20
+
+
+
+ true
+
+
+ Enable
+
+
+ AGETI-CVME-MASTER-TMA:Evt-SR-Pinger-H-Ena-Sel
+
+
+ Enable
+
+
+
+ 219
+ 212
+ 157
+
+
+
+ 1
+
+
+
+
+
+ 10
+ 234
+ 101
+ 22
+
+
+
+
+ Sans Serif
+ 13
+
+
+
+ true
+
+
+ Qt::LeftToRight
+
+
+ Hor. Pinger
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ QFrame::NoFrame
+
+
+
+
+
+ 520
+ 260
+ 100
+ 28
+
+
+
+
+ Monospace
+ 13
+ PreferDefault
+
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ true
+
+
+ AGETI-CVME-MASTER-TMA:Evt-SR-Pinger-V-EVRCount-I
+
+
+
+ 160
+ 160
+ 164
+
+
+
+ caLineEdit::Default
+
+
+ caLineEdit::None
+
+
+
+
+
+ 10
+ 263
+ 101
+ 22
+
+
+
+
+ Sans Serif
+ 13
+
+
+
+ true
+
+
+ Qt::LeftToRight
+
+
+ Ver. Pinger
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ QFrame::NoFrame
+
+
+
+
+
+ 139
+ 264
+ 70
+ 20
+
+
+
+ true
+
+
+ Disable
+
+
+ AGETI-CVME-MASTER-TMA:Evt-SR-Pinger-V-Ena-Sel
+
+
+ Disable
+
+
+
+ 219
+ 212
+ 157
+
+
+
+ 0
+
+
+
+
+
+ 215
+ 264
+ 70
+ 20
+
+
+
+ true
+
+
+ Enable
+
+
+ AGETI-CVME-MASTER-TMA:Evt-SR-Pinger-V-Ena-Sel
+
+
+ Enable
+
+
+
+ 219
+ 212
+ 157
+
+
+
+ 1
+
+
+
+
+
+ 135
+ 260
+ 78
+ 28
+
+
+
+ true
+
+
+
+ 0
+ 0
+ 176
+
+
+
+ caGraphics::Filled
+
+
+ 1
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caGraphics::IfZero
+
+
+ AGETI-CVME-MASTER-TMA:Evt-SR-Pinger-V-Ena-Sel
+
+
+ caGraphics::Rectangle
+
+
+ 22
+
+
+ 180
+
+
+ 0
+
+
+ 90
+
+
+
+
+
+ 211
+ 260
+ 78
+ 28
+
+
+
+ true
+
+
+
+ 0
+ 0
+ 176
+
+
+
+ caGraphics::Filled
+
+
+ 1
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caGraphics::Calc
+
+
+ A=1
+
+
+ AGETI-CVME-MASTER-TMA:Evt-SR-Pinger-V-Ena-Sel
+
+
+ caGraphics::Rectangle
+
+
+ 22
+
+
+ 180
+
+
+
+
+
+ 10
+ 147
+ 121
+ 22
+
+
+
+
+ Sans Serif
+ 13
+
+
+
+ true
+
+
+ ABOMA-ELSE
+
+
+ Qt::AlignAbsolute|Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::Height
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ QFrame::NoFrame
+
+
+
+
+
+ 135
+ 144
+ 78
+ 28
+
+
+
+ true
+
+
+
+ 0
+ 0
+ 176
+
+
+
+ caGraphics::Filled
+
+
+ 1
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caGraphics::IfZero
+
+
+ AGETI-CVME-MASTER-TMA:Evt-BO-Ramp-Ena-Sel
+
+
+ caGraphics::Rectangle
+
+
+ 22
+
+
+ 180
+
+
+ 0
+
+
+ 90
+
+
+
+
+
+ 139
+ 148
+ 70
+ 20
+
+
+
+ true
+
+
+ Disable
+
+
+ AGETI-CVME-MASTER-TMA:Evt-BO-Ramp-Ena-Sel
+
+
+ Disable
+
+
+
+ 219
+ 212
+ 157
+
+
+
+ 0
+
+
+
+
+
+ 211
+ 144
+ 78
+ 28
+
+
+
+ true
+
+
+
+ 0
+ 0
+ 176
+
+
+
+ caGraphics::Filled
+
+
+ 1
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caGraphics::Calc
+
+
+ A=1
+
+
+ AGETI-CVME-MASTER-TMA:Evt-BO-Ramp-Ena-Sel
+
+
+ caGraphics::Rectangle
+
+
+ 22
+
+
+ 180
+
+
+
+
+
+ 520
+ 144
+ 100
+ 28
+
+
+
+
+ Monospace
+ 13
+ PreferDefault
+
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ true
+
+
+
+AGETI-CVME-MASTER-TMA:Evt-BO-Ramp-EVRCount-I
+
+
+
+ 160
+ 160
+ 164
+
+
+
+ caLineEdit::Default
+
+
+ caLineEdit::None
+
+
+
+
+
+ 215
+ 148
+ 70
+ 20
+
+
+
+ true
+
+
+ Enable
+
+
+ AGETI-CVME-MASTER-TMA:Evt-BO-Ramp-Ena-Sel
+
+
+ Enable
+
+
+
+ 219
+ 212
+ 157
+
+
+
+ 1
+
+
+
+
+
+ 520
+ 57
+ 100
+ 28
+
+
+
+
+ Monospace
+ 13
+ PreferDefault
+
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ true
+
+
+
+AGETI-CVME-MASTER-TMA:Evt-LI-Gun-EVRCount-I
+
+
+
+ 160
+ 160
+ 164
+
+
+
+ caLineEdit::Default
+
+
+ caLineEdit::None
+
+
+
+
+
+ 300
+ 88
+ 100
+ 28
+
+
+
+ 2
+
+
+ 0
+
+
+ AGEBD-SCRUBBING:WARMUPCYCLES-BOIN-SP.VAL
+
+
+ caSpinbox::User
+
+
+ true
+
+
+
+
+
+ 300
+ 120
+ 100
+ 28
+
+
+
+ 2
+
+
+ 0
+
+
+ AGEBD-SCRUBBING:WARMUPCYCLES-BOMB-SP.VAL
+
+
+ caSpinbox::User
+
+
+ true
+
+
+
+
+
+ 300
+ 150
+ 100
+ 25
+
+
+
+ 2
+
+
+ 0
+
+
+ AGEBD-SCRUBBING:WARMUPCYCLES-BOME-SP.VAL
+
+
+ caSpinbox::User
+
+
+ true
+
+
+
+
+
+ 300
+ 180
+ 100
+ 25
+
+
+
+ 2
+
+
+ 0
+
+
+ AGEBD-SCRUBBING:WARMUPCYCLES-BOEX-SP.VAL
+
+
+ caSpinbox::User
+
+
+ true
+
+
+
+
+
+ 300
+ 210
+ 100
+ 25
+
+
+
+ 2
+
+
+ 0
+
+
+ AGEBD-SCRUBBING:WARMUPCYCLES-SRIN-SP.VAL
+
+
+ caSpinbox::User
+
+
+ true
+
+
+
+
+
+ 300
+ 30
+ 100
+ 41
+
+
+
+
+ 9
+ 75
+ true
+
+
+
+ Warmup Cycles
+Setpoint
+
+
+ Qt::PlainText
+
+
+ Qt::AlignCenter
+
+
+ true
+
+
+
+
+
+ 410
+ 117
+ 100
+ 28
+
+
+
+
+ Monospace
+ 13
+ PreferDefault
+
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ true
+
+
+ AGEBD-SCRUBBING:WARMUPCYCLES-BOMB-RB.VAL
+
+
+
+ 160
+ 160
+ 164
+
+
+
+ caLineEdit::Default
+
+
+ caLineEdit::User
+
+
+ caLineEdit::None
+
+
+
+
+
+ 410
+ 88
+ 100
+ 28
+
+
+
+
+ Monospace
+ 13
+ PreferDefault
+
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ true
+
+
+ AGEBD-SCRUBBING:WARMUPCYCLES-BOIN-RB.VAL
+
+
+
+ 160
+ 160
+ 164
+
+
+
+ caLineEdit::Default
+
+
+ caLineEdit::User
+
+
+ caLineEdit::None
+
+
+
+
+
+ 410
+ 146
+ 100
+ 28
+
+
+
+
+ Monospace
+ 13
+ PreferDefault
+
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ true
+
+
+ AGEBD-SCRUBBING:WARMUPCYCLES-BOME-RB.VAL
+
+
+
+ 160
+ 160
+ 164
+
+
+
+ caLineEdit::Default
+
+
+ caLineEdit::User
+
+
+ caLineEdit::None
+
+
+
+
+
+ 410
+ 204
+ 100
+ 28
+
+
+
+
+ Monospace
+ 13
+ PreferDefault
+
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ true
+
+
+ AGEBD-SCRUBBING:WARMUPCYCLES-SRIN-RB.VAL
+
+
+
+ 160
+ 160
+ 164
+
+
+
+ caLineEdit::Default
+
+
+ caLineEdit::User
+
+
+ caLineEdit::None
+
+
+
+
+
+ 410
+ 175
+ 100
+ 28
+
+
+
+
+ Monospace
+ 13
+ PreferDefault
+
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ true
+
+
+ AGEBD-SCRUBBING:WARMUPCYCLES-BOEX-RB.VAL
+
+
+
+ 160
+ 160
+ 164
+
+
+
+ caLineEdit::Default
+
+
+ caLineEdit::User
+
+
+ caLineEdit::None
+
+
+
+
+
+ 410
+ 30
+ 100
+ 41
+
+
+
+
+ 9
+ 75
+ true
+
+
+
+ Warmup Cycles
+Remaining
+
+
+ Qt::AlignCenter
+
+
+ true
+
+
+ BOO_Ext_External_frame_8
+ BOO_Ext_Disable_frame_8
+ BOO_Ext_Disable_frame_5
+ BOO_Ext_External_frame_5
+ BOO_Ext_Disable_frame_4
+ BOO_Ext_External_frame_4
+ Inj_trig_Enable_frame
+ BOO_Ext_Disable_frame_2
+ BOO_Ext_External_frame_2
+ Inj_trig_Enable
+ Inj_trig_
+ BOO_Ext_External_2
+ Inj_trig_Disable_frame
+ BOO_Ext_Diasable_2
+ BOO_Ext
+ Inj_trig_Disable
+ Gun_trig_2
+ Gun_trig_Disable_frame_2
+ Gun_trig_External_frame_2
+ Gun_trig_External_2
+ Gun_trig_Diasable_2
+ BOO_Ext_Diasable_4
+ BOO_Ext_External_4
+ BOO_Ext_3
+ BOO_Ext_External_frame_6
+ BOO_Ext_External_6
+ BOO_Ext_Disable_frame_6
+ BOO_Ext_5
+ BOO_Ext_Diasable_6
+ BOO_Ext_Diasable_5
+ BOO_Ext_External_5
+ BOO_Ext_4
+ caled_23
+ calineedit
+ calineedit_4
+ calineedit_6
+ calineedit_7
+ calineedit_8
+ calineedit_9
+ BOO_Ext_Disable_frame_7
+ BOO_Ext_Diasable_7
+ BOO_Ext_External_frame_7
+ BOO_Ext_External_7
+ BOO_Ext_6
+ calineedit_10
+ BOO_Ext_7
+ BOO_Ext_Diasable_8
+ BOO_Ext_External_8
+ Gun_trig_3
+ BOO_Ext_Disable_frame_3
+ BOO_Ext_Diasable_3
+ BOO_Ext_External_frame_3
+ calineedit_13
+ BOO_Ext_External_3
+ calineedit_2
+ caspinbox_10
+ caspinbox_11
+ caspinbox_12
+ caspinbox_13
+ caspinbox_14
+ calabel_18
+ calineedit_16
+ calineedit_5
+ calineedit_17
+ calineedit_18
+ calineedit_19
+ calabel_19
+
+
+
+
+ 420
+ 750
+ 1081
+ 241
+
+
+
+
+
+
+ ;AGEBD-TIMING:TARGET-BUCKET
+
+
+ caCartesianPlot::Sticks
+
+
+
+ 0
+ 255
+ 0
+
+
+
+ ;X08DB-DFPM-DI:FW-SIS0DAQ-CH0-FPM-WF
+
+
+ caCartesianPlot::Sticks
+
+
+
+ 255
+ 170
+ 255
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+ 160
+ 160
+ 160
+
+
+
+ caCartesianPlot::User
+
+
+ caCartesianPlot::User
+
+
+ 0;480
+
+
+ 0;1.3
+
+
+ true
+
+
+ false
+
+
+ 24
+
+
+
+
+
+ 5
+ 750
+ 410
+ 241
+
+
+
+ Filling Pattern Feedback (FPFB)
+
+
+
+
+ 0
+ 20
+ 40
+ 40
+
+
+
+ AGEBD-TIMING:GO
+
+
+
+ 0
+ 255
+ 0
+
+
+
+
+
+
+ 10
+ 60
+ 391
+ 30
+
+
+
+
+ 9
+
+
+
+ space separated bucket ranges (e.g., 0-450) and single buckets
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::WidthAndHeight
+
+
+
+
+
+ 10
+ 90
+ 391
+ 45
+
+
+
+ AGEBD-TIMING:CONTROL-FILLPATTERN-string.VAL
+
+
+ 0
+
+
+ caLineEdit::User
+
+
+ caLineEdit::User
+
+
+ 479.000000000000000
+
+
+
+
+
+
+ 210
+ 190
+ 191
+ 40
+
+
+
+
+ 20
+
+
+
+ Reset
+
+
+ EPushButton::WidthAndHeight
+
+
+ AGEBD-TIMING:ZERO-TARGET-BUCKET
+
+
+ Reset
+
+
+
+ 160
+ 160
+ 160
+
+
+
+
+ 160
+ 160
+ 160
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+
+ 240
+ 140
+ 150
+ 40
+
+
+
+ 3
+
+
+ 0
+
+
+ true
+
+
+ AGEBD-TIMING:CURRENT-THRESHOLD
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ caSpinbox::Channel
+
+
+
+
+
+ 10
+ 190
+ 80
+ 40
+
+
+
+
+ 25
+ 75
+ true
+
+
+
+ Nth
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+
+
+ 90
+ 190
+ 111
+ 40
+
+
+
+ 3
+
+
+ 0
+
+
+ AGEBD-TIMING:FPFB-NTH
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ caSpinbox::Channel
+
+
+
+
+
+ 10
+ 140
+ 211
+ 40
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ FPFB Threshold
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+
+
+
+ 5
+ 130
+ 530
+ 140
+
+
+
+ Top-Up Grenzen
+
+
+
+
+ 220
+ 95
+ 140
+ 40
+
+
+
+ 3
+
+
+ 1
+
+
+ AGEBD-SCRUBBING:CONTROL-CURRENT-MIN
+
+
+ caSpinbox::User
+
+
+ true
+
+
+
+
+
+ 220
+ 50
+ 140
+ 40
+
+
+
+ 3
+
+
+ 1
+
+
+ AGEBD-SCRUBBING:CONTROL-CURRENT-MAX
+
+
+ caSpinbox::User
+
+
+ true
+
+
+
+
+
+ 10
+ 95
+ 50
+ 40
+
+
+
+
+ 12
+ 75
+ true
+
+
+
+ Start
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+
+
+ 10
+ 50
+ 50
+ 40
+
+
+
+
+ 13
+ 75
+ true
+
+
+
+ Stop
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+
+
+ 70
+ 95
+ 140
+ 40
+
+
+
+ 3
+
+
+ 1
+
+
+ AGEBD-SCRUBBING:CONTROL-VACUUM-MIN
+
+
+ caSpinbox::User
+
+
+ true
+
+
+
+
+
+ 220
+ 20
+ 140
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ Strom
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 70
+ 20
+ 140
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ Vakuum
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 70
+ 50
+ 140
+ 40
+
+
+
+ 3
+
+
+ 1
+
+
+ AGEBD-SCRUBBING:CONTROL-VACUUM-MAX
+
+
+ caSpinbox::User
+
+
+ true
+
+
+
+
+
+ 370
+ 20
+ 140
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ Zeit
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 370
+ 50
+ 140
+ 40
+
+
+
+ 3
+
+
+ 0
+
+
+ AGEBD-SCRUBBING:CONTROL-TIME-MAX
+
+
+ caSpinbox::User
+
+
+ true
+
+
+
+
+
+ 370
+ 95
+ 140
+ 40
+
+
+
+ 3
+
+
+ 0
+
+
+ AGEBD-SCRUBBING:CONTROL-TIME-MIN
+
+
+ caSpinbox::User
+
+
+ true
+
+
+
+
+
+
+ 5
+ 280
+ 255
+ 160
+
+
+
+ Gun Ladung
+
+
+
+
+ 50
+ 20
+ 211
+ 40
+
+
+
+
+ 20
+ 75
+ true
+
+
+
+ Gun Grid
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 125
+ 120
+ 120
+ 40
+
+
+
+ 3
+
+
+ 0
+
+
+ AGEBD-SCRUBBING:CONTROL-GUNGRID-FPFB
+
+
+ caSpinbox::User
+
+
+ true
+
+
+
+
+
+ 125
+ 70
+ 120
+ 40
+
+
+
+ 3
+
+
+ 0
+
+
+ AGEBD-SCRUBBING:CONTROL-GUNGRID-ACCUM
+
+
+ caSpinbox::User
+
+
+ true
+
+
+
+
+
+ 5
+ 70
+ 110
+ 40
+
+
+
+
+ 12
+ 75
+ true
+
+
+
+ Accumulate
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 5
+ 120
+ 110
+ 40
+
+
+
+
+ 12
+ 75
+ true
+
+
+
+ Top-Up
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+
+ 550
+ 0
+ 951
+ 271
+
+
+
+
+ 10
+ 75
+ true
+
+
+
+ Beam Current (last 10 minutes)
+
+
+
+
+
+
+
+
+ ARS07-DPCT-0000:CURR;AGEBD-SCRUBBING:CONTROL-CURRENT-MAX;AGEBD-SCRUBBING:CONTROL-CURRENT-MIN
+
+
+ caStripPlot::Second
+
+
+ 600.000000000000000
+
+
+ caStripPlot::High
+
+
+ 11
+
+
+ caStripPlot::linear
+
+
+ 404.000000000000000
+
+
+ 399.000000000000000
+
+
+ caStripPlot::User
+
+
+ caStripPlot::User
+
+
+ caStripPlot::Lines
+
+
+
+ 0
+ 255
+ 0
+
+
+
+ 404.000000000000000
+
+
+ 399.000000000000000
+
+
+ caStripPlot::User
+
+
+ caStripPlot::User
+
+
+
+ 255
+ 0
+ 0
+
+
+
+ 404.000000000000000
+
+
+ 399.000000000000000
+
+
+ caStripPlot::User
+
+
+ caStripPlot::User
+
+
+
+ 255
+ 0
+ 0
+
+
+
+ 404.000000000000000
+
+
+ 399.000000000000000
+
+
+ caStripPlot::User
+
+
+ caStripPlot::User
+
+
+
+ 239
+ 41
+ 41
+
+
+
+ 0.000000410000000
+
+
+ 0.000000001000000
+
+
+ caStripPlot::User
+
+
+ caStripPlot::User
+
+
+
+ 239
+ 41
+ 41
+
+
+
+ 0.000000410000000
+
+
+ 0.000000001000000
+
+
+ caStripPlot::User
+
+
+ caStripPlot::User
+
+
+
+ 255
+ 0
+ 255
+
+
+
+ 0.000000100000000
+
+
+ 0.000000001000000
+
+
+
+ 218
+ 218
+ 218
+
+
+
+ true
+
+
+ false
+
+
+
+
+ 60
+ 30
+ 250
+ 50
+
+
+
+
+ Lucida Sans Typewriter
+ 32
+ 75
+ true
+
+
+
+ Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft
+
+
+ ARS07-DPCT-0000:CURR
+
+
+
+ 0
+ 255
+ 0
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caLineEdit::Static
+
+
+ 1
+
+
+ caLineEdit::User
+
+
+ caLineEdit::WidthAndHeight
+
+
+ true
+
+
+
+
+
+ 660
+ 30
+ 250
+ 50
+
+
+
+
+ Lucida Sans Typewriter
+ 32
+ 75
+ true
+
+
+
+ Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing
+
+
+ AGEBD-PARAMS:LIFETIME
+
+
+
+ 0
+ 255
+ 255
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caLineEdit::Static
+
+
+ 1
+
+
+ caLineEdit::User
+
+
+ caLineEdit::WidthAndHeight
+
+
+ true
+
+
+
+
+
+ 350
+ 30
+ 250
+ 50
+
+
+
+
+ Lucida Sans Typewriter
+ 32
+ 75
+ true
+
+
+
+ AGEBD-PARAMS:TRANSMISSION
+
+
+
+ 255
+ 170
+ 0
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caLineEdit::Static
+
+
+ 1
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Height
+
+
+ true
+
+
+
+
+
+
+ 410
+ 30
+ 120
+ 40
+
+
+
+
+ 12
+ 75
+ true
+
+
+
+ Dyn Vac Frac
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+
+
+ 410
+ 80
+ 120
+ 40
+
+
+
+ 1
+
+
+ 2
+
+
+
+AGEBD-SCRUBBING:CONTROL-VACUUM-DYN-FRAC
+
+
+ caSpinbox::User
+
+
+ true
+
+
+
+
+
+ 270
+ 280
+ 360
+ 180
+
+
+
+ Strahlwaschen
+
+
+
+
+
+ 10
+ 20
+ 191
+ 40
+
+
+
+
+ 20
+ 75
+ true
+
+
+
+ Scrubbing
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 0
+ 95
+ 360
+ 85
+
+
+
+
+ 85
+ 170
+ 0
+
+
+
+ caFrame::Calc
+
+
+ A>3
+
+
+ AGEBD-SCRUBBING:CONTROL-SCRUB
+
+
+
+
+ 230
+ 45
+ 100
+ 35
+
+
+
+
+ Monospace
+ 13
+ PreferDefault
+
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ true
+
+
+ ARSGE-CECL-MBFB:MBFB-T-Y-DDS-FRQ
+
+
+
+ 160
+ 160
+ 164
+
+
+
+ caLineEdit::Default
+
+
+ caLineEdit::User
+
+
+ caLineEdit::None
+
+
+ true
+
+
+
+
+
+ 65
+ 45
+ 100
+ 35
+
+
+
+ 3
+
+
+ 0
+
+
+ AGEBD-SCRUBBING:MBFBY-GAIN-SP.VAL
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ caSpinbox::User
+
+
+ 100.000000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 230
+ 5
+ 100
+ 35
+
+
+
+
+ Monospace
+ 13
+ PreferDefault
+
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ true
+
+
+ ARSGE-CECL-MBFB:MBFB-T-X-DDS-FRQ
+
+
+
+ 160
+ 160
+ 164
+
+
+
+ caLineEdit::Default
+
+
+ caLineEdit::User
+
+
+ caLineEdit::None
+
+
+ true
+
+
+
+
+
+ 10
+ 45
+ 45
+ 35
+
+
+
+
+ 8
+ 75
+ true
+
+
+
+ MBFBy
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+
+
+ 65
+ 5
+ 100
+ 35
+
+
+
+ 3
+
+
+ 0
+
+
+ AGEBD-SCRUBBING:MBFBX-GAIN-SP.VAL
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ caSpinbox::User
+
+
+ 100.000000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 10
+ 5
+ 45
+ 35
+
+
+
+
+ 8
+ 75
+ true
+
+
+
+ MBFBx
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+
+
+ 175
+ 45
+ 45
+ 35
+
+
+
+
+ Monospace
+ 13
+ PreferDefault
+
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ true
+
+
+ ARSGE-CECL-MBFB:MBFB-T-Y-DDS-GAIN
+
+
+
+ 160
+ 160
+ 164
+
+
+
+ caLineEdit::Default
+
+
+ caLineEdit::User
+
+
+ caLineEdit::None
+
+
+ false
+
+
+
+
+
+ 175
+ 5
+ 45
+ 35
+
+
+
+
+ Monospace
+ 13
+ PreferDefault
+
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ true
+
+
+ ARSGE-CECL-MBFB:MBFB-T-X-DDS-GAIN
+
+
+
+ 160
+ 160
+ 164
+
+
+
+ caLineEdit::Default
+
+
+ caLineEdit::User
+
+
+ caLineEdit::None
+
+
+ false
+
+
+
+
+
+ 335
+ 5
+ 17
+ 17
+
+
+
+ true
+
+
+ false
+
+
+ 15
+
+
+ 15
+
+
+
+ARSGE-MBFBT-AMP-03:SET-ON-OFF
+
+
+
+ 0
+ 255
+ 0
+
+
+
+
+
+
+ 335
+ 23
+ 17
+ 17
+
+
+
+ true
+
+
+ false
+
+
+ 15
+
+
+ 15
+
+
+
+ARSGE-MBFBT-AMP-04:SET-ON-OFF
+
+
+
+ 0
+ 255
+ 0
+
+
+
+
+
+
+ 335
+ 45
+ 17
+ 17
+
+
+
+ true
+
+
+ false
+
+
+ 15
+
+
+ 15
+
+
+ ARSGE-MBFBT-AMP-01:SET-ON-OFF
+
+
+
+ 0
+ 255
+ 0
+
+
+
+
+
+
+ 335
+ 63
+ 17
+ 17
+
+
+
+ true
+
+
+ false
+
+
+ 15
+
+
+ 15
+
+
+
+ARSGE-MBFBT-AMP-02:SET-ON-OFF
+
+
+
+ 0
+ 255
+ 0
+
+
+
+
+
+
+
+ 0
+ 95
+ 360
+ 85
+
+
+
+
+ 85
+ 170
+ 0
+
+
+
+ caFrame::Calc
+
+
+ A<4 & A>0
+
+
+ AGEBD-SCRUBBING:CONTROL-SCRUB
+
+
+
+
+ 70
+ 45
+ 150
+ 35
+
+
+
+ 4
+
+
+ 2
+
+
+ ARS01-MKIK-0320:I-SET
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ caSpinbox::User
+
+
+ 100.000000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 10
+ 45
+ 50
+ 35
+
+
+
+
+ 10
+ 75
+ true
+
+
+
+ PINGy
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+
+
+ 70
+ 5
+ 150
+ 35
+
+
+
+ 4
+
+
+ 2
+
+
+ ARS01-MKIK-0290:I-SET
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ caSpinbox::User
+
+
+ 100.000000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 10
+ 5
+ 50
+ 35
+
+
+
+
+ 10
+ 75
+ true
+
+
+
+ PINGx
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+
+
+ 230
+ 5
+ 35
+ 35
+
+
+
+
+ 35
+ 35
+
+
+
+ ARS01-MKIK-0290:CTRL-ON-OFF
+
+
+
+
+
+ 230
+ 45
+ 35
+ 35
+
+
+
+
+ 35
+ 35
+
+
+
+ ARS01-MKIK-0320:CTRL-ON-OFF
+
+
+
+
+
+
+
+
+ caMenu
+ QComboBox
+
+
+
+ caChoice
+ QWidget
+
+
+
+ caTextEntry
+ caLineEdit
+
+
+
+ caMessageButton
+ QPushButton
+
+
+
+ caToggleButton
+ QCheckBox
+
+
+
+ caSpinbox
+ QFrame
+
+
+
+ caFrame
+ QFrame
+
+ 1
+
+
+ caLabel
+ QLabel
+
+
+
+ caGraphics
+ QWidget
+
+
+
+ caLed
+ QWidget
+
+
+
+ caLineEdit
+ QLineEdit
+
+
+
+ caCartesianPlot
+ QwtPlot
+
+
+
+ caStripPlot
+ QwtPlot
+
+ 1
+
+
+ caCalc
+ QLabel
+
+
+
+ wmSignalPropagator
+ QLabel
+
+
+
+ QwtPlot
+ QFrame
+
+
+
+
+
+
+ cacalc_2
+ emitSignal(bool)
+ wmsignalpropagator
+ reloadwindow()
+
+
+ 2020
+ 374
+
+
+ 2022
+ 545
+
+
+
+
+
diff --git a/services/scrubbing/current/systemd/AGEBD-SERVICE-SCRUBBING.service b/services/scrubbing/current/systemd/AGEBD-SERVICE-SCRUBBING.service
new file mode 100644
index 0000000..1bf2013
--- /dev/null
+++ b/services/scrubbing/current/systemd/AGEBD-SERVICE-SCRUBBING.service
@@ -0,0 +1,16 @@
+[Unit]
+Description=AGEBD-SERVICE-SCRUBBING
+After=network.target
+
+[Service]
+Environment=AGEBD_ENV={{ agebd_env }}
+ExecStart=/sls/bd/hla/{{ agebd_env }}/bin/start_service.sh SCRUBBING
+Restart=no
+
+[Install]
+WantedBy=default.target
+
+# https://www.freedesktop.org/software/systemd/man/latest/systemd.service.html
+# systemctl --user daemon-reload
+# systemctl --user enable /sls/bd/bin/systemd/AGEBD-SERVICE-SCRUBBING.service
+# systemctl --user start AGEBD-SERVICE-SCRUBBING
diff --git a/services/shifttool/current/app/pyproject.toml b/services/shifttool/current/app/pyproject.toml
new file mode 100644
index 0000000..e5be901
--- /dev/null
+++ b/services/shifttool/current/app/pyproject.toml
@@ -0,0 +1,48 @@
+[project]
+name = "agebd-shifttool"
+version = "0.1.0"
+description = "AGEBD-SHIFTTOOL Service"
+requires-python = "==3.10.*"
+dependencies = [
+ "agebd",
+]
+# TODO: elog
+
+[dependency-groups]
+dev = [
+ "pyepics>=3.5.8",
+ "pytest>=8.4.2",
+ "ruff>=0.15.20",
+]
+
+[tool.uv.sources]
+# Path is relative to where agebd package is deployed on hla
+# machines (see CI/CD in .gitea/workflows)
+agebd = { path = "../../../../packages/agebd", editable = true }
+
+[build-system]
+requires = ["hatchling"]
+build-backend = "hatchling.build"
+
+[tool.uv]
+package = true
+
+[tool.pytest.ini_options]
+pythonpath = ["src"]
+env = [
+ "AGEBD_ENV=local",
+]
+
+[tool.ruff]
+include = [
+ "src/**/*.py",
+ "tests/**/*.py",
+]
+line-length = 100
+
+[tool.ruff.lint]
+# use isort to sort imports
+extend-select = ["I"]
+
+[tool.ruff.lint.isort]
+known-first-party = ["agebd"]
diff --git a/services/shifttool/current/app/src/agebd_shifttool/__init__.py b/services/shifttool/current/app/src/agebd_shifttool/__init__.py
new file mode 100644
index 0000000..1800c27
--- /dev/null
+++ b/services/shifttool/current/app/src/agebd_shifttool/__init__.py
@@ -0,0 +1 @@
+from .service import PVs, Service
diff --git a/services/shifttool/current/app/src/agebd_shifttool/main.py b/services/shifttool/current/app/src/agebd_shifttool/main.py
new file mode 100644
index 0000000..01aa2ab
--- /dev/null
+++ b/services/shifttool/current/app/src/agebd_shifttool/main.py
@@ -0,0 +1,31 @@
+import typer
+
+from agebd.enums import LogLevel
+from agebd.runner import CallbackRunner
+from agebd.utils import init_logging
+from agebd_shifttool import PVs, Service
+
+# TODO: remove: cicd test 10
+
+
+def main(
+ log_level: LogLevel = typer.Option(
+ LogLevel.INFO,
+ "--log-level",
+ "-l",
+ # Looks at the OS env variable first. If empty, falls back to "INFO"
+ envvar="AGEBD_LOG_LEVEL",
+ # help="Set log level: DEBUG, INFO, WARNING, ERROR, CRITICAL",
+ case_sensitive=False,
+ ),
+):
+ init_logging(log_level)
+ service_name = "SHIFTTOOL"
+ pvs = PVs(service_name=service_name)
+ service = Service(name=service_name, pvs=pvs)
+ runner = CallbackRunner(service=service)
+ runner.start()
+
+
+if __name__ == "__main__":
+ typer.run(main)
diff --git a/services/shifttool/current/app/src/agebd_shifttool/service.py b/services/shifttool/current/app/src/agebd_shifttool/service.py
new file mode 100644
index 0000000..78b6503
--- /dev/null
+++ b/services/shifttool/current/app/src/agebd_shifttool/service.py
@@ -0,0 +1,269 @@
+import locale
+import time
+from datetime import datetime
+from time import time
+
+import elog
+
+from agebd.pv import get_pv_class
+from agebd.service.base import BaseService
+from agebd.service.pvs import BasePVs
+from agebd.utils import printgetversion
+
+# Setze die Locale auf Deutsch (z. B. 'de_DE' oder 'de_CH' für Schweiz)
+locale.setlocale(locale.LC_TIME, "de_CH.UTF-8") # oder 'de_CH.UTF-8'
+
+__version__ = printgetversion(__file__)
+
+PV = get_pv_class()
+
+
+class PVs(BasePVs):
+ req_MakeElog = PV("AGEOP-SHIFTTOOL:REQ-SHIFT-ENTRY.VAL")
+ req_UpdateTeam = PV("AGEOP-SHIFTTOOL:REQ-UPDATE-TEAM.VAL")
+
+ shift = PV("AGEOP-SHIFTTOOL:TXT-SHIFT.VAL")
+ crew = PV("AGEOP-SHIFTTOOL:TXT-SHIFT-CREW.VAL")
+
+ operators = [
+ PV("AGEOP-SHIFTTOOL:TXT-OPERATOR-01.VAL"),
+ PV("AGEOP-SHIFTTOOL:TXT-OPERATOR-02.VAL"),
+ PV("AGEOP-SHIFTTOOL:TXT-OPERATOR-03.VAL"),
+ PV("AGEOP-SHIFTTOOL:TXT-OPERATOR-04.VAL"),
+ PV("AGEOP-SHIFTTOOL:TXT-OPERATOR-05.VAL"),
+ ]
+ links = {
+ "Problem-01": [
+ PV("AGEOP-SHIFTTOOL:LINK-Problem-01.VAL"),
+ "https://elog-gfa.psi.ch/sls/?cmd=Neu&pEintrag=Problem&pAutor=Rast%2C%20Streich%2C%20Weber&pEffekt=Downtime",
+ ],
+ "Problem-02": [
+ PV("AGEOP-SHIFTTOOL:LINK-Problem-02.VAL"),
+ "https://elog-gfa.psi.ch/sls/?cmd=Neu&pEintrag=Problem&pAutor=Rast%2C%20Streich%2C%20Weber&pEffekt=Beamdrop",
+ ],
+ "Problem-03": [
+ PV("AGEOP-SHIFTTOOL:LINK-Problem-03.VAL"),
+ "https://elog-gfa.psi.ch/sls/?cmd=Neu&pEintrag=Problem&pAutor=Rast%2C%20Streich%2C%20Weber&pEffekt=Lifetime",
+ ],
+ "Problem-04": [
+ PV("AGEOP-SHIFTTOOL:LINK-Problem-04.VAL"),
+ "https://elog-gfa.psi.ch/sls/?cmd=Neu&pEintrag=Problem&pAutor=Rast%2C%20Streich%2C%20Weber&pEffekt=Beamsize",
+ ],
+ "Problem-05": [
+ PV("AGEOP-SHIFTTOOL:LINK-Problem-05.VAL"),
+ "https://elog-gfa.psi.ch/sls/?cmd=Neu&pEintrag=Problem&pAutor=Rast%2C%20Streich%2C%20Weber&pEffekt=keiner",
+ ],
+ "Problem-06": [
+ PV("AGEOP-SHIFTTOOL:LINK-Problem-06.VAL"),
+ "https://elog-gfa.psi.ch/sls/?cmd=Neu&pEintrag=Problem&pAutor=Rast%2C%20Streich%2C%20Weber&pEffekt=anderer",
+ ],
+ "Optimierung-01": [
+ PV("AGEOP-SHIFTTOOL:LINK-Optimierung-01.VAL"),
+ "https://elog-gfa.psi.ch/sls/?cmd=Neu&pEintrag=Tuning&pAutor=Rast%2C%20Streich%2C%20Weber&pTitel=Optimierung%20Transfer",
+ ],
+ "Optimierung-02": [
+ PV("AGEOP-SHIFTTOOL:LINK-Optimierung-02.VAL"),
+ "https://elog-gfa.psi.ch/sls/?cmd=Neu&pEintrag=Tuning&pAutor=Rast%2C%20Streich%2C%20Weber&pTitel=Optimierung%20Tau%2FYsig",
+ ],
+ "Optimierung-03": [
+ PV("AGEOP-SHIFTTOOL:LINK-Optimierung-03.VAL"),
+ "https://elog-gfa.psi.ch/sls/?cmd=Neu&pEintrag=Tuning&pAutor=Rast%2C%20Streich%2C%20Weber&pTitel=Optimierung",
+ ],
+ "Optimierung-04": [
+ PV("AGEOP-SHIFTTOOL:LINK-Optimierung-04.VAL"),
+ "https://elog-gfa.psi.ch/sls/?cmd=Neu&pEintrag=Tuning&pAutor=Rast%2C%20Streich%2C%20Weber&pTitel=Optimierung",
+ ],
+ "Optimierung-05": [
+ PV("AGEOP-SHIFTTOOL:LINK-Optimierung-05.VAL"),
+ "https://elog-gfa.psi.ch/sls/?cmd=Neu&pEintrag=Tuning&pAutor=Rast%2C%20Streich%2C%20Weber&pTitel=Optimierung",
+ ],
+ "Optimierung-06": [
+ PV("AGEOP-SHIFTTOOL:LINK-Optimierung-06.VAL"),
+ "https://elog-gfa.psi.ch/sls/?cmd=Neu&pEintrag=Tuning&pAutor=Rast%2C%20Streich%2C%20Weber&pTitel=Optimierung",
+ ],
+ "Piquet": [
+ PV("AGEOP-SHIFTTOOL:LINK-Piquet.VAL"),
+ ],
+ "Info": [
+ PV("AGEOP-SHIFTTOOL:LINK-Info.VAL"),
+ ],
+ "AktuellesProtokoll": [
+ PV("AGEOP-SHIFTTOOL:LINK-AktuellesProtokoll.VAL"),
+ ],
+ "AndereEintraege-01": [
+ PV("AGEOP-SHIFTTOOL:LINK-AndereEintraege-01.VAL"),
+ ],
+ "AndereEintraege-02": [
+ PV("AGEOP-SHIFTTOOL:LINK-AndereEintraege-02.VAL"),
+ ],
+ "AndereEintraege-03": [
+ PV("AGEOP-SHIFTTOOL:LINK-AndereEintraege-03.VAL"),
+ ],
+ "ListenAnzeigen-01": [
+ PV("AGEOP-SHIFTTOOL:LINK-ListenAnzeigen-01.VAL"),
+ ],
+ "ListenAnzeigen-02": [
+ PV("AGEOP-SHIFTTOOL:LINK-ListenAnzeigen-02.VAL"),
+ ],
+ "ListenAnzeigen-03": [
+ PV("AGEOP-SHIFTTOOL:LINK-ListenAnzeigen-03.VAL"),
+ ],
+ "ListenAnzeigen-04": [
+ PV("AGEOP-SHIFTTOOL:LINK-ListenAnzeigen-04.VAL"),
+ ],
+ "PiquetWoche": [
+ PV("AGEOP-SHIFTTOOL:LINK-PiquetWoche.VAL"),
+ ],
+ "OffeneAuftraege": [
+ PV("AGEOP-SHIFTTOOL:LINK-OffeneAuftraege.VAL"),
+ ],
+ }
+
+ minisave = [
+ PV("AGEBD-PARAMS:LIFETIME.VAL"),
+ PV("AGEBD-DBPM3CURR:CURRENT-AVG.VAL"),
+ PV("AGEBD-PARAMS:INJECTION-RATE.VAL"),
+ PV("AGEBD-DBPM3CURR:ACCUMULATED-BEAM-DOSE.VAL"),
+ PV("AGEOP-CPCL-TRANSMISSION:ICT-BRTL_2_BPM-RING.VAL"),
+ PV("ARSGE-CECL-FOFB1:X-RMS-UM.VAL"),
+ PV("ARSGE-CECL-FOFB1:Y-RMS-UM.VAL"),
+ PV("X01DD-FE-ABS1:STATUS.VAL"),
+ PV("X08DB-FE-ABS1:STATUS.VAL"),
+ PV("X01DA-FE-ABS1:STATUS.VAL"),
+ PV("X01DA-OP-PSYS:SH-A-OPEN.VAL"),
+ PV("X02DA-FE-ABS1:STATUS.VAL"),
+ PV("X02DA-OP-PSYS:SH-A-OPEN.VAL"),
+ PV("X06DA-FE-ABS1:STATUS.VAL"),
+ PV("X06DA-OP-PSYS:SH-A-OPEN.VAL"),
+ PV("X07DA-FE-ABS1:STATUS.VAL"),
+ PV("X07D-OP-PSYS:SH-A-OPEN.VAL"),
+ PV("X07DB-FE-ABS1:STATUS.VAL"),
+ PV("X07D-OP-PSYS:SH-B-OPEN.VAL"),
+ PV("X10DA-FE-ABS1:STATUS.VAL"),
+ PV("X10DA-OP-PSYS:SH-A-OPEN.VAL"),
+ PV("X04SA-UIND:GAP-READ.VAL"),
+ PV("X04SA-UIND:SCTRL.VAL"),
+ PV("X06SA-UIND:GAP-READ.VAL"),
+ PV("X06SA-UIND:SCTRL.VAL"),
+ PV("X09LB-UIND:GAP-READ.VAL"),
+ PV("X09LB-UIND:SCTRL.VAL"),
+ PV("X10SA-UIND:GAP-READ.VAL"),
+ PV("X10SA-UIND:SCTRL.VAL"),
+ PV("X12SA-UIND:GAP-READ.VAL"),
+ PV("X12SA-UIND:SCTRL.VAL"),
+ ]
+
+ NShiftTasks = PV("AGEOP-SHIFTTOOL:CNT-TODO.VAL")
+
+ def __init__(self, service_name: str, pv_factory=PV):
+ super().__init__(service_name, pv_factory)
+ PV = pv_factory
+
+ self.CallbackPV = PV("AGEOP-SHIFTTOOL:REQ-CALC.VAL")
+
+
+class Service(BaseService[PVs]):
+ def __init__(
+ self,
+ name: str,
+ pvs: PVs,
+ version: str = __version__,
+ sleep_interval: float = 0.1,
+ ):
+ super().__init__(name, pvs, version, sleep_interval)
+
+ # FACILITY = SLS
+ self.logbook = elog.open(
+ "https://elog-gfa.psi.ch/SLS/",
+ user="robot",
+ password="robot",
+ use_ssl=True,
+ )
+ self.path = "/sls/op/data/applications/minisave/"
+
+ def minisave(self):
+
+ # table overview of current machine and beamline parameters
+
+ return
+
+ def update(self):
+ pvs = self.pvs
+
+ if self.CallbackFired:
+ self.req_UpdateTeam = pvs.req_UpdateTeam.get()
+ self.req_MakeElog = pvs.req_MakeElog.get()
+ print(self.req_UpdateTeam, self.req_MakeElog)
+
+ # if shift crew update request detected update current shift crew
+ if self.req_UpdateTeam or self.req_MakeElog:
+ pvs.req_UpdateTeam.put(0)
+ print("Team aktualisieren")
+
+ self.logtxt = []
+ self.logtxt.append("Eingetragene Mannschaft:")
+ self.date = datetime.now()
+ self.hour = int(self.date.strftime("%H"))
+
+ # Format the date
+ self.day_abbr = self.date.strftime(
+ "%a"
+ ) # Abbreviated weekday (e.g., "Mi" for Mittwoch)
+ self.date_str = self.date.strftime(
+ "%d-%b-%Y"
+ ) # Day-Month-Year (e.g., "17-Jun-2026")
+ self.week_num = self.date.isocalendar()[1] # ISO calendar week number (e.g., 25)
+ self.timestamp = f"{self.day_abbr} {self.date_str} KW{self.week_num}"
+
+ if self.hour > 4 and self.hour < 8:
+ self.shift = "Früh-Schicht"
+ elif self.hour > 12 and self.hour < 16:
+ self.shift = "Spät-Schicht"
+ elif self.hour > 20:
+ self.shift = "Nacht-Schicht"
+ else:
+ self.shift = "Verschlafen"
+
+ self.shift += ", " + self.timestamp
+ pvs.shift.put(self.shift)
+
+ self.operators = []
+ for op in pvs.operators:
+ op = op.get(as_string=True)
+ if len(op) > 1:
+ self.operators.append(op)
+
+ print(self.operators)
+ self.crew = ", ".join(self.operators)
+ pvs.crew.put(self.crew)
+ self.logtxt.append(self.crew)
+ print(self.crew)
+
+ # if shift entry request detected and current shift entry not yet made, make it
+ if self.req_MakeElog:
+ pvs.req_MakeElog.put(0)
+ print("Schicht eintragen")
+
+ # Write to elog
+ self.logtxt = "".join(self.logtxt)
+
+ self.dict_of_attributes = {
+ "Wann": time(),
+ "Autor": self.crew,
+ "Eintrag": "Schicht-Übergabe",
+ "Titel": self.shift,
+ "Encoding": "html",
+ }
+
+ print(" ...elog entry prepared...")
+
+ self.msg_id = self.logbook.post(
+ self.logtxt,
+ attributes=self.dict_of_attributes,
+ suppress_email_notification=True,
+ attribute_as_param="value",
+ )
+ print(" ...elog entry submitted...")
+
+ # callback done
+ self.CallbackFired = 0
diff --git a/services/shifttool/current/app/tests/test_app.py b/services/shifttool/current/app/tests/test_app.py
new file mode 100644
index 0000000..257fc01
--- /dev/null
+++ b/services/shifttool/current/app/tests/test_app.py
@@ -0,0 +1,9 @@
+from agebd_shifttool import PVs, Service
+
+
+def test_app():
+ service_name = "DUMMY"
+ pvs = PVs(service_name=service_name)
+ service = Service(name=service_name, pvs=pvs)
+ service.CallbackFired = 1
+ service.update()
diff --git a/services/shifttool/current/app/uv.lock b/services/shifttool/current/app/uv.lock
new file mode 100644
index 0000000..753115b
--- /dev/null
+++ b/services/shifttool/current/app/uv.lock
@@ -0,0 +1,297 @@
+version = 1
+revision = 3
+requires-python = "==3.10.*"
+
+[[package]]
+name = "agebd"
+version = "0.1.0"
+source = { editable = "../../../../packages/agebd" }
+dependencies = [
+ { name = "h5py" },
+ { name = "typer" },
+]
+
+[package.metadata]
+requires-dist = [
+ { name = "h5py", specifier = ">=3.16.0" },
+ { name = "typer", specifier = ">=0.23.2" },
+]
+
+[package.metadata.requires-dev]
+dev = [
+ { name = "pyright", specifier = ">=1.1.410" },
+ { name = "pytest", specifier = ">=8.4.2" },
+ { name = "ruff", specifier = ">=0.15.19" },
+]
+
+[[package]]
+name = "agebd-shifttool"
+version = "0.1.0"
+source = { editable = "." }
+dependencies = [
+ { name = "agebd" },
+]
+
+[package.dev-dependencies]
+dev = [
+ { name = "pyepics" },
+ { name = "pytest" },
+ { name = "ruff" },
+]
+
+[package.metadata]
+requires-dist = [{ name = "agebd", editable = "../../../../packages/agebd" }]
+
+[package.metadata.requires-dev]
+dev = [
+ { name = "pyepics", specifier = ">=3.5.8" },
+ { name = "pytest", specifier = ">=8.4.2" },
+ { name = "ruff", specifier = ">=0.15.20" },
+]
+
+[[package]]
+name = "annotated-doc"
+version = "0.0.4"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/57/ba/046ceea27344560984e26a590f90bc7f4a75b06701f653222458922b558c/annotated_doc-0.0.4.tar.gz", hash = "sha256:fbcda96e87e9c92ad167c2e53839e57503ecfda18804ea28102353485033faa4", size = 7288, upload-time = "2025-11-10T22:07:42.062Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl", hash = "sha256:571ac1dc6991c450b25a9c2d84a3705e2ae7a53467b5d111c24fa8baabbed320", size = 5303, upload-time = "2025-11-10T22:07:40.673Z" },
+]
+
+[[package]]
+name = "colorama"
+version = "0.4.6"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" },
+]
+
+[[package]]
+name = "exceptiongroup"
+version = "1.3.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "typing-extensions" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" },
+]
+
+[[package]]
+name = "h5py"
+version = "3.16.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "numpy" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/db/33/acd0ce6863b6c0d7735007df01815403f5589a21ff8c2e1ee2587a38f548/h5py-3.16.0.tar.gz", hash = "sha256:a0dbaad796840ccaa67a4c144a0d0c8080073c34c76d5a6941d6818678ef2738", size = 446526, upload-time = "2026-03-06T13:49:08.07Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/3a/6b/231413e58a787a89b316bb0d1777da3c62257e4797e09afd8d17ad3549dc/h5py-3.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e06f864bedb2c8e7c1358e6c73af48519e317457c444d6f3d332bb4e8fa6d7d9", size = 3724137, upload-time = "2026-03-06T13:47:35.242Z" },
+ { url = "https://files.pythonhosted.org/packages/74/f9/557ce3aad0fe8471fb5279bab0fc56ea473858a022c4ce8a0b8f303d64e9/h5py-3.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ec86d4fffd87a0f4cb3d5796ceb5a50123a2a6d99b43e616e5504e66a953eca3", size = 3090112, upload-time = "2026-03-06T13:47:37.634Z" },
+ { url = "https://files.pythonhosted.org/packages/7a/f5/e15b3d0dc8a18e56409a839e6468d6fb589bc5207c917399c2e0706eeb44/h5py-3.16.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:86385ea895508220b8a7e45efa428aeafaa586bd737c7af9ee04661d8d84a10d", size = 4844847, upload-time = "2026-03-06T13:47:39.811Z" },
+ { url = "https://files.pythonhosted.org/packages/cb/92/a8851d936547efe30cc0ce5245feac01f3ec6171f7899bc3f775c72030b3/h5py-3.16.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:8975273c2c5921c25700193b408e28d6bdd0111c37468b2d4e25dcec4cd1d84d", size = 5065352, upload-time = "2026-03-06T13:47:41.489Z" },
+ { url = "https://files.pythonhosted.org/packages/2b/ae/f2adc5d0ca9626db3277a3d87516e124cbc5d0eea0bd79bc085702d04f2c/h5py-3.16.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:1677ad48b703f44efc9ea0c3ab284527f81bc4f318386aaaebc5fede6bbae56f", size = 4839173, upload-time = "2026-03-06T13:47:43.586Z" },
+ { url = "https://files.pythonhosted.org/packages/64/0b/e0c8c69da1d8838da023a50cd3080eae5d475691f7636b35eff20bb6ef20/h5py-3.16.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7c4dd4cf5f0a4e36083f73172f6cfc25a5710789269547f132a20975bfe2434c", size = 5076216, upload-time = "2026-03-06T13:47:45.315Z" },
+ { url = "https://files.pythonhosted.org/packages/66/35/d88fd6718832133c885004c61ceeeb24dbd6397ef877dbed6b3a64d6a286/h5py-3.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:bdef06507725b455fccba9c16529121a5e1fbf56aa375f7d9713d9e8ff42454d", size = 3183639, upload-time = "2026-03-06T13:47:47.041Z" },
+]
+
+[[package]]
+name = "iniconfig"
+version = "2.3.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" },
+]
+
+[[package]]
+name = "markdown-it-py"
+version = "4.2.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "mdurl" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/06/ff/7841249c247aa650a76b9ee4bbaeae59370dc8bfd2f6c01f3630c35eb134/markdown_it_py-4.2.0.tar.gz", hash = "sha256:04a21681d6fbb623de53f6f364d352309d4094dd4194040a10fd51833e418d49", size = 82454, upload-time = "2026-05-07T12:08:28.36Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl", hash = "sha256:9f7ebbcd14fe59494226453aed97c1070d83f8d24b6fc3a3bcf9a38092641c4a", size = 91687, upload-time = "2026-05-07T12:08:27.182Z" },
+]
+
+[[package]]
+name = "mdurl"
+version = "0.1.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" },
+]
+
+[[package]]
+name = "numpy"
+version = "2.2.6"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/76/21/7d2a95e4bba9dc13d043ee156a356c0a8f0c6309dff6b21b4d71a073b8a8/numpy-2.2.6.tar.gz", hash = "sha256:e29554e2bef54a90aa5cc07da6ce955accb83f21ab5de01a62c8478897b264fd", size = 20276440, upload-time = "2025-05-17T22:38:04.611Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/9a/3e/ed6db5be21ce87955c0cbd3009f2803f59fa08df21b5df06862e2d8e2bdd/numpy-2.2.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b412caa66f72040e6d268491a59f2c43bf03eb6c96dd8f0307829feb7fa2b6fb", size = 21165245, upload-time = "2025-05-17T21:27:58.555Z" },
+ { url = "https://files.pythonhosted.org/packages/22/c2/4b9221495b2a132cc9d2eb862e21d42a009f5a60e45fc44b00118c174bff/numpy-2.2.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e41fd67c52b86603a91c1a505ebaef50b3314de0213461c7a6e99c9a3beff90", size = 14360048, upload-time = "2025-05-17T21:28:21.406Z" },
+ { url = "https://files.pythonhosted.org/packages/fd/77/dc2fcfc66943c6410e2bf598062f5959372735ffda175b39906d54f02349/numpy-2.2.6-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:37e990a01ae6ec7fe7fa1c26c55ecb672dd98b19c3d0e1d1f326fa13cb38d163", size = 5340542, upload-time = "2025-05-17T21:28:30.931Z" },
+ { url = "https://files.pythonhosted.org/packages/7a/4f/1cb5fdc353a5f5cc7feb692db9b8ec2c3d6405453f982435efc52561df58/numpy-2.2.6-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:5a6429d4be8ca66d889b7cf70f536a397dc45ba6faeb5f8c5427935d9592e9cf", size = 6878301, upload-time = "2025-05-17T21:28:41.613Z" },
+ { url = "https://files.pythonhosted.org/packages/eb/17/96a3acd228cec142fcb8723bd3cc39c2a474f7dcf0a5d16731980bcafa95/numpy-2.2.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:efd28d4e9cd7d7a8d39074a4d44c63eda73401580c5c76acda2ce969e0a38e83", size = 14297320, upload-time = "2025-05-17T21:29:02.78Z" },
+ { url = "https://files.pythonhosted.org/packages/b4/63/3de6a34ad7ad6646ac7d2f55ebc6ad439dbbf9c4370017c50cf403fb19b5/numpy-2.2.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc7b73d02efb0e18c000e9ad8b83480dfcd5dfd11065997ed4c6747470ae8915", size = 16801050, upload-time = "2025-05-17T21:29:27.675Z" },
+ { url = "https://files.pythonhosted.org/packages/07/b6/89d837eddef52b3d0cec5c6ba0456c1bf1b9ef6a6672fc2b7873c3ec4e2e/numpy-2.2.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:74d4531beb257d2c3f4b261bfb0fc09e0f9ebb8842d82a7b4209415896adc680", size = 15807034, upload-time = "2025-05-17T21:29:51.102Z" },
+ { url = "https://files.pythonhosted.org/packages/01/c8/dc6ae86e3c61cfec1f178e5c9f7858584049b6093f843bca541f94120920/numpy-2.2.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8fc377d995680230e83241d8a96def29f204b5782f371c532579b4f20607a289", size = 18614185, upload-time = "2025-05-17T21:30:18.703Z" },
+ { url = "https://files.pythonhosted.org/packages/5b/c5/0064b1b7e7c89137b471ccec1fd2282fceaae0ab3a9550f2568782d80357/numpy-2.2.6-cp310-cp310-win32.whl", hash = "sha256:b093dd74e50a8cba3e873868d9e93a85b78e0daf2e98c6797566ad8044e8363d", size = 6527149, upload-time = "2025-05-17T21:30:29.788Z" },
+ { url = "https://files.pythonhosted.org/packages/a3/dd/4b822569d6b96c39d1215dbae0582fd99954dcbcf0c1a13c61783feaca3f/numpy-2.2.6-cp310-cp310-win_amd64.whl", hash = "sha256:f0fd6321b839904e15c46e0d257fdd101dd7f530fe03fd6359c1ea63738703f3", size = 12904620, upload-time = "2025-05-17T21:30:48.994Z" },
+ { url = "https://files.pythonhosted.org/packages/9e/3b/d94a75f4dbf1ef5d321523ecac21ef23a3cd2ac8b78ae2aac40873590229/numpy-2.2.6-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0b605b275d7bd0c640cad4e5d30fa701a8d59302e127e5f79138ad62762c3e3d", size = 21040391, upload-time = "2025-05-17T21:44:35.948Z" },
+ { url = "https://files.pythonhosted.org/packages/17/f4/09b2fa1b58f0fb4f7c7963a1649c64c4d315752240377ed74d9cd878f7b5/numpy-2.2.6-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:7befc596a7dc9da8a337f79802ee8adb30a552a94f792b9c9d18c840055907db", size = 6786754, upload-time = "2025-05-17T21:44:47.446Z" },
+ { url = "https://files.pythonhosted.org/packages/af/30/feba75f143bdc868a1cc3f44ccfa6c4b9ec522b36458e738cd00f67b573f/numpy-2.2.6-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce47521a4754c8f4593837384bd3424880629f718d87c5d44f8ed763edd63543", size = 16643476, upload-time = "2025-05-17T21:45:11.871Z" },
+ { url = "https://files.pythonhosted.org/packages/37/48/ac2a9584402fb6c0cd5b5d1a91dcf176b15760130dd386bbafdbfe3640bf/numpy-2.2.6-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d042d24c90c41b54fd506da306759e06e568864df8ec17ccc17e9e884634fd00", size = 12812666, upload-time = "2025-05-17T21:45:31.426Z" },
+]
+
+[[package]]
+name = "packaging"
+version = "26.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d7/f1/e7a6dd94a8d4a5626c03e4e99c87f241ba9e350cd9e6d75123f992427270/packaging-26.2.tar.gz", hash = "sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661", size = 228134, upload-time = "2026-04-24T20:15:23.917Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/df/b2/87e62e8c3e2f4b32e5fe99e0b86d576da1312593b39f47d8ceef365e95ed/packaging-26.2-py3-none-any.whl", hash = "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e", size = 100195, upload-time = "2026-04-24T20:15:22.081Z" },
+]
+
+[[package]]
+name = "pluggy"
+version = "1.6.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" },
+]
+
+[[package]]
+name = "pyepics"
+version = "3.5.10"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "numpy" },
+ { name = "pyparsing" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/69/57/29e1e9ef11ba2a3419f489946ae1d8190025a1e4f4e1c1686758bb2b6e0a/pyepics-3.5.10.tar.gz", hash = "sha256:f390cf9be40aba757b9528888114bc14d8db01086d0c93914720b1772460375b", size = 6150481, upload-time = "2026-05-20T18:44:36.336Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d6/36/e517fd83bd97d6bfe4105e0c6b322070c5cc36fb56a8fab2866e319f8804/pyepics-3.5.10-py3-none-any.whl", hash = "sha256:c9fac2c54f2b595268e66fc348cf5ec24e63718e7dbd07d73d1b37d4da6bfee1", size = 5332376, upload-time = "2026-05-20T18:44:34.242Z" },
+]
+
+[[package]]
+name = "pygments"
+version = "2.20.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" },
+]
+
+[[package]]
+name = "pyparsing"
+version = "3.3.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f3/91/9c6ee907786a473bf81c5f53cf703ba0957b23ab84c264080fb5a450416f/pyparsing-3.3.2.tar.gz", hash = "sha256:c777f4d763f140633dcb6d8a3eda953bf7a214dc4eff598413c070bcdc117cbc", size = 6851574, upload-time = "2026-01-21T03:57:59.36Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl", hash = "sha256:850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d", size = 122781, upload-time = "2026-01-21T03:57:55.912Z" },
+]
+
+[[package]]
+name = "pytest"
+version = "9.1.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "colorama", marker = "sys_platform == 'win32'" },
+ { name = "exceptiongroup" },
+ { name = "iniconfig" },
+ { name = "packaging" },
+ { name = "pluggy" },
+ { name = "pygments" },
+ { name = "tomli" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/e4/47/b9efed96c114afcfa3c9d3fe98a76a1d14c74a9e266d397cf6eb64be5e01/pytest-9.1.1.tar.gz", hash = "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313", size = 1636369, upload-time = "2026-06-19T10:58:32.857Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/24/25/1de2678b631f5a49215c6c96fff41ba892b0a34df68d6d80292b1b48aa7f/pytest-9.1.1-py3-none-any.whl", hash = "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c", size = 386536, upload-time = "2026-06-19T10:58:31.347Z" },
+]
+
+[[package]]
+name = "rich"
+version = "15.0.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "markdown-it-py" },
+ { name = "pygments" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/c0/8f/0722ca900cc807c13a6a0c696dacf35430f72e0ec571c4275d2371fca3e9/rich-15.0.0.tar.gz", hash = "sha256:edd07a4824c6b40189fb7ac9bc4c52536e9780fbbfbddf6f1e2502c31b068c36", size = 230680, upload-time = "2026-04-12T08:24:00.75Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl", hash = "sha256:33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb", size = 310654, upload-time = "2026-04-12T08:24:02.83Z" },
+]
+
+[[package]]
+name = "ruff"
+version = "0.15.21"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/0f/36/6f65aa9989acdec45d417192d8f4e7921931d8a6cf87ac74bce3eed98a8e/ruff-0.15.21.tar.gz", hash = "sha256:d0cfc841c572283c36548f82664a54ce6565567f1b0d5b4cf2caac693d8b7500", size = 4769401, upload-time = "2026-07-09T20:01:34.005Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d0/c6/ede15cac6839f3dbce52565c8f5164a8210e669c7bc4decb03e5bdf47d0d/ruff-0.15.21-py3-none-linux_armv6l.whl", hash = "sha256:63ea0e965e5d73c90e95b2434beeafc70820536717f561b32ab6e777cb9bdf5d", size = 10854342, upload-time = "2026-07-09T20:00:53.998Z" },
+ { url = "https://files.pythonhosted.org/packages/28/9d/d825b07ee7ea9e2d61df92a860033c94e06e7300d50a1c2653aac27d24fe/ruff-0.15.21-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:0f212c5d7d54c01bbfe6dcab02b724a39300f3e34ed7acbe995ccb320a2c58bd", size = 11139539, upload-time = "2026-07-09T20:00:57.809Z" },
+ { url = "https://files.pythonhosted.org/packages/f5/de/3b107712e642f063c7a9e0887c427b22cb44097de5aab36c05f2e280670c/ruff-0.15.21-py3-none-macosx_11_0_arm64.whl", hash = "sha256:e6312e41bc96791299614995ea3a977c5857c3b5662b1ecef6755b02b87cb646", size = 10595437, upload-time = "2026-07-09T20:01:00.006Z" },
+ { url = "https://files.pythonhosted.org/packages/9a/6f/b4523cc90ba239ede441447a19d0c968846a3012e5a0b0c5b62831a3d5e3/ruff-0.15.21-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01d65b4831c6b2a4ba8ee6faa84049d44d982b7a706e622c4094c509e51673be", size = 10990053, upload-time = "2026-07-09T20:01:02.187Z" },
+ { url = "https://files.pythonhosted.org/packages/92/cc/c6a9872a5375f0628875481cf2f66b13d7d865bf3ca2e57f91c7e762d976/ruff-0.15.21-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2c5a913a589120ce67933d5d05fd6ddbcc2481c6a054980ee767f7414c72b4fd", size = 10666096, upload-time = "2026-07-09T20:01:04.299Z" },
+ { url = "https://files.pythonhosted.org/packages/ab/97/c621f7a17e097f1790fa3af6374138823b330b2d03fc38337945daca212c/ruff-0.15.21-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ef04b681d02ad4dc9620f00f83ac5c22f652d0e9a9cfe431d219b16ad5ccc41", size = 11537011, upload-time = "2026-07-09T20:01:06.771Z" },
+ { url = "https://files.pythonhosted.org/packages/ea/51/d928727e476e25ccc57c6f449ffd80241a651a973ad949d39cfb2a771d28/ruff-0.15.21-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:16d090c0740916594157e75b80d666eab8e78083b39b3b0e1d698f4670a17b86", size = 12347101, upload-time = "2026-07-09T20:01:08.859Z" },
+ { url = "https://files.pythonhosted.org/packages/1e/88/8cd62026802b16018ad06931d87997cf795ba2a6239ab659606c87d96bf0/ruff-0.15.21-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3a10e74757dd65004d779b73e2f3c5210156d9980b41224d50d2ebcf1db51e67", size = 11572001, upload-time = "2026-07-09T20:01:11.092Z" },
+ { url = "https://files.pythonhosted.org/packages/b2/97/f63084cf55444fc110e8cb985ebfcc592af47f597d44453d778cb81bc156/ruff-0.15.21-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bab0905d2f29e0d9fbc3c373ed23db0095edaa3f71f1f4f519ec15134d9e85c8", size = 11549239, upload-time = "2026-07-09T20:01:13.27Z" },
+ { url = "https://files.pythonhosted.org/packages/9d/77/f107da4a2874b7715914b03f09ba9c54424de3ff8a1cc5d015d3ee2ce0ac/ruff-0.15.21-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:00eca240af5789fec6fe7df74c088cc1f9644ed83027113468efba7c92b94075", size = 11535340, upload-time = "2026-07-09T20:01:15.206Z" },
+ { url = "https://files.pythonhosted.org/packages/d5/e9/601deb322d3303a7bf212b0100ead6f2ee3f6a044d89c30f2f92bf83c731/ruff-0.15.21-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:262ab31557a75141325e32d3357f3597645a7f084e732b6b054dde428ecd9341", size = 10964048, upload-time = "2026-07-09T20:01:17.723Z" },
+ { url = "https://files.pythonhosted.org/packages/ea/2e/0f2176d1e99c15192caea19c8c3a0a955246b4cb4de795042eeb616345cd/ruff-0.15.21-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:659c4e7a4212f83306045ec7c5e5a356d16d9a6ef4ae0c7a4d872914fc655d9d", size = 10667055, upload-time = "2026-07-09T20:01:19.73Z" },
+ { url = "https://files.pythonhosted.org/packages/48/60/abd74a02e0c4214f12a68becfd30af7165cfdcb0e661ecdc60bbb949c09a/ruff-0.15.21-py3-none-musllinux_1_2_i686.whl", hash = "sha256:9e866eab611a5f959d36df2d10e446973a3610bc42b0c15b31dc27977d59c233", size = 11242043, upload-time = "2026-07-09T20:01:21.947Z" },
+ { url = "https://files.pythonhosted.org/packages/b2/c6/583075d8ccabb4b229345edcaf1545eb3d8d6be90f686a479d7e94088bbf/ruff-0.15.21-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e89bc93c0d3803ba870b55c29671bad9dc6d94bb1eb181b056b52eb05b52854f", size = 11648064, upload-time = "2026-07-09T20:01:24.023Z" },
+ { url = "https://files.pythonhosted.org/packages/3a/3c/37d0ecb729a7cc2d393ea7dce316fc585680f35d93b8d62139d7d0a3700c/ruff-0.15.21-py3-none-win32.whl", hash = "sha256:01f8d5be84823c172b389e123174f781f9daf86d6c58719d603f941932195cdd", size = 10896555, upload-time = "2026-07-09T20:01:26.941Z" },
+ { url = "https://files.pythonhosted.org/packages/c0/b8/e43466b2a6067ce91e669068f6e28d6c719a920f014b070d5c8731725de3/ruff-0.15.21-py3-none-win_amd64.whl", hash = "sha256:d4b8d9a2f0f12b816b50447f6eccb9f4bb01a6b82c86b50fb3b5354b458dc6d3", size = 12038772, upload-time = "2026-07-09T20:01:29.497Z" },
+ { url = "https://files.pythonhosted.org/packages/dd/75/e90ab9aeece218a9fc5a5bc3ec97d0ee6bb3c4ff95869463c1de58e29a1c/ruff-0.15.21-py3-none-win_arm64.whl", hash = "sha256:6e83115d4b9377c1cbc13abf0e051f069fab0ef815ea0504a8a008cee24dd0a8", size = 11375265, upload-time = "2026-07-09T20:01:31.772Z" },
+]
+
+[[package]]
+name = "shellingham"
+version = "1.5.4"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/58/15/8b3609fd3830ef7b27b655beb4b4e9c62313a4e8da8c676e142cc210d58e/shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de", size = 10310, upload-time = "2023-10-24T04:13:40.426Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755, upload-time = "2023-10-24T04:13:38.866Z" },
+]
+
+[[package]]
+name = "tomli"
+version = "2.4.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/22/de/48c59722572767841493b26183a0d1cc411d54fd759c5607c4590b6563a6/tomli-2.4.1.tar.gz", hash = "sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f", size = 17543, upload-time = "2026-03-25T20:22:03.828Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/7b/61/cceae43728b7de99d9b847560c262873a1f6c98202171fd5ed62640b494b/tomli-2.4.1-py3-none-any.whl", hash = "sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe", size = 14583, upload-time = "2026-03-25T20:22:03.012Z" },
+]
+
+[[package]]
+name = "typer"
+version = "0.27.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "annotated-doc" },
+ { name = "colorama", marker = "sys_platform == 'win32'" },
+ { name = "rich" },
+ { name = "shellingham" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/37/78/fda3361b56efc27944f24225f6ecd13d96d6fcfe37bd0eb34e2f4c63f9fc/typer-0.27.0.tar.gz", hash = "sha256:629bd12ea5d13a17148125d9a264f949eb171fb3f120f9b04d85873cab054fa5", size = 203430, upload-time = "2026-07-15T19:21:07.007Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/40/03/26a383c9e58c213199d1aad1c3d353cfc22d4444ec6d2c0bf8ad02523843/typer-0.27.0-py3-none-any.whl", hash = "sha256:6f4b27631e47f077871b7dc30e933ec0131c1390fbe0e387ea5574b5bac9ccf1", size = 122716, upload-time = "2026-07-15T19:21:05.553Z" },
+]
+
+[[package]]
+name = "typing-extensions"
+version = "4.16.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f6/cc/6253133b5bb138fc3306cebfbda2c520f545d36b5be2c7255cc528bb45d6/typing_extensions-4.16.0.tar.gz", hash = "sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5", size = 113555, upload-time = "2026-07-02T08:40:05.92Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/49/d3/b8441a820a491ddfc024b0b0cf0393375b75ea13866d9c66727e54c2fc80/typing_extensions-4.16.0-py3-none-any.whl", hash = "sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8", size = 45571, upload-time = "2026-07-02T08:40:04.659Z" },
+]
diff --git a/services/shifttool/current/ioc/AGEBD-CPCL-SHIFTTOOL_main.subs b/services/shifttool/current/ioc/AGEBD-CPCL-SHIFTTOOL_main.subs
new file mode 100644
index 0000000..6141523
--- /dev/null
+++ b/services/shifttool/current/ioc/AGEBD-CPCL-SHIFTTOOL_main.subs
@@ -0,0 +1,4 @@
+file SHIFTTOOL.template {
+ pattern { DEVICE }
+ { AGEBD-SHIFTTOOL{{ agebd_env }} }
+}
diff --git a/services/shifttool/current/ioc/AGEBD-CPCL-SHIFTTOOL_parameters.yaml b/services/shifttool/current/ioc/AGEBD-CPCL-SHIFTTOOL_parameters.yaml
new file mode 100644
index 0000000..ff8e70f
--- /dev/null
+++ b/services/shifttool/current/ioc/AGEBD-CPCL-SHIFTTOOL_parameters.yaml
@@ -0,0 +1,6 @@
+cpu_architecture: x86_64
+epics_version: 7.0.8
+ioc_host: sls-vserv-bd-01{{ agebd_env }}
+ioc_port: {{ ioc_port }}
+os: RHEL8
+os_id: rhel
diff --git a/services/shifttool/current/ioc/README.md b/services/shifttool/current/ioc/README.md
new file mode 100644
index 0000000..028b87b
--- /dev/null
+++ b/services/shifttool/current/ioc/README.md
@@ -0,0 +1 @@
+# TODO: does it have an ioc? (in A_OP?)
diff --git a/services/shifttool/current/ioc/SHIFTTOOL.template b/services/shifttool/current/ioc/SHIFTTOOL.template
new file mode 100644
index 0000000..857d84a
--- /dev/null
+++ b/services/shifttool/current/ioc/SHIFTTOOL.template
@@ -0,0 +1,37 @@
+# This is a template for preaparing an IOC providing BD Service specific PVs
+# Access Security Groups:
+# DEFAULT - logt wenn EGU oder so veraendert werden
+# LOG - logt wenn neuer wert geschrieben wird
+# PROTECTED - verhindert versuchte caputs auf alle fields ausser VAL
+# READONLY - verhindert versuchte caputs und aktiviert caputlog
+# Input links can specify CA, CP, or CPP.
+# If the input link specifies CA, it will be forced to be a Channel Access link.
+# If the input link specifies CP, it will also be forced to be a Channel Access link; in addition, it will cause the record containing the input link to process whenever a monitor is posted, no matter what the record's SCAN field specifies.
+# If the input link specifies CPP, it means the same thing as CP, except that the record will be processed if and only if the record itself specifies passive in its SCAN field. Output links can specify CA, which will simply cause them to be Channel Access links.
+#
+
+record(ao, "$(DEVICE):AO") {
+ field(DESC, "Analog Output Record (ao)")
+ field(ASG, "PROTECTED")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(bo, "$(DEVICE):BO") {
+ field(DESC, "Binary Output Record (bo)")
+ field(ASG, "READONLY")
+ field(ZSV, "MINOR")
+ field(OSV, "NO_ALARM")
+ field(VAL, "1")
+ field(PINI, "YES")
+}
+
+# TODO: ok?
+record(bo, "$(DEVICE):CALLBACK") {
+ field(DESC, "Callback PV to listen to for changes")
+ field(ASG, "READONLY")
+ field(ZSV, "MINOR")
+ field(OSV, "NO_ALARM")
+ field(VAL, "1")
+ field(PINI, "YES")
+}
\ No newline at end of file
diff --git a/services/shifttool/current/ioc/startup.script b/services/shifttool/current/ioc/startup.script
new file mode 100644
index 0000000..0fa52ff
--- /dev/null
+++ b/services/shifttool/current/ioc/startup.script
@@ -0,0 +1 @@
+epicsEnvSet("ENGINEER", "armborst")
diff --git a/services/shifttool/current/qt/A_BD_.ui b/services/shifttool/current/qt/A_BD_.ui
new file mode 100644
index 0000000..472b163
--- /dev/null
+++ b/services/shifttool/current/qt/A_BD_.ui
@@ -0,0 +1,103 @@
+
+
+ MainWindow
+
+
+
+ 0
+ 0
+ 800
+ 600
+
+
+
+ MainWindow
+
+
+
+
+
+ 0
+ 60
+ 100
+ 50
+
+
+
+ 1
+
+
+ 0
+
+
+ AGEBD-SHIFTTOOL-DEV:AO
+
+
+ 9.000000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 0
+ 0
+ 601
+ 22
+
+
+
+ Toggle AGEBD-ALH-DEV:SHIFTTOOL-ONOFF
+
+
+ AGEBD-ALH-DEV:SHIFTTOOL-ONOFF
+
+
+
+
+
+ 6
+ 34
+ 401
+ 21
+
+
+
+
+ 13
+
+
+
+ Value of AGEBD-SHIFTTOOL-DEV:AO
+
+
+
+
+
+
+
+
+ caNumeric
+ QFrame
+
+
+
+ caToggleButton
+ QCheckBox
+
+
+
+
+
+
diff --git a/services/shifttool/current/qt/README.md b/services/shifttool/current/qt/README.md
new file mode 100644
index 0000000..6e3690d
--- /dev/null
+++ b/services/shifttool/current/qt/README.md
@@ -0,0 +1 @@
+# TODO: ui for this service...
diff --git a/services/shifttool/current/systemd/AGEBD-SERVICE-SHIFTTOOL.service b/services/shifttool/current/systemd/AGEBD-SERVICE-SHIFTTOOL.service
new file mode 100644
index 0000000..ee945c0
--- /dev/null
+++ b/services/shifttool/current/systemd/AGEBD-SERVICE-SHIFTTOOL.service
@@ -0,0 +1,16 @@
+[Unit]
+Description=AGEBD-SERVICE-SHIFTTOOL
+After=network.target
+
+[Service]
+Environment=AGEBD_ENV={{ agebd_env }}
+ExecStart=/sls/bd/hla/{{ agebd_env }}/bin/start_service.sh SHIFTTOOL
+Restart=no
+
+[Install]
+WantedBy=default.target
+
+# https://www.freedesktop.org/software/systemd/man/latest/systemd.service.html
+# systemctl --user daemon-reload
+# systemctl --user enable /sls/bd/bin/systemd/AGEBD-SERVICE-SHIFTTOOL.service
+# systemctl --user start AGEBD-SERVICE-SHIFTTOOL
diff --git a/services/taubpm/current/app/uv.lock b/services/taubpm/current/app/uv.lock
index 9f28c51..226f226 100644
--- a/services/taubpm/current/app/uv.lock
+++ b/services/taubpm/current/app/uv.lock
@@ -7,11 +7,15 @@ name = "agebd"
version = "0.1.0"
source = { editable = "../../../../packages/agebd" }
dependencies = [
+ { name = "h5py" },
{ name = "typer" },
]
[package.metadata]
-requires-dist = [{ name = "typer", specifier = ">=0.23.2" }]
+requires-dist = [
+ { name = "h5py", specifier = ">=3.16.0" },
+ { name = "typer", specifier = ">=0.23.2" },
+]
[package.metadata.requires-dev]
dev = [
@@ -79,6 +83,24 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" },
]
+[[package]]
+name = "h5py"
+version = "3.16.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "numpy" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/db/33/acd0ce6863b6c0d7735007df01815403f5589a21ff8c2e1ee2587a38f548/h5py-3.16.0.tar.gz", hash = "sha256:a0dbaad796840ccaa67a4c144a0d0c8080073c34c76d5a6941d6818678ef2738", size = 446526, upload-time = "2026-03-06T13:49:08.07Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/3a/6b/231413e58a787a89b316bb0d1777da3c62257e4797e09afd8d17ad3549dc/h5py-3.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e06f864bedb2c8e7c1358e6c73af48519e317457c444d6f3d332bb4e8fa6d7d9", size = 3724137, upload-time = "2026-03-06T13:47:35.242Z" },
+ { url = "https://files.pythonhosted.org/packages/74/f9/557ce3aad0fe8471fb5279bab0fc56ea473858a022c4ce8a0b8f303d64e9/h5py-3.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ec86d4fffd87a0f4cb3d5796ceb5a50123a2a6d99b43e616e5504e66a953eca3", size = 3090112, upload-time = "2026-03-06T13:47:37.634Z" },
+ { url = "https://files.pythonhosted.org/packages/7a/f5/e15b3d0dc8a18e56409a839e6468d6fb589bc5207c917399c2e0706eeb44/h5py-3.16.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:86385ea895508220b8a7e45efa428aeafaa586bd737c7af9ee04661d8d84a10d", size = 4844847, upload-time = "2026-03-06T13:47:39.811Z" },
+ { url = "https://files.pythonhosted.org/packages/cb/92/a8851d936547efe30cc0ce5245feac01f3ec6171f7899bc3f775c72030b3/h5py-3.16.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:8975273c2c5921c25700193b408e28d6bdd0111c37468b2d4e25dcec4cd1d84d", size = 5065352, upload-time = "2026-03-06T13:47:41.489Z" },
+ { url = "https://files.pythonhosted.org/packages/2b/ae/f2adc5d0ca9626db3277a3d87516e124cbc5d0eea0bd79bc085702d04f2c/h5py-3.16.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:1677ad48b703f44efc9ea0c3ab284527f81bc4f318386aaaebc5fede6bbae56f", size = 4839173, upload-time = "2026-03-06T13:47:43.586Z" },
+ { url = "https://files.pythonhosted.org/packages/64/0b/e0c8c69da1d8838da023a50cd3080eae5d475691f7636b35eff20bb6ef20/h5py-3.16.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7c4dd4cf5f0a4e36083f73172f6cfc25a5710789269547f132a20975bfe2434c", size = 5076216, upload-time = "2026-03-06T13:47:45.315Z" },
+ { url = "https://files.pythonhosted.org/packages/66/35/d88fd6718832133c885004c61ceeeb24dbd6397ef877dbed6b3a64d6a286/h5py-3.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:bdef06507725b455fccba9c16529121a5e1fbf56aa375f7d9713d9e8ff42454d", size = 3183639, upload-time = "2026-03-06T13:47:47.041Z" },
+]
+
[[package]]
name = "iniconfig"
version = "2.3.0"
diff --git a/services/taupct/current/app/pyproject.toml b/services/taupct/current/app/pyproject.toml
new file mode 100644
index 0000000..c5e2511
--- /dev/null
+++ b/services/taupct/current/app/pyproject.toml
@@ -0,0 +1,48 @@
+[project]
+name = "agebd-taupct"
+version = "0.1.0"
+description = "AGEBD-TAUPCT Service"
+requires-python = "==3.10.*"
+dependencies = [
+ "agebd",
+ "numpy>=2.2.6",
+]
+
+[dependency-groups]
+dev = [
+ "pyepics>=3.5.8",
+ "pytest>=8.4.2",
+ "ruff>=0.15.20",
+]
+
+[tool.uv.sources]
+# Path is relative to where agebd package is deployed on hla
+# machines (see CI/CD in .gitea/workflows)
+agebd = { path = "../../../../packages/agebd", editable = true }
+
+[build-system]
+requires = ["hatchling"]
+build-backend = "hatchling.build"
+
+[tool.uv]
+package = true
+
+[tool.pytest.ini_options]
+pythonpath = ["src"]
+env = [
+ "AGEBD_ENV=local",
+]
+
+[tool.ruff]
+include = [
+ "src/**/*.py",
+ "tests/**/*.py",
+]
+line-length = 100
+
+[tool.ruff.lint]
+# use isort to sort imports
+extend-select = ["I"]
+
+[tool.ruff.lint.isort]
+known-first-party = ["agebd"]
diff --git a/services/taupct/current/app/src/agebd_taupct/__init__.py b/services/taupct/current/app/src/agebd_taupct/__init__.py
new file mode 100644
index 0000000..1800c27
--- /dev/null
+++ b/services/taupct/current/app/src/agebd_taupct/__init__.py
@@ -0,0 +1 @@
+from .service import PVs, Service
diff --git a/services/taupct/current/app/src/agebd_taupct/main.py b/services/taupct/current/app/src/agebd_taupct/main.py
new file mode 100644
index 0000000..4559f96
--- /dev/null
+++ b/services/taupct/current/app/src/agebd_taupct/main.py
@@ -0,0 +1,31 @@
+import typer
+
+from agebd.enums import LogLevel
+from agebd.runner import CallbackRunner
+from agebd.utils import init_logging
+from agebd_taupct import PVs, Service
+
+# TODO: remove: cicd test 10
+
+
+def main(
+ log_level: LogLevel = typer.Option(
+ LogLevel.INFO,
+ "--log-level",
+ "-l",
+ # Looks at the OS env variable first. If empty, falls back to "INFO"
+ envvar="AGEBD_LOG_LEVEL",
+ # help="Set log level: DEBUG, INFO, WARNING, ERROR, CRITICAL",
+ case_sensitive=False,
+ ),
+):
+ init_logging(log_level)
+ service_name = "TAUPCT"
+ pvs = PVs(service_name=service_name)
+ service = Service(name=service_name, pvs=pvs)
+ runner = CallbackRunner(service=service)
+ runner.start()
+
+
+if __name__ == "__main__":
+ typer.run(main)
diff --git a/services/taupct/current/app/src/agebd_taupct/service.py b/services/taupct/current/app/src/agebd_taupct/service.py
new file mode 100644
index 0000000..ec2f515
--- /dev/null
+++ b/services/taupct/current/app/src/agebd_taupct/service.py
@@ -0,0 +1,172 @@
+from time import sleep
+
+import numpy as np
+from epics import dbr
+
+from agebd.pv import get_pv_class
+from agebd.service.base import BaseService
+from agebd.service.pvs import BasePVs
+from agebd.utils import printgetversion
+
+__version__ = printgetversion(__file__)
+
+PV = get_pv_class()
+
+
+class PVs(BasePVs):
+ ## Service specific PVs from dedicated IOC
+ NsamplesTAU = PV("AGEBD-TAUPCT:CONTROL-NSAMPLES-FIT-TAU.VAL")
+ NsamplesROC = PV("AGEBD-TAUPCT:CONTROL-NSAMPLES-FIT-ROC.VAL")
+ MinCurr = PV("AGEBD-TAUPCT:CONTROL-MIN-CURR.VAL")
+
+ # Output PVs
+ inj_tau = PV("AGEBD-TAUPCT:TAU.VAL")
+ inj_tau_err = PV("AGEBD-TAUPCT:TAU-ERR.VAL")
+ inj_rate = PV("AGEBD-TAUPCT:INJRATE.VAL")
+ inj_rate_err = PV("AGEBD-TAUPCT:INJRATE-ERR.VAL")
+
+ ## Service specific PVs from other IOCs
+ inj_active = PV("AGEBD-PARAMS:INJECTION-ACTIVE.VAL")
+ dump_valve = PV("ARS01-VVPG-0210:PLC_STATUS.VAL")
+
+ def __init__(self, service_name: str, pv_factory=PV):
+ super().__init__(service_name, pv_factory)
+ PV = pv_factory
+
+ self.CallbackPV = PV("ARS07-CECL-DPCT0:CURR.VAL", auto_monitor=dbr.DBE_VALUE)
+ # CallbackPV = PV('ARS07-DPCT-0000:AVG-CURR.VAL', auto_monitor = dbr.DBE_VALUE)
+ # ARS07-DPCT-0000:CURR (5 Hz, i.e., dt = 0.2 s)
+ # ARS07-DPCT-0000:AVG-CURR (5 Hz, i.e., dt = 0.2 s)
+
+
+class Service(BaseService[PVs]):
+ def __init__(
+ self,
+ name: str,
+ pvs: PVs,
+ version: str = __version__,
+ sleep_interval: float = 0.1,
+ ):
+ super().__init__(name, pvs, version, sleep_interval)
+
+ self.reset()
+
+ def reset(self):
+ pvs = self.pvs
+
+ self.IterSinceReset = 0
+ self.NsamplesTAU = int(pvs.NsamplesTAU.get())
+ self.NsamplesROC = int(pvs.NsamplesROC.get())
+ NsamplesMAX = int(np.nanmax([self.NsamplesTAU, self.NsamplesROC]))
+ self.MinCurr = pvs.MinCurr.get()
+ self.t = np.empty(NsamplesMAX)
+ self.I = np.empty(NsamplesMAX)
+ self.inj_active = pvs.inj_active.get()
+
+ def update(self):
+ pvs = self.pvs
+
+ # when callback is fired, this code will be executed
+ if self.CallbackFired:
+ #######################################################################################
+ #######################################################################################
+ # here goes all the code that your service
+ # is supposed to be running when the callback is fired
+
+ conditions_cb_invalid = (
+ not self.inj_active == pvs.inj_active.get() # <-- injection status changed
+ or self.CallbackValue < self.MinCurr # <-- stored beam
+ or not 0 <= self.CallbackValue <= 500 # <-- measurement realistic
+ )
+
+ # set values to zero and wait without beam
+ if not pvs.dump_valve.get() == 1:
+ pvs.inj_tau.put(np.nan)
+ pvs.inj_tau_err.put(0.0)
+ pvs.inj_rate.put(0.0)
+ pvs.inj_rate_err.put(0.0)
+ sleep(0.5)
+
+ elif conditions_cb_invalid:
+ self.reset()
+ print("Callback Invalid --> Reset ({:})".format(self.CallbackTimestamp))
+
+ else:
+ self.t[:-1] = self.t[1:]
+ self.I[:-1] = self.I[1:]
+ self.t[-1] = self.CallbackTimestamp
+ self.I[-1] = self.CallbackValue
+
+ self.IterSinceReset += 1
+
+ if (
+ self.IterSinceReset > self.NsamplesROC
+ and self.IterSinceReset > self.NsamplesTAU
+ ):
+ t = self.t - self.t[0]
+
+ p, pcov = np.polyfit(t, self.I, 1, cov=True)
+ perr = np.sqrt(np.diag(pcov))
+
+ injrate = p[0] * 60
+ injrate_err = perr[0] * 60
+
+ pvs.inj_rate.put(injrate)
+ pvs.inj_rate_err.put(injrate_err)
+
+ # injection rate in mA/hour to minimize risk of log(x) with x < 0:
+ injrate = injrate * 60
+ injrate_err = injrate_err * 60
+
+ # if injrate/p[1] < 1:
+ if not self.inj_active and self.IterSinceReset > self.NsamplesTAU:
+ tau = 1 / np.log(1 - injrate / p[1]) # (-dt in hours) / ln(1 - dI/I0)
+ tau_err = injrate_err * (-1) / (
+ (injrate - p[1]) * np.log(1 - injrate / p[1]) ** 2
+ ) + perr[1] * (injrate_err) / (
+ p[1] * (injrate - p[1]) * np.log(1 - injrate / p[1]) ** 2
+ )
+
+ pvs.inj_tau.put(tau)
+ pvs.inj_tau_err.put(tau_err)
+
+ elif self.IterSinceReset > self.NsamplesROC:
+ t = self.t[-self.NsamplesROC :]
+ I = self.I[-self.NsamplesROC :]
+
+ t = t - t[0]
+
+ p, pcov = np.polyfit(t, I, 1, cov=True)
+ perr = np.sqrt(np.diag(pcov))
+
+ injrate = p[0] * 60
+ injrate_err = perr[0] * 60
+
+ pvs.inj_rate.put(injrate)
+ pvs.inj_rate_err.put(injrate_err)
+
+ # injection rate in mA/hour to minimize risk of log(x) with x < 0:
+ injrate = injrate * 60
+ injrate_err = injrate_err * 60
+ #######################################################################################
+ #######################################################################################
+
+ # callback done
+ self.CallbackFired = 0
+
+ #######################################################################################
+ #######################################################################################
+ # here goes all the code that your service
+ # is supposed to be running in any case, e.g.,
+ # update some pvs/vals
+ conditions_reset = (
+ not self.NsamplesROC == pvs.NsamplesROC.get()
+ or not self.NsamplesTAU == pvs.NsamplesTAU.get()
+ or not self.MinCurr == pvs.MinCurr.get()
+ )
+ if conditions_reset:
+ self.reset()
+ # maybe sleep to limit the update loop execution rate
+ # sleep(1)
+ #######################################################################################
+ #######################################################################################
diff --git a/services/taupct/current/app/tests/test_app.py b/services/taupct/current/app/tests/test_app.py
new file mode 100644
index 0000000..a8bf6c4
--- /dev/null
+++ b/services/taupct/current/app/tests/test_app.py
@@ -0,0 +1,9 @@
+from agebd_taupct import PVs, Service
+
+
+def test_app():
+ service_name = "DUMMY"
+ pvs = PVs(service_name=service_name)
+ service = Service(name=service_name, pvs=pvs)
+ service.CallbackFired = 1
+ service.update()
diff --git a/services/taupct/current/app/uv.lock b/services/taupct/current/app/uv.lock
new file mode 100644
index 0000000..cc8aea1
--- /dev/null
+++ b/services/taupct/current/app/uv.lock
@@ -0,0 +1,301 @@
+version = 1
+revision = 3
+requires-python = "==3.10.*"
+
+[[package]]
+name = "agebd"
+version = "0.1.0"
+source = { editable = "../../../../packages/agebd" }
+dependencies = [
+ { name = "h5py" },
+ { name = "typer" },
+]
+
+[package.metadata]
+requires-dist = [
+ { name = "h5py", specifier = ">=3.16.0" },
+ { name = "typer", specifier = ">=0.23.2" },
+]
+
+[package.metadata.requires-dev]
+dev = [
+ { name = "pyright", specifier = ">=1.1.410" },
+ { name = "pytest", specifier = ">=8.4.2" },
+ { name = "ruff", specifier = ">=0.15.19" },
+]
+
+[[package]]
+name = "agebd-taupct"
+version = "0.1.0"
+source = { editable = "." }
+dependencies = [
+ { name = "agebd" },
+ { name = "numpy" },
+]
+
+[package.dev-dependencies]
+dev = [
+ { name = "pyepics" },
+ { name = "pytest" },
+ { name = "ruff" },
+]
+
+[package.metadata]
+requires-dist = [
+ { name = "agebd", editable = "../../../../packages/agebd" },
+ { name = "numpy", specifier = ">=2.2.6" },
+]
+
+[package.metadata.requires-dev]
+dev = [
+ { name = "pyepics", specifier = ">=3.5.8" },
+ { name = "pytest", specifier = ">=8.4.2" },
+ { name = "ruff", specifier = ">=0.15.20" },
+]
+
+[[package]]
+name = "annotated-doc"
+version = "0.0.4"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/57/ba/046ceea27344560984e26a590f90bc7f4a75b06701f653222458922b558c/annotated_doc-0.0.4.tar.gz", hash = "sha256:fbcda96e87e9c92ad167c2e53839e57503ecfda18804ea28102353485033faa4", size = 7288, upload-time = "2025-11-10T22:07:42.062Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl", hash = "sha256:571ac1dc6991c450b25a9c2d84a3705e2ae7a53467b5d111c24fa8baabbed320", size = 5303, upload-time = "2025-11-10T22:07:40.673Z" },
+]
+
+[[package]]
+name = "colorama"
+version = "0.4.6"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" },
+]
+
+[[package]]
+name = "exceptiongroup"
+version = "1.3.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "typing-extensions" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" },
+]
+
+[[package]]
+name = "h5py"
+version = "3.16.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "numpy" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/db/33/acd0ce6863b6c0d7735007df01815403f5589a21ff8c2e1ee2587a38f548/h5py-3.16.0.tar.gz", hash = "sha256:a0dbaad796840ccaa67a4c144a0d0c8080073c34c76d5a6941d6818678ef2738", size = 446526, upload-time = "2026-03-06T13:49:08.07Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/3a/6b/231413e58a787a89b316bb0d1777da3c62257e4797e09afd8d17ad3549dc/h5py-3.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e06f864bedb2c8e7c1358e6c73af48519e317457c444d6f3d332bb4e8fa6d7d9", size = 3724137, upload-time = "2026-03-06T13:47:35.242Z" },
+ { url = "https://files.pythonhosted.org/packages/74/f9/557ce3aad0fe8471fb5279bab0fc56ea473858a022c4ce8a0b8f303d64e9/h5py-3.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ec86d4fffd87a0f4cb3d5796ceb5a50123a2a6d99b43e616e5504e66a953eca3", size = 3090112, upload-time = "2026-03-06T13:47:37.634Z" },
+ { url = "https://files.pythonhosted.org/packages/7a/f5/e15b3d0dc8a18e56409a839e6468d6fb589bc5207c917399c2e0706eeb44/h5py-3.16.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:86385ea895508220b8a7e45efa428aeafaa586bd737c7af9ee04661d8d84a10d", size = 4844847, upload-time = "2026-03-06T13:47:39.811Z" },
+ { url = "https://files.pythonhosted.org/packages/cb/92/a8851d936547efe30cc0ce5245feac01f3ec6171f7899bc3f775c72030b3/h5py-3.16.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:8975273c2c5921c25700193b408e28d6bdd0111c37468b2d4e25dcec4cd1d84d", size = 5065352, upload-time = "2026-03-06T13:47:41.489Z" },
+ { url = "https://files.pythonhosted.org/packages/2b/ae/f2adc5d0ca9626db3277a3d87516e124cbc5d0eea0bd79bc085702d04f2c/h5py-3.16.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:1677ad48b703f44efc9ea0c3ab284527f81bc4f318386aaaebc5fede6bbae56f", size = 4839173, upload-time = "2026-03-06T13:47:43.586Z" },
+ { url = "https://files.pythonhosted.org/packages/64/0b/e0c8c69da1d8838da023a50cd3080eae5d475691f7636b35eff20bb6ef20/h5py-3.16.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7c4dd4cf5f0a4e36083f73172f6cfc25a5710789269547f132a20975bfe2434c", size = 5076216, upload-time = "2026-03-06T13:47:45.315Z" },
+ { url = "https://files.pythonhosted.org/packages/66/35/d88fd6718832133c885004c61ceeeb24dbd6397ef877dbed6b3a64d6a286/h5py-3.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:bdef06507725b455fccba9c16529121a5e1fbf56aa375f7d9713d9e8ff42454d", size = 3183639, upload-time = "2026-03-06T13:47:47.041Z" },
+]
+
+[[package]]
+name = "iniconfig"
+version = "2.3.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" },
+]
+
+[[package]]
+name = "markdown-it-py"
+version = "4.2.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "mdurl" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/06/ff/7841249c247aa650a76b9ee4bbaeae59370dc8bfd2f6c01f3630c35eb134/markdown_it_py-4.2.0.tar.gz", hash = "sha256:04a21681d6fbb623de53f6f364d352309d4094dd4194040a10fd51833e418d49", size = 82454, upload-time = "2026-05-07T12:08:28.36Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl", hash = "sha256:9f7ebbcd14fe59494226453aed97c1070d83f8d24b6fc3a3bcf9a38092641c4a", size = 91687, upload-time = "2026-05-07T12:08:27.182Z" },
+]
+
+[[package]]
+name = "mdurl"
+version = "0.1.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" },
+]
+
+[[package]]
+name = "numpy"
+version = "2.2.6"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/76/21/7d2a95e4bba9dc13d043ee156a356c0a8f0c6309dff6b21b4d71a073b8a8/numpy-2.2.6.tar.gz", hash = "sha256:e29554e2bef54a90aa5cc07da6ce955accb83f21ab5de01a62c8478897b264fd", size = 20276440, upload-time = "2025-05-17T22:38:04.611Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/9a/3e/ed6db5be21ce87955c0cbd3009f2803f59fa08df21b5df06862e2d8e2bdd/numpy-2.2.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b412caa66f72040e6d268491a59f2c43bf03eb6c96dd8f0307829feb7fa2b6fb", size = 21165245, upload-time = "2025-05-17T21:27:58.555Z" },
+ { url = "https://files.pythonhosted.org/packages/22/c2/4b9221495b2a132cc9d2eb862e21d42a009f5a60e45fc44b00118c174bff/numpy-2.2.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e41fd67c52b86603a91c1a505ebaef50b3314de0213461c7a6e99c9a3beff90", size = 14360048, upload-time = "2025-05-17T21:28:21.406Z" },
+ { url = "https://files.pythonhosted.org/packages/fd/77/dc2fcfc66943c6410e2bf598062f5959372735ffda175b39906d54f02349/numpy-2.2.6-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:37e990a01ae6ec7fe7fa1c26c55ecb672dd98b19c3d0e1d1f326fa13cb38d163", size = 5340542, upload-time = "2025-05-17T21:28:30.931Z" },
+ { url = "https://files.pythonhosted.org/packages/7a/4f/1cb5fdc353a5f5cc7feb692db9b8ec2c3d6405453f982435efc52561df58/numpy-2.2.6-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:5a6429d4be8ca66d889b7cf70f536a397dc45ba6faeb5f8c5427935d9592e9cf", size = 6878301, upload-time = "2025-05-17T21:28:41.613Z" },
+ { url = "https://files.pythonhosted.org/packages/eb/17/96a3acd228cec142fcb8723bd3cc39c2a474f7dcf0a5d16731980bcafa95/numpy-2.2.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:efd28d4e9cd7d7a8d39074a4d44c63eda73401580c5c76acda2ce969e0a38e83", size = 14297320, upload-time = "2025-05-17T21:29:02.78Z" },
+ { url = "https://files.pythonhosted.org/packages/b4/63/3de6a34ad7ad6646ac7d2f55ebc6ad439dbbf9c4370017c50cf403fb19b5/numpy-2.2.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc7b73d02efb0e18c000e9ad8b83480dfcd5dfd11065997ed4c6747470ae8915", size = 16801050, upload-time = "2025-05-17T21:29:27.675Z" },
+ { url = "https://files.pythonhosted.org/packages/07/b6/89d837eddef52b3d0cec5c6ba0456c1bf1b9ef6a6672fc2b7873c3ec4e2e/numpy-2.2.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:74d4531beb257d2c3f4b261bfb0fc09e0f9ebb8842d82a7b4209415896adc680", size = 15807034, upload-time = "2025-05-17T21:29:51.102Z" },
+ { url = "https://files.pythonhosted.org/packages/01/c8/dc6ae86e3c61cfec1f178e5c9f7858584049b6093f843bca541f94120920/numpy-2.2.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8fc377d995680230e83241d8a96def29f204b5782f371c532579b4f20607a289", size = 18614185, upload-time = "2025-05-17T21:30:18.703Z" },
+ { url = "https://files.pythonhosted.org/packages/5b/c5/0064b1b7e7c89137b471ccec1fd2282fceaae0ab3a9550f2568782d80357/numpy-2.2.6-cp310-cp310-win32.whl", hash = "sha256:b093dd74e50a8cba3e873868d9e93a85b78e0daf2e98c6797566ad8044e8363d", size = 6527149, upload-time = "2025-05-17T21:30:29.788Z" },
+ { url = "https://files.pythonhosted.org/packages/a3/dd/4b822569d6b96c39d1215dbae0582fd99954dcbcf0c1a13c61783feaca3f/numpy-2.2.6-cp310-cp310-win_amd64.whl", hash = "sha256:f0fd6321b839904e15c46e0d257fdd101dd7f530fe03fd6359c1ea63738703f3", size = 12904620, upload-time = "2025-05-17T21:30:48.994Z" },
+ { url = "https://files.pythonhosted.org/packages/9e/3b/d94a75f4dbf1ef5d321523ecac21ef23a3cd2ac8b78ae2aac40873590229/numpy-2.2.6-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0b605b275d7bd0c640cad4e5d30fa701a8d59302e127e5f79138ad62762c3e3d", size = 21040391, upload-time = "2025-05-17T21:44:35.948Z" },
+ { url = "https://files.pythonhosted.org/packages/17/f4/09b2fa1b58f0fb4f7c7963a1649c64c4d315752240377ed74d9cd878f7b5/numpy-2.2.6-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:7befc596a7dc9da8a337f79802ee8adb30a552a94f792b9c9d18c840055907db", size = 6786754, upload-time = "2025-05-17T21:44:47.446Z" },
+ { url = "https://files.pythonhosted.org/packages/af/30/feba75f143bdc868a1cc3f44ccfa6c4b9ec522b36458e738cd00f67b573f/numpy-2.2.6-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce47521a4754c8f4593837384bd3424880629f718d87c5d44f8ed763edd63543", size = 16643476, upload-time = "2025-05-17T21:45:11.871Z" },
+ { url = "https://files.pythonhosted.org/packages/37/48/ac2a9584402fb6c0cd5b5d1a91dcf176b15760130dd386bbafdbfe3640bf/numpy-2.2.6-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d042d24c90c41b54fd506da306759e06e568864df8ec17ccc17e9e884634fd00", size = 12812666, upload-time = "2025-05-17T21:45:31.426Z" },
+]
+
+[[package]]
+name = "packaging"
+version = "26.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d7/f1/e7a6dd94a8d4a5626c03e4e99c87f241ba9e350cd9e6d75123f992427270/packaging-26.2.tar.gz", hash = "sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661", size = 228134, upload-time = "2026-04-24T20:15:23.917Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/df/b2/87e62e8c3e2f4b32e5fe99e0b86d576da1312593b39f47d8ceef365e95ed/packaging-26.2-py3-none-any.whl", hash = "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e", size = 100195, upload-time = "2026-04-24T20:15:22.081Z" },
+]
+
+[[package]]
+name = "pluggy"
+version = "1.6.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" },
+]
+
+[[package]]
+name = "pyepics"
+version = "3.5.10"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "numpy" },
+ { name = "pyparsing" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/69/57/29e1e9ef11ba2a3419f489946ae1d8190025a1e4f4e1c1686758bb2b6e0a/pyepics-3.5.10.tar.gz", hash = "sha256:f390cf9be40aba757b9528888114bc14d8db01086d0c93914720b1772460375b", size = 6150481, upload-time = "2026-05-20T18:44:36.336Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d6/36/e517fd83bd97d6bfe4105e0c6b322070c5cc36fb56a8fab2866e319f8804/pyepics-3.5.10-py3-none-any.whl", hash = "sha256:c9fac2c54f2b595268e66fc348cf5ec24e63718e7dbd07d73d1b37d4da6bfee1", size = 5332376, upload-time = "2026-05-20T18:44:34.242Z" },
+]
+
+[[package]]
+name = "pygments"
+version = "2.20.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" },
+]
+
+[[package]]
+name = "pyparsing"
+version = "3.3.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f3/91/9c6ee907786a473bf81c5f53cf703ba0957b23ab84c264080fb5a450416f/pyparsing-3.3.2.tar.gz", hash = "sha256:c777f4d763f140633dcb6d8a3eda953bf7a214dc4eff598413c070bcdc117cbc", size = 6851574, upload-time = "2026-01-21T03:57:59.36Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl", hash = "sha256:850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d", size = 122781, upload-time = "2026-01-21T03:57:55.912Z" },
+]
+
+[[package]]
+name = "pytest"
+version = "9.1.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "colorama", marker = "sys_platform == 'win32'" },
+ { name = "exceptiongroup" },
+ { name = "iniconfig" },
+ { name = "packaging" },
+ { name = "pluggy" },
+ { name = "pygments" },
+ { name = "tomli" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/e4/47/b9efed96c114afcfa3c9d3fe98a76a1d14c74a9e266d397cf6eb64be5e01/pytest-9.1.1.tar.gz", hash = "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313", size = 1636369, upload-time = "2026-06-19T10:58:32.857Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/24/25/1de2678b631f5a49215c6c96fff41ba892b0a34df68d6d80292b1b48aa7f/pytest-9.1.1-py3-none-any.whl", hash = "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c", size = 386536, upload-time = "2026-06-19T10:58:31.347Z" },
+]
+
+[[package]]
+name = "rich"
+version = "15.0.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "markdown-it-py" },
+ { name = "pygments" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/c0/8f/0722ca900cc807c13a6a0c696dacf35430f72e0ec571c4275d2371fca3e9/rich-15.0.0.tar.gz", hash = "sha256:edd07a4824c6b40189fb7ac9bc4c52536e9780fbbfbddf6f1e2502c31b068c36", size = 230680, upload-time = "2026-04-12T08:24:00.75Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl", hash = "sha256:33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb", size = 310654, upload-time = "2026-04-12T08:24:02.83Z" },
+]
+
+[[package]]
+name = "ruff"
+version = "0.15.21"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/0f/36/6f65aa9989acdec45d417192d8f4e7921931d8a6cf87ac74bce3eed98a8e/ruff-0.15.21.tar.gz", hash = "sha256:d0cfc841c572283c36548f82664a54ce6565567f1b0d5b4cf2caac693d8b7500", size = 4769401, upload-time = "2026-07-09T20:01:34.005Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d0/c6/ede15cac6839f3dbce52565c8f5164a8210e669c7bc4decb03e5bdf47d0d/ruff-0.15.21-py3-none-linux_armv6l.whl", hash = "sha256:63ea0e965e5d73c90e95b2434beeafc70820536717f561b32ab6e777cb9bdf5d", size = 10854342, upload-time = "2026-07-09T20:00:53.998Z" },
+ { url = "https://files.pythonhosted.org/packages/28/9d/d825b07ee7ea9e2d61df92a860033c94e06e7300d50a1c2653aac27d24fe/ruff-0.15.21-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:0f212c5d7d54c01bbfe6dcab02b724a39300f3e34ed7acbe995ccb320a2c58bd", size = 11139539, upload-time = "2026-07-09T20:00:57.809Z" },
+ { url = "https://files.pythonhosted.org/packages/f5/de/3b107712e642f063c7a9e0887c427b22cb44097de5aab36c05f2e280670c/ruff-0.15.21-py3-none-macosx_11_0_arm64.whl", hash = "sha256:e6312e41bc96791299614995ea3a977c5857c3b5662b1ecef6755b02b87cb646", size = 10595437, upload-time = "2026-07-09T20:01:00.006Z" },
+ { url = "https://files.pythonhosted.org/packages/9a/6f/b4523cc90ba239ede441447a19d0c968846a3012e5a0b0c5b62831a3d5e3/ruff-0.15.21-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01d65b4831c6b2a4ba8ee6faa84049d44d982b7a706e622c4094c509e51673be", size = 10990053, upload-time = "2026-07-09T20:01:02.187Z" },
+ { url = "https://files.pythonhosted.org/packages/92/cc/c6a9872a5375f0628875481cf2f66b13d7d865bf3ca2e57f91c7e762d976/ruff-0.15.21-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2c5a913a589120ce67933d5d05fd6ddbcc2481c6a054980ee767f7414c72b4fd", size = 10666096, upload-time = "2026-07-09T20:01:04.299Z" },
+ { url = "https://files.pythonhosted.org/packages/ab/97/c621f7a17e097f1790fa3af6374138823b330b2d03fc38337945daca212c/ruff-0.15.21-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ef04b681d02ad4dc9620f00f83ac5c22f652d0e9a9cfe431d219b16ad5ccc41", size = 11537011, upload-time = "2026-07-09T20:01:06.771Z" },
+ { url = "https://files.pythonhosted.org/packages/ea/51/d928727e476e25ccc57c6f449ffd80241a651a973ad949d39cfb2a771d28/ruff-0.15.21-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:16d090c0740916594157e75b80d666eab8e78083b39b3b0e1d698f4670a17b86", size = 12347101, upload-time = "2026-07-09T20:01:08.859Z" },
+ { url = "https://files.pythonhosted.org/packages/1e/88/8cd62026802b16018ad06931d87997cf795ba2a6239ab659606c87d96bf0/ruff-0.15.21-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3a10e74757dd65004d779b73e2f3c5210156d9980b41224d50d2ebcf1db51e67", size = 11572001, upload-time = "2026-07-09T20:01:11.092Z" },
+ { url = "https://files.pythonhosted.org/packages/b2/97/f63084cf55444fc110e8cb985ebfcc592af47f597d44453d778cb81bc156/ruff-0.15.21-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bab0905d2f29e0d9fbc3c373ed23db0095edaa3f71f1f4f519ec15134d9e85c8", size = 11549239, upload-time = "2026-07-09T20:01:13.27Z" },
+ { url = "https://files.pythonhosted.org/packages/9d/77/f107da4a2874b7715914b03f09ba9c54424de3ff8a1cc5d015d3ee2ce0ac/ruff-0.15.21-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:00eca240af5789fec6fe7df74c088cc1f9644ed83027113468efba7c92b94075", size = 11535340, upload-time = "2026-07-09T20:01:15.206Z" },
+ { url = "https://files.pythonhosted.org/packages/d5/e9/601deb322d3303a7bf212b0100ead6f2ee3f6a044d89c30f2f92bf83c731/ruff-0.15.21-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:262ab31557a75141325e32d3357f3597645a7f084e732b6b054dde428ecd9341", size = 10964048, upload-time = "2026-07-09T20:01:17.723Z" },
+ { url = "https://files.pythonhosted.org/packages/ea/2e/0f2176d1e99c15192caea19c8c3a0a955246b4cb4de795042eeb616345cd/ruff-0.15.21-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:659c4e7a4212f83306045ec7c5e5a356d16d9a6ef4ae0c7a4d872914fc655d9d", size = 10667055, upload-time = "2026-07-09T20:01:19.73Z" },
+ { url = "https://files.pythonhosted.org/packages/48/60/abd74a02e0c4214f12a68becfd30af7165cfdcb0e661ecdc60bbb949c09a/ruff-0.15.21-py3-none-musllinux_1_2_i686.whl", hash = "sha256:9e866eab611a5f959d36df2d10e446973a3610bc42b0c15b31dc27977d59c233", size = 11242043, upload-time = "2026-07-09T20:01:21.947Z" },
+ { url = "https://files.pythonhosted.org/packages/b2/c6/583075d8ccabb4b229345edcaf1545eb3d8d6be90f686a479d7e94088bbf/ruff-0.15.21-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e89bc93c0d3803ba870b55c29671bad9dc6d94bb1eb181b056b52eb05b52854f", size = 11648064, upload-time = "2026-07-09T20:01:24.023Z" },
+ { url = "https://files.pythonhosted.org/packages/3a/3c/37d0ecb729a7cc2d393ea7dce316fc585680f35d93b8d62139d7d0a3700c/ruff-0.15.21-py3-none-win32.whl", hash = "sha256:01f8d5be84823c172b389e123174f781f9daf86d6c58719d603f941932195cdd", size = 10896555, upload-time = "2026-07-09T20:01:26.941Z" },
+ { url = "https://files.pythonhosted.org/packages/c0/b8/e43466b2a6067ce91e669068f6e28d6c719a920f014b070d5c8731725de3/ruff-0.15.21-py3-none-win_amd64.whl", hash = "sha256:d4b8d9a2f0f12b816b50447f6eccb9f4bb01a6b82c86b50fb3b5354b458dc6d3", size = 12038772, upload-time = "2026-07-09T20:01:29.497Z" },
+ { url = "https://files.pythonhosted.org/packages/dd/75/e90ab9aeece218a9fc5a5bc3ec97d0ee6bb3c4ff95869463c1de58e29a1c/ruff-0.15.21-py3-none-win_arm64.whl", hash = "sha256:6e83115d4b9377c1cbc13abf0e051f069fab0ef815ea0504a8a008cee24dd0a8", size = 11375265, upload-time = "2026-07-09T20:01:31.772Z" },
+]
+
+[[package]]
+name = "shellingham"
+version = "1.5.4"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/58/15/8b3609fd3830ef7b27b655beb4b4e9c62313a4e8da8c676e142cc210d58e/shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de", size = 10310, upload-time = "2023-10-24T04:13:40.426Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755, upload-time = "2023-10-24T04:13:38.866Z" },
+]
+
+[[package]]
+name = "tomli"
+version = "2.4.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/22/de/48c59722572767841493b26183a0d1cc411d54fd759c5607c4590b6563a6/tomli-2.4.1.tar.gz", hash = "sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f", size = 17543, upload-time = "2026-03-25T20:22:03.828Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/7b/61/cceae43728b7de99d9b847560c262873a1f6c98202171fd5ed62640b494b/tomli-2.4.1-py3-none-any.whl", hash = "sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe", size = 14583, upload-time = "2026-03-25T20:22:03.012Z" },
+]
+
+[[package]]
+name = "typer"
+version = "0.27.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "annotated-doc" },
+ { name = "colorama", marker = "sys_platform == 'win32'" },
+ { name = "rich" },
+ { name = "shellingham" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/37/78/fda3361b56efc27944f24225f6ecd13d96d6fcfe37bd0eb34e2f4c63f9fc/typer-0.27.0.tar.gz", hash = "sha256:629bd12ea5d13a17148125d9a264f949eb171fb3f120f9b04d85873cab054fa5", size = 203430, upload-time = "2026-07-15T19:21:07.007Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/40/03/26a383c9e58c213199d1aad1c3d353cfc22d4444ec6d2c0bf8ad02523843/typer-0.27.0-py3-none-any.whl", hash = "sha256:6f4b27631e47f077871b7dc30e933ec0131c1390fbe0e387ea5574b5bac9ccf1", size = 122716, upload-time = "2026-07-15T19:21:05.553Z" },
+]
+
+[[package]]
+name = "typing-extensions"
+version = "4.16.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f6/cc/6253133b5bb138fc3306cebfbda2c520f545d36b5be2c7255cc528bb45d6/typing_extensions-4.16.0.tar.gz", hash = "sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5", size = 113555, upload-time = "2026-07-02T08:40:05.92Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/49/d3/b8441a820a491ddfc024b0b0cf0393375b75ea13866d9c66727e54c2fc80/typing_extensions-4.16.0-py3-none-any.whl", hash = "sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8", size = 45571, upload-time = "2026-07-02T08:40:04.659Z" },
+]
diff --git a/services/taupct/current/ioc/AGEBD-CPCL-TAUPCT_main.subs b/services/taupct/current/ioc/AGEBD-CPCL-TAUPCT_main.subs
new file mode 100644
index 0000000..ab45b7c
--- /dev/null
+++ b/services/taupct/current/ioc/AGEBD-CPCL-TAUPCT_main.subs
@@ -0,0 +1,4 @@
+file TAUPCT.template {
+ pattern { DEVICE }
+ { AGEBD-TAUPCT{{ agebd_env }} }
+}
diff --git a/services/taupct/current/ioc/AGEBD-CPCL-TAUPCT_parameters.yaml b/services/taupct/current/ioc/AGEBD-CPCL-TAUPCT_parameters.yaml
new file mode 100644
index 0000000..ff8e70f
--- /dev/null
+++ b/services/taupct/current/ioc/AGEBD-CPCL-TAUPCT_parameters.yaml
@@ -0,0 +1,6 @@
+cpu_architecture: x86_64
+epics_version: 7.0.8
+ioc_host: sls-vserv-bd-01{{ agebd_env }}
+ioc_port: {{ ioc_port }}
+os: RHEL8
+os_id: rhel
diff --git a/services/taupct/current/ioc/TAUPCT.template b/services/taupct/current/ioc/TAUPCT.template
new file mode 100644
index 0000000..e984743
--- /dev/null
+++ b/services/taupct/current/ioc/TAUPCT.template
@@ -0,0 +1,70 @@
+record(ao, "$(DEVICE):CONTROL-NSAMPLES-FIT-TAU") {
+ field(DESC, "Nr. of charge points for TAU fit")
+ field(VAL, "60")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-NSAMPLES-FIT-ROC") {
+ field(DESC, "Nr. of charge points for ROC fit")
+ field(VAL, "5")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-MIN-CURR") {
+ field(DESC, "Minimum current")
+ field(VAL, "0.1")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):TAU") {
+ field(DESC, "PCT injection rate")
+ field(PREC, "3")
+ field(EGU, "hours")
+}
+
+record(ao, "$(DEVICE):TAU-ERR") {
+ field(DESC, "PCT injection rate error")
+ field(PREC, "3")
+ field(EGU, "hours")
+}
+
+record(ao, "$(DEVICE):INJRATE") {
+ field(DESC, "PCT injection rate")
+ field(PREC, "3")
+ field(EGU, "mA/min")
+ field(FLNK, "$(DEVICE):INJRATE-nC")
+}
+
+record(ao, "$(DEVICE):INJRATE-ERR") {
+ field(DESC, "PCT injection rate error")
+ field(PREC, "3")
+ field(EGU, "mA/min")
+ field(FLNK, "$(DEVICE):INJRATE-ERR-nC")
+}
+
+record(calc, "$(DEVICE):INJRATE-nC") {
+ field(DESC, "Rate der Akkumulation im Speicherring")
+ field(ASG, "READONLY")
+ field(PREC, "3")
+ field(EGU, "nC/shot")
+ field(CALC, "A / 60 / 3.125 * 0.96")
+ field(INPA, "$(DEVICE):INJRATE")
+}
+
+record(calc, "$(DEVICE):INJRATE-ERR-nC") {
+ field(DESC, "Fehler der Injektionsrate Speicherring")
+ field(ASG, "READONLY")
+ field(PREC, "3")
+ field(EGU, "nC/shot")
+ field(CALC, "A / 60 / 3.125 * 0.96")
+ field(INPA, "$(DEVICE):INJRATE-ERR")
+}
+
+record(calc, "$(DEVICE):LOSSRATIO") {
+ field(DESC, "Lossratio now to nominal 400 mA, 10 h")
+ field(ASG, "READONLY")
+ field(PREC, "3")
+ field(CALC, "(I / B) / 50") # = (strom / e / tau) / (400 / e / 10)
+ field(INPB, "$(DEVICE):TAU CP")
+ field(INPI, "ARS07-DPCT-0000:CURR")
+}
\ No newline at end of file
diff --git a/services/taupct/current/ioc/startup.script b/services/taupct/current/ioc/startup.script
new file mode 100644
index 0000000..0fa52ff
--- /dev/null
+++ b/services/taupct/current/ioc/startup.script
@@ -0,0 +1 @@
+epicsEnvSet("ENGINEER", "armborst")
diff --git a/services/taupct/current/qt/A_BD_LifetimePCT.ui b/services/taupct/current/qt/A_BD_LifetimePCT.ui
new file mode 100644
index 0000000..8ab773b
--- /dev/null
+++ b/services/taupct/current/qt/A_BD_LifetimePCT.ui
@@ -0,0 +1,527 @@
+
+
+ MainWindow
+
+
+
+ 0
+ 0
+ 570
+ 260
+
+
+
+ MainWindow
+
+
+
+
+
+ 10
+ 60
+ 260
+ 30
+
+
+
+ Nr. of points for Lifetime fit
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+
+
+ 10
+ 140
+ 260
+ 30
+
+
+
+ Minimum Current
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+
+
+ 10
+ 180
+ 260
+ 30
+
+
+
+ Lifetime
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+
+
+ 280
+ 180
+ 120
+ 30
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TAUPCT:TAU
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 3
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 400.000000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 440
+ 180
+ 120
+ 30
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TAUPCT:TAU-ERR
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 3
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 400.000000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 410
+ 180
+ 21
+ 30
+
+
+
+ ±
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 280
+ 220
+ 120
+ 30
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TAUPCT:INJRATE
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 3
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 400.000000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 440
+ 220
+ 120
+ 30
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TAUPCT:INJRATE-ERR
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 3
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 400.000000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 410
+ 220
+ 21
+ 30
+
+
+
+ ±
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 660
+ 130
+ 70
+ 20
+
+
+
+
+
+
+ 660
+ 70
+ 70
+ 20
+
+
+
+ Reload
+
+
+ RELOAD
+
+
+ A
+
+
+ AGEBD-ALH:TAUPCT-GUIRELOAD
+
+
+ caCalc::TriggerZeroToOne
+
+
+
+
+
+ 10
+ 220
+ 260
+ 30
+
+
+
+ Injection rate
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+
+
+ 280
+ 60
+ 280
+ 30
+
+
+
+ AGEBD-TAUPCT:CONTROL-NSAMPLES-FIT-TAU
+
+
+ caLineEdit::User
+
+
+
+
+
+ 280
+ 140
+ 280
+ 30
+
+
+
+ AGEBD-TAUPCT:CONTROL-MIN-CURR
+
+
+ 12
+
+
+ caLineEdit::User
+
+
+
+
+
+ 0
+ 10
+ 561
+ 40
+
+
+
+ AGEBD-ALH:TAUPCT-ONOFF
+
+
+ caChoice::Column
+
+
+ 1
+
+
+
+
+
+ 280
+ 100
+ 280
+ 30
+
+
+
+ AGEBD-TAUPCT:CONTROL-NSAMPLES-FIT-ROC
+
+
+ caLineEdit::User
+
+
+
+
+
+ 10
+ 100
+ 260
+ 30
+
+
+
+ Nr. of points for inj. rate fit
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+
+
+
+ caChoice
+ QWidget
+
+
+
+ caTextEntry
+ caLineEdit
+
+
+
+ caLabel
+ QLabel
+
+
+
+ caLineEdit
+ QLineEdit
+
+
+
+ caCalc
+ QLabel
+
+
+
+ wmSignalPropagator
+ QLabel
+
+
+
+
+
+
+ cacalc_2
+ emitSignal(bool)
+ wmsignalpropagator
+ reloadwindow()
+
+
+ 695
+ 80
+
+
+ 699
+ 145
+
+
+
+
+
diff --git a/services/taupct/current/systemd/AGEBD-SERVICE-TAUPCT.service b/services/taupct/current/systemd/AGEBD-SERVICE-TAUPCT.service
new file mode 100644
index 0000000..95c1241
--- /dev/null
+++ b/services/taupct/current/systemd/AGEBD-SERVICE-TAUPCT.service
@@ -0,0 +1,16 @@
+[Unit]
+Description=AGEBD-SERVICE-TAUPCT
+After=network.target
+
+[Service]
+Environment=AGEBD_ENV={{ agebd_env }}
+ExecStart=/sls/bd/hla/{{ agebd_env }}/bin/start_service.sh TAUPCT
+Restart=no
+
+[Install]
+WantedBy=default.target
+
+# https://www.freedesktop.org/software/systemd/man/latest/systemd.service.html
+# systemctl --user daemon-reload
+# systemctl --user enable /sls/bd/bin/systemd/AGEBD-SERVICE-TAUPCT.service
+# systemctl --user start AGEBD-SERVICE-TAUPCT
diff --git a/services/timing/current/app/pyproject.toml b/services/timing/current/app/pyproject.toml
new file mode 100644
index 0000000..d1be494
--- /dev/null
+++ b/services/timing/current/app/pyproject.toml
@@ -0,0 +1,48 @@
+[project]
+name = "agebd-timing"
+version = "0.1.0"
+description = "AGEBD-TIMING Service"
+requires-python = "==3.10.*"
+dependencies = [
+ "agebd",
+ "numpy>=2.2.6",
+]
+
+[dependency-groups]
+dev = [
+ "pyepics>=3.5.8",
+ "pytest>=8.4.2",
+ "ruff>=0.15.20",
+]
+
+[tool.uv.sources]
+# Path is relative to where agebd package is deployed on hla
+# machines (see CI/CD in .gitea/workflows)
+agebd = { path = "../../../../packages/agebd", editable = true }
+
+[build-system]
+requires = ["hatchling"]
+build-backend = "hatchling.build"
+
+[tool.uv]
+package = true
+
+[tool.pytest.ini_options]
+pythonpath = ["src"]
+env = [
+ "AGEBD_ENV=local",
+]
+
+[tool.ruff]
+include = [
+ "src/**/*.py",
+ "tests/**/*.py",
+]
+line-length = 100
+
+[tool.ruff.lint]
+# use isort to sort imports
+extend-select = ["I"]
+
+[tool.ruff.lint.isort]
+known-first-party = ["agebd"]
diff --git a/services/timing/current/app/src/agebd_timing/__init__.py b/services/timing/current/app/src/agebd_timing/__init__.py
new file mode 100644
index 0000000..1800c27
--- /dev/null
+++ b/services/timing/current/app/src/agebd_timing/__init__.py
@@ -0,0 +1 @@
+from .service import PVs, Service
diff --git a/services/timing/current/app/src/agebd_timing/main.py b/services/timing/current/app/src/agebd_timing/main.py
new file mode 100644
index 0000000..5312def
--- /dev/null
+++ b/services/timing/current/app/src/agebd_timing/main.py
@@ -0,0 +1,31 @@
+import typer
+
+from agebd.enums import LogLevel
+from agebd.runner import CallbackRunner
+from agebd.utils import init_logging
+from agebd_timing import PVs, Service
+
+
+# TODO: remove: cicd test 10
+
+def main(
+ log_level: LogLevel = typer.Option(
+ LogLevel.INFO,
+ "--log-level",
+ "-l",
+ # Looks at the OS env variable first. If empty, falls back to "INFO"
+ envvar="AGEBD_LOG_LEVEL",
+ # help="Set log level: DEBUG, INFO, WARNING, ERROR, CRITICAL",
+ case_sensitive=False,
+ ),
+):
+ init_logging(log_level)
+ service_name = "TIMING"
+ pvs = PVs(service_name=service_name)
+ service = Service(name=service_name, pvs=pvs)
+ runner = CallbackRunner(service=service)
+ runner.start()
+
+
+if __name__ == "__main__":
+ typer.run(main)
diff --git a/services/timing/current/app/src/agebd_timing/service.py b/services/timing/current/app/src/agebd_timing/service.py
new file mode 100644
index 0000000..32641ed
--- /dev/null
+++ b/services/timing/current/app/src/agebd_timing/service.py
@@ -0,0 +1,285 @@
+from time import perf_counter, sleep
+
+import numpy as np
+
+from agebd.pv import get_pv_class
+from agebd.service.base import BaseService
+from agebd.service.pvs import BasePVs
+from agebd.utils import printgetversion
+
+__version__ = printgetversion(__file__)
+
+PV = get_pv_class()
+
+
+class PVs(BasePVs):
+ ## dedicated timing service pvs
+ # separate go pv to enable start/stop without interrupting processing of, e.g., fill pattern changes
+ go = PV("AGEBD-TIMING:GO.VAL")
+ # fillpattern definition in top up panel
+ fillpattern_string = PV("AGEBD-TIMING:CONTROL-FILLPATTERN-string.VAL")
+ # request to reset index to start with zero bucket (e.g., after beam loss)
+ zero_bucket = PV("AGEBD-TIMING:ZERO-TARGET-BUCKET.VAL")
+ # waveform to reflect current target bucket in filling pattern plots on console slsw02
+ plot_target_bucket = PV("AGEBD-TIMING:TARGET-BUCKET.VAL")
+ # waveform to reflect current target filling pattern in filling pattern plots on console slsw02
+ plot_target_fillpattern = PV("AGEBD-TIMING:TARGET-FILLPATTERN.VAL")
+ # current above which the feedback mode is started
+ current_threshold = PV("AGEBD-TIMING:CURRENT-THRESHOLD.VAL")
+ # choice of filling pattern feedback mode to use (0: BPM, 1: APD, 2: FPFB or 3: every nth bucket)
+ fpfb_mode = PV("AGEBD-TIMING:FPFB-MODE.VAL")
+ # choice of n for every nth bucket mode
+ fpfb_nth = PV("AGEBD-TIMING:FPFB-NTH.VAL")
+
+ ## other pvs used by this service
+ # Beam current measured by PCT
+ pct_beam_current = PV("ARS07-DPCT-0000:CURR.VAL")
+ # trig_master: enables the storage-ring injection (start sending events)
+ trig_master = PV("AGETI-CVME-MASTER-TMA:SR-Inj-Status-Sel.VAL")
+ # trig_secret: everything is correct with the "machine" and injection can be done
+ trig_secret = PV("AGEBD-INJECTIONGUARD:STATUS-SECRET-MASTER.VAL")
+ # filling pattern measurement from BPM
+ fill_meas_bpm = PV("ARSGE-CECL-FPFB:FPFB-BUNCH-CHARGE.VAL")
+ # filling pattern measurement from APD
+ fill_meas_apd = PV("X08DB-DFPM-DI:FW-SIS0DAQ-CH0-FPM-WF.VAL")
+ # Pedro's filling pattern feedback reference definition
+ fpfb_ref = PV("ARSGE-CECL-FPFB:FPFB-REF-FILL-PATTERN.VAL")
+ # Pedro's filling pattern feedback suggested bucket indices
+ fpfb_indices = PV("ARSGE-CECL-FPFB:BUNCH-IDX-INJECTION-LIST.VAL")
+
+ ## manual injection timing master pvs
+ # target bucket for injection
+ bt = PV("AGETI-CVME-MASTER-TMA:FP-Manual-Bucket-SP.VAL")
+ # fire request for gun
+ fire = PV("AGETI-CVME-MASTER-TMA:FP-Manual-Trigger-SP.VAL")
+
+ # feedback from linac evr
+ # lastbucket = PV('ALIRF-VME-A:Last-Bucket-I.VAL')
+ # nextbucket = PV('ALIRF-VME-A:Bucket-I.VAL')
+
+ def __init__(self, service_name: str, pv_factory=PV):
+ super().__init__(service_name, pv_factory)
+ PV = pv_factory
+
+ # trigger gun fire followed by bucket update with start of sequence event (3 Hz)
+ self.CallbackPV = PV("AGETI-CVME-MASTER-TMA:Evt-SOS-EVRCount-I.VAL")
+
+
+class Service(BaseService[PVs]):
+ def __init__(
+ self,
+ name: str,
+ pvs: PVs,
+ version: str = __version__,
+ sleep_interval: float = 0.1,
+ ):
+ super().__init__(name, pvs, version, sleep_interval)
+
+ self.index = 0
+ self.fire = 1
+ self.timer = perf_counter()
+ self.updatefp()
+ self.master = pvs.trig_master.get() and pvs.trig_secret.get()
+ self.getmaster()
+
+ def update(self):
+ pvs = self.pvs
+
+ if self.CallbackFired:
+ # confirm callback function run
+ self.CallbackFired = 0
+
+ # get next bucket
+ self.updatebucket()
+
+ # check if master trigger state changed
+ self.getmaster()
+
+ if self.master and pvs.go.get():
+ # update target bucket
+ # write next bucket to timing master
+ if -1 < self.bucket < 481:
+ pvs.bt.put(self.bucket, wait=True)
+ else:
+ print(f"invalid bucket: {self.bucket:}")
+ self.lastbuckets[:-1] = self.lastbuckets[1:]
+ self.lastbuckets[-1] = self.bucket
+
+ # request firing of gun
+ pvs.fire.put(self.fire, wait=True)
+ self.Nshots += 1
+
+ # increment target bucket for next shot by 1
+ self.index += 1
+
+ if self.index > self.N - 1:
+ self.index = 0
+
+ self.CallbackFired = 0
+
+ # update fillpattern if pv has changed or zeroing requested
+ elif self.fps != pvs.fillpattern_string.get() or pvs.zero_bucket.get():
+ self.updatefp()
+ pvs.zero_bucket.put(0)
+
+ if self.master != self.master_old:
+ # wait for some 3 Hz cycles in case master trigger was just switched on
+ # --> safety in case it will be switched off again very fast
+ # --> avoid going into callback loop of last 3 Hz cycle with arbitrary delay, i.e., off sync
+ self.Nshots = self.NshotsMax + 1
+ self.updatebucket()
+
+ if self.master:
+ sleep(1)
+
+ # stop self if master was switched off
+ else:
+ pvs.go.put(0)
+
+ def getmaster(self):
+ pvs = self.pvs
+
+ self.master_old = self.master
+ self.master = pvs.trig_master.get() and pvs.trig_secret.get()
+
+ def updatefp(self):
+ pvs = self.pvs
+
+ self.fps = pvs.fillpattern_string.get()
+
+ try:
+ check1 = (
+ self.fps.replace("-", "").replace(" ", "").isdecimal()
+ ) # also catches empty string
+ check2, check3 = 0, 0
+ if check1:
+ fillpattern = []
+ for v in [x for x in self.fps.split(" ")]:
+ if "-" in v and not "" in v.split("-"):
+ i, f = [int(x) for x in v.split("-")]
+ fillpattern.append(np.arange(int(i), int(f)))
+ else:
+ fillpattern.append([int(v)])
+
+ self.fillpattern = np.sort(np.concatenate(fillpattern))
+
+ check2 = np.max(self.fillpattern) < 481
+ check3 = np.min(self.fillpattern) > -1
+
+ if not check2:
+ pvs.fillpattern_string.put(
+ "Error: last bucket is > 480".encode(encoding="ascii")
+ )
+
+ elif not check3:
+ pvs.fillpattern_string.put(
+ "Error: first bucket is < 0".encode(encoding="ascii")
+ )
+
+ else:
+ pvs.fillpattern_string.put(
+ "Error: allowed chars are [0-9,-, ]".encode(encoding="ascii")
+ )
+
+ if not all([check1, check2, check3]):
+ sleep(1)
+ pvs.fillpattern_string.put("0-450".encode(encoding="ascii"))
+ self.fillpattern = np.arange(0, 450, 1)
+
+ except:
+ pvs.fillpattern_string.put("0-450".encode(encoding="ascii"))
+ self.fillpattern = np.arange(0, 450, 1)
+
+ # fill pattern as 480 long array
+ self.fillpattern_480 = np.zeros(480)
+ self.fillpattern_480[self.fillpattern] = 1
+ pvs.plot_target_fillpattern.put(self.fillpattern_480)
+ pvs.fpfb_ref.put(self.fillpattern_480)
+
+ # fill pattern as 480 long array of bools
+ self.fillpattern_bool = self.fillpattern_480.astype(bool)
+
+ # length of fill pattern to loop over
+ self.N = len(self.fillpattern)
+
+ # nr. of shots until new target fillpattern is retrieved
+ self.NshotsMax = int(self.N / 15 + 1)
+ self.Nshots = self.NshotsMax + 1
+
+ # prepare array for list of last buckets that got a shot
+ self.lastbuckets = np.ones(self.NshotsMax) * -1
+
+ # reset bucket index
+ self.index = 0
+
+ def updatebucket(self):
+ pvs = self.pvs
+
+ # use selected filling pattern feedback mode above threshold current to update fill pattern before updating bucket
+ if pvs.pct_beam_current.get() > pvs.current_threshold.get() and (
+ self.Nshots > self.NshotsMax or (perf_counter() - self.timer) > 30
+ ):
+ fillpattern_old = self.fillpattern
+ self.Nshots = 0
+
+ # update timer to only update every XX seconds
+ self.timer = perf_counter()
+
+ # (0: BPM, 1: APD, 2: FPFB or 3: every nth bucket)
+ self.fpfb_mode = pvs.fpfb_mode.get()
+
+ # fpfb based on sorted list of buckets from BPM fill pattern measurement
+ if self.fpfb_mode == 0:
+ self.fill_meas_bpm = pvs.fill_meas_bpm.get()
+ self.fillpattern = np.argsort(self.fill_meas_bpm[self.fillpattern_bool])
+
+ # fpfb based on sorted list of buckets from APD fill pattern measurement
+ elif self.fpfb_mode == 1:
+ self.fill_meas_apd = pvs.fill_meas_apd.get()
+ self.fillpattern = np.argsort(self.fill_meas_apd[self.fillpattern_bool])
+
+ # fpfb based on sorted list of buckets given by fpfb from pedro
+ elif self.fpfb_mode == 2:
+ self.fillpattern = pvs.fpfb_indices.get()[: self.N]
+
+ # fpfb based on filling every nth bucket
+ elif self.fpfb_mode == 3:
+ # calculate interleaved fill pattern array (has same length and reference as before, i.e., these do not need to be updated)
+ self.fpfb_nth = int(pvs.fpfb_nth.get())
+ self.fillpattern = np.concatenate(
+ [self.fillpattern[n :: self.fpfb_nth] for n in range(self.fpfb_nth)]
+ )
+
+ if self.fpfb_mode in [0, 1, 2]:
+ # reset bucket index
+ self.index = 0
+
+ indices = np.sort(
+ np.concatenate(
+ [np.where(bucket == self.fillpattern)[0] for bucket in self.lastbuckets]
+ )
+ )
+ # print(indices)
+
+ # calculate next bucket
+ self.bucket = self.fillpattern[self.index]
+ if (self.bucket in self.lastbuckets) and self.N > 1:
+ # increment target bucket for next shot by 1
+ self.index += 1
+
+ if self.index > self.N - 1:
+ self.index = 0
+
+ self.bucket = self.fillpattern[self.index]
+
+ plot_target_bucket = np.zeros(480)
+ plot_target_bucket[self.bucket] = 1
+ pvs.plot_target_bucket.put(plot_target_bucket)
+
+ # print('self.bucket', self.bucket)
+
+ # # write next bucket to timing master
+ # if -1 < self.bucket < 481:
+ # pvs.bt.put(self.bucket, wait=True)
+ # else:
+ # print(f'invalid bucket: {self.bucket:}')
diff --git a/services/timing/current/app/tests/test_app.py b/services/timing/current/app/tests/test_app.py
new file mode 100644
index 0000000..f058e5e
--- /dev/null
+++ b/services/timing/current/app/tests/test_app.py
@@ -0,0 +1,9 @@
+from agebd_timing import PVs, Service
+
+
+def test_app():
+ service_name = "DUMMY"
+ pvs = PVs(service_name=service_name)
+ service = Service(name=service_name, pvs=pvs)
+ service.CallbackFired = 1
+ service.update()
diff --git a/services/timing/current/app/uv.lock b/services/timing/current/app/uv.lock
new file mode 100644
index 0000000..9eca90c
--- /dev/null
+++ b/services/timing/current/app/uv.lock
@@ -0,0 +1,301 @@
+version = 1
+revision = 3
+requires-python = "==3.10.*"
+
+[[package]]
+name = "agebd"
+version = "0.1.0"
+source = { editable = "../../../../packages/agebd" }
+dependencies = [
+ { name = "h5py" },
+ { name = "typer" },
+]
+
+[package.metadata]
+requires-dist = [
+ { name = "h5py", specifier = ">=3.16.0" },
+ { name = "typer", specifier = ">=0.23.2" },
+]
+
+[package.metadata.requires-dev]
+dev = [
+ { name = "pyright", specifier = ">=1.1.410" },
+ { name = "pytest", specifier = ">=8.4.2" },
+ { name = "ruff", specifier = ">=0.15.19" },
+]
+
+[[package]]
+name = "agebd-timing"
+version = "0.1.0"
+source = { editable = "." }
+dependencies = [
+ { name = "agebd" },
+ { name = "numpy" },
+]
+
+[package.dev-dependencies]
+dev = [
+ { name = "pyepics" },
+ { name = "pytest" },
+ { name = "ruff" },
+]
+
+[package.metadata]
+requires-dist = [
+ { name = "agebd", editable = "../../../../packages/agebd" },
+ { name = "numpy", specifier = ">=2.2.6" },
+]
+
+[package.metadata.requires-dev]
+dev = [
+ { name = "pyepics", specifier = ">=3.5.8" },
+ { name = "pytest", specifier = ">=8.4.2" },
+ { name = "ruff", specifier = ">=0.15.20" },
+]
+
+[[package]]
+name = "annotated-doc"
+version = "0.0.4"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/57/ba/046ceea27344560984e26a590f90bc7f4a75b06701f653222458922b558c/annotated_doc-0.0.4.tar.gz", hash = "sha256:fbcda96e87e9c92ad167c2e53839e57503ecfda18804ea28102353485033faa4", size = 7288, upload-time = "2025-11-10T22:07:42.062Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl", hash = "sha256:571ac1dc6991c450b25a9c2d84a3705e2ae7a53467b5d111c24fa8baabbed320", size = 5303, upload-time = "2025-11-10T22:07:40.673Z" },
+]
+
+[[package]]
+name = "colorama"
+version = "0.4.6"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" },
+]
+
+[[package]]
+name = "exceptiongroup"
+version = "1.3.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "typing-extensions" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" },
+]
+
+[[package]]
+name = "h5py"
+version = "3.16.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "numpy" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/db/33/acd0ce6863b6c0d7735007df01815403f5589a21ff8c2e1ee2587a38f548/h5py-3.16.0.tar.gz", hash = "sha256:a0dbaad796840ccaa67a4c144a0d0c8080073c34c76d5a6941d6818678ef2738", size = 446526, upload-time = "2026-03-06T13:49:08.07Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/3a/6b/231413e58a787a89b316bb0d1777da3c62257e4797e09afd8d17ad3549dc/h5py-3.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e06f864bedb2c8e7c1358e6c73af48519e317457c444d6f3d332bb4e8fa6d7d9", size = 3724137, upload-time = "2026-03-06T13:47:35.242Z" },
+ { url = "https://files.pythonhosted.org/packages/74/f9/557ce3aad0fe8471fb5279bab0fc56ea473858a022c4ce8a0b8f303d64e9/h5py-3.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ec86d4fffd87a0f4cb3d5796ceb5a50123a2a6d99b43e616e5504e66a953eca3", size = 3090112, upload-time = "2026-03-06T13:47:37.634Z" },
+ { url = "https://files.pythonhosted.org/packages/7a/f5/e15b3d0dc8a18e56409a839e6468d6fb589bc5207c917399c2e0706eeb44/h5py-3.16.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:86385ea895508220b8a7e45efa428aeafaa586bd737c7af9ee04661d8d84a10d", size = 4844847, upload-time = "2026-03-06T13:47:39.811Z" },
+ { url = "https://files.pythonhosted.org/packages/cb/92/a8851d936547efe30cc0ce5245feac01f3ec6171f7899bc3f775c72030b3/h5py-3.16.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:8975273c2c5921c25700193b408e28d6bdd0111c37468b2d4e25dcec4cd1d84d", size = 5065352, upload-time = "2026-03-06T13:47:41.489Z" },
+ { url = "https://files.pythonhosted.org/packages/2b/ae/f2adc5d0ca9626db3277a3d87516e124cbc5d0eea0bd79bc085702d04f2c/h5py-3.16.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:1677ad48b703f44efc9ea0c3ab284527f81bc4f318386aaaebc5fede6bbae56f", size = 4839173, upload-time = "2026-03-06T13:47:43.586Z" },
+ { url = "https://files.pythonhosted.org/packages/64/0b/e0c8c69da1d8838da023a50cd3080eae5d475691f7636b35eff20bb6ef20/h5py-3.16.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7c4dd4cf5f0a4e36083f73172f6cfc25a5710789269547f132a20975bfe2434c", size = 5076216, upload-time = "2026-03-06T13:47:45.315Z" },
+ { url = "https://files.pythonhosted.org/packages/66/35/d88fd6718832133c885004c61ceeeb24dbd6397ef877dbed6b3a64d6a286/h5py-3.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:bdef06507725b455fccba9c16529121a5e1fbf56aa375f7d9713d9e8ff42454d", size = 3183639, upload-time = "2026-03-06T13:47:47.041Z" },
+]
+
+[[package]]
+name = "iniconfig"
+version = "2.3.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" },
+]
+
+[[package]]
+name = "markdown-it-py"
+version = "4.2.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "mdurl" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/06/ff/7841249c247aa650a76b9ee4bbaeae59370dc8bfd2f6c01f3630c35eb134/markdown_it_py-4.2.0.tar.gz", hash = "sha256:04a21681d6fbb623de53f6f364d352309d4094dd4194040a10fd51833e418d49", size = 82454, upload-time = "2026-05-07T12:08:28.36Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl", hash = "sha256:9f7ebbcd14fe59494226453aed97c1070d83f8d24b6fc3a3bcf9a38092641c4a", size = 91687, upload-time = "2026-05-07T12:08:27.182Z" },
+]
+
+[[package]]
+name = "mdurl"
+version = "0.1.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" },
+]
+
+[[package]]
+name = "numpy"
+version = "2.2.6"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/76/21/7d2a95e4bba9dc13d043ee156a356c0a8f0c6309dff6b21b4d71a073b8a8/numpy-2.2.6.tar.gz", hash = "sha256:e29554e2bef54a90aa5cc07da6ce955accb83f21ab5de01a62c8478897b264fd", size = 20276440, upload-time = "2025-05-17T22:38:04.611Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/9a/3e/ed6db5be21ce87955c0cbd3009f2803f59fa08df21b5df06862e2d8e2bdd/numpy-2.2.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b412caa66f72040e6d268491a59f2c43bf03eb6c96dd8f0307829feb7fa2b6fb", size = 21165245, upload-time = "2025-05-17T21:27:58.555Z" },
+ { url = "https://files.pythonhosted.org/packages/22/c2/4b9221495b2a132cc9d2eb862e21d42a009f5a60e45fc44b00118c174bff/numpy-2.2.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e41fd67c52b86603a91c1a505ebaef50b3314de0213461c7a6e99c9a3beff90", size = 14360048, upload-time = "2025-05-17T21:28:21.406Z" },
+ { url = "https://files.pythonhosted.org/packages/fd/77/dc2fcfc66943c6410e2bf598062f5959372735ffda175b39906d54f02349/numpy-2.2.6-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:37e990a01ae6ec7fe7fa1c26c55ecb672dd98b19c3d0e1d1f326fa13cb38d163", size = 5340542, upload-time = "2025-05-17T21:28:30.931Z" },
+ { url = "https://files.pythonhosted.org/packages/7a/4f/1cb5fdc353a5f5cc7feb692db9b8ec2c3d6405453f982435efc52561df58/numpy-2.2.6-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:5a6429d4be8ca66d889b7cf70f536a397dc45ba6faeb5f8c5427935d9592e9cf", size = 6878301, upload-time = "2025-05-17T21:28:41.613Z" },
+ { url = "https://files.pythonhosted.org/packages/eb/17/96a3acd228cec142fcb8723bd3cc39c2a474f7dcf0a5d16731980bcafa95/numpy-2.2.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:efd28d4e9cd7d7a8d39074a4d44c63eda73401580c5c76acda2ce969e0a38e83", size = 14297320, upload-time = "2025-05-17T21:29:02.78Z" },
+ { url = "https://files.pythonhosted.org/packages/b4/63/3de6a34ad7ad6646ac7d2f55ebc6ad439dbbf9c4370017c50cf403fb19b5/numpy-2.2.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc7b73d02efb0e18c000e9ad8b83480dfcd5dfd11065997ed4c6747470ae8915", size = 16801050, upload-time = "2025-05-17T21:29:27.675Z" },
+ { url = "https://files.pythonhosted.org/packages/07/b6/89d837eddef52b3d0cec5c6ba0456c1bf1b9ef6a6672fc2b7873c3ec4e2e/numpy-2.2.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:74d4531beb257d2c3f4b261bfb0fc09e0f9ebb8842d82a7b4209415896adc680", size = 15807034, upload-time = "2025-05-17T21:29:51.102Z" },
+ { url = "https://files.pythonhosted.org/packages/01/c8/dc6ae86e3c61cfec1f178e5c9f7858584049b6093f843bca541f94120920/numpy-2.2.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8fc377d995680230e83241d8a96def29f204b5782f371c532579b4f20607a289", size = 18614185, upload-time = "2025-05-17T21:30:18.703Z" },
+ { url = "https://files.pythonhosted.org/packages/5b/c5/0064b1b7e7c89137b471ccec1fd2282fceaae0ab3a9550f2568782d80357/numpy-2.2.6-cp310-cp310-win32.whl", hash = "sha256:b093dd74e50a8cba3e873868d9e93a85b78e0daf2e98c6797566ad8044e8363d", size = 6527149, upload-time = "2025-05-17T21:30:29.788Z" },
+ { url = "https://files.pythonhosted.org/packages/a3/dd/4b822569d6b96c39d1215dbae0582fd99954dcbcf0c1a13c61783feaca3f/numpy-2.2.6-cp310-cp310-win_amd64.whl", hash = "sha256:f0fd6321b839904e15c46e0d257fdd101dd7f530fe03fd6359c1ea63738703f3", size = 12904620, upload-time = "2025-05-17T21:30:48.994Z" },
+ { url = "https://files.pythonhosted.org/packages/9e/3b/d94a75f4dbf1ef5d321523ecac21ef23a3cd2ac8b78ae2aac40873590229/numpy-2.2.6-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0b605b275d7bd0c640cad4e5d30fa701a8d59302e127e5f79138ad62762c3e3d", size = 21040391, upload-time = "2025-05-17T21:44:35.948Z" },
+ { url = "https://files.pythonhosted.org/packages/17/f4/09b2fa1b58f0fb4f7c7963a1649c64c4d315752240377ed74d9cd878f7b5/numpy-2.2.6-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:7befc596a7dc9da8a337f79802ee8adb30a552a94f792b9c9d18c840055907db", size = 6786754, upload-time = "2025-05-17T21:44:47.446Z" },
+ { url = "https://files.pythonhosted.org/packages/af/30/feba75f143bdc868a1cc3f44ccfa6c4b9ec522b36458e738cd00f67b573f/numpy-2.2.6-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce47521a4754c8f4593837384bd3424880629f718d87c5d44f8ed763edd63543", size = 16643476, upload-time = "2025-05-17T21:45:11.871Z" },
+ { url = "https://files.pythonhosted.org/packages/37/48/ac2a9584402fb6c0cd5b5d1a91dcf176b15760130dd386bbafdbfe3640bf/numpy-2.2.6-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d042d24c90c41b54fd506da306759e06e568864df8ec17ccc17e9e884634fd00", size = 12812666, upload-time = "2025-05-17T21:45:31.426Z" },
+]
+
+[[package]]
+name = "packaging"
+version = "26.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d7/f1/e7a6dd94a8d4a5626c03e4e99c87f241ba9e350cd9e6d75123f992427270/packaging-26.2.tar.gz", hash = "sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661", size = 228134, upload-time = "2026-04-24T20:15:23.917Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/df/b2/87e62e8c3e2f4b32e5fe99e0b86d576da1312593b39f47d8ceef365e95ed/packaging-26.2-py3-none-any.whl", hash = "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e", size = 100195, upload-time = "2026-04-24T20:15:22.081Z" },
+]
+
+[[package]]
+name = "pluggy"
+version = "1.6.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" },
+]
+
+[[package]]
+name = "pyepics"
+version = "3.5.10"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "numpy" },
+ { name = "pyparsing" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/69/57/29e1e9ef11ba2a3419f489946ae1d8190025a1e4f4e1c1686758bb2b6e0a/pyepics-3.5.10.tar.gz", hash = "sha256:f390cf9be40aba757b9528888114bc14d8db01086d0c93914720b1772460375b", size = 6150481, upload-time = "2026-05-20T18:44:36.336Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d6/36/e517fd83bd97d6bfe4105e0c6b322070c5cc36fb56a8fab2866e319f8804/pyepics-3.5.10-py3-none-any.whl", hash = "sha256:c9fac2c54f2b595268e66fc348cf5ec24e63718e7dbd07d73d1b37d4da6bfee1", size = 5332376, upload-time = "2026-05-20T18:44:34.242Z" },
+]
+
+[[package]]
+name = "pygments"
+version = "2.20.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" },
+]
+
+[[package]]
+name = "pyparsing"
+version = "3.3.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f3/91/9c6ee907786a473bf81c5f53cf703ba0957b23ab84c264080fb5a450416f/pyparsing-3.3.2.tar.gz", hash = "sha256:c777f4d763f140633dcb6d8a3eda953bf7a214dc4eff598413c070bcdc117cbc", size = 6851574, upload-time = "2026-01-21T03:57:59.36Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl", hash = "sha256:850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d", size = 122781, upload-time = "2026-01-21T03:57:55.912Z" },
+]
+
+[[package]]
+name = "pytest"
+version = "9.1.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "colorama", marker = "sys_platform == 'win32'" },
+ { name = "exceptiongroup" },
+ { name = "iniconfig" },
+ { name = "packaging" },
+ { name = "pluggy" },
+ { name = "pygments" },
+ { name = "tomli" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/e4/47/b9efed96c114afcfa3c9d3fe98a76a1d14c74a9e266d397cf6eb64be5e01/pytest-9.1.1.tar.gz", hash = "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313", size = 1636369, upload-time = "2026-06-19T10:58:32.857Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/24/25/1de2678b631f5a49215c6c96fff41ba892b0a34df68d6d80292b1b48aa7f/pytest-9.1.1-py3-none-any.whl", hash = "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c", size = 386536, upload-time = "2026-06-19T10:58:31.347Z" },
+]
+
+[[package]]
+name = "rich"
+version = "15.0.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "markdown-it-py" },
+ { name = "pygments" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/c0/8f/0722ca900cc807c13a6a0c696dacf35430f72e0ec571c4275d2371fca3e9/rich-15.0.0.tar.gz", hash = "sha256:edd07a4824c6b40189fb7ac9bc4c52536e9780fbbfbddf6f1e2502c31b068c36", size = 230680, upload-time = "2026-04-12T08:24:00.75Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl", hash = "sha256:33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb", size = 310654, upload-time = "2026-04-12T08:24:02.83Z" },
+]
+
+[[package]]
+name = "ruff"
+version = "0.15.21"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/0f/36/6f65aa9989acdec45d417192d8f4e7921931d8a6cf87ac74bce3eed98a8e/ruff-0.15.21.tar.gz", hash = "sha256:d0cfc841c572283c36548f82664a54ce6565567f1b0d5b4cf2caac693d8b7500", size = 4769401, upload-time = "2026-07-09T20:01:34.005Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d0/c6/ede15cac6839f3dbce52565c8f5164a8210e669c7bc4decb03e5bdf47d0d/ruff-0.15.21-py3-none-linux_armv6l.whl", hash = "sha256:63ea0e965e5d73c90e95b2434beeafc70820536717f561b32ab6e777cb9bdf5d", size = 10854342, upload-time = "2026-07-09T20:00:53.998Z" },
+ { url = "https://files.pythonhosted.org/packages/28/9d/d825b07ee7ea9e2d61df92a860033c94e06e7300d50a1c2653aac27d24fe/ruff-0.15.21-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:0f212c5d7d54c01bbfe6dcab02b724a39300f3e34ed7acbe995ccb320a2c58bd", size = 11139539, upload-time = "2026-07-09T20:00:57.809Z" },
+ { url = "https://files.pythonhosted.org/packages/f5/de/3b107712e642f063c7a9e0887c427b22cb44097de5aab36c05f2e280670c/ruff-0.15.21-py3-none-macosx_11_0_arm64.whl", hash = "sha256:e6312e41bc96791299614995ea3a977c5857c3b5662b1ecef6755b02b87cb646", size = 10595437, upload-time = "2026-07-09T20:01:00.006Z" },
+ { url = "https://files.pythonhosted.org/packages/9a/6f/b4523cc90ba239ede441447a19d0c968846a3012e5a0b0c5b62831a3d5e3/ruff-0.15.21-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01d65b4831c6b2a4ba8ee6faa84049d44d982b7a706e622c4094c509e51673be", size = 10990053, upload-time = "2026-07-09T20:01:02.187Z" },
+ { url = "https://files.pythonhosted.org/packages/92/cc/c6a9872a5375f0628875481cf2f66b13d7d865bf3ca2e57f91c7e762d976/ruff-0.15.21-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2c5a913a589120ce67933d5d05fd6ddbcc2481c6a054980ee767f7414c72b4fd", size = 10666096, upload-time = "2026-07-09T20:01:04.299Z" },
+ { url = "https://files.pythonhosted.org/packages/ab/97/c621f7a17e097f1790fa3af6374138823b330b2d03fc38337945daca212c/ruff-0.15.21-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ef04b681d02ad4dc9620f00f83ac5c22f652d0e9a9cfe431d219b16ad5ccc41", size = 11537011, upload-time = "2026-07-09T20:01:06.771Z" },
+ { url = "https://files.pythonhosted.org/packages/ea/51/d928727e476e25ccc57c6f449ffd80241a651a973ad949d39cfb2a771d28/ruff-0.15.21-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:16d090c0740916594157e75b80d666eab8e78083b39b3b0e1d698f4670a17b86", size = 12347101, upload-time = "2026-07-09T20:01:08.859Z" },
+ { url = "https://files.pythonhosted.org/packages/1e/88/8cd62026802b16018ad06931d87997cf795ba2a6239ab659606c87d96bf0/ruff-0.15.21-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3a10e74757dd65004d779b73e2f3c5210156d9980b41224d50d2ebcf1db51e67", size = 11572001, upload-time = "2026-07-09T20:01:11.092Z" },
+ { url = "https://files.pythonhosted.org/packages/b2/97/f63084cf55444fc110e8cb985ebfcc592af47f597d44453d778cb81bc156/ruff-0.15.21-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bab0905d2f29e0d9fbc3c373ed23db0095edaa3f71f1f4f519ec15134d9e85c8", size = 11549239, upload-time = "2026-07-09T20:01:13.27Z" },
+ { url = "https://files.pythonhosted.org/packages/9d/77/f107da4a2874b7715914b03f09ba9c54424de3ff8a1cc5d015d3ee2ce0ac/ruff-0.15.21-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:00eca240af5789fec6fe7df74c088cc1f9644ed83027113468efba7c92b94075", size = 11535340, upload-time = "2026-07-09T20:01:15.206Z" },
+ { url = "https://files.pythonhosted.org/packages/d5/e9/601deb322d3303a7bf212b0100ead6f2ee3f6a044d89c30f2f92bf83c731/ruff-0.15.21-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:262ab31557a75141325e32d3357f3597645a7f084e732b6b054dde428ecd9341", size = 10964048, upload-time = "2026-07-09T20:01:17.723Z" },
+ { url = "https://files.pythonhosted.org/packages/ea/2e/0f2176d1e99c15192caea19c8c3a0a955246b4cb4de795042eeb616345cd/ruff-0.15.21-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:659c4e7a4212f83306045ec7c5e5a356d16d9a6ef4ae0c7a4d872914fc655d9d", size = 10667055, upload-time = "2026-07-09T20:01:19.73Z" },
+ { url = "https://files.pythonhosted.org/packages/48/60/abd74a02e0c4214f12a68becfd30af7165cfdcb0e661ecdc60bbb949c09a/ruff-0.15.21-py3-none-musllinux_1_2_i686.whl", hash = "sha256:9e866eab611a5f959d36df2d10e446973a3610bc42b0c15b31dc27977d59c233", size = 11242043, upload-time = "2026-07-09T20:01:21.947Z" },
+ { url = "https://files.pythonhosted.org/packages/b2/c6/583075d8ccabb4b229345edcaf1545eb3d8d6be90f686a479d7e94088bbf/ruff-0.15.21-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e89bc93c0d3803ba870b55c29671bad9dc6d94bb1eb181b056b52eb05b52854f", size = 11648064, upload-time = "2026-07-09T20:01:24.023Z" },
+ { url = "https://files.pythonhosted.org/packages/3a/3c/37d0ecb729a7cc2d393ea7dce316fc585680f35d93b8d62139d7d0a3700c/ruff-0.15.21-py3-none-win32.whl", hash = "sha256:01f8d5be84823c172b389e123174f781f9daf86d6c58719d603f941932195cdd", size = 10896555, upload-time = "2026-07-09T20:01:26.941Z" },
+ { url = "https://files.pythonhosted.org/packages/c0/b8/e43466b2a6067ce91e669068f6e28d6c719a920f014b070d5c8731725de3/ruff-0.15.21-py3-none-win_amd64.whl", hash = "sha256:d4b8d9a2f0f12b816b50447f6eccb9f4bb01a6b82c86b50fb3b5354b458dc6d3", size = 12038772, upload-time = "2026-07-09T20:01:29.497Z" },
+ { url = "https://files.pythonhosted.org/packages/dd/75/e90ab9aeece218a9fc5a5bc3ec97d0ee6bb3c4ff95869463c1de58e29a1c/ruff-0.15.21-py3-none-win_arm64.whl", hash = "sha256:6e83115d4b9377c1cbc13abf0e051f069fab0ef815ea0504a8a008cee24dd0a8", size = 11375265, upload-time = "2026-07-09T20:01:31.772Z" },
+]
+
+[[package]]
+name = "shellingham"
+version = "1.5.4"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/58/15/8b3609fd3830ef7b27b655beb4b4e9c62313a4e8da8c676e142cc210d58e/shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de", size = 10310, upload-time = "2023-10-24T04:13:40.426Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755, upload-time = "2023-10-24T04:13:38.866Z" },
+]
+
+[[package]]
+name = "tomli"
+version = "2.4.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/22/de/48c59722572767841493b26183a0d1cc411d54fd759c5607c4590b6563a6/tomli-2.4.1.tar.gz", hash = "sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f", size = 17543, upload-time = "2026-03-25T20:22:03.828Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/7b/61/cceae43728b7de99d9b847560c262873a1f6c98202171fd5ed62640b494b/tomli-2.4.1-py3-none-any.whl", hash = "sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe", size = 14583, upload-time = "2026-03-25T20:22:03.012Z" },
+]
+
+[[package]]
+name = "typer"
+version = "0.27.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "annotated-doc" },
+ { name = "colorama", marker = "sys_platform == 'win32'" },
+ { name = "rich" },
+ { name = "shellingham" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/37/78/fda3361b56efc27944f24225f6ecd13d96d6fcfe37bd0eb34e2f4c63f9fc/typer-0.27.0.tar.gz", hash = "sha256:629bd12ea5d13a17148125d9a264f949eb171fb3f120f9b04d85873cab054fa5", size = 203430, upload-time = "2026-07-15T19:21:07.007Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/40/03/26a383c9e58c213199d1aad1c3d353cfc22d4444ec6d2c0bf8ad02523843/typer-0.27.0-py3-none-any.whl", hash = "sha256:6f4b27631e47f077871b7dc30e933ec0131c1390fbe0e387ea5574b5bac9ccf1", size = 122716, upload-time = "2026-07-15T19:21:05.553Z" },
+]
+
+[[package]]
+name = "typing-extensions"
+version = "4.16.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f6/cc/6253133b5bb138fc3306cebfbda2c520f545d36b5be2c7255cc528bb45d6/typing_extensions-4.16.0.tar.gz", hash = "sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5", size = 113555, upload-time = "2026-07-02T08:40:05.92Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/49/d3/b8441a820a491ddfc024b0b0cf0393375b75ea13866d9c66727e54c2fc80/typing_extensions-4.16.0-py3-none-any.whl", hash = "sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8", size = 45571, upload-time = "2026-07-02T08:40:04.659Z" },
+]
diff --git a/services/timing/current/ioc/AGEBD-CPCL-TIMING_main.subs b/services/timing/current/ioc/AGEBD-CPCL-TIMING_main.subs
new file mode 100644
index 0000000..1a840a4
--- /dev/null
+++ b/services/timing/current/ioc/AGEBD-CPCL-TIMING_main.subs
@@ -0,0 +1,4 @@
+file TIMING.template {
+ pattern { DEVICE }
+ { AGEBD-TIMING{{ agebd_env }} }
+}
diff --git a/services/timing/current/ioc/AGEBD-CPCL-TIMING_parameters.yaml b/services/timing/current/ioc/AGEBD-CPCL-TIMING_parameters.yaml
new file mode 100644
index 0000000..ff8e70f
--- /dev/null
+++ b/services/timing/current/ioc/AGEBD-CPCL-TIMING_parameters.yaml
@@ -0,0 +1,6 @@
+cpu_architecture: x86_64
+epics_version: 7.0.8
+ioc_host: sls-vserv-bd-01{{ agebd_env }}
+ioc_port: {{ ioc_port }}
+os: RHEL8
+os_id: rhel
diff --git a/services/timing/current/ioc/TIMING.template b/services/timing/current/ioc/TIMING.template
new file mode 100644
index 0000000..a9bd791
--- /dev/null
+++ b/services/timing/current/ioc/TIMING.template
@@ -0,0 +1,409 @@
+###############################
+## follow bucket flags
+###############################
+
+record(bo, "$(DEVICE):CONTROL-FLW-BCKT-GUN") {
+ field(DESC, "Gun")
+ field(ASG, "PROTECTED")
+ field(PINI, "YES")
+}
+
+record(bo, "$(DEVICE):CONTROL-FLW-BCKT-lindi-ictone") {
+ field(DESC, "Linac ICT 1/2")
+ field(ASG, "PROTECTED")
+ field(PINI, "YES")
+}
+
+record(bo, "$(DEVICE):CONTROL-FLW-BCKT-lindi-icts23") {
+ field(DESC, "Linac ICT 3")
+ field(ASG, "PROTECTED")
+ field(PINI, "YES")
+}
+
+record(bo, "$(DEVICE):CONTROL-FLW-BCKT-lirf-llemast") {
+ field(DESC, "Linac RF LLE Master")
+ field(ASG, "PROTECTED")
+ field(PINI, "YES")
+}
+
+record(bo, "$(DEVICE):CONTROL-FLW-BCKT-lirf-preamp1") {
+ field(DESC, "Linac RF Preamp 1")
+ field(ASG, "PROTECTED")
+ field(PINI, "YES")
+}
+
+record(bo, "$(DEVICE):CONTROL-FLW-BCKT-lirf-preamp2") {
+ field(DESC, "Linac RF Preamp 2")
+ field(ASG, "PROTECTED")
+ field(PINI, "YES")
+}
+
+record(bo, "$(DEVICE):CONTROL-FLW-BCKT-lirf-klystr1") {
+ field(DESC, "Linac RF Klystron 1")
+ field(ASG, "PROTECTED")
+ field(PINI, "YES")
+}
+
+record(bo, "$(DEVICE):CONTROL-FLW-BCKT-lirf-klystr2") {
+ field(DESC, "Linac RF Klystron 2")
+ field(ASG, "PROTECTED")
+ field(PINI, "YES")
+}
+
+record(bo, "$(DEVICE):CONTROL-FLW-BCKT-lirf-3GHzQdm") {
+ field(DESC, "Linac RF 3GHz Qdm")
+ field(ASG, "PROTECTED")
+ field(PINI, "YES")
+}
+
+record(bo, "$(DEVICE):CONTROL-FLW-BCKT-lirf-500-PBU") {
+ field(DESC, "Linac RF 500 MHz PBU")
+ field(ASG, "PROTECTED")
+ field(PINI, "YES")
+}
+
+record(bo, "$(DEVICE):CONTROL-FLW-BCKT-lirf-3GHzScp") {
+ field(DESC, "Linac RF 3 GHz Scope")
+ field(ASG, "PROTECTED")
+ field(PINI, "YES")
+}
+
+record(bo, "$(DEVICE):CONTROL-FLW-BCKT-lirf-Kly1PMU") {
+ field(DESC, "Linac RF Klystron 1 PMU")
+ field(ASG, "PROTECTED")
+ field(PINI, "YES")
+}
+
+record(bo, "$(DEVICE):CONTROL-FLW-BCKT-lirf-Kly2PMU") {
+ field(DESC, "Linac RF Klystron 2 PMU")
+ field(ASG, "PROTECTED")
+ field(PINI, "YES")
+}
+
+record(bo, "$(DEVICE):CONTROL-FLW-BCKT-BOINKI") {
+ field(DESC, "Booster Inj. Kicker")
+ field(ASG, "PROTECTED")
+ field(PINI, "YES")
+}
+
+record(bo, "$(DEVICE):CONTROL-FLW-BCKT-BOINSE") {
+ field(DESC, "Booster Inj. Septum")
+ field(ASG, "PROTECTED")
+ field(PINI, "YES")
+}
+
+record(bo, "$(DEVICE):CONTROL-FLW-BCKT-BOEXKI") {
+ field(DESC, "Booster Ext. Kicker")
+ field(ASG, "PROTECTED")
+ field(PINI, "YES")
+}
+
+record(bo, "$(DEVICE):CONTROL-FLW-BCKT-BOEXSE") {
+ field(DESC, "Booster Ext. Septum")
+ field(ASG, "PROTECTED")
+ field(PINI, "YES")
+}
+
+record(bo, "$(DEVICE):CONTROL-FLW-BCKT-BTRICT") {
+ field(DESC, "BRTL ICT")
+ field(ASG, "PROTECTED")
+ field(PINI, "YES")
+}
+
+record(bo, "$(DEVICE):CONTROL-FLW-BCKT-BTRBPM") {
+ field(DESC, "BRTL BPM")
+ field(ASG, "PROTECTED")
+ field(PINI, "YES")
+}
+
+record(bo, "$(DEVICE):CONTROL-FLW-BCKT-SRINSE") {
+ field(DESC, "Ring Inj. Septum")
+ field(ASG, "PROTECTED")
+ field(PINI, "YES")
+}
+
+record(bo, "$(DEVICE):CONTROL-FLW-BCKT-SRINK1") {
+ field(DESC, "Ring Inj. Kicker 1")
+ field(ASG, "PROTECTED")
+ field(PINI, "YES")
+}
+
+record(bo, "$(DEVICE):CONTROL-FLW-BCKT-SRINK2") {
+ field(DESC, "Ring Inj. Kicker 2")
+ field(ASG, "PROTECTED")
+ field(PINI, "YES")
+}
+
+record(bo, "$(DEVICE):CONTROL-FLW-BCKT-SRINK3") {
+ field(DESC, "Ring Inj. Kicker 3")
+ field(ASG, "PROTECTED")
+ field(PINI, "YES")
+}
+
+record(bo, "$(DEVICE):CONTROL-FLW-BCKT-SRINK4") {
+ field(DESC, "Ring Inj. Kicker 4")
+ field(ASG, "PROTECTED")
+ field(PINI, "YES")
+}
+
+###############################
+## base delays for bucket zero
+###############################
+
+record(ao, "$(DEVICE):CONTROL-ZERO-DELAY-GUN") {
+ field(DESC, "Gun delay for bucket zero")
+ field(ASG, "PROTECTED")
+ field(PREC, "0")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-ZERO-DELAY-lindi-ictone") {
+ field(DESC, "Linac ICT delay for bucket zero")
+ field(ASG, "PROTECTED")
+ field(PREC, "0")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-ZERO-DELAY-lindi-icts23") {
+ field(DESC, "Linac ICT delay for bucket zero")
+ field(ASG, "PROTECTED")
+ field(PREC, "0")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-ZERO-DELAY-lirf-llemast") {
+ field(DESC, "Linac RF lemast delay for bucket zero")
+ field(ASG, "PROTECTED")
+ field(PREC, "3")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-ZERO-DELAY-lirf-preamp1") {
+ field(DESC, "Linac RF reamp1 delay for bucket zero")
+ field(ASG, "PROTECTED")
+ field(PREC, "0")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-ZERO-DELAY-lirf-preamp2") {
+ field(DESC, "Linac RF reamp2 delay for bucket zero")
+ field(ASG, "PROTECTED")
+ field(PREC, "0")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-ZERO-DELAY-lirf-klystr1") {
+ field(DESC, "Linac RF lystr1 delay for bucket zero")
+ field(ASG, "PROTECTED")
+ field(PREC, "0")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-ZERO-DELAY-lirf-klystr2") {
+ field(DESC, "Linac RF lystr2 delay for bucket zero")
+ field(ASG, "PROTECTED")
+ field(PREC, "0")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-ZERO-DELAY-lirf-3GHzQdm") {
+ field(DESC, "Linac RF GHzQdm delay for bucket zero")
+ field(ASG, "PROTECTED")
+ field(PREC, "0")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-ZERO-DELAY-lirf-500-PBU") {
+ field(DESC, "Linac RF 00-PBU delay for bucket zero")
+ field(ASG, "PROTECTED")
+ field(PREC, "0")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-ZERO-DELAY-lirf-3GHzScp") {
+ field(DESC, "Linac RF GHzScp delay for bucket zero")
+ field(ASG, "PROTECTED")
+ field(PREC, "0")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-ZERO-DELAY-lirf-Kly1PMU") {
+ field(DESC, "Linac RF ly1PMU delay for bucket zero")
+ field(ASG, "PROTECTED")
+ field(PREC, "0")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-ZERO-DELAY-lirf-Kly2PMU") {
+ field(DESC, "Linac RF ly2PMU delay for bucket zero")
+ field(ASG, "PROTECTED")
+ field(PREC, "0")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-ZERO-DELAY-BOINKI") {
+ field(DESC, "Booster inj kicker delay for bucket zero")
+ field(ASG, "PROTECTED")
+ field(PREC, "0")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-ZERO-DELAY-BOINSE") {
+ field(DESC, "Booster inj sept delay for bucket zero")
+ field(ASG, "PROTECTED")
+ field(PREC, "0")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-ZERO-DELAY-BOEXKI") {
+ field(DESC, "Booster ext kicker delay for bucket zero")
+ field(ASG, "PROTECTED")
+ field(PREC, "0")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-ZERO-DELAY-BOEXSE") {
+ field(DESC, "Booster ext septum delay for bucket zero")
+ field(ASG, "PROTECTED")
+ field(PREC, "0")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-ZERO-DELAY-BTRICT") {
+ field(DESC, "BRTL ICT delay for bucket zero")
+ field(ASG, "PROTECTED")
+ field(PREC, "0")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-ZERO-DELAY-BTRBPM") {
+ field(DESC, "BRTL BPM delay for bucket zero")
+ field(ASG, "PROTECTED")
+ field(PREC, "0")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-ZERO-DELAY-SRINSE") {
+ field(DESC, "SR septum delay for bucket zero")
+ field(ASG, "PROTECTED")
+ field(PREC, "0")
+ field(PINI, "YES")
+}
+
+
+record(ao, "$(DEVICE):CONTROL-ZERO-DELAY-SRINK1") {
+ field(DESC, "SR kicker bump delay for bucket zero")
+ field(ASG, "PROTECTED")
+ field(PREC, "0")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-ZERO-DELAY-SRINK2") {
+ field(DESC, "SR kicker bump delay for bucket zero")
+ field(ASG, "PROTECTED")
+ field(PREC, "0")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-ZERO-DELAY-SRINK3") {
+ field(DESC, "SR kicker bump delay for bucket zero")
+ field(ASG, "PROTECTED")
+ field(PREC, "0")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-ZERO-DELAY-SRINK4") {
+ field(DESC, "SR kicker bump delay for bucket zero")
+ field(ASG, "PROTECTED")
+ field(PREC, "0")
+ field(PINI, "YES")
+}
+
+###############################
+## HLA pvs
+###############################
+
+record(lso, "$(DEVICE):CONTROL-FILLPATTERN-string") {
+ field(DESC, "Fillpattern - String Define")
+ field(OMSL, "supervisory")
+ field(SIZV, "1000")
+ field(PINI, "YES")
+}
+
+record(waveform,"$(DEVICE):TARGET-BUCKET") {
+ field(DESC, "Fillpattern - current bucket of 0...480")
+ field(ASG, "PROTECTED")
+ field(FTVL, "FLOAT")
+ field(NELM, "480")
+ field(PINI, "YES")
+}
+
+record(waveform,"$(DEVICE):TARGET-FILLPATTERN") {
+ field(DESC, "Fillpattern reference plot")
+ field(ASG, "PROTECTED")
+ field(FTVL, "FLOAT")
+ field(NELM, "480")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):SETALL-DELAY") {
+ field(DESC, "Delay for setting all timings")
+ field(EGU, "seconds")
+ field(VAL, "0")
+ field(PREC, "5")
+ field(PINI, "YES")
+}
+
+record(int64out, "$(DEVICE):SETALL-ERROR") {
+ field(DESC, "Error counter for setting all timings")
+ field(ASG, "PROTECTED")
+ field(VAL, "0")
+}
+
+record(bo,"$(DEVICE):ZERO-TARGET-BUCKET") {
+ field(DESC, "request target bucket 0")
+ field(ASG, "PROTECTED")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(bo,"$(DEVICE):SYNC-BASE-DELAYS") {
+ field(DESC, "request base delay sync to master")
+ field(ASG, "PROTECTED")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(bo,"$(DEVICE):GO") {
+ field(DESC, "pause/stop timing service callbacks")
+ field(ASG, "PROTECTED")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CURRENT-THRESHOLD") {
+ field(DESC, "current above which fpfb is started")
+ field(ASG, "PROTECTED")
+ field(EGU, "mA")
+ field(VAL, "300")
+ field(PREC, "5")
+ field(PINI, "YES")
+}
+
+record(int64out, "$(DEVICE):FPFB-NTH") {
+ field(DESC, "n for every nth bucket fpfb mode")
+ field(ASG, "PROTECTED")
+ field(VAL, "2")
+ field(PINI, "YES")
+}
+
+record(mbbo, "$(DEVICE):FPFB-MODE") {
+ field(DESC, "choice of fpfb mode to use")
+ field(ASG, "PROTECTED")
+ field(ZRST, "Sorted BPM Measurement")
+ field(ONST, "Sorted APD Measurement")
+ field(TWST, "FPFB from Pedro via EPICS")
+ field(THST, "Every Nth Bucket")
+ field(PINI, "YES")
+ field(VAL, "0")
+}
\ No newline at end of file
diff --git a/services/timing/current/ioc/cfg/AGEBD-CPCL-TIMING_set.req b/services/timing/current/ioc/cfg/AGEBD-CPCL-TIMING_set.req
new file mode 100644
index 0000000..4e0f824
--- /dev/null
+++ b/services/timing/current/ioc/cfg/AGEBD-CPCL-TIMING_set.req
@@ -0,0 +1,48 @@
+#ENABLE-PASS=2
+AGEBD-TIMING:CONTROL-ZERO-DELAY-GUN
+AGEBD-TIMING:CONTROL-ZERO-DELAY-lindi-ictone
+AGEBD-TIMING:CONTROL-ZERO-DELAY-lindi-icts23
+AGEBD-TIMING:CONTROL-ZERO-DELAY-lirf-llemast
+AGEBD-TIMING:CONTROL-ZERO-DELAY-lirf-preamp1
+AGEBD-TIMING:CONTROL-ZERO-DELAY-lirf-preamp2
+AGEBD-TIMING:CONTROL-ZERO-DELAY-lirf-klystr1
+AGEBD-TIMING:CONTROL-ZERO-DELAY-lirf-klystr2
+AGEBD-TIMING:CONTROL-ZERO-DELAY-lirf-3GHzQdm
+AGEBD-TIMING:CONTROL-ZERO-DELAY-lirf-500-PBU
+AGEBD-TIMING:CONTROL-ZERO-DELAY-lirf-3GHzScp
+AGEBD-TIMING:CONTROL-ZERO-DELAY-lirf-Kly1PMU
+AGEBD-TIMING:CONTROL-ZERO-DELAY-lirf-Kly2PMU
+AGEBD-TIMING:CONTROL-ZERO-DELAY-BOINKI
+AGEBD-TIMING:CONTROL-ZERO-DELAY-BOINSE
+AGEBD-TIMING:CONTROL-ZERO-DELAY-BOEXKI
+AGEBD-TIMING:CONTROL-ZERO-DELAY-BOEXSE
+AGEBD-TIMING:CONTROL-ZERO-DELAY-BTRICT
+AGEBD-TIMING:CONTROL-ZERO-DELAY-SRINSE
+AGEBD-TIMING:CONTROL-ZERO-DELAY-SRINK1
+AGEBD-TIMING:CONTROL-ZERO-DELAY-SRINK2
+AGEBD-TIMING:CONTROL-ZERO-DELAY-SRINK3
+AGEBD-TIMING:CONTROL-ZERO-DELAY-SRINK4
+AGEBD-TIMING:CONTROL-FLW-BCKT-GUN
+AGEBD-TIMING:CONTROL-FLW-BCKT-lindi-ictone
+AGEBD-TIMING:CONTROL-FLW-BCKT-lindi-icts23
+AGEBD-TIMING:CONTROL-FLW-BCKT-lirf-llemast
+AGEBD-TIMING:CONTROL-FLW-BCKT-lirf-preamp1
+AGEBD-TIMING:CONTROL-FLW-BCKT-lirf-preamp2
+AGEBD-TIMING:CONTROL-FLW-BCKT-lirf-klystr1
+AGEBD-TIMING:CONTROL-FLW-BCKT-lirf-klystr2
+AGEBD-TIMING:CONTROL-FLW-BCKT-lirf-3GHzQdm
+AGEBD-TIMING:CONTROL-FLW-BCKT-lirf-500-PBU
+AGEBD-TIMING:CONTROL-FLW-BCKT-lirf-3GHzScp
+AGEBD-TIMING:CONTROL-FLW-BCKT-lirf-Kly1PMU
+AGEBD-TIMING:CONTROL-FLW-BCKT-lirf-Kly2PMU
+AGEBD-TIMING:CONTROL-FLW-BCKT-BOINKI
+AGEBD-TIMING:CONTROL-FLW-BCKT-BOINSE
+AGEBD-TIMING:CONTROL-FLW-BCKT-BOEXKI
+AGEBD-TIMING:CONTROL-FLW-BCKT-BOEXSE
+AGEBD-TIMING:CONTROL-FLW-BCKT-BTRICT
+AGEBD-TIMING:CONTROL-FLW-BCKT-BTRBPM
+AGEBD-TIMING:CONTROL-FLW-BCKT-SRINSE
+AGEBD-TIMING:CONTROL-FLW-BCKT-SRINK1
+AGEBD-TIMING:CONTROL-FLW-BCKT-SRINK2
+AGEBD-TIMING:CONTROL-FLW-BCKT-SRINK3
+AGEBD-TIMING:CONTROL-FLW-BCKT-SRINK4
\ No newline at end of file
diff --git a/services/timing/current/ioc/startup.script b/services/timing/current/ioc/startup.script
new file mode 100644
index 0000000..0fa52ff
--- /dev/null
+++ b/services/timing/current/ioc/startup.script
@@ -0,0 +1 @@
+epicsEnvSet("ENGINEER", "armborst")
diff --git a/services/timing/current/qt/A_BD_Timing.ui b/services/timing/current/qt/A_BD_Timing.ui
new file mode 100644
index 0000000..596cb26
--- /dev/null
+++ b/services/timing/current/qt/A_BD_Timing.ui
@@ -0,0 +1,4571 @@
+
+
+ MainWindow
+
+
+
+ 0
+ 0
+ 750
+ 880
+
+
+
+
+
+
+ (Qt::Window | Qt::FramelessWindowHint);
+
+
+
+
+
+ 1390
+ 270
+ 70
+ 20
+
+
+
+
+
+
+ 1390
+ 210
+ 70
+ 20
+
+
+
+ Reload
+
+
+ RELOAD
+
+
+ A
+
+
+ AGEBD-ALH:TIMING-GUIRELOAD
+
+
+ caCalc::TriggerZeroToOne
+
+
+
+
+
+ 10
+ 20
+ 161
+ 31
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ Fillpattern
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+
+
+ 10
+ 170
+ 431
+ 705
+
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
+
+ 0
+ 10
+ 200
+ 25
+
+
+
+
+ 14
+
+
+
+ GUN
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 0
+ 100
+ 200
+ 25
+
+
+
+
+ 14
+
+
+
+ Linac - LLE Master
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 210
+ 10
+ 210
+ 25
+
+
+
+ 6
+
+
+ 0
+
+
+ AGEBD-TIMING:CONTROL-ZERO-DELAY-GUN
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 500.000000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 210
+ 100
+ 210
+ 25
+
+
+
+ 6
+
+
+ 3
+
+
+ AGEBD-TIMING:CONTROL-ZERO-DELAY-lirf-llemast
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 5.000000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 0
+ 400
+ 200
+ 25
+
+
+
+
+ 14
+
+
+
+ Booster Inj Kicker
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 210
+ 400
+ 210
+ 25
+
+
+
+ 6
+
+
+ 0
+
+
+ AGEBD-TIMING:CONTROL-ZERO-DELAY-BOINKI
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 10000000.000000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 0
+ 430
+ 200
+ 25
+
+
+
+
+ 14
+
+
+
+ Booster Inj Septum
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 210
+ 430
+ 210
+ 25
+
+
+
+ 6
+
+
+ 0
+
+
+ AGEBD-TIMING:CONTROL-ZERO-DELAY-BOINSE
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 10000000.000000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 210
+ 460
+ 210
+ 25
+
+
+
+ 6
+
+
+ 0
+
+
+ AGEBD-TIMING:CONTROL-ZERO-DELAY-BOEXKI
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ caSpinbox::User
+
+
+ 10000000.000000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 0
+ 460
+ 200
+ 25
+
+
+
+
+ 14
+
+
+
+ Booster Ext Kicker
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 210
+ 490
+ 210
+ 25
+
+
+
+ 6
+
+
+ 0
+
+
+ AGEBD-TIMING:CONTROL-ZERO-DELAY-BOEXSE
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ caSpinbox::User
+
+
+ 10000000.000000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 0
+ 490
+ 200
+ 25
+
+
+
+
+ 14
+
+
+
+ Booster Ext Septum
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 210
+ 550
+ 210
+ 25
+
+
+
+ 6
+
+
+ 0
+
+
+ AGEBD-TIMING:CONTROL-ZERO-DELAY-SRINSE
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ caSpinbox::User
+
+
+ 10000000.000000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 0
+ 550
+ 200
+ 25
+
+
+
+
+ 14
+
+
+
+ Ring Inj Septum
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 0
+ 580
+ 200
+ 25
+
+
+
+
+ 14
+
+
+
+ Ring Inj 4 Kicker K1
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 0
+ 520
+ 200
+ 25
+
+
+
+
+ 14
+
+
+
+ ICT 4 (BRTL)
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 210
+ 520
+ 210
+ 25
+
+
+
+ 6
+
+
+ 0
+
+
+ AGEBD-TIMING:CONTROL-ZERO-DELAY-BTRICT
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ caSpinbox::User
+
+
+ 10000000.000000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 0
+ 190
+ 200
+ 25
+
+
+
+
+ 14
+
+
+
+ Linac - Klystron 1
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 0
+ 310
+ 200
+ 25
+
+
+
+
+ 14
+
+
+
+ Linac - 3 GHz Scope
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 0
+ 220
+ 200
+ 25
+
+
+
+
+ 14
+
+
+
+ Linac - klystron 2
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 0
+ 160
+ 200
+ 25
+
+
+
+
+ 14
+
+
+
+ Linac - Preamp2
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 0
+ 130
+ 200
+ 25
+
+
+
+
+ 14
+
+
+
+ Linac - Preamp1
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 0
+ 250
+ 200
+ 25
+
+
+
+
+ 14
+
+
+
+ Linac - 3 GHz Qdm
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 0
+ 340
+ 200
+ 25
+
+
+
+
+ 14
+
+
+
+ Linac - Kly 1 PMU
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 0
+ 280
+ 200
+ 25
+
+
+
+
+ 14
+
+
+
+ Linac - 500 MHz_PBU
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 0
+ 370
+ 200
+ 25
+
+
+
+
+ 14
+
+
+
+ Linac - Kly 2 PMU
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 210
+ 220
+ 210
+ 25
+
+
+
+ 6
+
+
+ 0
+
+
+ AGEBD-TIMING:CONTROL-ZERO-DELAY-lirf-klystr2
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 10000000.000000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 210
+ 310
+ 210
+ 25
+
+
+
+ 6
+
+
+ 0
+
+
+ AGEBD-TIMING:CONTROL-ZERO-DELAY-lirf-3GHzScp
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 10000000.000000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 210
+ 280
+ 210
+ 25
+
+
+
+ 6
+
+
+ 0
+
+
+ AGEBD-TIMING:CONTROL-ZERO-DELAY-lirf-500-PBU
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 10000000.000000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 210
+ 340
+ 210
+ 25
+
+
+
+ 6
+
+
+ 0
+
+
+ AGEBD-TIMING:CONTROL-ZERO-DELAY-lirf-Kly1PMU
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 10000000.000000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 210
+ 190
+ 210
+ 25
+
+
+
+ 6
+
+
+ 0
+
+
+ AGEBD-TIMING:CONTROL-ZERO-DELAY-lirf-klystr1
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 10000000.000000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 210
+ 130
+ 210
+ 25
+
+
+
+ 6
+
+
+ 0
+
+
+ AGEBD-TIMING:CONTROL-ZERO-DELAY-lirf-preamp1
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 10000000.000000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 210
+ 250
+ 210
+ 25
+
+
+
+ 6
+
+
+ 0
+
+
+ AGEBD-TIMING:CONTROL-ZERO-DELAY-lirf-3GHzQdm
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 10000000.000000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 210
+ 160
+ 210
+ 25
+
+
+
+ 6
+
+
+ 0
+
+
+ AGEBD-TIMING:CONTROL-ZERO-DELAY-lirf-preamp2
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 10000000.000000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 210
+ 370
+ 210
+ 25
+
+
+
+ 6
+
+
+ 0
+
+
+ AGEBD-TIMING:CONTROL-ZERO-DELAY-lirf-Kly2PMU
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 10000000.000000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 0
+ 40
+ 200
+ 25
+
+
+
+
+ 14
+
+
+
+ ICT 1 & 2 (Linac)
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 0
+ 610
+ 200
+ 25
+
+
+
+
+ 14
+
+
+
+ Ring Inj 4 Kicker K2
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 0
+ 640
+ 200
+ 25
+
+
+
+
+ 14
+
+
+
+ Ring Inj 4 Kicker K3
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 0
+ 670
+ 200
+ 25
+
+
+
+
+ 14
+
+
+
+ Ring Inj 4 Kicker K4
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 210
+ 580
+ 210
+ 25
+
+
+
+ 6
+
+
+ 0
+
+
+ AGEBD-TIMING:CONTROL-ZERO-DELAY-SRINK1
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ caSpinbox::User
+
+
+ 10000000.000000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 210
+ 610
+ 210
+ 25
+
+
+
+ 6
+
+
+ 0
+
+
+ AGEBD-TIMING:CONTROL-ZERO-DELAY-SRINK2
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ caSpinbox::User
+
+
+ 10000000.000000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 210
+ 640
+ 210
+ 25
+
+
+
+ 6
+
+
+ 0
+
+
+ AGEBD-TIMING:CONTROL-ZERO-DELAY-SRINK3
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ caSpinbox::User
+
+
+ 10000000.000000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 210
+ 670
+ 210
+ 25
+
+
+
+ 6
+
+
+ 0
+
+
+ AGEBD-TIMING:CONTROL-ZERO-DELAY-SRINK4
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ caSpinbox::User
+
+
+ 10000000.000000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 0
+ 70
+ 200
+ 25
+
+
+
+
+ 14
+
+
+
+ ICT 3 (LTB)
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 210
+ 40
+ 210
+ 25
+
+
+
+ 6
+
+
+ 0
+
+
+ AGEBD-TIMING:CONTROL-ZERO-DELAY-lindi-ictone
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 10000000.000000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 210
+ 70
+ 210
+ 25
+
+
+
+ 6
+
+
+ 0
+
+
+ AGEBD-TIMING:CONTROL-ZERO-DELAY-lindi-icts23
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 10000000.000000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+
+ 480
+ 170
+ 260
+ 705
+
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
+
+ 10
+ 10
+ 100
+ 25
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ ALIRF-VME-A-GUN:CH1-DLY
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 0
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 400.000000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 10
+ 100
+ 100
+ 25
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ ALIRF-A1-LLE-CTR:MASTER-DELF
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 3
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 400.000000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 10
+ 400
+ 100
+ 25
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ ABOMA-VME-KY-EVR0:SETUP.OT1D
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 0
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 400.000000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 10
+ 430
+ 100
+ 25
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ ABOMA-VME-KY-EVR0:SETUP.OT0D
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 0
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 400.000000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 10
+ 460
+ 100
+ 25
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ ABOMA-VME-KY-EVR1:SETUP.OT1D
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 0
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 400.000000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 10
+ 520
+ 100
+ 25
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ ALIDI-CECL-DIAG:EEVR-EVENT2-PULSE-DELAY
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 0
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 400.000000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 10
+ 490
+ 100
+ 25
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ ABOMA-VME-KY-EVR1:SETUP.OT0D
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 0
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 400.000000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 10
+ 550
+ 100
+ 25
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ ABOMA-VME-KY-EVR1:SETUP.OT2D
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 0
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 400.000000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 10
+ 580
+ 100
+ 25
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ ABOMA-VME-KY-EVR1:SETUP.OT3D
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 0
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 400.000000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 10
+ 130
+ 100
+ 25
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ ALIRF-VME-A-EVR2:SETUP.OT0D
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 0
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 400.000000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 10
+ 160
+ 100
+ 25
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ ALIRF-VME-A-EVR2:SETUP.OT1D
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 0
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 400.000000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 10
+ 190
+ 100
+ 25
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ ALIRF-VME-A-EVR2:SETUP.OT2D
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 0
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 400.000000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 10
+ 220
+ 100
+ 25
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ ALIRF-VME-A-EVR2:SETUP.OT3D
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 0
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 400.000000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 10
+ 250
+ 100
+ 25
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ ALIRF-VME-A-EVR2:SETUP.OT4D
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 0
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 400.000000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 10
+ 340
+ 100
+ 25
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ ALIRF-VME-A-EVR2:SETUP.OTAD
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 0
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 400.000000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 10
+ 280
+ 100
+ 25
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ ALIRF-VME-A-EVR2:SETUP.OT5D
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 0
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 400.000000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 10
+ 370
+ 100
+ 25
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ ALIRF-VME-A-EVR2:SETUP.OTCD
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 0
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 400.000000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 10
+ 310
+ 100
+ 25
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ ALIRF-VME-A-EVR2:SETUP.OT6D
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 0
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 400.000000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 10
+ 40
+ 100
+ 25
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ ALIDI-CECL-DIAG:EEVR-EVENT0-PULSE-DELAY
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 0
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 1000000.000000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 10
+ 610
+ 100
+ 25
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ ABOMA-VME-KY-EVR1:SETUP.OTBD
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 0
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 400.000000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 10
+ 640
+ 100
+ 25
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ ABOMA-VME-KY-EVR1:SETUP.OTCD
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 0
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 400.000000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 10
+ 670
+ 100
+ 25
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ ABOMA-VME-KY-EVR1:SETUP.OTDD
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 0
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 400.000000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 10
+ 70
+ 100
+ 25
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ ALIDI-CECL-DIAG:EEVR-EVENT1-PULSE-DELAY
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 0
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 1000000.000000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 120
+ 310
+ 131
+ 25
+
+
+
+
+ 14
+
+
+
+ in 8 ns ticks
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 120
+ 340
+ 131
+ 25
+
+
+
+
+ 14
+
+
+
+ in 8 ns ticks
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 120
+ 280
+ 131
+ 25
+
+
+
+
+ 14
+
+
+
+ in 8 ns ticks
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 120
+ 160
+ 131
+ 25
+
+
+
+
+ 14
+
+
+
+ in 8 ns ticks
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 120
+ 220
+ 131
+ 25
+
+
+
+
+ 14
+
+
+
+ in 8 ns ticks
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 120
+ 610
+ 131
+ 25
+
+
+
+
+ 14
+
+
+
+ in 8 ns ticks
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 120
+ 130
+ 131
+ 25
+
+
+
+
+ 14
+
+
+
+ in 8 ns ticks
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 120
+ 370
+ 131
+ 25
+
+
+
+
+ 14
+
+
+
+ in 8 ns ticks
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 120
+ 40
+ 131
+ 25
+
+
+
+
+ 14
+
+
+
+ in 8 ns ticks
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 120
+ 400
+ 131
+ 25
+
+
+
+
+ 14
+
+
+
+ in 8 ns ticks
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 120
+ 520
+ 131
+ 25
+
+
+
+
+ 14
+
+
+
+ in 8 ns ticks
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 120
+ 430
+ 131
+ 25
+
+
+
+
+ 14
+
+
+
+ in 8 ns ticks
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 120
+ 550
+ 131
+ 25
+
+
+
+
+ 14
+
+
+
+ in 8 ns ticks
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 120
+ 190
+ 131
+ 25
+
+
+
+
+ 14
+
+
+
+ in 8 ns ticks
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 120
+ 640
+ 131
+ 25
+
+
+
+
+ 14
+
+
+
+ in 8 ns ticks
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 120
+ 10
+ 131
+ 25
+
+
+
+
+ 14
+
+
+
+ in 2 ns ticks
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 120
+ 100
+ 151
+ 25
+
+
+
+
+ 14
+
+
+
+ in us, 4 ns res
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 120
+ 460
+ 131
+ 25
+
+
+
+
+ 14
+
+
+
+ in 8 ns ticks
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 120
+ 670
+ 131
+ 25
+
+
+
+
+ 14
+
+
+
+ in 8 ns ticks
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 120
+ 250
+ 131
+ 25
+
+
+
+
+ 14
+
+
+
+ in 8 ns ticks
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 120
+ 70
+ 131
+ 25
+
+
+
+
+ 14
+
+
+
+ in 8 ns ticks
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 120
+ 580
+ 131
+ 25
+
+
+
+
+ 14
+
+
+
+ in 8 ns ticks
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 120
+ 490
+ 131
+ 25
+
+
+
+
+ 14
+
+
+
+ in 8 ns ticks
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+
+ 10
+ 50
+ 411
+ 30
+
+
+
+
+ 9
+
+
+
+ space separated bucket ranges (e.g., 0-450) and single buckets
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::WidthAndHeight
+
+
+
+
+
+ 550
+ 10
+ 100
+ 60
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ ALIRF-VME-A-GUN:CH1-DLY
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 0
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 400.000000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 410
+ 10
+ 140
+ 40
+
+
+
+
+ 25
+ 75
+ true
+
+
+
+ Bucket
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+
+
+ 440
+ 170
+ 41
+ 705
+
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
+
+ 10
+ 10
+ 30
+ 25
+
+
+
+
+
+
+
+ 30
+ 30
+
+
+
+ false
+
+
+ AGEBD-TIMING:CONTROL-FLW-BCKT-GUN
+
+
+
+
+
+ 10
+ 100
+ 30
+ 25
+
+
+
+
+
+
+
+ 30
+ 30
+
+
+
+ false
+
+
+ AGEBD-TIMING:CONTROL-FLW-BCKT-lirf-llemast
+
+
+
+
+
+ 10
+ 400
+ 30
+ 25
+
+
+
+
+
+
+
+ 30
+ 30
+
+
+
+ false
+
+
+ AGEBD-TIMING:CONTROL-FLW-BCKT-BOINKI
+
+
+
+
+
+ 10
+ 430
+ 30
+ 25
+
+
+
+
+
+
+
+ 30
+ 30
+
+
+
+ false
+
+
+ AGEBD-TIMING:CONTROL-FLW-BCKT-BOINSE
+
+
+
+
+
+ 10
+ 460
+ 30
+ 25
+
+
+
+
+
+
+
+ 30
+ 30
+
+
+
+ false
+
+
+ AGEBD-TIMING:CONTROL-FLW-BCKT-BOEXKI
+
+
+
+
+
+ 10
+ 490
+ 30
+ 25
+
+
+
+
+
+
+
+ 30
+ 30
+
+
+
+ false
+
+
+ AGEBD-TIMING:CONTROL-FLW-BCKT-BOEXSE
+
+
+
+
+
+ 10
+ 520
+ 30
+ 25
+
+
+
+
+
+
+
+ 30
+ 30
+
+
+
+ false
+
+
+ AGEBD-TIMING:CONTROL-FLW-BCKT-BTRICT
+
+
+
+
+
+ 10
+ 550
+ 30
+ 25
+
+
+
+
+
+
+
+ 30
+ 30
+
+
+
+ false
+
+
+ AGEBD-TIMING:CONTROL-FLW-BCKT-SRINSE
+
+
+
+
+
+ 10
+ 670
+ 30
+ 25
+
+
+
+
+
+
+
+ 30
+ 30
+
+
+
+ false
+
+
+ AGEBD-TIMING:CONTROL-FLW-BCKT-SRINK4
+
+
+
+
+
+ 10
+ 130
+ 30
+ 30
+
+
+
+
+
+
+
+ 30
+ 30
+
+
+
+ false
+
+
+ AGEBD-TIMING:CONTROL-FLW-BCKT-lirf-preamp1
+
+
+
+
+
+ 10
+ 250
+ 30
+ 25
+
+
+
+
+
+
+
+ 30
+ 30
+
+
+
+ false
+
+
+ AGEBD-TIMING:CONTROL-FLW-BCKT-lirf-3GHzQdm
+
+
+
+
+
+ 10
+ 280
+ 30
+ 25
+
+
+
+
+
+
+
+ 30
+ 30
+
+
+
+ false
+
+
+ AGEBD-TIMING:CONTROL-FLW-BCKT-lirf-500-PBU
+
+
+
+
+
+ 10
+ 160
+ 30
+ 25
+
+
+
+
+
+
+
+ 30
+ 30
+
+
+
+ false
+
+
+ AGEBD-TIMING:CONTROL-FLW-BCKT-lirf-preamp2
+
+
+
+
+
+ 10
+ 220
+ 30
+ 25
+
+
+
+
+
+
+
+ 30
+ 30
+
+
+
+ false
+
+
+ AGEBD-TIMING:CONTROL-FLW-BCKT-lirf-klystr2
+
+
+
+
+
+ 10
+ 310
+ 30
+ 25
+
+
+
+
+
+
+
+ 30
+ 30
+
+
+
+ false
+
+
+ AGEBD-TIMING:CONTROL-FLW-BCKT-lirf-3GHzScp
+
+
+
+
+
+ 10
+ 340
+ 30
+ 25
+
+
+
+
+
+
+
+ 30
+ 30
+
+
+
+ false
+
+
+ AGEBD-TIMING:CONTROL-FLW-BCKT-lirf-Kly1PMU
+
+
+
+
+
+ 10
+ 190
+ 30
+ 25
+
+
+
+
+
+
+
+ 30
+ 30
+
+
+
+ false
+
+
+ AGEBD-TIMING:CONTROL-FLW-BCKT-lirf-klystr1
+
+
+
+
+
+ 10
+ 370
+ 30
+ 25
+
+
+
+
+
+
+
+ 30
+ 30
+
+
+
+ false
+
+
+ AGEBD-TIMING:CONTROL-FLW-BCKT-lirf-Kly2PMU
+
+
+
+
+
+ 10
+ 40
+ 30
+ 25
+
+
+
+
+
+
+
+ 30
+ 30
+
+
+
+ false
+
+
+ AGEBD-TIMING:CONTROL-FLW-BCKT-lindi-ictone
+
+
+
+
+
+ 10
+ 70
+ 30
+ 25
+
+
+
+
+
+
+
+ 30
+ 30
+
+
+
+ false
+
+
+ AGEBD-TIMING:CONTROL-FLW-BCKT-lindi-icts23
+
+
+
+
+
+ 10
+ 640
+ 30
+ 25
+
+
+
+
+
+
+
+ 30
+ 30
+
+
+
+ false
+
+
+ AGEBD-TIMING:CONTROL-FLW-BCKT-SRINK3
+
+
+
+
+
+ 10
+ 610
+ 30
+ 25
+
+
+
+
+
+
+
+ 30
+ 30
+
+
+
+ false
+
+
+ AGEBD-TIMING:CONTROL-FLW-BCKT-SRINK2
+
+
+
+
+
+ 10
+ 580
+ 30
+ 25
+
+
+
+
+
+
+
+ 30
+ 30
+
+
+
+ false
+
+
+ AGEBD-TIMING:CONTROL-FLW-BCKT-SRINK1
+
+
+ catogglebutton_3
+ catogglebutton_6
+ catogglebutton_7
+ catogglebutton_10
+ catogglebutton_12
+ catogglebutton_15
+ catogglebutton_16
+ catogglebutton_19
+ catogglebutton_21
+ catogglebutton_23
+ catogglebutton_24
+ catogglebutton_28
+ catogglebutton_29
+ catogglebutton_32
+ catogglebutton_33
+ catogglebutton_34
+ catogglebutton_37
+ catogglebutton_2
+ catogglebutton
+ catogglebutton_5
+ catogglebutton_20
+ catogglebutton_22
+ catogglebutton_25
+
+
+
+
+ 571
+ 75
+ 80
+ 25
+
+
+
+
+ 13
+
+
+
+ Put Time
+
+
+ Qt::AlignCenter
+
+
+ ESimpleLabel::WidthAndHeight
+
+
+
+
+
+ 661
+ 80
+ 80
+ 20
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TIMING:SETALL-DELAY
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 5
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 400.000000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 660
+ 105
+ 80
+ 20
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TIMING:SETALL-ERROR
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 0
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 400.000000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+ true
+
+
+
+ 570
+ 105
+ 80
+ 25
+
+
+
+
+ 12
+
+
+
+ > 150 ms
+
+
+ Qt::AlignCenter
+
+
+ ESimpleLabel::WidthAndHeight
+
+
+
+
+
+ 10
+ 80
+ 550
+ 45
+
+
+
+ AGEBD-TIMING:CONTROL-FILLPATTERN-string.VAL
+
+
+ 0
+
+
+ caLineEdit::User
+
+
+ caLineEdit::User
+
+
+ 479.000000000000000
+
+
+
+
+
+ 660
+ 40
+ 80
+ 30
+
+
+
+
+ 14
+
+
+
+ Reset
+
+
+ EPushButton::WidthAndHeight
+
+
+ AGEBD-TIMING:ZERO-TARGET-BUCKET
+
+
+ Reset
+
+
+
+ 160
+ 160
+ 160
+
+
+
+
+ 160
+ 160
+ 160
+
+
+
+ onoff
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 400
+ 140
+ 81
+ 30
+
+
+
+
+ 16
+ 75
+ true
+
+
+
+ Follow
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 10
+ 140
+ 271
+ 30
+
+
+
+
+ 15
+ 75
+ true
+
+
+
+ Base Delays (Bucket 0)
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+
+
+ 490
+ 140
+ 241
+ 30
+
+
+
+
+ 15
+ 75
+ true
+
+
+
+ Changed EVR Delays
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+
+
+ 410
+ 50
+ 131
+ 20
+
+
+
+
+
+
+
+ 183
+ 157
+ 92
+
+
+
+ Timing Master
+
+
+ /ioc/modules/qt/A_GE_TI_MASTER_control_expert.ui
+
+
+ SYS=AGETI-CVME-MASTER,DEVICE=EVG0,TMA=TMA,DBUFF=DBUFF230,EVT=12,LINAC=ALIRF-VME-A,DEV_LINAC=EVR2,PM=ABOMA-VME-KY,DEV_PM1=EVR0,DEV_PM2=EVR1;stylefile=/sls/controls/config/qt/slses.qss
+
+
+ caRelatedDisplay::as_is
+
+
+
+
+
+ 310
+ 130
+ 70
+ 20
+
+
+
+ onoff
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 192
+ 192
+ 192
+
+
+
+ !A
+
+
+ AGEBD-ALH:TIMING-ONOFF
+
+
+
+
+
+ 660
+ 10
+ 80
+ 30
+
+
+
+
+ 14
+
+
+
+ Reset
+
+
+ EPushButton::WidthAndHeight
+
+
+ AGETI-CVME-MASTER-TMA:FP-Local-Reset-Bucket-SP
+
+
+ Reset
+
+
+
+ 160
+ 160
+ 160
+
+
+
+
+ 160
+ 160
+ 160
+
+
+
+ AGEBD-ALH:TIMING-ONOFF
+
+
+ 0
+
+
+ 1
+
+
+ frame
+ wmsignalpropagator
+ cacalc_2
+ calabel
+ frame_2
+ calabel_42
+ caLineEdit_35
+ calabel_43
+ frame_3
+ calabel_44
+ caLineEdit_47
+ caLineEdit_48
+ calabel_49
+ catextentry_5
+ camessagebutton_39
+ calabel_45
+ calabel_5
+ calabel_39
+ carelateddisplay_20
+ cacalc
+ camessagebutton_40
+
+
+
+
+ caRelatedDisplay
+ QWidget
+
+
+
+ caTextEntry
+ caLineEdit
+
+
+
+ caMessageButton
+ QPushButton
+
+
+
+ caToggleButton
+ QCheckBox
+
+
+
+ caSpinbox
+ QFrame
+
+
+
+ caLabel
+ QLabel
+
+
+
+ caLineEdit
+ QLineEdit
+
+
+
+ caCalc
+ QLabel
+
+
+
+ wmSignalPropagator
+ QLabel
+
+
+
+
+
+
+ cacalc_2
+ emitSignal(bool)
+ wmsignalpropagator
+ reloadwindow()
+
+
+ 1220
+ 224
+
+
+ 1222
+ 277
+
+
+
+
+
diff --git a/services/timing/current/systemd/AGEBD-SERVICE-TIMING.service b/services/timing/current/systemd/AGEBD-SERVICE-TIMING.service
new file mode 100644
index 0000000..596bcec
--- /dev/null
+++ b/services/timing/current/systemd/AGEBD-SERVICE-TIMING.service
@@ -0,0 +1,16 @@
+[Unit]
+Description=AGEBD-SERVICE-TIMING
+After=network.target
+
+[Service]
+Environment=AGEBD_ENV={{ agebd_env }}
+ExecStart=/sls/bd/hla/{{ agebd_env }}/bin/start_service.sh TIMING
+Restart=no
+
+[Install]
+WantedBy=default.target
+
+# https://www.freedesktop.org/software/systemd/man/latest/systemd.service.html
+# systemctl --user daemon-reload
+# systemctl --user enable /sls/bd/bin/systemd/AGEBD-SERVICE-TIMING.service
+# systemctl --user start AGEBD-SERVICE-TIMING
diff --git a/services/topuptool/current/app/pyproject.toml b/services/topuptool/current/app/pyproject.toml
new file mode 100644
index 0000000..9525511
--- /dev/null
+++ b/services/topuptool/current/app/pyproject.toml
@@ -0,0 +1,48 @@
+[project]
+name = "agebd-topuptool"
+version = "0.1.0"
+description = "AGEBD-TOPUPTOOL Service"
+requires-python = "==3.10.*"
+dependencies = [
+ "agebd",
+ "numpy>=2.2.6",
+]
+
+[dependency-groups]
+dev = [
+ "pyepics>=3.5.8",
+ "pytest>=8.4.2",
+ "ruff>=0.15.20",
+]
+
+[tool.uv.sources]
+# Path is relative to where agebd package is deployed on hla
+# machines (see CI/CD in .gitea/workflows)
+agebd = { path = "../../../../packages/agebd", editable = true }
+
+[build-system]
+requires = ["hatchling"]
+build-backend = "hatchling.build"
+
+[tool.uv]
+package = true
+
+[tool.pytest.ini_options]
+pythonpath = ["src"]
+env = [
+ "AGEBD_ENV=local",
+]
+
+[tool.ruff]
+include = [
+ "src/**/*.py",
+ "tests/**/*.py",
+]
+line-length = 100
+
+[tool.ruff.lint]
+# use isort to sort imports
+extend-select = ["I"]
+
+[tool.ruff.lint.isort]
+known-first-party = ["agebd"]
diff --git a/services/topuptool/current/app/src/agebd_topuptool/__init__.py b/services/topuptool/current/app/src/agebd_topuptool/__init__.py
new file mode 100644
index 0000000..1800c27
--- /dev/null
+++ b/services/topuptool/current/app/src/agebd_topuptool/__init__.py
@@ -0,0 +1 @@
+from .service import PVs, Service
diff --git a/services/topuptool/current/app/src/agebd_topuptool/main.py b/services/topuptool/current/app/src/agebd_topuptool/main.py
new file mode 100644
index 0000000..b23988c
--- /dev/null
+++ b/services/topuptool/current/app/src/agebd_topuptool/main.py
@@ -0,0 +1,35 @@
+import typer
+
+from agebd.enums import LogLevel
+from agebd.utils import init_logging
+from agebd_topuptool import PVs, Service
+from agebd_topuptool.runner import Runner
+
+# TODO: remove: cicd test 10
+
+
+def main(
+ log_level: LogLevel = typer.Option(
+ LogLevel.INFO,
+ "--log-level",
+ "-l",
+ # Looks at the OS env variable first. If empty, falls back to "INFO"
+ envvar="AGEBD_LOG_LEVEL",
+ # help="Set log level: DEBUG, INFO, WARNING, ERROR, CRITICAL",
+ case_sensitive=False,
+ ),
+):
+ """
+ Uses custom/old Runner because migrating to the agebd Runner would be quite
+ complex.
+ """
+ init_logging(log_level)
+ service_name = "TOPUPTOOL"
+ pvs = PVs(service_name=service_name)
+ service = Service(pvs=pvs)
+ runner = Runner(svc=service)
+ runner.start()
+
+
+if __name__ == "__main__":
+ typer.run(main)
diff --git a/services/topuptool/current/app/src/agebd_topuptool/runner.py b/services/topuptool/current/app/src/agebd_topuptool/runner.py
new file mode 100644
index 0000000..e1c36e1
--- /dev/null
+++ b/services/topuptool/current/app/src/agebd_topuptool/runner.py
@@ -0,0 +1,209 @@
+import traceback
+from time import perf_counter, sleep
+
+import numpy as np
+from epics import poll
+
+from agebd_topuptool.service import Service
+
+
+class Runner:
+ def __init__(self, svc: Service) -> None:
+ self.svc = svc
+
+ def start(self):
+ svc = self.svc
+ pvs = self.svc.pvs
+
+ while not pvs.abort.get():
+ if pvs.onoff.get() == 1:
+ # add callback for triggering the loop
+ if not svc.CallbackActive:
+ pvs.status.put("running")
+ pvs.vac_all.add_callback(
+ callback=self.svc.PressureChangeCallback, index=1, svc=svc
+ )
+ svc.CallbackActive = 1
+
+ # reload control PVs
+ svc.update()
+
+ # check stop/abort conitions if injection is active
+ if svc.injection:
+ # ensure disabled scrubbing during injection
+ svc.stop_scrubbing()
+
+ # abort injection when limits exceeded
+ if svc.conditions_abort_injection:
+ # disable injection when upper limit reached
+ svc.stop_injection()
+ print("injection aborted")
+
+ if not svc.abort:
+ svc.abort = 1
+ svc.abort_t0 = perf_counter()
+
+ svc.set_status(svc.states["abort"], wait=60)
+
+ elif svc.conditions_stop_injection:
+ # disable injection when upper limit reached
+ svc.stop_injection()
+ print("injection stopped")
+
+ # start scrubbing if activated
+ if svc.scrubbi:
+ sleep(0.1)
+ svc.start_scrubbing()
+
+ svc.set_status(svc.states["decay + scrub"])
+
+ else:
+ svc.set_status(svc.states["decay - scrub"])
+
+ elif svc.info != svc.states["inject"]:
+ svc.set_status(svc.states["inject"])
+
+ # do nothing if master trigger missing
+ elif not svc.trig_master:
+ svc.set_status(svc.states["wait 4 master"])
+
+ # do nothing for 60s if injection was aborted
+ elif svc.abort:
+ dt = perf_counter() - svc.abort_t0
+
+ if dt > 60:
+ svc.abort = 0
+
+ else:
+ svc.set_status(svc.states["abort"], wait=60 - dt)
+
+ sleep(0.1)
+
+ # start acting when callback fired or 100 ms passed
+ elif svc.ChangeTrue or perf_counter() > svc.tl + 0.1:
+ # start time for next loop firing, if no vacuum changes
+ svc.tl = perf_counter()
+
+ if svc.conditions_start_injection and svc.info not in [
+ svc.states["inject"],
+ svc.states["warmup"],
+ ]:
+ # disable injection to be sure
+ pvs.trig_guntxb.put(0)
+ pvs.trig_gunevt.put(0)
+ pvs.trig_booinj.put(0)
+ pvs.trig_boormp.put(0)
+ pvs.trig_booext.put(0)
+ pvs.trig_rininj.put(0)
+
+ # disable pingers for injection
+ svc.stop_scrubbing()
+
+ # make sure that injection bump and pinger not both fired
+ sleep(0.4)
+
+ svc.prepare_injection()
+
+ svc.tp = perf_counter()
+
+ # do top up analysis
+ svc.topup_dt = (svc.tp - svc.topup_t0) / 60
+ svc.topup_dI = svc.topup_I0 - pvs.cur.get()
+ pvs.topup_dt.put(svc.topup_dt)
+ pvs.topup_dI.put(svc.topup_dI)
+ if svc.topup_I0 > 0:
+ if svc.topup_dI / svc.topup_I0 < 1:
+ pvs.topup_tau.put(
+ (-svc.topup_dt / 60) / np.log(1 - svc.topup_dI / svc.topup_I0)
+ )
+
+ svc.set_status(svc.states["warmup"], wait=20)
+
+ elif svc.info == svc.states["warmup"]:
+ waited = perf_counter() - svc.tp
+
+ if waited > 20:
+ # disable pingers for injection
+ svc.stop_scrubbing()
+
+ sleep(0.5)
+
+ svc.start_injection()
+
+ svc.set_status(svc.states["inject"])
+
+ else:
+ svc.set_status(svc.states["warmup"], wait=20 - waited)
+
+ elif svc.info in [svc.states["pause"], svc.states["wait 4 master"]]:
+ if svc.injection:
+ svc.set_status(svc.states["inject"])
+ else:
+ if pvs.pinger_v.get():
+ svc.set_status(svc.states["decay + scrub"])
+ else:
+ svc.set_status(svc.states["decay - scrub"])
+
+ # stop scrubbing when deactivated
+ elif not svc.scrubbi:
+ svc.stop_scrubbing()
+
+ # if scrubbing activated and lifetime drops below 1 hour --> stop scrubbing
+ elif svc.scrubbi and svc.tau < 1:
+ svc.stop_scrubbing()
+ print("Scrubbing aborted, tau < 1")
+
+ svc.ChangeTrue = 0
+
+ # inform watchdog(s)
+ pvs.running.put(0)
+
+ # wait for callback to fire
+ poll(evt=1.0e-5, iot=0.1)
+
+ else:
+ # WHILE PAUSED REBOOT OF THE SCRUBBING IOC SHOULD NOT DISTURB THE SERVICE
+
+ if svc.CallbackActive:
+ # remove callback
+ pvs.vac_all.remove_callback(index=1)
+ svc.CallbackActive = 0
+
+ # reload control PVs
+ svc.update()
+
+ # disable injection and pingers when first paused
+ if svc.info != svc.states["pause"]:
+ svc.stop_injection()
+ svc.stop_scrubbing()
+
+ svc.set_status(svc.states["pause"])
+ pvs.status.put("paused")
+
+ sleep(0.1)
+
+ # sleep and inform watchdog(s)
+ pvs.alive.put(0)
+
+ if pvs.abort.get():
+ # confirm clean abort
+ pvs.status.put("killed")
+ print("Got Killed by Master Service!")
+ pvs.abortreq.put(0)
+
+ # elif svc.crashed:
+
+ # # confirm crash
+ # pvs.status.put('crashed')
+ # print('Service crashed on exception!')
+ # print('----- svc.exception.__traceback__ -----')
+ # print(svc.exception.__traceback__)
+ # print()
+ # print('----- traceback.format_exc() -----')
+ # print(traceback.format_exc())
+
+ else:
+ # confirm unknown exit
+ pvs.status.put("unknown crash")
+ print("Service crashed without exception!")
+ print(traceback.format_exc())
diff --git a/services/topuptool/current/app/src/agebd_topuptool/service.py b/services/topuptool/current/app/src/agebd_topuptool/service.py
new file mode 100644
index 0000000..3754214
--- /dev/null
+++ b/services/topuptool/current/app/src/agebd_topuptool/service.py
@@ -0,0 +1,256 @@
+from datetime import datetime
+from time import perf_counter
+
+import numpy as np
+from epics import PV, dbr
+
+from agebd.pv import LocalPVLink, get_pv_class
+from agebd.service.pvs import BasePVs
+from agebd.utils import printgetversion
+
+__version__ = printgetversion(__file__)
+
+PV = get_pv_class()
+
+
+class PVs(BasePVs):
+ ## Control PVs
+ # top-up control mode
+ # topumod = PV('.VAL')
+ # top-up mode vacuum limits
+ vac_max = PV("AGEBD-TOPUPTOOL:CONTROL-VACUUM-MAX.VAL")
+ vac_min = PV("AGEBD-TOPUPTOOL:CONTROL-VACUUM-MIN.VAL")
+ # top-up mode current limits
+ cur_max = PV("AGEBD-TOPUPTOOL:CONTROL-CURRENT-MAX.VAL")
+ cur_min = PV("AGEBD-TOPUPTOOL:CONTROL-CURRENT-MIN.VAL")
+ # top-up mode periodic refill (using cur_max)
+ # topufrq = PV('.VAL')
+
+ vac_dyn = PV("AGEBD-TOPUPTOOL:CONTROL-VACUUM-DYN.VAL")
+ vac_dyn_frac = PV("AGEBD-TOPUPTOOL:CONTROL-VACUUM-DYN-FRAC.VAL")
+
+ grd_max = PV("AGEBD-TOPUPTOOL:CONTROL-GUNGRID-MAX.VAL")
+ scrubbing = PV("AGEBD-TOPUPTOOL:CONTROL-SCRUB.VAL")
+
+ # Input PVs
+ vac_all = PV("ARIVA-VMAVE-ALL:PRESS-MAX.VAL")
+ vac_acc = PV("ARIVA-VMAVE:PRESS-MAX.VAL")
+ vac_fe = PV("ARIVA-VMAVE-FE:PRESS-MAX.VAL")
+ # cur = PV('AGEBD-DBPM3CURR:CURRENT-AVG.VAL')
+ cur = PV("ARS07-DPCT-0000:CURR.VAL")
+ injguard = PV("AGEBD-INJECTIONGUARD:CHECK-SUM.VAL")
+
+ injactive = PV("AGEBD-PARAMS:INJECTION-ACTIVE")
+
+ tau = PV("AGEBD-PARAMS:LIFETIME.VAL")
+
+ fpfb_adc = PV("ARSGE-CECL-FPFB:BEAM-DUMP-ABS-ADC-DATA")
+ fpfb_max = PV("ARSGE-CECL-FPFB:FPFB-BEAM-DUMP-THR")
+
+ # Regulated PVs
+ trig_master = PV("AGETI-CVME-MASTER-TMA:SR-Inj-Status-Sel.VAL")
+ trig_guntxb = PV("ALIRF-VME-A-GUN:CH1-MODE.VAL")
+ trig_gunevt = PV("AGETI-CVME-MASTER-TMA:Evt-LI-Gun-Ena-Sel.VAL")
+ trig_booinj = PV("AGETI-CVME-MASTER-TMA:Evt-BO-Inj-Ena-Sel.VAL")
+ trig_boormp = PV("AGETI-CVME-MASTER-TMA:Evt-Old-BO-HW-Ena-Sel.VAL")
+ trig_booext = PV(
+ "AGETI-CVME-MASTER-TMA:Evt-BO-Ext-Ena-Sel.VAL"
+ ) # Alias AGETI-CVME-MASTER-TMA:Evt-10
+ trig_rininj = PV(
+ "AGETI-CVME-MASTER-TMA:Evt-SR-Inj-Ena-Sel.VAL"
+ ) # Alias AGETI-CVME-MASTER-TMA:Evt-26
+ gun_grid = PV("ALIRF-GUN-GRID:V-SET.VAL")
+ pinger_v = PV("ARS01-MKIK-0320:CTRL-ON-OFF.VAL")
+ pinger_h = PV("ARS01-MKIK-0290:CTRL-ON-OFF.VAL")
+
+ topup_dt = PV("AGEBD-TOPUPTOOL:TOPUP-DELTAT.VAL")
+ topup_dI = PV("AGEBD-TOPUPTOOL:TOPUP-DELTAI.VAL")
+ topup_tau = PV("AGEBD-TOPUPTOOL:TOPUP-TAU.VAL")
+
+ def __init__(self, service_name: str, pv_factory=PV):
+ super().__init__(service_name, pv_factory)
+ PV = pv_factory
+
+ # TODO: can we do this cleaner? Maybe mechanism for
+ # settings initial values in dev mode (e.g. ini file)
+ if isinstance(self.onoff, LocalPVLink):
+ self.onoff.value = True
+
+ # Option 2:
+ ## Service specific PVs from dedicated IOC
+ self.my_pv2 = PV("AGEBD-TOPUPTOOL:BO") # TODO: is this a good PV to use?
+
+ ## Service specific PVs from other IOCs
+ # ...
+
+ # TODO: class attribute names usually lowercase
+ # usually it is advisable to trigger the mainloop of a service on changes of certain PVs:
+ self.CallbackPV = PV("AGEBD-TOPUPTOOL:CALLBACK", auto_monitor=dbr.DBE_VALUE) # TODO: ok?
+
+
+class Service:
+ ## define some "static" class attributes, i.e., persistent over every class call v = vals()
+ # trigger for execution of loop (controlled by PV callback)
+ ChangeTrue = 0
+ # current state of callback
+ CallbackActive = 0
+ # start time for next loop firing, if no vacuum changes
+ tl = perf_counter()
+ # waittime before injection after preparation
+ tp = perf_counter()
+ # status for GUI message
+ status = "Service Restarted"
+ # injection abort status
+ abort = 0
+ # injection abort timer
+ abort_t0 = perf_counter()
+ # states of state machine
+ states = {
+ "abort": "Injection Abort",
+ "decay + scrub": "Decaying Beam, Scrub ON",
+ "decay - scrub": "Decaying Beam, Scrub OFF",
+ "inject": "Injecting",
+ "wait 4 master": "Waiting for Master Trigger",
+ "warmup": "Septum Warmup",
+ "pause": "Service Paused",
+ }
+
+ def __init__(self, pvs: PVs):
+ self.pvs = pvs
+
+ pvs.started.put(str(datetime.now())[:-7])
+ pvs.version.put(__version__)
+
+ # self.vac = np.max([pv.get() for pv in pvs.vac])
+ self.vac = pvs.vac_all.get()
+ self.vac_acc = pvs.vac_acc.get()
+ # self.vac = pvs.vac_fe.get()
+ self.vac_array = np.repeat(self.vac_acc, 10)
+ self.vac_dyn = self.vac * pvs.vac_dyn_frac.get()
+ pvs.vac_dyn.put(self.vac_dyn * 1e9)
+
+ self.topup_t0 = perf_counter()
+ self.topup_I0 = pvs.cur_min.get()
+ self.topup_dI = 0
+ self.topup_dt = 0
+
+ def update(self):
+ pvs = self.pvs
+
+ # (re-)load input PVs
+ self.injection = pvs.injactive.get()
+ self.vac = pvs.vac_all.get()
+ self.vac_acc = pvs.vac_acc.get()
+ self.cur = pvs.cur.get()
+ self.trig_master = pvs.trig_master.get()
+ self.injguard = pvs.injguard.get()
+ self.info = pvs.info.get().split(",")[0]
+ self.tau = pvs.tau.get()
+
+ # (re-)load control PVs
+ self.vac_max = pvs.vac_max.get() * 1e-9
+ self.vac_dyn = np.max(self.vac_array[:5]) * pvs.vac_dyn_frac.get()
+ pvs.vac_dyn.put(self.vac_dyn * 1e9)
+
+ # roll oldest value arr[0] to end, i.e., arr[-1]
+ self.vac_array = np.roll(self.vac_array, -2)
+ # replace oldest value with new value
+ self.vac_array[-2:] = self.vac_acc
+
+ self.vac_min = pvs.vac_min.get() * 1e-9
+ self.cur_max = pvs.cur_max.get()
+ self.cur_min = pvs.cur_min.get()
+ self.grd_max = pvs.grd_max.get()
+ self.scrubbi = pvs.scrubbing.get()
+
+ self.conditions_start_injection = ( # is any lower limit reached?
+ self.vac <= self.vac_min or self.cur <= self.cur_min
+ ) and ( # is no upper limit exceeded ?
+ self.cur <= self.cur_max and self.vac <= self.vac_max and self.vac_acc <= self.vac_dyn
+ )
+
+ self.conditions_stop_injection = (
+ # is upper current limit reached/exceeded?
+ self.cur >= self.cur_max or self.vac >= self.vac_max
+ )
+
+ self.conditions_abort_injection = (
+ # is any upper limit reached/exceeded?
+ self.vac_acc >= self.vac_dyn
+ or np.max(pvs.fpfb_adc.get()) >= 0.95 * pvs.fpfb_max.get()
+ or self.cur > self.cur_max * 1.02
+ or self.injguard != 1
+ )
+
+ def stop_injection(self):
+ pvs = self.pvs
+
+ # disable gun trigger
+ pvs.trig_guntxb.put(0)
+
+ # stop all injection events
+ pvs.trig_gunevt.put(0)
+ pvs.trig_booinj.put(0)
+ pvs.trig_boormp.put(0)
+ pvs.trig_booext.put(0)
+ pvs.trig_rininj.put(0)
+
+ self.injection = 0
+
+ # prepare top-up analysis
+ self.topup_I0 = pvs.cur.get()
+ self.topup_t0 = perf_counter()
+
+ def start_injection(self):
+ pvs = self.pvs
+
+ # enable gun trigger
+ pvs.trig_guntxb.put(2)
+
+ def prepare_injection(self):
+ pvs = self.pvs
+
+ # ensure correct injector settings
+ pvs.gun_grid.put(self.grd_max)
+
+ # start all injection events
+ pvs.trig_gunevt.put(1)
+ pvs.trig_booinj.put(1)
+ pvs.trig_boormp.put(1)
+ pvs.trig_booext.put(1)
+ pvs.trig_rininj.put(1)
+
+ def start_scrubbing(self):
+ pvs = self.pvs
+
+ pvs.pinger_v.put(1)
+ pvs.pinger_h.put(1)
+ print("pingers switched ON")
+
+ def stop_scrubbing(self):
+ pvs = self.pvs
+
+ if pvs.pinger_v.get():
+ pvs.pinger_v.put(0)
+ print("Vertical pinger switched OFF")
+
+ if pvs.pinger_h.get():
+ pvs.pinger_h.put(0)
+ print("Horizontal pinger switched OFF")
+
+ def set_status(self, status, wait=0):
+ pvs = self.pvs
+
+ if self.info != status:
+ self.info = status
+
+ if wait == 0:
+ pvs.info.put(status)
+
+ if wait > 0:
+ pvs.info.put(status + ", Wait {:.0f}s".format(wait))
+
+ # define callback function to trigger loop execution on change of corresponding pv change
+ def PressureChangeCallback(self, pvname=None, value=None, char_value=None, **kw):
+ # trigger execution of loop with actual callback since execution of code here not reliable
+ self.ChangeTrue += 1
diff --git a/services/topuptool/current/app/tests/test_app.py b/services/topuptool/current/app/tests/test_app.py
new file mode 100644
index 0000000..d639688
--- /dev/null
+++ b/services/topuptool/current/app/tests/test_app.py
@@ -0,0 +1,8 @@
+from agebd_topuptool import PVs, Service
+
+
+def test_app():
+ service_name = "DUMMY"
+ pvs = PVs(service_name=service_name)
+ service = Service(pvs=pvs)
+ service.update()
diff --git a/services/topuptool/current/app/uv.lock b/services/topuptool/current/app/uv.lock
new file mode 100644
index 0000000..a521ef2
--- /dev/null
+++ b/services/topuptool/current/app/uv.lock
@@ -0,0 +1,301 @@
+version = 1
+revision = 3
+requires-python = "==3.10.*"
+
+[[package]]
+name = "agebd"
+version = "0.1.0"
+source = { editable = "../../../../packages/agebd" }
+dependencies = [
+ { name = "h5py" },
+ { name = "typer" },
+]
+
+[package.metadata]
+requires-dist = [
+ { name = "h5py", specifier = ">=3.16.0" },
+ { name = "typer", specifier = ">=0.23.2" },
+]
+
+[package.metadata.requires-dev]
+dev = [
+ { name = "pyright", specifier = ">=1.1.410" },
+ { name = "pytest", specifier = ">=8.4.2" },
+ { name = "ruff", specifier = ">=0.15.19" },
+]
+
+[[package]]
+name = "agebd-topuptool"
+version = "0.1.0"
+source = { editable = "." }
+dependencies = [
+ { name = "agebd" },
+ { name = "numpy" },
+]
+
+[package.dev-dependencies]
+dev = [
+ { name = "pyepics" },
+ { name = "pytest" },
+ { name = "ruff" },
+]
+
+[package.metadata]
+requires-dist = [
+ { name = "agebd", editable = "../../../../packages/agebd" },
+ { name = "numpy", specifier = ">=2.2.6" },
+]
+
+[package.metadata.requires-dev]
+dev = [
+ { name = "pyepics", specifier = ">=3.5.8" },
+ { name = "pytest", specifier = ">=8.4.2" },
+ { name = "ruff", specifier = ">=0.15.20" },
+]
+
+[[package]]
+name = "annotated-doc"
+version = "0.0.4"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/57/ba/046ceea27344560984e26a590f90bc7f4a75b06701f653222458922b558c/annotated_doc-0.0.4.tar.gz", hash = "sha256:fbcda96e87e9c92ad167c2e53839e57503ecfda18804ea28102353485033faa4", size = 7288, upload-time = "2025-11-10T22:07:42.062Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl", hash = "sha256:571ac1dc6991c450b25a9c2d84a3705e2ae7a53467b5d111c24fa8baabbed320", size = 5303, upload-time = "2025-11-10T22:07:40.673Z" },
+]
+
+[[package]]
+name = "colorama"
+version = "0.4.6"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" },
+]
+
+[[package]]
+name = "exceptiongroup"
+version = "1.3.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "typing-extensions" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" },
+]
+
+[[package]]
+name = "h5py"
+version = "3.16.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "numpy" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/db/33/acd0ce6863b6c0d7735007df01815403f5589a21ff8c2e1ee2587a38f548/h5py-3.16.0.tar.gz", hash = "sha256:a0dbaad796840ccaa67a4c144a0d0c8080073c34c76d5a6941d6818678ef2738", size = 446526, upload-time = "2026-03-06T13:49:08.07Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/3a/6b/231413e58a787a89b316bb0d1777da3c62257e4797e09afd8d17ad3549dc/h5py-3.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e06f864bedb2c8e7c1358e6c73af48519e317457c444d6f3d332bb4e8fa6d7d9", size = 3724137, upload-time = "2026-03-06T13:47:35.242Z" },
+ { url = "https://files.pythonhosted.org/packages/74/f9/557ce3aad0fe8471fb5279bab0fc56ea473858a022c4ce8a0b8f303d64e9/h5py-3.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ec86d4fffd87a0f4cb3d5796ceb5a50123a2a6d99b43e616e5504e66a953eca3", size = 3090112, upload-time = "2026-03-06T13:47:37.634Z" },
+ { url = "https://files.pythonhosted.org/packages/7a/f5/e15b3d0dc8a18e56409a839e6468d6fb589bc5207c917399c2e0706eeb44/h5py-3.16.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:86385ea895508220b8a7e45efa428aeafaa586bd737c7af9ee04661d8d84a10d", size = 4844847, upload-time = "2026-03-06T13:47:39.811Z" },
+ { url = "https://files.pythonhosted.org/packages/cb/92/a8851d936547efe30cc0ce5245feac01f3ec6171f7899bc3f775c72030b3/h5py-3.16.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:8975273c2c5921c25700193b408e28d6bdd0111c37468b2d4e25dcec4cd1d84d", size = 5065352, upload-time = "2026-03-06T13:47:41.489Z" },
+ { url = "https://files.pythonhosted.org/packages/2b/ae/f2adc5d0ca9626db3277a3d87516e124cbc5d0eea0bd79bc085702d04f2c/h5py-3.16.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:1677ad48b703f44efc9ea0c3ab284527f81bc4f318386aaaebc5fede6bbae56f", size = 4839173, upload-time = "2026-03-06T13:47:43.586Z" },
+ { url = "https://files.pythonhosted.org/packages/64/0b/e0c8c69da1d8838da023a50cd3080eae5d475691f7636b35eff20bb6ef20/h5py-3.16.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7c4dd4cf5f0a4e36083f73172f6cfc25a5710789269547f132a20975bfe2434c", size = 5076216, upload-time = "2026-03-06T13:47:45.315Z" },
+ { url = "https://files.pythonhosted.org/packages/66/35/d88fd6718832133c885004c61ceeeb24dbd6397ef877dbed6b3a64d6a286/h5py-3.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:bdef06507725b455fccba9c16529121a5e1fbf56aa375f7d9713d9e8ff42454d", size = 3183639, upload-time = "2026-03-06T13:47:47.041Z" },
+]
+
+[[package]]
+name = "iniconfig"
+version = "2.3.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" },
+]
+
+[[package]]
+name = "markdown-it-py"
+version = "4.2.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "mdurl" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/06/ff/7841249c247aa650a76b9ee4bbaeae59370dc8bfd2f6c01f3630c35eb134/markdown_it_py-4.2.0.tar.gz", hash = "sha256:04a21681d6fbb623de53f6f364d352309d4094dd4194040a10fd51833e418d49", size = 82454, upload-time = "2026-05-07T12:08:28.36Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl", hash = "sha256:9f7ebbcd14fe59494226453aed97c1070d83f8d24b6fc3a3bcf9a38092641c4a", size = 91687, upload-time = "2026-05-07T12:08:27.182Z" },
+]
+
+[[package]]
+name = "mdurl"
+version = "0.1.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" },
+]
+
+[[package]]
+name = "numpy"
+version = "2.2.6"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/76/21/7d2a95e4bba9dc13d043ee156a356c0a8f0c6309dff6b21b4d71a073b8a8/numpy-2.2.6.tar.gz", hash = "sha256:e29554e2bef54a90aa5cc07da6ce955accb83f21ab5de01a62c8478897b264fd", size = 20276440, upload-time = "2025-05-17T22:38:04.611Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/9a/3e/ed6db5be21ce87955c0cbd3009f2803f59fa08df21b5df06862e2d8e2bdd/numpy-2.2.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b412caa66f72040e6d268491a59f2c43bf03eb6c96dd8f0307829feb7fa2b6fb", size = 21165245, upload-time = "2025-05-17T21:27:58.555Z" },
+ { url = "https://files.pythonhosted.org/packages/22/c2/4b9221495b2a132cc9d2eb862e21d42a009f5a60e45fc44b00118c174bff/numpy-2.2.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e41fd67c52b86603a91c1a505ebaef50b3314de0213461c7a6e99c9a3beff90", size = 14360048, upload-time = "2025-05-17T21:28:21.406Z" },
+ { url = "https://files.pythonhosted.org/packages/fd/77/dc2fcfc66943c6410e2bf598062f5959372735ffda175b39906d54f02349/numpy-2.2.6-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:37e990a01ae6ec7fe7fa1c26c55ecb672dd98b19c3d0e1d1f326fa13cb38d163", size = 5340542, upload-time = "2025-05-17T21:28:30.931Z" },
+ { url = "https://files.pythonhosted.org/packages/7a/4f/1cb5fdc353a5f5cc7feb692db9b8ec2c3d6405453f982435efc52561df58/numpy-2.2.6-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:5a6429d4be8ca66d889b7cf70f536a397dc45ba6faeb5f8c5427935d9592e9cf", size = 6878301, upload-time = "2025-05-17T21:28:41.613Z" },
+ { url = "https://files.pythonhosted.org/packages/eb/17/96a3acd228cec142fcb8723bd3cc39c2a474f7dcf0a5d16731980bcafa95/numpy-2.2.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:efd28d4e9cd7d7a8d39074a4d44c63eda73401580c5c76acda2ce969e0a38e83", size = 14297320, upload-time = "2025-05-17T21:29:02.78Z" },
+ { url = "https://files.pythonhosted.org/packages/b4/63/3de6a34ad7ad6646ac7d2f55ebc6ad439dbbf9c4370017c50cf403fb19b5/numpy-2.2.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc7b73d02efb0e18c000e9ad8b83480dfcd5dfd11065997ed4c6747470ae8915", size = 16801050, upload-time = "2025-05-17T21:29:27.675Z" },
+ { url = "https://files.pythonhosted.org/packages/07/b6/89d837eddef52b3d0cec5c6ba0456c1bf1b9ef6a6672fc2b7873c3ec4e2e/numpy-2.2.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:74d4531beb257d2c3f4b261bfb0fc09e0f9ebb8842d82a7b4209415896adc680", size = 15807034, upload-time = "2025-05-17T21:29:51.102Z" },
+ { url = "https://files.pythonhosted.org/packages/01/c8/dc6ae86e3c61cfec1f178e5c9f7858584049b6093f843bca541f94120920/numpy-2.2.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8fc377d995680230e83241d8a96def29f204b5782f371c532579b4f20607a289", size = 18614185, upload-time = "2025-05-17T21:30:18.703Z" },
+ { url = "https://files.pythonhosted.org/packages/5b/c5/0064b1b7e7c89137b471ccec1fd2282fceaae0ab3a9550f2568782d80357/numpy-2.2.6-cp310-cp310-win32.whl", hash = "sha256:b093dd74e50a8cba3e873868d9e93a85b78e0daf2e98c6797566ad8044e8363d", size = 6527149, upload-time = "2025-05-17T21:30:29.788Z" },
+ { url = "https://files.pythonhosted.org/packages/a3/dd/4b822569d6b96c39d1215dbae0582fd99954dcbcf0c1a13c61783feaca3f/numpy-2.2.6-cp310-cp310-win_amd64.whl", hash = "sha256:f0fd6321b839904e15c46e0d257fdd101dd7f530fe03fd6359c1ea63738703f3", size = 12904620, upload-time = "2025-05-17T21:30:48.994Z" },
+ { url = "https://files.pythonhosted.org/packages/9e/3b/d94a75f4dbf1ef5d321523ecac21ef23a3cd2ac8b78ae2aac40873590229/numpy-2.2.6-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0b605b275d7bd0c640cad4e5d30fa701a8d59302e127e5f79138ad62762c3e3d", size = 21040391, upload-time = "2025-05-17T21:44:35.948Z" },
+ { url = "https://files.pythonhosted.org/packages/17/f4/09b2fa1b58f0fb4f7c7963a1649c64c4d315752240377ed74d9cd878f7b5/numpy-2.2.6-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:7befc596a7dc9da8a337f79802ee8adb30a552a94f792b9c9d18c840055907db", size = 6786754, upload-time = "2025-05-17T21:44:47.446Z" },
+ { url = "https://files.pythonhosted.org/packages/af/30/feba75f143bdc868a1cc3f44ccfa6c4b9ec522b36458e738cd00f67b573f/numpy-2.2.6-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce47521a4754c8f4593837384bd3424880629f718d87c5d44f8ed763edd63543", size = 16643476, upload-time = "2025-05-17T21:45:11.871Z" },
+ { url = "https://files.pythonhosted.org/packages/37/48/ac2a9584402fb6c0cd5b5d1a91dcf176b15760130dd386bbafdbfe3640bf/numpy-2.2.6-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d042d24c90c41b54fd506da306759e06e568864df8ec17ccc17e9e884634fd00", size = 12812666, upload-time = "2025-05-17T21:45:31.426Z" },
+]
+
+[[package]]
+name = "packaging"
+version = "26.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d7/f1/e7a6dd94a8d4a5626c03e4e99c87f241ba9e350cd9e6d75123f992427270/packaging-26.2.tar.gz", hash = "sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661", size = 228134, upload-time = "2026-04-24T20:15:23.917Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/df/b2/87e62e8c3e2f4b32e5fe99e0b86d576da1312593b39f47d8ceef365e95ed/packaging-26.2-py3-none-any.whl", hash = "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e", size = 100195, upload-time = "2026-04-24T20:15:22.081Z" },
+]
+
+[[package]]
+name = "pluggy"
+version = "1.6.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" },
+]
+
+[[package]]
+name = "pyepics"
+version = "3.5.10"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "numpy" },
+ { name = "pyparsing" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/69/57/29e1e9ef11ba2a3419f489946ae1d8190025a1e4f4e1c1686758bb2b6e0a/pyepics-3.5.10.tar.gz", hash = "sha256:f390cf9be40aba757b9528888114bc14d8db01086d0c93914720b1772460375b", size = 6150481, upload-time = "2026-05-20T18:44:36.336Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d6/36/e517fd83bd97d6bfe4105e0c6b322070c5cc36fb56a8fab2866e319f8804/pyepics-3.5.10-py3-none-any.whl", hash = "sha256:c9fac2c54f2b595268e66fc348cf5ec24e63718e7dbd07d73d1b37d4da6bfee1", size = 5332376, upload-time = "2026-05-20T18:44:34.242Z" },
+]
+
+[[package]]
+name = "pygments"
+version = "2.20.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" },
+]
+
+[[package]]
+name = "pyparsing"
+version = "3.3.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f3/91/9c6ee907786a473bf81c5f53cf703ba0957b23ab84c264080fb5a450416f/pyparsing-3.3.2.tar.gz", hash = "sha256:c777f4d763f140633dcb6d8a3eda953bf7a214dc4eff598413c070bcdc117cbc", size = 6851574, upload-time = "2026-01-21T03:57:59.36Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl", hash = "sha256:850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d", size = 122781, upload-time = "2026-01-21T03:57:55.912Z" },
+]
+
+[[package]]
+name = "pytest"
+version = "9.1.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "colorama", marker = "sys_platform == 'win32'" },
+ { name = "exceptiongroup" },
+ { name = "iniconfig" },
+ { name = "packaging" },
+ { name = "pluggy" },
+ { name = "pygments" },
+ { name = "tomli" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/e4/47/b9efed96c114afcfa3c9d3fe98a76a1d14c74a9e266d397cf6eb64be5e01/pytest-9.1.1.tar.gz", hash = "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313", size = 1636369, upload-time = "2026-06-19T10:58:32.857Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/24/25/1de2678b631f5a49215c6c96fff41ba892b0a34df68d6d80292b1b48aa7f/pytest-9.1.1-py3-none-any.whl", hash = "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c", size = 386536, upload-time = "2026-06-19T10:58:31.347Z" },
+]
+
+[[package]]
+name = "rich"
+version = "15.0.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "markdown-it-py" },
+ { name = "pygments" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/c0/8f/0722ca900cc807c13a6a0c696dacf35430f72e0ec571c4275d2371fca3e9/rich-15.0.0.tar.gz", hash = "sha256:edd07a4824c6b40189fb7ac9bc4c52536e9780fbbfbddf6f1e2502c31b068c36", size = 230680, upload-time = "2026-04-12T08:24:00.75Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl", hash = "sha256:33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb", size = 310654, upload-time = "2026-04-12T08:24:02.83Z" },
+]
+
+[[package]]
+name = "ruff"
+version = "0.15.21"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/0f/36/6f65aa9989acdec45d417192d8f4e7921931d8a6cf87ac74bce3eed98a8e/ruff-0.15.21.tar.gz", hash = "sha256:d0cfc841c572283c36548f82664a54ce6565567f1b0d5b4cf2caac693d8b7500", size = 4769401, upload-time = "2026-07-09T20:01:34.005Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d0/c6/ede15cac6839f3dbce52565c8f5164a8210e669c7bc4decb03e5bdf47d0d/ruff-0.15.21-py3-none-linux_armv6l.whl", hash = "sha256:63ea0e965e5d73c90e95b2434beeafc70820536717f561b32ab6e777cb9bdf5d", size = 10854342, upload-time = "2026-07-09T20:00:53.998Z" },
+ { url = "https://files.pythonhosted.org/packages/28/9d/d825b07ee7ea9e2d61df92a860033c94e06e7300d50a1c2653aac27d24fe/ruff-0.15.21-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:0f212c5d7d54c01bbfe6dcab02b724a39300f3e34ed7acbe995ccb320a2c58bd", size = 11139539, upload-time = "2026-07-09T20:00:57.809Z" },
+ { url = "https://files.pythonhosted.org/packages/f5/de/3b107712e642f063c7a9e0887c427b22cb44097de5aab36c05f2e280670c/ruff-0.15.21-py3-none-macosx_11_0_arm64.whl", hash = "sha256:e6312e41bc96791299614995ea3a977c5857c3b5662b1ecef6755b02b87cb646", size = 10595437, upload-time = "2026-07-09T20:01:00.006Z" },
+ { url = "https://files.pythonhosted.org/packages/9a/6f/b4523cc90ba239ede441447a19d0c968846a3012e5a0b0c5b62831a3d5e3/ruff-0.15.21-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01d65b4831c6b2a4ba8ee6faa84049d44d982b7a706e622c4094c509e51673be", size = 10990053, upload-time = "2026-07-09T20:01:02.187Z" },
+ { url = "https://files.pythonhosted.org/packages/92/cc/c6a9872a5375f0628875481cf2f66b13d7d865bf3ca2e57f91c7e762d976/ruff-0.15.21-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2c5a913a589120ce67933d5d05fd6ddbcc2481c6a054980ee767f7414c72b4fd", size = 10666096, upload-time = "2026-07-09T20:01:04.299Z" },
+ { url = "https://files.pythonhosted.org/packages/ab/97/c621f7a17e097f1790fa3af6374138823b330b2d03fc38337945daca212c/ruff-0.15.21-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ef04b681d02ad4dc9620f00f83ac5c22f652d0e9a9cfe431d219b16ad5ccc41", size = 11537011, upload-time = "2026-07-09T20:01:06.771Z" },
+ { url = "https://files.pythonhosted.org/packages/ea/51/d928727e476e25ccc57c6f449ffd80241a651a973ad949d39cfb2a771d28/ruff-0.15.21-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:16d090c0740916594157e75b80d666eab8e78083b39b3b0e1d698f4670a17b86", size = 12347101, upload-time = "2026-07-09T20:01:08.859Z" },
+ { url = "https://files.pythonhosted.org/packages/1e/88/8cd62026802b16018ad06931d87997cf795ba2a6239ab659606c87d96bf0/ruff-0.15.21-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3a10e74757dd65004d779b73e2f3c5210156d9980b41224d50d2ebcf1db51e67", size = 11572001, upload-time = "2026-07-09T20:01:11.092Z" },
+ { url = "https://files.pythonhosted.org/packages/b2/97/f63084cf55444fc110e8cb985ebfcc592af47f597d44453d778cb81bc156/ruff-0.15.21-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bab0905d2f29e0d9fbc3c373ed23db0095edaa3f71f1f4f519ec15134d9e85c8", size = 11549239, upload-time = "2026-07-09T20:01:13.27Z" },
+ { url = "https://files.pythonhosted.org/packages/9d/77/f107da4a2874b7715914b03f09ba9c54424de3ff8a1cc5d015d3ee2ce0ac/ruff-0.15.21-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:00eca240af5789fec6fe7df74c088cc1f9644ed83027113468efba7c92b94075", size = 11535340, upload-time = "2026-07-09T20:01:15.206Z" },
+ { url = "https://files.pythonhosted.org/packages/d5/e9/601deb322d3303a7bf212b0100ead6f2ee3f6a044d89c30f2f92bf83c731/ruff-0.15.21-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:262ab31557a75141325e32d3357f3597645a7f084e732b6b054dde428ecd9341", size = 10964048, upload-time = "2026-07-09T20:01:17.723Z" },
+ { url = "https://files.pythonhosted.org/packages/ea/2e/0f2176d1e99c15192caea19c8c3a0a955246b4cb4de795042eeb616345cd/ruff-0.15.21-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:659c4e7a4212f83306045ec7c5e5a356d16d9a6ef4ae0c7a4d872914fc655d9d", size = 10667055, upload-time = "2026-07-09T20:01:19.73Z" },
+ { url = "https://files.pythonhosted.org/packages/48/60/abd74a02e0c4214f12a68becfd30af7165cfdcb0e661ecdc60bbb949c09a/ruff-0.15.21-py3-none-musllinux_1_2_i686.whl", hash = "sha256:9e866eab611a5f959d36df2d10e446973a3610bc42b0c15b31dc27977d59c233", size = 11242043, upload-time = "2026-07-09T20:01:21.947Z" },
+ { url = "https://files.pythonhosted.org/packages/b2/c6/583075d8ccabb4b229345edcaf1545eb3d8d6be90f686a479d7e94088bbf/ruff-0.15.21-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e89bc93c0d3803ba870b55c29671bad9dc6d94bb1eb181b056b52eb05b52854f", size = 11648064, upload-time = "2026-07-09T20:01:24.023Z" },
+ { url = "https://files.pythonhosted.org/packages/3a/3c/37d0ecb729a7cc2d393ea7dce316fc585680f35d93b8d62139d7d0a3700c/ruff-0.15.21-py3-none-win32.whl", hash = "sha256:01f8d5be84823c172b389e123174f781f9daf86d6c58719d603f941932195cdd", size = 10896555, upload-time = "2026-07-09T20:01:26.941Z" },
+ { url = "https://files.pythonhosted.org/packages/c0/b8/e43466b2a6067ce91e669068f6e28d6c719a920f014b070d5c8731725de3/ruff-0.15.21-py3-none-win_amd64.whl", hash = "sha256:d4b8d9a2f0f12b816b50447f6eccb9f4bb01a6b82c86b50fb3b5354b458dc6d3", size = 12038772, upload-time = "2026-07-09T20:01:29.497Z" },
+ { url = "https://files.pythonhosted.org/packages/dd/75/e90ab9aeece218a9fc5a5bc3ec97d0ee6bb3c4ff95869463c1de58e29a1c/ruff-0.15.21-py3-none-win_arm64.whl", hash = "sha256:6e83115d4b9377c1cbc13abf0e051f069fab0ef815ea0504a8a008cee24dd0a8", size = 11375265, upload-time = "2026-07-09T20:01:31.772Z" },
+]
+
+[[package]]
+name = "shellingham"
+version = "1.5.4"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/58/15/8b3609fd3830ef7b27b655beb4b4e9c62313a4e8da8c676e142cc210d58e/shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de", size = 10310, upload-time = "2023-10-24T04:13:40.426Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755, upload-time = "2023-10-24T04:13:38.866Z" },
+]
+
+[[package]]
+name = "tomli"
+version = "2.4.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/22/de/48c59722572767841493b26183a0d1cc411d54fd759c5607c4590b6563a6/tomli-2.4.1.tar.gz", hash = "sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f", size = 17543, upload-time = "2026-03-25T20:22:03.828Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/7b/61/cceae43728b7de99d9b847560c262873a1f6c98202171fd5ed62640b494b/tomli-2.4.1-py3-none-any.whl", hash = "sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe", size = 14583, upload-time = "2026-03-25T20:22:03.012Z" },
+]
+
+[[package]]
+name = "typer"
+version = "0.27.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "annotated-doc" },
+ { name = "colorama", marker = "sys_platform == 'win32'" },
+ { name = "rich" },
+ { name = "shellingham" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/37/78/fda3361b56efc27944f24225f6ecd13d96d6fcfe37bd0eb34e2f4c63f9fc/typer-0.27.0.tar.gz", hash = "sha256:629bd12ea5d13a17148125d9a264f949eb171fb3f120f9b04d85873cab054fa5", size = 203430, upload-time = "2026-07-15T19:21:07.007Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/40/03/26a383c9e58c213199d1aad1c3d353cfc22d4444ec6d2c0bf8ad02523843/typer-0.27.0-py3-none-any.whl", hash = "sha256:6f4b27631e47f077871b7dc30e933ec0131c1390fbe0e387ea5574b5bac9ccf1", size = 122716, upload-time = "2026-07-15T19:21:05.553Z" },
+]
+
+[[package]]
+name = "typing-extensions"
+version = "4.16.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f6/cc/6253133b5bb138fc3306cebfbda2c520f545d36b5be2c7255cc528bb45d6/typing_extensions-4.16.0.tar.gz", hash = "sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5", size = 113555, upload-time = "2026-07-02T08:40:05.92Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/49/d3/b8441a820a491ddfc024b0b0cf0393375b75ea13866d9c66727e54c2fc80/typing_extensions-4.16.0-py3-none-any.whl", hash = "sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8", size = 45571, upload-time = "2026-07-02T08:40:04.659Z" },
+]
diff --git a/services/topuptool/current/ioc/AGEBD-CPCL-TOPUPTOOL_main.subs b/services/topuptool/current/ioc/AGEBD-CPCL-TOPUPTOOL_main.subs
new file mode 100644
index 0000000..374cb6e
--- /dev/null
+++ b/services/topuptool/current/ioc/AGEBD-CPCL-TOPUPTOOL_main.subs
@@ -0,0 +1,4 @@
+file TOPUPTOOL.template {
+ pattern { DEVICE }
+ { AGEBD-TOPUPTOOL{{ agebd_env }} }
+}
diff --git a/services/topuptool/current/ioc/AGEBD-CPCL-TOPUPTOOL_parameters.yaml b/services/topuptool/current/ioc/AGEBD-CPCL-TOPUPTOOL_parameters.yaml
new file mode 100644
index 0000000..ff8e70f
--- /dev/null
+++ b/services/topuptool/current/ioc/AGEBD-CPCL-TOPUPTOOL_parameters.yaml
@@ -0,0 +1,6 @@
+cpu_architecture: x86_64
+epics_version: 7.0.8
+ioc_host: sls-vserv-bd-01{{ agebd_env }}
+ioc_port: {{ ioc_port }}
+os: RHEL8
+os_id: rhel
diff --git a/services/topuptool/current/ioc/TOPUPTOOL.template b/services/topuptool/current/ioc/TOPUPTOOL.template
new file mode 100644
index 0000000..43540d9
--- /dev/null
+++ b/services/topuptool/current/ioc/TOPUPTOOL.template
@@ -0,0 +1,121 @@
+# HLA Service Control Parameters
+
+record(bo, "$(DEVICE):CONTROL-SCRUB") {
+ field(DESC, "Activate scrubbung during decay")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-VACUUM-MAX") {
+ field(DESC, "Stop injection at this vacuum pressure")
+ field(EGU, "1e-9 mbar")
+ field(VAL, "30")
+ field(PREC, "3")
+ field(FLNK, "$(DEVICE):CONTROL-VACUUM-MAX-PLOT")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-VACUUM-DYN") {
+ field(DESC, "Stop injection at this vacuum pressure")
+ field(EGU, "1e-9 mbar")
+ field(VAL, "27")
+ field(PREC, "3")
+ field(FLNK, "$(DEVICE):CONTROL-VACUUM-DYN-PLOT")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-VACUUM-DYN-FRAC") {
+ field(DESC, "Fraction defining dynamic pressure ")
+ field(VAL, "1.05")
+ field(PREC, "3")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-VACUUM-MIN") {
+ field(DESC, "Start injection at this vacuum pressure")
+ field(EGU, "1e-9 mbar")
+ field(VAL, "24")
+ field(PREC, "3")
+ field(FLNK, "$(DEVICE):CONTROL-VACUUM-MIN-PLOT")
+ field(PINI, "YES")
+}
+
+record(calc, "$(DEVICE):CONTROL-VACUUM-MAX-PLOT") {
+ field(DESC, "Stop injection at this vacuum pressure")
+ field(ASG, "READONLY")
+ field(EGU, "mbar")
+ field(PREC, "-5")
+ field(CALC, "A/1e9")
+ field(INPA, "$(DEVICE):CONTROL-VACUUM-MAX")
+}
+
+record(calc, "$(DEVICE):CONTROL-VACUUM-DYN-PLOT") {
+ field(DESC, "Stop injection at this vacuum pressure")
+ field(ASG, "READONLY")
+ field(EGU, "mbar")
+ field(PREC, "-5")
+ field(CALC, "A/1e9")
+ field(INPA, "$(DEVICE):CONTROL-VACUUM-DYN")
+}
+
+record(calc, "$(DEVICE):CONTROL-VACUUM-MIN-PLOT") {
+ field(DESC, "Stop injection at this vacuum pressure")
+ field(ASG, "READONLY")
+ field(EGU, "mbar")
+ field(PREC, "-5")
+ field(CALC, "A/1e9")
+ field(INPA, "$(DEVICE):CONTROL-VACUUM-MIN")
+}
+
+record(ao, "$(DEVICE):CONTROL-CURRENT-MAX") {
+ field(DESC, "Stop injection at this current")
+ field(EGU, "mA")
+ field(VAL, "400")
+ field(PREC, "3")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-CURRENT-MIN") {
+ field(DESC, "Start injection at this current")
+ field(EGU, "mA")
+ field(VAL, "396")
+ field(PREC, "3")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-GUNGRID-MAX") {
+ field(DESC, "Set gun grid to val before injection")
+ field(EGU, "V")
+ field(VAL, "170")
+ field(PREC, "3")
+ field(PINI, "YES")
+}
+
+# HLA Service Output/Result Parameters
+
+record(ao, "$(DEVICE):TOPUP-TAU") {
+ field(DESC, "Average tau since last top up")
+ field(EGU, "h")
+ field(VAL, "100")
+ field(PREC, "3")
+ field(VAL, "-1")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):TOPUP-DELTAT") {
+ field(DESC, "Time since last top up")
+ field(EGU, "min")
+ field(VAL, "100")
+ field(PREC, "3")
+ field(VAL, "-1")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):TOPUP-DELTAI") {
+ field(DESC, "Current change since last top up")
+ field(EGU, "mA")
+ field(VAL, "100")
+ field(PREC, "3")
+ field(VAL, "-1")
+ field(PINI, "YES")
+}
diff --git a/services/topuptool/current/ioc/startup.script b/services/topuptool/current/ioc/startup.script
new file mode 100644
index 0000000..0fa52ff
--- /dev/null
+++ b/services/topuptool/current/ioc/startup.script
@@ -0,0 +1 @@
+epicsEnvSet("ENGINEER", "armborst")
diff --git a/services/topuptool/current/qt/A_BD_TopUpTool.ui b/services/topuptool/current/qt/A_BD_TopUpTool.ui
new file mode 100644
index 0000000..9800d32
--- /dev/null
+++ b/services/topuptool/current/qt/A_BD_TopUpTool.ui
@@ -0,0 +1,3533 @@
+
+
+ MainWindow
+
+
+
+ 0
+ 0
+ 1852
+ 610
+
+
+
+ MainWindow
+
+
+
+
+
+ 10
+ 10
+ 391
+ 61
+
+
+
+ AGEBD-ALH:TOPUPTOOL-ONOFF
+
+
+ caChoice::Column
+
+
+ 1
+
+
+
+
+
+ 729
+ 0
+ 1111
+ 601
+
+
+
+
+ 10
+ 75
+ true
+
+
+
+ Strahlstrom
+
+
+
+
+
+ mA
+
+
+ ARS07-DPCT-0000:CURR
+
+
+ caStripPlot::Second
+
+
+ 480.000000000000000
+
+
+ caStripPlot::High
+
+
+ 8
+
+
+ caStripPlot::linear
+
+
+ caStripPlot::fixedScale
+
+
+ caStripPlot::off
+
+
+ 408.000000000000000
+
+
+ 300.000000000000000
+
+
+ caStripPlot::Channel
+
+
+ caStripPlot::Channel
+
+
+
+ 0
+ 255
+ 0
+
+
+
+ 0.000000100000000
+
+
+ 0.000000001000000
+
+
+ caStripPlot::User
+
+
+ caStripPlot::User
+
+
+
+ 241
+ 252
+ 122
+
+
+
+ 0.000000100000000
+
+
+ 0.000000001000000
+
+
+ caStripPlot::User
+
+
+ caStripPlot::User
+
+
+
+ 239
+ 41
+ 41
+
+
+
+ 0.000000100000000
+
+
+ 0.000000001000000
+
+
+ caStripPlot::User
+
+
+ caStripPlot::User
+
+
+
+ 239
+ 41
+ 41
+
+
+
+ 0.000000100000000
+
+
+ 0.000000001000000
+
+
+ caStripPlot::User
+
+
+ caStripPlot::User
+
+
+ 0.000000100000000
+
+
+ 0.000000001000000
+
+
+ 0.000000100000000
+
+
+ 0.000000001000000
+
+
+
+ 218
+ 218
+ 218
+
+
+
+ false
+
+
+
+
+
+ 280
+ 140
+ 85
+ 40
+
+
+
+ 3
+
+
+ 0
+
+
+ AGEBD-TOPUPTOOL:CONTROL-GUNGRID-MAX
+
+
+ caSpinbox::User
+
+
+ true
+
+
+
+
+
+ 160
+ 140
+ 105
+ 40
+
+
+
+
+ 15
+ 75
+ true
+
+
+
+ Gun Grid
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+
+
+ 1990
+ 540
+ 70
+ 20
+
+
+
+
+
+
+ 1980
+ 360
+ 71
+ 20
+
+
+
+ RELOAD
+
+
+ Qt::AlignCenter
+
+
+ RELOAD
+
+
+ A
+
+
+ AGEBD-ALH:SCRUBBING-GUIRELOAD
+
+
+ caCalc::TriggerOneToZero
+
+
+
+
+
+ 10
+ 90
+ 391
+ 41
+
+
+
+ AGEBD-ALH:SCRUBBING-INFO
+
+
+ caLineEdit::Alarm_Default
+
+
+ caLineEdit::onBackground
+
+
+ caLineEdit::User
+
+
+
+
+
+ 570
+ 190
+ 50
+ 30
+
+
+
+ AGEBD-TOPUPTOOL:TOPUP-DELTAT
+
+
+ caLineEdit::Default
+
+
+ caLineEdit::onBackground
+
+
+ 2
+
+
+ caLineEdit::User
+
+
+
+
+
+ 570
+ 310
+ 50
+ 30
+
+
+
+ AGEBD-TOPUPTOOL:TOPUP-TAU
+
+
+ caLineEdit::Default
+
+
+ caLineEdit::onBackground
+
+
+ 2
+
+
+ caLineEdit::User
+
+
+
+
+
+ 480
+ 310
+ 50
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ Tau
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 480
+ 230
+ 50
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ dI
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 480
+ 190
+ 50
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ dt
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 570
+ 230
+ 50
+ 30
+
+
+
+ AGEBD-TOPUPTOOL:TOPUP-DELTAI
+
+
+ caLineEdit::Default
+
+
+ caLineEdit::onBackground
+
+
+ 2
+
+
+ caLineEdit::User
+
+
+
+
+
+ 10
+ 330
+ 601
+ 270
+
+
+
+ Top-Up Save Einstellungen
+
+
+
+
+ 133
+ 172
+ 78
+ 28
+
+
+
+ true
+
+
+
+ 0
+ 0
+ 176
+
+
+
+ caGraphics::Filled
+
+
+ 1
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caGraphics::IfZero
+
+
+ AGETI-CVME-MASTER-TMA:Evt-10-Ena-Sel
+
+
+ caGraphics::Rectangle
+
+
+ 22
+
+
+ 180
+
+
+ 0
+
+
+ 90
+
+
+
+
+
+ 209
+ 56
+ 78
+ 28
+
+
+
+ true
+
+
+
+ 0
+ 0
+ 176
+
+
+
+ caGraphics::Filled
+
+
+ 1
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caGraphics::Calc
+
+
+ A=2
+
+
+ ALIRF-VME-A-GUN:CH1-MODE
+
+
+ caGraphics::Rectangle
+
+
+ 22
+
+
+ 180
+
+
+
+
+
+ 213
+ 31
+ 70
+ 20
+
+
+
+ true
+
+
+ Enable
+
+
+ AGETI-CVME-MASTER-TMA:SR-Inj-Status-Sel
+
+
+ Enable
+
+
+
+ 219
+ 212
+ 157
+
+
+
+ 1
+
+
+
+
+
+ 9
+ 33
+ 100
+ 22
+
+
+
+
+ Sans Serif
+ 13
+
+
+
+ true
+
+
+ Master
+
+
+ Qt::AlignAbsolute|Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::Height
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ QFrame::NoFrame
+
+
+
+
+
+ 137
+ 60
+ 70
+ 20
+
+
+
+ true
+
+
+ Disable
+
+
+ ALIRF-VME-A-GUN:CH1-MODE
+
+
+ Disable
+
+
+
+ 219
+ 212
+ 157
+
+
+
+ 0
+
+
+
+
+
+ 209
+ 172
+ 78
+ 28
+
+
+
+ true
+
+
+
+ 0
+ 0
+ 176
+
+
+
+ caGraphics::Filled
+
+
+ 1
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caGraphics::Calc
+
+
+ A=1
+
+
+ AGETI-CVME-MASTER-TMA:Evt-10-Ena-Sel
+
+
+ caGraphics::Rectangle
+
+
+ 22
+
+
+ 180
+
+
+
+
+
+ 213
+ 176
+ 70
+ 20
+
+
+
+ true
+
+
+ Enable
+
+
+ AGETI-CVME-MASTER-TMA:Evt-10-Ena-Sel
+
+
+ Enable
+
+
+
+ 219
+ 212
+ 157
+
+
+
+ 1
+
+
+
+
+
+ 133
+ 27
+ 78
+ 28
+
+
+
+ true
+
+
+
+ 0
+ 0
+ 176
+
+
+
+ caGraphics::Filled
+
+
+ 1
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caGraphics::Calc
+
+
+ A=0
+
+
+ AGETI-CVME-MASTER-TMA:SR-Inj-Status-Sel
+
+
+ caGraphics::Rectangle
+
+
+ 22
+
+
+ 180
+
+
+
+
+
+ 137
+ 176
+ 70
+ 20
+
+
+
+ true
+
+
+ Disable
+
+
+ AGETI-CVME-MASTER-TMA:Evt-10-Ena-Sel
+
+
+ Disable
+
+
+
+ 219
+ 212
+ 157
+
+
+
+ 0
+
+
+
+
+
+ 9
+ 178
+ 100
+ 22
+
+
+
+
+ Sans Serif
+ 13
+
+
+
+ true
+
+
+ Booster Ext
+
+
+ Qt::AlignAbsolute|Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::Height
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ QFrame::NoFrame
+
+
+
+
+
+ 209
+ 27
+ 78
+ 28
+
+
+
+ true
+
+
+
+ 0
+ 0
+ 176
+
+
+
+ caGraphics::Filled
+
+
+ 1
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caGraphics::Calc
+
+
+ A=1
+
+
+ AGETI-CVME-MASTER-TMA:SR-Inj-Status-Sel
+
+
+ caGraphics::Rectangle
+
+
+ 22
+
+
+ 180
+
+
+ 0
+
+
+ 90
+
+
+
+
+
+ 213
+ 60
+ 70
+ 20
+
+
+
+ true
+
+
+ External
+
+
+ ALIRF-VME-A-GUN:CH1-MODE
+
+
+ External
+
+
+
+ 219
+ 212
+ 157
+
+
+
+ 2
+
+
+
+
+
+ 9
+ 62
+ 100
+ 22
+
+
+
+
+ Sans Serif
+ 13
+
+
+
+ true
+
+
+ Gun TX
+
+
+ Qt::AlignAbsolute|Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::Height
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ QFrame::NoFrame
+
+
+
+
+
+ 133
+ 56
+ 78
+ 28
+
+
+
+ true
+
+
+
+ 0
+ 0
+ 176
+
+
+
+ caGraphics::Filled
+
+
+ 1
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caGraphics::IfZero
+
+
+ ALIRF-VME-A-GUN:CH1-MODE
+
+
+ caGraphics::Rectangle
+
+
+ 22
+
+
+ 180
+
+
+ 0
+
+
+ 90
+
+
+
+
+
+ 137
+ 31
+ 70
+ 20
+
+
+
+ true
+
+
+ Disable
+
+
+ AGETI-CVME-MASTER-TMA:SR-Inj-Status-Sel
+
+
+ Disable
+
+
+
+ 219
+ 212
+ 157
+
+
+
+ 0
+
+
+
+
+
+ 137
+ 147
+ 70
+ 20
+
+
+
+ true
+
+
+ Disable
+
+
+ AGETI-CVME-MASTER-TMA:Evt-Old-BO-HW-Ena-Sel
+
+
+ Disable
+
+
+
+ 219
+ 212
+ 157
+
+
+
+ 0
+
+
+
+
+
+ 9
+ 149
+ 121
+ 22
+
+
+
+
+ Sans Serif
+ 13
+
+
+
+ true
+
+
+ Booster Ramp
+
+
+ Qt::AlignAbsolute|Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::Height
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ QFrame::NoFrame
+
+
+
+
+
+ 133
+ 143
+ 78
+ 28
+
+
+
+ true
+
+
+
+ 0
+ 0
+ 176
+
+
+
+ caGraphics::Filled
+
+
+ 1
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caGraphics::IfZero
+
+
+ AGETI-CVME-MASTER-TMA:Evt-Old-BO-HW-Ena-Sel
+
+
+ caGraphics::Rectangle
+
+
+ 22
+
+
+ 180
+
+
+ 0
+
+
+ 90
+
+
+
+
+
+ 213
+ 147
+ 70
+ 20
+
+
+
+ true
+
+
+ External
+
+
+ AGETI-CVME-MASTER-TMA:Evt-Old-BO-HW-Ena-Sel
+
+
+ External
+
+
+
+ 219
+ 212
+ 157
+
+
+
+ 1
+
+
+
+
+
+ 209
+ 143
+ 78
+ 28
+
+
+
+ true
+
+
+
+ 0
+ 0
+ 176
+
+
+
+ caGraphics::Filled
+
+
+ 1
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caGraphics::Calc
+
+
+ A=1
+
+
+ AGETI-CVME-MASTER-TMA:Evt-Old-BO-HW-Ena-Sel
+
+
+ caGraphics::Rectangle
+
+
+ 22
+
+
+ 180
+
+
+
+
+
+ 137
+ 205
+ 70
+ 20
+
+
+
+ true
+
+
+ Disable
+
+
+ AGETI-CVME-MASTER-TMA:Evt-SR-Inj-Ena-Sel
+
+
+ Disable
+
+
+
+ 219
+ 212
+ 157
+
+
+
+ 0
+
+
+
+
+
+ 213
+ 205
+ 70
+ 20
+
+
+
+ true
+
+
+ Enable
+
+
+ AGETI-CVME-MASTER-TMA:Evt-SR-Inj-Ena-Sel
+
+
+ Enable
+
+
+
+ 219
+ 212
+ 157
+
+
+
+ 1
+
+
+
+
+
+ 209
+ 201
+ 78
+ 28
+
+
+
+ true
+
+
+
+ 0
+ 0
+ 176
+
+
+
+ caGraphics::Filled
+
+
+ 1
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caGraphics::Calc
+
+
+ A=1
+
+
+ AGETI-CVME-MASTER-TMA:Evt-SR-Inj-Ena-Sel
+
+
+ caGraphics::Rectangle
+
+
+ 22
+
+
+ 180
+
+
+
+
+
+ 9
+ 204
+ 150
+ 22
+
+
+
+
+ Sans Serif
+ 13
+
+
+
+ true
+
+
+ Qt::LeftToRight
+
+
+ Ring Inj
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ QFrame::NoFrame
+
+
+
+
+
+ 133
+ 201
+ 78
+ 28
+
+
+
+ true
+
+
+
+ 0
+ 0
+ 176
+
+
+
+ caGraphics::Filled
+
+
+ 1
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caGraphics::IfZero
+
+
+ AGETI-CVME-MASTER-TMA:Evt-SR-Inj-Ena-Sel
+
+
+ caGraphics::Rectangle
+
+
+ 22
+
+
+ 180
+
+
+ 0
+
+
+ 90
+
+
+
+
+
+ 209
+ 85
+ 78
+ 28
+
+
+
+ true
+
+
+
+ 0
+ 0
+ 176
+
+
+
+ caGraphics::Filled
+
+
+ 1
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caGraphics::Calc
+
+
+ A=1
+
+
+ AGETI-CVME-MASTER-TMA:Evt-LI-Gun-Ena-Sel
+
+
+ caGraphics::Rectangle
+
+
+ 22
+
+
+ 180
+
+
+
+
+
+ 213
+ 89
+ 70
+ 20
+
+
+
+ true
+
+
+ Enable
+
+
+ AGETI-CVME-MASTER-TMA:Evt-LI-Gun-Ena-Sel
+
+
+ Enable
+
+
+
+ 219
+ 212
+ 157
+
+
+
+ 1
+
+
+
+
+
+ 133
+ 85
+ 78
+ 28
+
+
+
+ true
+
+
+
+ 0
+ 0
+ 176
+
+
+
+ caGraphics::Filled
+
+
+ 1
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caGraphics::IfZero
+
+
+ AGETI-CVME-MASTER-TMA:Evt-LI-Gun-Ena-Sel
+
+
+ caGraphics::Rectangle
+
+
+ 22
+
+
+ 180
+
+
+ 0
+
+
+ 90
+
+
+
+
+
+ 9
+ 91
+ 91
+ 22
+
+
+
+
+ Sans Serif
+ 13
+
+
+
+ true
+
+
+ Qt::LeftToRight
+
+
+ Gun Event
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ QFrame::NoFrame
+
+
+
+
+
+ 137
+ 89
+ 70
+ 20
+
+
+
+ true
+
+
+ Disable
+
+
+ AGETI-CVME-MASTER-TMA:Evt-LI-Gun-Ena-Sel
+
+
+ Disable
+
+
+
+ 219
+ 212
+ 157
+
+
+
+ 0
+
+
+
+
+
+ 137
+ 118
+ 70
+ 20
+
+
+
+ true
+
+
+ Disable
+
+
+ AGETI-CVME-MASTER-TMA:Evt-BO-Inj-Ena-Sel
+
+
+ Disable
+
+
+
+ 219
+ 212
+ 157
+
+
+
+ 0
+
+
+
+
+
+ 213
+ 118
+ 70
+ 20
+
+
+
+ true
+
+
+ Enable
+
+
+ AGETI-CVME-MASTER-TMA:Evt-BO-Inj-Ena-Sel
+
+
+ Enable
+
+
+
+ 219
+ 212
+ 157
+
+
+
+ 1
+
+
+
+
+
+ 133
+ 114
+ 78
+ 28
+
+
+
+ true
+
+
+
+ 0
+ 0
+ 176
+
+
+
+ caGraphics::Filled
+
+
+ 1
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caGraphics::IfZero
+
+
+ AGETI-CVME-MASTER-TMA:Evt-BO-Inj-Ena-Sel
+
+
+ caGraphics::Rectangle
+
+
+ 22
+
+
+ 180
+
+
+ 0
+
+
+ 90
+
+
+
+
+
+ 209
+ 114
+ 78
+ 28
+
+
+
+ true
+
+
+
+ 0
+ 0
+ 176
+
+
+
+ caGraphics::Filled
+
+
+ 1
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caGraphics::Calc
+
+
+ A=1
+
+
+ AGETI-CVME-MASTER-TMA:Evt-BO-Inj-Ena-Sel
+
+
+ caGraphics::Rectangle
+
+
+ 22
+
+
+ 180
+
+
+
+
+
+ 9
+ 120
+ 111
+ 22
+
+
+
+
+ Sans Serif
+ 13
+
+
+
+ true
+
+
+ Qt::LeftToRight
+
+
+ Booster Inj
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ QFrame::NoFrame
+
+
+
+
+
+ 98
+ 27
+ 28
+ 28
+
+
+
+ true
+
+
+ false
+
+
+ 22
+
+
+ 22
+
+
+ AGEBD-INJECTIONGUARD:STATUS-SECRET-MASTER
+
+
+ caLed::Alarm
+
+
+
+
+
+ 303
+ 27
+ 100
+ 28
+
+
+
+
+ Monospace
+ 13
+ PreferDefault
+
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ true
+
+
+ AGETI-CVME-MASTER-TMA:Event-Seq-Cnt-I
+
+
+
+ 160
+ 160
+ 164
+
+
+
+ caLineEdit::Default
+
+
+ caLineEdit::None
+
+
+
+
+
+ 303
+ 56
+ 100
+ 28
+
+
+
+
+ Monospace
+ 13
+ PreferDefault
+
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ true
+
+
+ ALIRF-VME-A:SoftEvent-Linac-Gun-Evnt-Count-I
+
+
+
+ 160
+ 160
+ 164
+
+
+
+ caLineEdit::Default
+
+
+ caLineEdit::None
+
+
+
+
+
+ 303
+ 85
+ 100
+ 28
+
+
+
+
+ Monospace
+ 13
+ PreferDefault
+
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ true
+
+
+ AGETI-CVME-MASTER-TMA:Evt-LI-Gun-EVRCount-I
+
+
+
+ 160
+ 160
+ 164
+
+
+
+ caLineEdit::Default
+
+
+ caLineEdit::None
+
+
+
+
+
+ 303
+ 114
+ 100
+ 28
+
+
+
+
+ Monospace
+ 13
+ PreferDefault
+
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ true
+
+
+ AGETI-CVME-MASTER-TMA:Evt-BO-Inj-EVRCount-I
+
+
+
+ 160
+ 160
+ 164
+
+
+
+ caLineEdit::Default
+
+
+ caLineEdit::None
+
+
+
+
+
+ 303
+ 143
+ 100
+ 28
+
+
+
+
+ Monospace
+ 13
+ PreferDefault
+
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ true
+
+
+ AGETI-CVME-MASTER-TMA:Evt-Old-BO-HW-EVRCount-I
+
+
+
+ 160
+ 160
+ 164
+
+
+
+ caLineEdit::Default
+
+
+ caLineEdit::None
+
+
+
+
+
+ 303
+ 172
+ 100
+ 28
+
+
+
+
+ Monospace
+ 13
+ PreferDefault
+
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ true
+
+
+
+AGETI-CVME-MASTER-TMA:Evt-BO-Ext-EVRCount-I
+
+
+
+ 160
+ 160
+ 164
+
+
+
+ caLineEdit::Default
+
+
+ caLineEdit::None
+
+
+
+
+
+ 303
+ 201
+ 100
+ 28
+
+
+
+
+ Monospace
+ 13
+ PreferDefault
+
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ true
+
+
+
+AGETI-CVME-MASTER-TMA:Evt-SR-Inj-EVRCount-I
+
+
+
+ 160
+ 160
+ 164
+
+
+
+ caLineEdit::Default
+
+
+ caLineEdit::None
+
+
+
+
+
+ 453
+ 27
+ 140
+ 28
+
+
+
+ 2
+
+
+ 1
+
+
+ AGEBD-TOPUPTOOL:CONTROL-CURRENT-MAX
+
+
+ caSpinbox::User
+
+
+ true
+
+
+
+
+
+ 304
+ 230
+ 100
+ 28
+
+
+
+
+ Monospace
+ 13
+ PreferDefault
+
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ true
+
+
+
+AGETI-CVME-MASTER-TMA:Evt-14.VALA
+
+
+
+ 160
+ 160
+ 164
+
+
+
+ caLineEdit::Default
+
+
+ caLineEdit::None
+
+
+
+
+
+ 214
+ 234
+ 70
+ 20
+
+
+
+ true
+
+
+ Enable
+
+
+ AGETI-CVME-MASTER-TMA:Evt-SR-Pinger-Ena-Sel
+
+
+ Enable
+
+
+
+ 219
+ 212
+ 157
+
+
+
+ 1
+
+
+
+
+
+ 138
+ 234
+ 70
+ 20
+
+
+
+ true
+
+
+ Disable
+
+
+ AGETI-CVME-MASTER-TMA:Evt-SR-Pinger-Ena-Sel
+
+
+ Disable
+
+
+
+ 219
+ 212
+ 157
+
+
+
+ 0
+
+
+
+
+
+ 133
+ 230
+ 78
+ 28
+
+
+
+ true
+
+
+
+ 0
+ 0
+ 176
+
+
+
+ caGraphics::Filled
+
+
+ 1
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caGraphics::IfZero
+
+
+ AGETI-CVME-MASTER-TMA:Evt-SR-Pinger-Ena-Sel
+
+
+ caGraphics::Rectangle
+
+
+ 22
+
+
+ 180
+
+
+ 0
+
+
+ 90
+
+
+
+
+
+ 10
+ 233
+ 101
+ 22
+
+
+
+
+ Sans Serif
+ 13
+
+
+
+ true
+
+
+ Qt::LeftToRight
+
+
+ Pingers
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ QFrame::NoFrame
+
+
+
+
+
+ 210
+ 230
+ 78
+ 28
+
+
+
+ true
+
+
+
+ 0
+ 0
+ 176
+
+
+
+ caGraphics::Filled
+
+
+ 1
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caGraphics::Calc
+
+
+ A=1
+
+
+ AGETI-CVME-MASTER-TMA:Evt-SR-Pinger-Ena-Sel
+
+
+ caGraphics::Rectangle
+
+
+ 22
+
+
+ 180
+
+
+
+
+
+ 423
+ 27
+ 28
+ 28
+
+
+
+
+ 40
+ 40
+
+
+
+ caToggleButton::WidthAndHeight
+
+
+ caToggleButton::Alarm
+
+
+
+
+
+ 423
+ 56
+ 28
+ 28
+
+
+
+
+ 40
+ 40
+
+
+
+ caToggleButton::WidthAndHeight
+
+
+ caToggleButton::Alarm
+
+
+
+
+
+ 423
+ 114
+ 28
+ 28
+
+
+
+
+ 40
+ 40
+
+
+
+ caToggleButton::WidthAndHeight
+
+
+ caToggleButton::Alarm
+
+
+
+
+
+ 423
+ 85
+ 28
+ 28
+
+
+
+
+ 40
+ 40
+
+
+
+ caToggleButton::WidthAndHeight
+
+
+ caToggleButton::Alarm
+
+
+
+
+
+ 423
+ 201
+ 28
+ 28
+
+
+
+
+ 40
+ 40
+
+
+
+ caToggleButton::WidthAndHeight
+
+
+ caToggleButton::Alarm
+
+
+
+
+
+ 423
+ 143
+ 28
+ 28
+
+
+
+
+ 40
+ 40
+
+
+
+ caToggleButton::WidthAndHeight
+
+
+ caToggleButton::Alarm
+
+
+
+
+
+ 423
+ 172
+ 28
+ 28
+
+
+
+
+ 40
+ 40
+
+
+
+ caToggleButton::WidthAndHeight
+
+
+ caToggleButton::Alarm
+
+
+
+
+
+ 423
+ 230
+ 28
+ 28
+
+
+
+
+ 40
+ 40
+
+
+
+ caToggleButton::WidthAndHeight
+
+
+ caToggleButton::Alarm
+
+
+
+
+
+ 453
+ 56
+ 140
+ 28
+
+
+
+ 2
+
+
+ 1
+
+
+ AGEBD-TOPUPTOOL:CONTROL-CURRENT-MAX
+
+
+ caSpinbox::User
+
+
+ true
+
+
+
+
+
+ 453
+ 114
+ 140
+ 28
+
+
+
+ 2
+
+
+ 1
+
+
+ AGEBD-TOPUPTOOL:CONTROL-CURRENT-MAX
+
+
+ caSpinbox::User
+
+
+ true
+
+
+
+
+
+ 453
+ 85
+ 140
+ 28
+
+
+
+ 2
+
+
+ 1
+
+
+ AGEBD-TOPUPTOOL:CONTROL-CURRENT-MAX
+
+
+ caSpinbox::User
+
+
+ true
+
+
+
+
+
+ 453
+ 230
+ 140
+ 28
+
+
+
+ 2
+
+
+ 1
+
+
+ AGEBD-TOPUPTOOL:CONTROL-CURRENT-MAX
+
+
+ caSpinbox::User
+
+
+ true
+
+
+
+
+
+ 453
+ 201
+ 140
+ 28
+
+
+
+ 2
+
+
+ 1
+
+
+ AGEBD-TOPUPTOOL:CONTROL-CURRENT-MAX
+
+
+ caSpinbox::User
+
+
+ true
+
+
+
+
+
+ 453
+ 172
+ 140
+ 28
+
+
+
+ 2
+
+
+ 1
+
+
+ AGEBD-TOPUPTOOL:CONTROL-CURRENT-MAX
+
+
+ caSpinbox::User
+
+
+ true
+
+
+
+
+
+ 453
+ 143
+ 140
+ 28
+
+
+
+ 2
+
+
+ 1
+
+
+ AGEBD-TOPUPTOOL:CONTROL-CURRENT-MAX
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ BOO_Ext_External_frame_7
+ BOO_Ext_Disable_frame_7
+ BOO_Ext_Disable_frame_5
+ BOO_Ext_External_frame_5
+ BOO_Ext_Disable_frame_4
+ BOO_Ext_External_frame_4
+ Inj_trig_Enable_frame
+ BOO_Ext_Disable_frame_2
+ BOO_Ext_External_frame_2
+ Gun_trig_Disable_frame
+ Gun_trig_External_frame
+ Inj_trig_Enable
+ Inj_trig_
+ Gun_trig_Diasable
+ BOO_Ext_External_2
+ Inj_trig_Disable_frame
+ BOO_Ext_Diasable_2
+ BOO_Ext
+ Gun_trig_External
+ Gun_trig
+ Inj_trig_Disable
+ Gun_trig_2
+ Gun_trig_Disable_frame_2
+ Gun_trig_External_frame_2
+ Gun_trig_External_2
+ Gun_trig_Diasable_2
+ BOO_Ext_Diasable_4
+ BOO_Ext_External_4
+ BOO_Ext_3
+ BOO_Ext_External_frame_6
+ BOO_Ext_External_6
+ BOO_Ext_Disable_frame_6
+ BOO_Ext_5
+ BOO_Ext_Diasable_6
+ BOO_Ext_Diasable_5
+ BOO_Ext_External_5
+ BOO_Ext_4
+ caled_23
+ calineedit
+ calineedit_2
+ calineedit_4
+ calineedit_6
+ calineedit_7
+ calineedit_8
+ calineedit_9
+ caspinbox_6
+ calineedit_10
+ BOO_Ext_External_7
+ BOO_Ext_Diasable_7
+ BOO_Ext_6
+ catogglebutton
+ catogglebutton_2
+ catogglebutton_3
+ catogglebutton_4
+ catogglebutton_5
+ catogglebutton_6
+ catogglebutton_7
+ catogglebutton_8
+ caspinbox_8
+ caspinbox_9
+ caspinbox_10
+ caspinbox_11
+ caspinbox_12
+ caspinbox_13
+ caspinbox_14
+
+
+
+
+ 440
+ 20
+ 271
+ 50
+
+
+
+
+ Lucida Sans Typewriter
+ 32
+ 75
+ true
+
+
+
+ Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft
+
+
+ ARS07-DPCT-0000:CURR
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 170
+ 255
+ 127
+
+
+
+ caLineEdit::Static
+
+
+ 1
+
+
+ caLineEdit::User
+
+
+ caLineEdit::WidthAndHeight
+
+
+ true
+
+
+
+
+
+ 10
+ 170
+ 461
+ 151
+
+
+
+ Top-Up Schwellen
+
+
+
+
+ 160
+ 60
+ 140
+ 40
+
+
+
+ 3
+
+
+ 1
+
+
+ AGEBD-TOPUPTOOL:CONTROL-CURRENT-MAX
+
+
+ caSpinbox::User
+
+
+ true
+
+
+
+
+
+ 310
+ 30
+ 140
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ min
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 10
+ 30
+ 140
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ pbar
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 310
+ 65
+ 140
+ 40
+
+
+
+ 3
+
+
+ 1
+
+
+ AGEBD-TOPUPTOOL:CONTROL-TIME-FREQ
+
+
+ caSpinbox::User
+
+
+ true
+
+
+
+
+
+ 160
+ 30
+ 140
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ mA
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 160
+ 105
+ 140
+ 40
+
+
+
+ 3
+
+
+ 1
+
+
+ AGEBD-TOPUPTOOL:CONTROL-CURRENT-MIN
+
+
+ caSpinbox::User
+
+
+ true
+
+
+
+
+
+ 10
+ 60
+ 140
+ 40
+
+
+
+ 3
+
+
+ 1
+
+
+ AGEBD-TOPUPTOOL:CONTROL-VAC-MAX
+
+
+ caSpinbox::User
+
+
+ true
+
+
+
+
+
+ 10
+ 105
+ 140
+ 40
+
+
+
+ 3
+
+
+ 1
+
+
+ AGEBD-TOPUPTOOL:CONTROL-VAC-MIN
+
+
+ caSpinbox::User
+
+
+ true
+
+
+
+
+
+
+ 480
+ 270
+ 71
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ dI/dt
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 630
+ 190
+ 50
+ 30
+
+
+
+ AGEBD-TOPUPTOOL:TOPUP-DELTAT
+
+
+ caLineEdit::Default
+
+
+ caLineEdit::onBackground
+
+
+ 2
+
+
+ caLineEdit::User
+
+
+
+
+
+ 630
+ 230
+ 50
+ 30
+
+
+
+ AGEBD-TOPUPTOOL:TOPUP-DELTAI
+
+
+ caLineEdit::Default
+
+
+ caLineEdit::onBackground
+
+
+ 2
+
+
+ caLineEdit::User
+
+
+
+
+
+ 570
+ 270
+ 50
+ 30
+
+
+
+ AGEBD-TOPUPTOOL:TOPUP-TAU
+
+
+ caLineEdit::Default
+
+
+ caLineEdit::onBackground
+
+
+ 2
+
+
+ caLineEdit::User
+
+
+
+
+
+ 630
+ 270
+ 50
+ 30
+
+
+
+ AGEBD-TOPUPTOOL:TOPUP-DELTAI
+
+
+ caLineEdit::Default
+
+
+ caLineEdit::onBackground
+
+
+ 2
+
+
+ caLineEdit::User
+
+
+
+
+
+ 550
+ 150
+ 71
+ 30
+
+
+
+
+ 15
+ 75
+ true
+
+
+
+ Decay
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 630
+ 150
+ 71
+ 30
+
+
+
+
+ 15
+ 75
+ true
+
+
+
+ Inject
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 440
+ 90
+ 161
+ 30
+
+
+
+
+ 15
+ 75
+ true
+
+
+
+ Next Injection
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 620
+ 90
+ 51
+ 31
+
+
+
+ AGEBD-TOPUPTOOL:TOPUP-DELTAT
+
+
+ caLineEdit::Default
+
+
+ caLineEdit::onBackground
+
+
+ 2
+
+
+ caLineEdit::User
+
+
+
+
+
+
+ caChoice
+ QWidget
+
+
+
+ caMessageButton
+ QPushButton
+
+
+
+ caToggleButton
+ QCheckBox
+
+
+
+ caSpinbox
+ QFrame
+
+
+
+ caLabel
+ QLabel
+
+
+
+ caGraphics
+ QWidget
+
+
+
+ caLed
+ QWidget
+
+
+
+ caLineEdit
+ QLineEdit
+
+
+
+ caStripPlot
+ QwtPlot
+
+ 1
+
+
+ caCalc
+ QLabel
+
+
+
+ wmSignalPropagator
+ QLabel
+
+
+
+ QwtPlot
+ QFrame
+
+
+
+
+
+
+ cacalc_2
+ emitSignal(bool)
+ wmsignalpropagator
+ reloadwindow()
+
+
+ 2020
+ 374
+
+
+ 2022
+ 545
+
+
+
+
+
diff --git a/services/topuptool/current/systemd/AGEBD-SERVICE-TOPUPTOOL.service b/services/topuptool/current/systemd/AGEBD-SERVICE-TOPUPTOOL.service
new file mode 100644
index 0000000..beb2436
--- /dev/null
+++ b/services/topuptool/current/systemd/AGEBD-SERVICE-TOPUPTOOL.service
@@ -0,0 +1,16 @@
+[Unit]
+Description=AGEBD-SERVICE-TOPUPTOOL
+After=network.target
+
+[Service]
+Environment=AGEBD_ENV={{ agebd_env }}
+ExecStart=/sls/bd/hla/{{ agebd_env }}/bin/start_service.sh TOPUPTOOL
+Restart=no
+
+[Install]
+WantedBy=default.target
+
+# https://www.freedesktop.org/software/systemd/man/latest/systemd.service.html
+# systemctl --user daemon-reload
+# systemctl --user enable /sls/bd/bin/systemd/AGEBD-SERVICE-TOPUPTOOL.service
+# systemctl --user start AGEBD-SERVICE-TOPUPTOOL
diff --git a/services/tune/current/app/pyproject.toml b/services/tune/current/app/pyproject.toml
new file mode 100644
index 0000000..c501328
--- /dev/null
+++ b/services/tune/current/app/pyproject.toml
@@ -0,0 +1,51 @@
+[project]
+name = "agebd-tune"
+version = "0.1.0"
+description = "AGEBD-TUNE Service"
+requires-python = "==3.10.*"
+dependencies = [
+ "agebd",
+ "nafflib>=2.1.1",
+ "numpy>=2.2.6",
+ "scikit-learn>=1.7.2",
+ "scipy>=1.15.3",
+]
+
+[dependency-groups]
+dev = [
+ "pyepics>=3.5.8",
+ "pytest>=8.4.2",
+ "ruff>=0.15.20",
+]
+
+[tool.uv.sources]
+# Path is relative to where agebd package is deployed on hla
+# machines (see CI/CD in .gitea/workflows)
+agebd = { path = "../../../../packages/agebd", editable = true }
+
+[build-system]
+requires = ["hatchling"]
+build-backend = "hatchling.build"
+
+[tool.uv]
+package = true
+
+[tool.pytest.ini_options]
+pythonpath = ["src"]
+env = [
+ "AGEBD_ENV=local",
+]
+
+[tool.ruff]
+include = [
+ "src/**/*.py",
+ "tests/**/*.py",
+]
+line-length = 100
+
+[tool.ruff.lint]
+# use isort to sort imports
+extend-select = ["I"]
+
+[tool.ruff.lint.isort]
+known-first-party = ["agebd"]
diff --git a/services/tune/current/app/src/agebd_tune/__init__.py b/services/tune/current/app/src/agebd_tune/__init__.py
new file mode 100644
index 0000000..1800c27
--- /dev/null
+++ b/services/tune/current/app/src/agebd_tune/__init__.py
@@ -0,0 +1 @@
+from .service import PVs, Service
diff --git a/services/tune/current/app/src/agebd_tune/main.py b/services/tune/current/app/src/agebd_tune/main.py
new file mode 100644
index 0000000..f3eaab0
--- /dev/null
+++ b/services/tune/current/app/src/agebd_tune/main.py
@@ -0,0 +1,31 @@
+import typer
+
+from agebd.enums import LogLevel
+from agebd.runner import CallbackRunner
+from agebd.utils import init_logging
+from agebd_tune import PVs, Service
+
+
+# TODO: remove: cicd test 10
+
+def main(
+ log_level: LogLevel = typer.Option(
+ LogLevel.INFO,
+ "--log-level",
+ "-l",
+ # Looks at the OS env variable first. If empty, falls back to "INFO"
+ envvar="AGEBD_LOG_LEVEL",
+ # help="Set log level: DEBUG, INFO, WARNING, ERROR, CRITICAL",
+ case_sensitive=False,
+ ),
+):
+ init_logging(log_level)
+ service_name = "TUNE"
+ pvs = PVs(service_name=service_name)
+ service = Service(name=service_name, pvs=pvs)
+ runner = CallbackRunner(service=service)
+ runner.start()
+
+
+if __name__ == "__main__":
+ typer.run(main)
diff --git a/services/tune/current/app/src/agebd_tune/service.py b/services/tune/current/app/src/agebd_tune/service.py
new file mode 100644
index 0000000..2c9945a
--- /dev/null
+++ b/services/tune/current/app/src/agebd_tune/service.py
@@ -0,0 +1,325 @@
+import pickle # ONLY FOR TESTING
+import time
+from time import sleep, time
+
+import nafflib
+import numpy as np
+from epics import PV
+
+# TODO: handle how to incorporate this into the framework
+from OMFacility import Facility
+from scipy.fft import fft
+from sklearn.utils.extmath import randomized_svd
+
+from agebd.pv import get_pv_class
+from agebd.service.base import BaseService
+from agebd.service.pvs import BasePVs
+from agebd.utils import printgetversion
+
+__version__ = printgetversion(__file__)
+
+PV = get_pv_class()
+
+
+class PVs(BasePVs):
+ Q1_fft = PV("AGEBD-TUNE:HORIZONTAL-PEAK1-FREQ") # horizontal tune from FFT
+ Q2_fft = PV("AGEBD-TUNE:VERTICAL-PEAK1-FREQ") # vertical tune from FFT
+ Q1_naff = PV("AGEBD-TUNE:Q1_NAFF") # horizontal tune from NAFF
+ Q2_naff = PV("AGEBD-TUNE:Q2_NAFF") # vertical tune from NAFF
+
+ roi_Xi = PV("AGEBD-TUNE:CONTROL-ROI-Xi")
+ roi_Xf = PV("AGEBD-TUNE:CONTROL-ROI-Xf")
+ roi_Yi = PV("AGEBD-TUNE:CONTROL-ROI-Yi")
+ roi_Yf = PV("AGEBD-TUNE:CONTROL-ROI-Yf")
+
+ TbT_firstIndex = PV("AGEBD-TUNE:CONTROL-TbTFirstIndex")
+ TbT_lastIndex = PV("AGEBD-TUNE:CONTROL-TbTLastIndex")
+
+ specx_all = PV("AGEBD-TUNE:HORIZONTAL-SPEC-ALL")
+ specy_all = PV("AGEBD-TUNE:VERTICAL-SPEC-ALL")
+ specx_roi = PV("AGEBD-TUNE:HORIZONTAL-SPEC-ROI")
+ specy_roi = PV("AGEBD-TUNE:VERTICAL-SPEC-ROI")
+ osc_sample_all = PV("AGEBD-TUNE:OSCILLATION-SAMPLE-ALL")
+ spec_sample_all = PV("AGEBD-TUNE:SPEC-SAMPLE-ALL")
+
+ # to be implemented by Felix
+ measTime = PV("AGEBD-TUNE:MEAS-TIME") # time taken for measurement
+
+ NAveraging = PV("AGEBD-TUNE:CONTROL-NAveraging")
+ naff_compute = PV("AGEBD-TUNE:CONTROL-NAFF")
+ naff_harmonics = PV("AGEBD-TUNE:NAFF-HARMONICS")
+
+ BPMSelect_single = PV("AGEBD-TUNE:SINGLE-BPM") # select whether only a single BPM is to be used
+ BPMSelect_single_selected = PV("AGEBD-TUNE:BPM-SELECT-SINGLE")
+ SVDclean = PV("AGEBD-TUNE:SVD-CLEAN") # select whether to use SVD cleaning
+ SVDclean_NEig = PV("AGEBD-TUNE:SVD-CLEAN-Neigenvalues") # select whether to use SVD cleaning
+
+ osc_x = PV("AGEBD-TUNE:OSCILLATION-X-ALL") # horizontal TbT to be transmissed
+ osc_y = PV("AGEBD-TUNE:OSCILLATION-Y-ALL") # vertical TbT to be transmissed
+
+ # usually it is advisable to trigger the mainloop of a service on changes of certain PVs:
+ BPMTriggerEvent = PV("ARS07-CECL-DBPM3-1:EEVR-EVENT0-ID")
+
+ CallbackPV_24 = PV("AGETI-CVME-MASTER-TMA:Evt-BO-Ext-EVRCount-I")
+ CallbackPV_25 = PV("AGETI-CVME-MASTER-TMA:Evt-BO-Ext-BPM-EVRCount-I")
+ CallbackPV_31 = PV("AGETI-CVME-MASTER-TMA:Evt-SR-Pinger-H-EVRCount-I")
+ CallbackPV_32 = PV("AGETI-CVME-MASTER-TMA:Evt-SR-Inj-EVRCount-I")
+ CallbackPV_34 = PV("AGETI-CVME-MASTER-TMA:Evt-SR-FKICK-EVRCount-I")
+ CallbackPV_40 = PV("AGETI-CVME-MASTER-TMA:Evt-SR-BPM-EVRCount-I")
+
+ def __init__(self, service_name: str, pv_factory=PV):
+ super().__init__(service_name, pv_factory)
+ PV = pv_factory
+
+ S2 = Facility("/sls/bd/bin/MasterLayout.txt")
+ S2.Layout("full", -1)
+
+ disabledBPMs = ["ARS01-DBPM-0530", "ARS03-DBPM-0840", "ARS10-DBPM-0970", "ARS11-DBPM-0880"]
+ BPMNames_BPM = S2.listElement_TYPE("BPM")
+ BPMNames_BPMA = S2.listElement_TYPE("BPMA")
+ BPMNames = [item for item in BPMNames_BPM if item not in disabledBPMs]
+ BPMNamesA = [item for item in BPMNames_BPMA if item not in disabledBPMs]
+
+ BPMNames_x = [name + ":DAQ-BEAM-STG0-X" for name in BPMNames]
+ BPMNames_y = [name + ":DAQ-BEAM-STG0-Y" for name in BPMNames]
+ BPMNames_I = [name + ":DAQ-BEAM-STG0-Q" for name in BPMNames]
+ BPMNamesA_x = [name + ":DAQ-BEAM-STG0-X" for name in BPMNamesA]
+ BPMNamesA_y = [name + ":DAQ-BEAM-STG0-Y" for name in BPMNamesA]
+ BPMNamesA_I = [name + ":DAQ-BEAM-STG0-Q" for name in BPMNamesA]
+
+ self.BPMx = [PV(name) for name in BPMNames_x]
+ self.BPMy = [PV(name) for name in BPMNames_y]
+ self.BPMI = [PV(name) for name in BPMNames_I]
+ self.BPMxA = [PV(name) for name in BPMNamesA_x]
+ self.BPMyA = [PV(name) for name in BPMNamesA_y]
+ self.BPMIA = [PV(name) for name in BPMNamesA_I]
+
+ self.CallbackPV = None
+
+
+class Service(BaseService[PVs]):
+ def __init__(
+ self,
+ name: str,
+ pvs: PVs,
+ version: str = __version__,
+ sleep_interval: float = 0.1,
+ ):
+ super().__init__(name, pvs, version, sleep_interval)
+
+ self.update_control()
+
+ def update_control(self):
+ pvs = self.pvs
+
+ BPMTriggerEvent = pvs.BPMTriggerEvent.get()
+
+ if BPMTriggerEvent == 24: # trigger is booster extraction
+ pvs.CallbackPV = pvs.CallbackPV_24
+ elif BPMTriggerEvent == 25: # trigger is booster extraction BPM
+ pvs.CallbackPV = pvs.CallbackPV_25
+ elif BPMTriggerEvent == 31: # trigger is pingerH event
+ pvs.CallbackPV = pvs.CallbackPV_31
+ elif BPMTriggerEvent == 32: # trigger is SR-Inj event
+ pvs.CallbackPV = pvs.CallbackPV_32
+ elif BPMTriggerEvent == 34: # trigger is pingerV event fast kicker event
+ pvs.CallbackPV = pvs.CallbackPV_34
+ elif BPMTriggerEvent == 40: # trigger is SR BPM Sync event
+ pvs.CallbackPV = pvs.CallbackPV_40
+ else:
+ print("BPM trigger event ID not understood. Value is: " + str(BPMTriggerEvent))
+
+ samplingRate = 2 # sampling rate of BPMs w.r.t. 1 MHz
+ TbT_firstIndex = np.int64(pvs.TbT_firstIndex.get())
+ TbT_lastIndex = np.int64(pvs.TbT_lastIndex.get())
+
+ # user was stupid: set first index higher than last index
+ if TbT_firstIndex >= TbT_lastIndex:
+ TbT_firstIndex = TbT_lastIndex - 1
+ pvs.TbT_firstIndex.put(TbT_firstIndex)
+
+ # user was stupid: set last index lower than first index
+ if TbT_lastIndex <= TbT_firstIndex:
+ TbT_lastIndex = TbT_firstIndex + 1
+ pvs.TbT_lastIndex.put(TbT_lastIndex)
+
+ self.Index_first = np.int64(
+ np.arange(TbT_firstIndex * samplingRate, TbT_lastIndex * samplingRate + 1, samplingRate)
+ )
+ self.Index_second = np.int64(
+ np.arange(
+ 1 + TbT_firstIndex * samplingRate,
+ TbT_lastIndex * samplingRate + 1 + 1,
+ samplingRate,
+ )
+ )
+ self.NIndex = len(range(TbT_firstIndex, TbT_lastIndex + 1))
+
+ # NAFF control parameters
+ self.naff_onoff = pvs.naff_compute.get()
+ self.naff_Nharmonics = int(pvs.naff_harmonics.get())
+
+ pvs.osc_sample_all.put(np.int64(np.arange(self.NIndex)))
+ pvs.spec_sample_all.put(np.linspace(0, 1, self.NIndex))
+
+ if pvs.BPMSelect_single.get():
+ BPMNames_single = pvs.BPMSelect_single_selected.get()
+
+ index_BPM = next((i for i, s in enumerate(BPMNames) if s == BPMNames_single), None)
+ index_BPMA = next((i for i, s in enumerate(BPMNamesA) if s == BPMNames_single), None)
+
+ if index_BPM is not None:
+ pvs.BPMx_selected = [pvs.BPMx[index_BPM]]
+ pvs.BPMy_selected = [pvs.BPMy[index_BPM]]
+ pvs.BPMI_selected = [pvs.BPMI[index_BPM]]
+ else:
+ pvs.BPMx_selected = [pvs.BPMxA[index_BPMA]]
+ pvs.BPMy_selected = [pvs.BPMyA[index_BPMA]]
+ pvs.BPMI_selected = [pvs.BPMIA[index_BPMA]]
+
+ self.NBPMs = 1
+ else:
+ pvs.BPMx_selected = pvs.BPMx
+ pvs.BPMy_selected = pvs.BPMy
+ pvs.BPMI_selected = pvs.BPMI
+ self.NBPMs = len(pvs.BPMx)
+ self.NSamples = int(pvs.NAveraging.get())
+ self.N_SVDeig = int(pvs.SVDclean_NEig.get())
+
+ def update(self):
+ pvs = self.pvs
+
+ if self.CallbackFired:
+ t_start = time()
+ self.update_control()
+ if self.NBPMs == 0:
+ return
+
+ x = np.zeros((self.NBPMs, self.NIndex, self.NSamples))
+ y = np.zeros((self.NBPMs, self.NIndex, self.NSamples))
+ for sample in range(self.NSamples):
+ if sample > 0:
+ sleep(1 / 3)
+
+ xtmp = np.array([pv.get() for pv in pvs.BPMx_selected])
+ ytmp = np.array([pv.get() for pv in pvs.BPMy_selected])
+ Itmp = np.array([pv.get() for pv in pvs.BPMI_selected])
+
+ index_max = np.argmax(Itmp[:, 0:2], axis=1)
+ for n in range(self.NBPMs):
+ if index_max[n] == 0:
+ x[n, :, sample] = xtmp[n, self.Index_first] - np.mean(
+ xtmp[n, self.Index_first]
+ ) # subtract mean values
+ y[n, :, sample] = ytmp[n, self.Index_first] - np.mean(
+ ytmp[n, self.Index_first]
+ ) # subtract mean values
+ else:
+ x[n, :, sample] = xtmp[n, self.Index_second] - np.mean(
+ xtmp[n, self.Index_second]
+ ) # subtract mean values
+ y[n, :, sample] = ytmp[n, self.Index_second] - np.mean(
+ ytmp[n, self.Index_second]
+ ) # subtract mean values
+
+ Ax = np.mean(x, axis=2) # average over NSamples
+ Ay = np.mean(y, axis=2)
+
+ if pvs.SVDclean.get():
+ Ux, Sx, Vx_T = randomized_svd(Ax, n_components=self.N_SVDeig)
+ Ax = Ux @ np.diag(Sx) @ Vx_T
+ Uy, Sy, Vy_T = randomized_svd(Ay, n_components=self.N_SVDeig)
+ Ay = Uy @ np.diag(Sy) @ Vy_T
+ Fx = fft(Ax[0, :]) # FFT first BPM only
+ Fy = fft(Ay[0, :])
+
+ specx = np.abs(Fx) # Take absolute of FFT to obtain amplitude spectra
+ specy = np.abs(Fy)
+ specx[: np.int64(np.ceil(self.NIndex * 0.01))] = 0 # remove DC component
+ specy[: np.int64(np.ceil(self.NIndex * 0.01))] = 0 # remove DC component
+
+ specx_avg = specx / np.max(specx) # normalize spectra of first BPM
+ specy_avg = specy / np.max(specy) # normalize spectra of first BPM
+
+ window_x_start = round(pvs.roi_Xi.get() * self.NIndex)
+ window_x_end = round(pvs.roi_Xf.get() * self.NIndex)
+ window_y_start = round(pvs.roi_Yi.get() * self.NIndex)
+ window_y_end = round(pvs.roi_Yf.get() * self.NIndex)
+ window_indices_x = np.arange(window_x_start, window_x_end + 1)
+ window_indices_y = np.arange(window_y_start, window_y_end + 1)
+
+ index_max_local_x = np.argmax(specx_avg[window_x_start:window_x_end])
+ index_max_local_y = np.argmax(specy_avg[window_y_start:window_y_end])
+ Q1_FFTval = window_indices_x[index_max_local_x] / self.NIndex
+ Q2_FFTval = window_indices_y[index_max_local_y] / self.NIndex
+
+ pvs.Q1_fft.put(Q1_FFTval)
+ pvs.Q2_fft.put(Q2_FFTval)
+
+ Ax_mixed = Ax.transpose()
+ Ay_mixed = Ay.transpose()
+ Ax_mixed = Ax_mixed.flatten()
+ Ay_mixed = Ay_mixed.flatten()
+
+ Q1_naff = np.nan
+ Q2_naff = np.nan
+
+ if self.naff_onoff:
+ h1_naff, _, _ = nafflib.get_tunes(Ax_mixed, self.naff_Nharmonics)
+ h2_naff, _, _ = nafflib.get_tunes(Ay_mixed, self.naff_Nharmonics)
+
+ h1_naff = h1_naff * self.NBPMs
+ h2_naff = h2_naff * self.NBPMs
+
+ Q1_naff = np.mod(h1_naff, 1)
+ Q2_naff = np.mod(h2_naff, 1)
+
+ Q1_naff[Q1_naff > 0.5] = (
+ 1 - Q1_naff[Q1_naff > 0.5]
+ ) # above-half integer peak found. Going down.
+ Q2_naff[Q2_naff > 0.5] = 1 - Q2_naff[Q2_naff > 0.5]
+
+ Q1_naff = Q1_naff[(Q1_naff >= Q1_FFTval - 0.01) & (Q1_naff <= Q1_FFTval + 0.01)]
+ Q2_naff = Q2_naff[(Q2_naff >= Q2_FFTval - 0.01) & (Q2_naff <= Q2_FFTval + 0.01)]
+
+ if len(Q1_naff) == 0:
+ Q1_naff = np.nan
+ else:
+ Q1_naff = np.mean(Q1_naff)
+
+ if len(Q2_naff) == 0:
+ Q2_naff = np.nan
+ else:
+ Q2_naff = np.mean(Q2_naff)
+
+ # if self.NBPMs == 1:
+ # integerX = 0
+ # integerY = 0
+ # else:
+ # integerX = 39
+ # integerY = 15
+ # dh1 = h1_naff*self.NBPMs-(integerX+Q1_FFTval)
+ # dh2 = h2_naff*self.NBPMs-(integerY+Q2_FFTval)
+ # if min(abs(dh1))>0.5:# correct integer not found. Increasing number of harmonics
+ # h1_naff, _, _ = nafflib.get_tunes(Ax_mixed,50)
+ # dh1 = h1_naff*self.NBPMs-(integerX+Q1_FFTval)
+ # if min(abs(dh2))>0.5:# correct integer not found. Increasing number of harmonics
+ # h2_naff, _, _ = nafflib.get_tunes(Ay_mixed,25)
+ # dh2 = h2_naff*self.NBPMs-(integerY+Q2_FFTval)
+ # Q1_naff = h1_naff[np.argmin(abs(dh1))]*self.NBPMs
+ # Q2_naff = h2_naff[np.argmin(abs(dh2))]*self.NBPMs
+
+ pvs.Q1_naff.put(Q1_naff)
+ pvs.Q2_naff.put(Q2_naff)
+
+ pvs.specx_all.put(specx_avg)
+ pvs.specy_all.put(specy_avg)
+ pvs.specx_roi.put(specx_avg[window_x_start - 1 : window_x_end])
+ pvs.specy_roi.put(specy_avg[window_y_start - 1 : window_y_end])
+
+ pvs.osc_x.put(Ax[0, :])
+ pvs.osc_y.put(Ay[0, :])
+ t_end = time()
+ pvs.measTime.put((t_end - t_start) * 1e3)
+
+ self.CallbackFired = 0
diff --git a/services/tune/current/app/tests/test_app.py b/services/tune/current/app/tests/test_app.py
new file mode 100644
index 0000000..2afcc45
--- /dev/null
+++ b/services/tune/current/app/tests/test_app.py
@@ -0,0 +1,9 @@
+from agebd_tune import PVs, Service
+
+
+def test_app():
+ service_name = "DUMMY"
+ pvs = PVs(service_name=service_name)
+ service = Service(name=service_name, pvs=pvs)
+ service.CallbackFired = 1
+ service.update()
diff --git a/services/tune/current/app/uv.lock b/services/tune/current/app/uv.lock
new file mode 100644
index 0000000..8ea8b91
--- /dev/null
+++ b/services/tune/current/app/uv.lock
@@ -0,0 +1,463 @@
+version = 1
+revision = 3
+requires-python = "==3.10.*"
+
+[[package]]
+name = "agebd"
+version = "0.1.0"
+source = { editable = "../../../../packages/agebd" }
+dependencies = [
+ { name = "h5py" },
+ { name = "typer" },
+]
+
+[package.metadata]
+requires-dist = [
+ { name = "h5py", specifier = ">=3.16.0" },
+ { name = "typer", specifier = ">=0.23.2" },
+]
+
+[package.metadata.requires-dev]
+dev = [
+ { name = "pyright", specifier = ">=1.1.410" },
+ { name = "pytest", specifier = ">=8.4.2" },
+ { name = "ruff", specifier = ">=0.15.19" },
+]
+
+[[package]]
+name = "agebd-tune"
+version = "0.1.0"
+source = { editable = "." }
+dependencies = [
+ { name = "agebd" },
+ { name = "nafflib" },
+ { name = "numpy" },
+ { name = "scikit-learn" },
+ { name = "scipy" },
+]
+
+[package.dev-dependencies]
+dev = [
+ { name = "pyepics" },
+ { name = "pytest" },
+ { name = "ruff" },
+]
+
+[package.metadata]
+requires-dist = [
+ { name = "agebd", editable = "../../../../packages/agebd" },
+ { name = "nafflib", specifier = ">=2.1.1" },
+ { name = "numpy", specifier = ">=2.2.6" },
+ { name = "scikit-learn", specifier = ">=1.7.2" },
+ { name = "scipy", specifier = ">=1.15.3" },
+]
+
+[package.metadata.requires-dev]
+dev = [
+ { name = "pyepics", specifier = ">=3.5.8" },
+ { name = "pytest", specifier = ">=8.4.2" },
+ { name = "ruff", specifier = ">=0.15.20" },
+]
+
+[[package]]
+name = "annotated-doc"
+version = "0.0.4"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/57/ba/046ceea27344560984e26a590f90bc7f4a75b06701f653222458922b558c/annotated_doc-0.0.4.tar.gz", hash = "sha256:fbcda96e87e9c92ad167c2e53839e57503ecfda18804ea28102353485033faa4", size = 7288, upload-time = "2025-11-10T22:07:42.062Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl", hash = "sha256:571ac1dc6991c450b25a9c2d84a3705e2ae7a53467b5d111c24fa8baabbed320", size = 5303, upload-time = "2025-11-10T22:07:40.673Z" },
+]
+
+[[package]]
+name = "colorama"
+version = "0.4.6"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" },
+]
+
+[[package]]
+name = "exceptiongroup"
+version = "1.3.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "typing-extensions" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" },
+]
+
+[[package]]
+name = "h5py"
+version = "3.16.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "numpy" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/db/33/acd0ce6863b6c0d7735007df01815403f5589a21ff8c2e1ee2587a38f548/h5py-3.16.0.tar.gz", hash = "sha256:a0dbaad796840ccaa67a4c144a0d0c8080073c34c76d5a6941d6818678ef2738", size = 446526, upload-time = "2026-03-06T13:49:08.07Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/3a/6b/231413e58a787a89b316bb0d1777da3c62257e4797e09afd8d17ad3549dc/h5py-3.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e06f864bedb2c8e7c1358e6c73af48519e317457c444d6f3d332bb4e8fa6d7d9", size = 3724137, upload-time = "2026-03-06T13:47:35.242Z" },
+ { url = "https://files.pythonhosted.org/packages/74/f9/557ce3aad0fe8471fb5279bab0fc56ea473858a022c4ce8a0b8f303d64e9/h5py-3.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ec86d4fffd87a0f4cb3d5796ceb5a50123a2a6d99b43e616e5504e66a953eca3", size = 3090112, upload-time = "2026-03-06T13:47:37.634Z" },
+ { url = "https://files.pythonhosted.org/packages/7a/f5/e15b3d0dc8a18e56409a839e6468d6fb589bc5207c917399c2e0706eeb44/h5py-3.16.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:86385ea895508220b8a7e45efa428aeafaa586bd737c7af9ee04661d8d84a10d", size = 4844847, upload-time = "2026-03-06T13:47:39.811Z" },
+ { url = "https://files.pythonhosted.org/packages/cb/92/a8851d936547efe30cc0ce5245feac01f3ec6171f7899bc3f775c72030b3/h5py-3.16.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:8975273c2c5921c25700193b408e28d6bdd0111c37468b2d4e25dcec4cd1d84d", size = 5065352, upload-time = "2026-03-06T13:47:41.489Z" },
+ { url = "https://files.pythonhosted.org/packages/2b/ae/f2adc5d0ca9626db3277a3d87516e124cbc5d0eea0bd79bc085702d04f2c/h5py-3.16.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:1677ad48b703f44efc9ea0c3ab284527f81bc4f318386aaaebc5fede6bbae56f", size = 4839173, upload-time = "2026-03-06T13:47:43.586Z" },
+ { url = "https://files.pythonhosted.org/packages/64/0b/e0c8c69da1d8838da023a50cd3080eae5d475691f7636b35eff20bb6ef20/h5py-3.16.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7c4dd4cf5f0a4e36083f73172f6cfc25a5710789269547f132a20975bfe2434c", size = 5076216, upload-time = "2026-03-06T13:47:45.315Z" },
+ { url = "https://files.pythonhosted.org/packages/66/35/d88fd6718832133c885004c61ceeeb24dbd6397ef877dbed6b3a64d6a286/h5py-3.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:bdef06507725b455fccba9c16529121a5e1fbf56aa375f7d9713d9e8ff42454d", size = 3183639, upload-time = "2026-03-06T13:47:47.041Z" },
+]
+
+[[package]]
+name = "iniconfig"
+version = "2.3.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" },
+]
+
+[[package]]
+name = "joblib"
+version = "1.5.3"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/41/f2/d34e8b3a08a9cc79a50b2208a93dce981fe615b64d5a4d4abee421d898df/joblib-1.5.3.tar.gz", hash = "sha256:8561a3269e6801106863fd0d6d84bb737be9e7631e33aaed3fb9ce5953688da3", size = 331603, upload-time = "2025-12-15T08:41:46.427Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/7b/91/984aca2ec129e2757d1e4e3c81c3fcda9d0f85b74670a094cc443d9ee949/joblib-1.5.3-py3-none-any.whl", hash = "sha256:5fc3c5039fc5ca8c0276333a188bbd59d6b7ab37fe6632daa76bc7f9ec18e713", size = 309071, upload-time = "2025-12-15T08:41:44.973Z" },
+]
+
+[[package]]
+name = "llvmlite"
+version = "0.48.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/dc/a0/acc8ffcd5bdc63df0097e22c719bfcd61b604358343089313a8aebbb24ab/llvmlite-0.48.0.tar.gz", hash = "sha256:543b19f9ef8f3c7c60d1468191e4ee1b1537bf9f8a3d56f64c0ddd98de92edd2", size = 184016, upload-time = "2026-07-02T20:20:05.308Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/a2/4e/32543c42568fb321b3bdfcf9106e4116ab8f5a7bbcfd9ecf5569b0c07d83/llvmlite-0.48.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:614aad57df707e3172efd5165f2aa7da6a0c6897e40dce590bf756396815ba76", size = 40480650, upload-time = "2026-07-01T18:41:01.945Z" },
+ { url = "https://files.pythonhosted.org/packages/a9/0d/6aa48abd423067139a129d1434b77bbcc56080db51d12a88510bb491ca3d/llvmlite-0.48.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:13532f248960ba888ad5ab8150494e2f3a3d20e5f59f264e63741ea5b0ba844c", size = 59890118, upload-time = "2026-07-01T18:41:10.608Z" },
+ { url = "https://files.pythonhosted.org/packages/5a/c7/aa917444d871a79608af49149de1b28764e87d2ab41f933c5cd02431d03d/llvmlite-0.48.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3ee0c77685a18f5fca994ae21d0763007fca5c5c64b41de37accc78b69079176", size = 58343459, upload-time = "2026-07-01T18:41:06.21Z" },
+ { url = "https://files.pythonhosted.org/packages/c5/2b/ceee1cdc263617109d514ac4d1b31f10a282662740ff7d5777baae25b3b5/llvmlite-0.48.0-cp310-cp310-win_amd64.whl", hash = "sha256:02853fe4214acb3780fc920c3fee10564b61d58a35e1b78afcc8a546c2deaba3", size = 41864734, upload-time = "2026-07-01T18:41:14.746Z" },
+]
+
+[[package]]
+name = "markdown-it-py"
+version = "4.2.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "mdurl" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/06/ff/7841249c247aa650a76b9ee4bbaeae59370dc8bfd2f6c01f3630c35eb134/markdown_it_py-4.2.0.tar.gz", hash = "sha256:04a21681d6fbb623de53f6f364d352309d4094dd4194040a10fd51833e418d49", size = 82454, upload-time = "2026-05-07T12:08:28.36Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl", hash = "sha256:9f7ebbcd14fe59494226453aed97c1070d83f8d24b6fc3a3bcf9a38092641c4a", size = 91687, upload-time = "2026-05-07T12:08:27.182Z" },
+]
+
+[[package]]
+name = "mdurl"
+version = "0.1.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" },
+]
+
+[[package]]
+name = "nafflib"
+version = "2.1.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "numba" },
+ { name = "numpy" },
+ { name = "pandas" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/01/0d/3d563dfc173916d5c0cc1fe614cdf312877540b9cea5bcd50a271ba5f6a3/nafflib-2.1.1.tar.gz", hash = "sha256:e4c67224c01db4b694d8f9c73c5b878178d80379ad99ae89adb4cce21ededd9b", size = 22926, upload-time = "2025-11-22T15:47:22.152Z" }
+
+[[package]]
+name = "numba"
+version = "0.66.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "llvmlite" },
+ { name = "numpy" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/ae/a0/570e3dc53e5602b49108f62a13e529f1eec8bfc7ef37d49c825924dcf546/numba-0.66.0.tar.gz", hash = "sha256:b900e63a0e26c05ea9a6d5a3a5a0a177cb64c5011887bf43edb8c3ed2c38d363", size = 2806181, upload-time = "2026-07-01T23:12:46.36Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/2b/48/d139bde40f2359351bfe26ee1b261937f458ac177ab810d4f045ae1c9d92/numba-0.66.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:27951c47e0def9bf8afe580eb961102902e2fd23cb77924b7d9d7cc0f8b444cb", size = 2727368, upload-time = "2026-07-01T23:12:04.282Z" },
+ { url = "https://files.pythonhosted.org/packages/36/e4/b780bfa9191410da50ba249cb3248a75014e17f611e72709cbddcb21f42d/numba-0.66.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:cc408c54b450f41582f4be1608f8981c1dcc44c7f40355cc150dd93015753407", size = 3803554, upload-time = "2026-07-01T23:12:06.379Z" },
+ { url = "https://files.pythonhosted.org/packages/1c/b2/a051b96626bdf5c4d8fa6b8d450605c09638d85dc872ab63ef9a67096dca/numba-0.66.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7c14c044c06b453ec3fa7715dfe75425e2ba72c73377a7ffde6d9ec511dfd94c", size = 3510065, upload-time = "2026-07-01T23:12:08.051Z" },
+ { url = "https://files.pythonhosted.org/packages/34/01/24dcdc3e919522e2efbd92969c281ff40deb1d5f8a994bcd0057081c158c/numba-0.66.0-cp310-cp310-win_amd64.whl", hash = "sha256:2338cc0d43609fe448930848fd35a5bc688761b986f81b597a6f45cc0f8c9577", size = 2780379, upload-time = "2026-07-01T23:12:09.772Z" },
+]
+
+[[package]]
+name = "numpy"
+version = "2.2.6"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/76/21/7d2a95e4bba9dc13d043ee156a356c0a8f0c6309dff6b21b4d71a073b8a8/numpy-2.2.6.tar.gz", hash = "sha256:e29554e2bef54a90aa5cc07da6ce955accb83f21ab5de01a62c8478897b264fd", size = 20276440, upload-time = "2025-05-17T22:38:04.611Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/9a/3e/ed6db5be21ce87955c0cbd3009f2803f59fa08df21b5df06862e2d8e2bdd/numpy-2.2.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b412caa66f72040e6d268491a59f2c43bf03eb6c96dd8f0307829feb7fa2b6fb", size = 21165245, upload-time = "2025-05-17T21:27:58.555Z" },
+ { url = "https://files.pythonhosted.org/packages/22/c2/4b9221495b2a132cc9d2eb862e21d42a009f5a60e45fc44b00118c174bff/numpy-2.2.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e41fd67c52b86603a91c1a505ebaef50b3314de0213461c7a6e99c9a3beff90", size = 14360048, upload-time = "2025-05-17T21:28:21.406Z" },
+ { url = "https://files.pythonhosted.org/packages/fd/77/dc2fcfc66943c6410e2bf598062f5959372735ffda175b39906d54f02349/numpy-2.2.6-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:37e990a01ae6ec7fe7fa1c26c55ecb672dd98b19c3d0e1d1f326fa13cb38d163", size = 5340542, upload-time = "2025-05-17T21:28:30.931Z" },
+ { url = "https://files.pythonhosted.org/packages/7a/4f/1cb5fdc353a5f5cc7feb692db9b8ec2c3d6405453f982435efc52561df58/numpy-2.2.6-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:5a6429d4be8ca66d889b7cf70f536a397dc45ba6faeb5f8c5427935d9592e9cf", size = 6878301, upload-time = "2025-05-17T21:28:41.613Z" },
+ { url = "https://files.pythonhosted.org/packages/eb/17/96a3acd228cec142fcb8723bd3cc39c2a474f7dcf0a5d16731980bcafa95/numpy-2.2.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:efd28d4e9cd7d7a8d39074a4d44c63eda73401580c5c76acda2ce969e0a38e83", size = 14297320, upload-time = "2025-05-17T21:29:02.78Z" },
+ { url = "https://files.pythonhosted.org/packages/b4/63/3de6a34ad7ad6646ac7d2f55ebc6ad439dbbf9c4370017c50cf403fb19b5/numpy-2.2.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc7b73d02efb0e18c000e9ad8b83480dfcd5dfd11065997ed4c6747470ae8915", size = 16801050, upload-time = "2025-05-17T21:29:27.675Z" },
+ { url = "https://files.pythonhosted.org/packages/07/b6/89d837eddef52b3d0cec5c6ba0456c1bf1b9ef6a6672fc2b7873c3ec4e2e/numpy-2.2.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:74d4531beb257d2c3f4b261bfb0fc09e0f9ebb8842d82a7b4209415896adc680", size = 15807034, upload-time = "2025-05-17T21:29:51.102Z" },
+ { url = "https://files.pythonhosted.org/packages/01/c8/dc6ae86e3c61cfec1f178e5c9f7858584049b6093f843bca541f94120920/numpy-2.2.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8fc377d995680230e83241d8a96def29f204b5782f371c532579b4f20607a289", size = 18614185, upload-time = "2025-05-17T21:30:18.703Z" },
+ { url = "https://files.pythonhosted.org/packages/5b/c5/0064b1b7e7c89137b471ccec1fd2282fceaae0ab3a9550f2568782d80357/numpy-2.2.6-cp310-cp310-win32.whl", hash = "sha256:b093dd74e50a8cba3e873868d9e93a85b78e0daf2e98c6797566ad8044e8363d", size = 6527149, upload-time = "2025-05-17T21:30:29.788Z" },
+ { url = "https://files.pythonhosted.org/packages/a3/dd/4b822569d6b96c39d1215dbae0582fd99954dcbcf0c1a13c61783feaca3f/numpy-2.2.6-cp310-cp310-win_amd64.whl", hash = "sha256:f0fd6321b839904e15c46e0d257fdd101dd7f530fe03fd6359c1ea63738703f3", size = 12904620, upload-time = "2025-05-17T21:30:48.994Z" },
+ { url = "https://files.pythonhosted.org/packages/9e/3b/d94a75f4dbf1ef5d321523ecac21ef23a3cd2ac8b78ae2aac40873590229/numpy-2.2.6-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0b605b275d7bd0c640cad4e5d30fa701a8d59302e127e5f79138ad62762c3e3d", size = 21040391, upload-time = "2025-05-17T21:44:35.948Z" },
+ { url = "https://files.pythonhosted.org/packages/17/f4/09b2fa1b58f0fb4f7c7963a1649c64c4d315752240377ed74d9cd878f7b5/numpy-2.2.6-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:7befc596a7dc9da8a337f79802ee8adb30a552a94f792b9c9d18c840055907db", size = 6786754, upload-time = "2025-05-17T21:44:47.446Z" },
+ { url = "https://files.pythonhosted.org/packages/af/30/feba75f143bdc868a1cc3f44ccfa6c4b9ec522b36458e738cd00f67b573f/numpy-2.2.6-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce47521a4754c8f4593837384bd3424880629f718d87c5d44f8ed763edd63543", size = 16643476, upload-time = "2025-05-17T21:45:11.871Z" },
+ { url = "https://files.pythonhosted.org/packages/37/48/ac2a9584402fb6c0cd5b5d1a91dcf176b15760130dd386bbafdbfe3640bf/numpy-2.2.6-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d042d24c90c41b54fd506da306759e06e568864df8ec17ccc17e9e884634fd00", size = 12812666, upload-time = "2025-05-17T21:45:31.426Z" },
+]
+
+[[package]]
+name = "packaging"
+version = "26.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d7/f1/e7a6dd94a8d4a5626c03e4e99c87f241ba9e350cd9e6d75123f992427270/packaging-26.2.tar.gz", hash = "sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661", size = 228134, upload-time = "2026-04-24T20:15:23.917Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/df/b2/87e62e8c3e2f4b32e5fe99e0b86d576da1312593b39f47d8ceef365e95ed/packaging-26.2-py3-none-any.whl", hash = "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e", size = 100195, upload-time = "2026-04-24T20:15:22.081Z" },
+]
+
+[[package]]
+name = "pandas"
+version = "2.3.3"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "numpy" },
+ { name = "python-dateutil" },
+ { name = "pytz" },
+ { name = "tzdata" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/33/01/d40b85317f86cf08d853a4f495195c73815fdf205eef3993821720274518/pandas-2.3.3.tar.gz", hash = "sha256:e05e1af93b977f7eafa636d043f9f94c7ee3ac81af99c13508215942e64c993b", size = 4495223, upload-time = "2025-09-29T23:34:51.853Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/3d/f7/f425a00df4fcc22b292c6895c6831c0c8ae1d9fac1e024d16f98a9ce8749/pandas-2.3.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:376c6446ae31770764215a6c937f72d917f214b43560603cd60da6408f183b6c", size = 11555763, upload-time = "2025-09-29T23:16:53.287Z" },
+ { url = "https://files.pythonhosted.org/packages/13/4f/66d99628ff8ce7857aca52fed8f0066ce209f96be2fede6cef9f84e8d04f/pandas-2.3.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e19d192383eab2f4ceb30b412b22ea30690c9e618f78870357ae1d682912015a", size = 10801217, upload-time = "2025-09-29T23:17:04.522Z" },
+ { url = "https://files.pythonhosted.org/packages/1d/03/3fc4a529a7710f890a239cc496fc6d50ad4a0995657dccc1d64695adb9f4/pandas-2.3.3-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5caf26f64126b6c7aec964f74266f435afef1c1b13da3b0636c7518a1fa3e2b1", size = 12148791, upload-time = "2025-09-29T23:17:18.444Z" },
+ { url = "https://files.pythonhosted.org/packages/40/a8/4dac1f8f8235e5d25b9955d02ff6f29396191d4e665d71122c3722ca83c5/pandas-2.3.3-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dd7478f1463441ae4ca7308a70e90b33470fa593429f9d4c578dd00d1fa78838", size = 12769373, upload-time = "2025-09-29T23:17:35.846Z" },
+ { url = "https://files.pythonhosted.org/packages/df/91/82cc5169b6b25440a7fc0ef3a694582418d875c8e3ebf796a6d6470aa578/pandas-2.3.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4793891684806ae50d1288c9bae9330293ab4e083ccd1c5e383c34549c6e4250", size = 13200444, upload-time = "2025-09-29T23:17:49.341Z" },
+ { url = "https://files.pythonhosted.org/packages/10/ae/89b3283800ab58f7af2952704078555fa60c807fff764395bb57ea0b0dbd/pandas-2.3.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:28083c648d9a99a5dd035ec125d42439c6c1c525098c58af0fc38dd1a7a1b3d4", size = 13858459, upload-time = "2025-09-29T23:18:03.722Z" },
+ { url = "https://files.pythonhosted.org/packages/85/72/530900610650f54a35a19476eca5104f38555afccda1aa11a92ee14cb21d/pandas-2.3.3-cp310-cp310-win_amd64.whl", hash = "sha256:503cf027cf9940d2ceaa1a93cfb5f8c8c7e6e90720a2850378f0b3f3b1e06826", size = 11346086, upload-time = "2025-09-29T23:18:18.505Z" },
+]
+
+[[package]]
+name = "pluggy"
+version = "1.6.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" },
+]
+
+[[package]]
+name = "pyepics"
+version = "3.5.10"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "numpy" },
+ { name = "pyparsing" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/69/57/29e1e9ef11ba2a3419f489946ae1d8190025a1e4f4e1c1686758bb2b6e0a/pyepics-3.5.10.tar.gz", hash = "sha256:f390cf9be40aba757b9528888114bc14d8db01086d0c93914720b1772460375b", size = 6150481, upload-time = "2026-05-20T18:44:36.336Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d6/36/e517fd83bd97d6bfe4105e0c6b322070c5cc36fb56a8fab2866e319f8804/pyepics-3.5.10-py3-none-any.whl", hash = "sha256:c9fac2c54f2b595268e66fc348cf5ec24e63718e7dbd07d73d1b37d4da6bfee1", size = 5332376, upload-time = "2026-05-20T18:44:34.242Z" },
+]
+
+[[package]]
+name = "pygments"
+version = "2.20.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" },
+]
+
+[[package]]
+name = "pyparsing"
+version = "3.3.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f3/91/9c6ee907786a473bf81c5f53cf703ba0957b23ab84c264080fb5a450416f/pyparsing-3.3.2.tar.gz", hash = "sha256:c777f4d763f140633dcb6d8a3eda953bf7a214dc4eff598413c070bcdc117cbc", size = 6851574, upload-time = "2026-01-21T03:57:59.36Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl", hash = "sha256:850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d", size = 122781, upload-time = "2026-01-21T03:57:55.912Z" },
+]
+
+[[package]]
+name = "pytest"
+version = "9.1.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "colorama", marker = "sys_platform == 'win32'" },
+ { name = "exceptiongroup" },
+ { name = "iniconfig" },
+ { name = "packaging" },
+ { name = "pluggy" },
+ { name = "pygments" },
+ { name = "tomli" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/e4/47/b9efed96c114afcfa3c9d3fe98a76a1d14c74a9e266d397cf6eb64be5e01/pytest-9.1.1.tar.gz", hash = "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313", size = 1636369, upload-time = "2026-06-19T10:58:32.857Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/24/25/1de2678b631f5a49215c6c96fff41ba892b0a34df68d6d80292b1b48aa7f/pytest-9.1.1-py3-none-any.whl", hash = "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c", size = 386536, upload-time = "2026-06-19T10:58:31.347Z" },
+]
+
+[[package]]
+name = "python-dateutil"
+version = "2.9.0.post0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "six" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" },
+]
+
+[[package]]
+name = "pytz"
+version = "2026.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/ff/46/dd499ec9038423421951e4fad73051febaa13d2df82b4064f87af8b8c0c3/pytz-2026.2.tar.gz", hash = "sha256:0e60b47b29f21574376f218fe21abc009894a2321ea16c6754f3cad6eb7cdd6a", size = 320861, upload-time = "2026-05-04T01:35:29.667Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/ec/dd/96da98f892250475bdf2328112d7468abdd4acc7b902b6af23f4ed958ea0/pytz-2026.2-py2.py3-none-any.whl", hash = "sha256:04156e608bee23d3792fd45c94ae47fae1036688e75032eea2e3bf0323d1f126", size = 510141, upload-time = "2026-05-04T01:35:27.408Z" },
+]
+
+[[package]]
+name = "rich"
+version = "15.0.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "markdown-it-py" },
+ { name = "pygments" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/c0/8f/0722ca900cc807c13a6a0c696dacf35430f72e0ec571c4275d2371fca3e9/rich-15.0.0.tar.gz", hash = "sha256:edd07a4824c6b40189fb7ac9bc4c52536e9780fbbfbddf6f1e2502c31b068c36", size = 230680, upload-time = "2026-04-12T08:24:00.75Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl", hash = "sha256:33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb", size = 310654, upload-time = "2026-04-12T08:24:02.83Z" },
+]
+
+[[package]]
+name = "ruff"
+version = "0.15.21"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/0f/36/6f65aa9989acdec45d417192d8f4e7921931d8a6cf87ac74bce3eed98a8e/ruff-0.15.21.tar.gz", hash = "sha256:d0cfc841c572283c36548f82664a54ce6565567f1b0d5b4cf2caac693d8b7500", size = 4769401, upload-time = "2026-07-09T20:01:34.005Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d0/c6/ede15cac6839f3dbce52565c8f5164a8210e669c7bc4decb03e5bdf47d0d/ruff-0.15.21-py3-none-linux_armv6l.whl", hash = "sha256:63ea0e965e5d73c90e95b2434beeafc70820536717f561b32ab6e777cb9bdf5d", size = 10854342, upload-time = "2026-07-09T20:00:53.998Z" },
+ { url = "https://files.pythonhosted.org/packages/28/9d/d825b07ee7ea9e2d61df92a860033c94e06e7300d50a1c2653aac27d24fe/ruff-0.15.21-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:0f212c5d7d54c01bbfe6dcab02b724a39300f3e34ed7acbe995ccb320a2c58bd", size = 11139539, upload-time = "2026-07-09T20:00:57.809Z" },
+ { url = "https://files.pythonhosted.org/packages/f5/de/3b107712e642f063c7a9e0887c427b22cb44097de5aab36c05f2e280670c/ruff-0.15.21-py3-none-macosx_11_0_arm64.whl", hash = "sha256:e6312e41bc96791299614995ea3a977c5857c3b5662b1ecef6755b02b87cb646", size = 10595437, upload-time = "2026-07-09T20:01:00.006Z" },
+ { url = "https://files.pythonhosted.org/packages/9a/6f/b4523cc90ba239ede441447a19d0c968846a3012e5a0b0c5b62831a3d5e3/ruff-0.15.21-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01d65b4831c6b2a4ba8ee6faa84049d44d982b7a706e622c4094c509e51673be", size = 10990053, upload-time = "2026-07-09T20:01:02.187Z" },
+ { url = "https://files.pythonhosted.org/packages/92/cc/c6a9872a5375f0628875481cf2f66b13d7d865bf3ca2e57f91c7e762d976/ruff-0.15.21-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2c5a913a589120ce67933d5d05fd6ddbcc2481c6a054980ee767f7414c72b4fd", size = 10666096, upload-time = "2026-07-09T20:01:04.299Z" },
+ { url = "https://files.pythonhosted.org/packages/ab/97/c621f7a17e097f1790fa3af6374138823b330b2d03fc38337945daca212c/ruff-0.15.21-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ef04b681d02ad4dc9620f00f83ac5c22f652d0e9a9cfe431d219b16ad5ccc41", size = 11537011, upload-time = "2026-07-09T20:01:06.771Z" },
+ { url = "https://files.pythonhosted.org/packages/ea/51/d928727e476e25ccc57c6f449ffd80241a651a973ad949d39cfb2a771d28/ruff-0.15.21-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:16d090c0740916594157e75b80d666eab8e78083b39b3b0e1d698f4670a17b86", size = 12347101, upload-time = "2026-07-09T20:01:08.859Z" },
+ { url = "https://files.pythonhosted.org/packages/1e/88/8cd62026802b16018ad06931d87997cf795ba2a6239ab659606c87d96bf0/ruff-0.15.21-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3a10e74757dd65004d779b73e2f3c5210156d9980b41224d50d2ebcf1db51e67", size = 11572001, upload-time = "2026-07-09T20:01:11.092Z" },
+ { url = "https://files.pythonhosted.org/packages/b2/97/f63084cf55444fc110e8cb985ebfcc592af47f597d44453d778cb81bc156/ruff-0.15.21-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bab0905d2f29e0d9fbc3c373ed23db0095edaa3f71f1f4f519ec15134d9e85c8", size = 11549239, upload-time = "2026-07-09T20:01:13.27Z" },
+ { url = "https://files.pythonhosted.org/packages/9d/77/f107da4a2874b7715914b03f09ba9c54424de3ff8a1cc5d015d3ee2ce0ac/ruff-0.15.21-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:00eca240af5789fec6fe7df74c088cc1f9644ed83027113468efba7c92b94075", size = 11535340, upload-time = "2026-07-09T20:01:15.206Z" },
+ { url = "https://files.pythonhosted.org/packages/d5/e9/601deb322d3303a7bf212b0100ead6f2ee3f6a044d89c30f2f92bf83c731/ruff-0.15.21-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:262ab31557a75141325e32d3357f3597645a7f084e732b6b054dde428ecd9341", size = 10964048, upload-time = "2026-07-09T20:01:17.723Z" },
+ { url = "https://files.pythonhosted.org/packages/ea/2e/0f2176d1e99c15192caea19c8c3a0a955246b4cb4de795042eeb616345cd/ruff-0.15.21-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:659c4e7a4212f83306045ec7c5e5a356d16d9a6ef4ae0c7a4d872914fc655d9d", size = 10667055, upload-time = "2026-07-09T20:01:19.73Z" },
+ { url = "https://files.pythonhosted.org/packages/48/60/abd74a02e0c4214f12a68becfd30af7165cfdcb0e661ecdc60bbb949c09a/ruff-0.15.21-py3-none-musllinux_1_2_i686.whl", hash = "sha256:9e866eab611a5f959d36df2d10e446973a3610bc42b0c15b31dc27977d59c233", size = 11242043, upload-time = "2026-07-09T20:01:21.947Z" },
+ { url = "https://files.pythonhosted.org/packages/b2/c6/583075d8ccabb4b229345edcaf1545eb3d8d6be90f686a479d7e94088bbf/ruff-0.15.21-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e89bc93c0d3803ba870b55c29671bad9dc6d94bb1eb181b056b52eb05b52854f", size = 11648064, upload-time = "2026-07-09T20:01:24.023Z" },
+ { url = "https://files.pythonhosted.org/packages/3a/3c/37d0ecb729a7cc2d393ea7dce316fc585680f35d93b8d62139d7d0a3700c/ruff-0.15.21-py3-none-win32.whl", hash = "sha256:01f8d5be84823c172b389e123174f781f9daf86d6c58719d603f941932195cdd", size = 10896555, upload-time = "2026-07-09T20:01:26.941Z" },
+ { url = "https://files.pythonhosted.org/packages/c0/b8/e43466b2a6067ce91e669068f6e28d6c719a920f014b070d5c8731725de3/ruff-0.15.21-py3-none-win_amd64.whl", hash = "sha256:d4b8d9a2f0f12b816b50447f6eccb9f4bb01a6b82c86b50fb3b5354b458dc6d3", size = 12038772, upload-time = "2026-07-09T20:01:29.497Z" },
+ { url = "https://files.pythonhosted.org/packages/dd/75/e90ab9aeece218a9fc5a5bc3ec97d0ee6bb3c4ff95869463c1de58e29a1c/ruff-0.15.21-py3-none-win_arm64.whl", hash = "sha256:6e83115d4b9377c1cbc13abf0e051f069fab0ef815ea0504a8a008cee24dd0a8", size = 11375265, upload-time = "2026-07-09T20:01:31.772Z" },
+]
+
+[[package]]
+name = "scikit-learn"
+version = "1.7.2"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "joblib" },
+ { name = "numpy" },
+ { name = "scipy" },
+ { name = "threadpoolctl" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/98/c2/a7855e41c9d285dfe86dc50b250978105dce513d6e459ea66a6aeb0e1e0c/scikit_learn-1.7.2.tar.gz", hash = "sha256:20e9e49ecd130598f1ca38a1d85090e1a600147b9c02fa6f15d69cb53d968fda", size = 7193136, upload-time = "2025-09-09T08:21:29.075Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/ba/3e/daed796fd69cce768b8788401cc464ea90b306fb196ae1ffed0b98182859/scikit_learn-1.7.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6b33579c10a3081d076ab403df4a4190da4f4432d443521674637677dc91e61f", size = 9336221, upload-time = "2025-09-09T08:20:19.328Z" },
+ { url = "https://files.pythonhosted.org/packages/1c/ce/af9d99533b24c55ff4e18d9b7b4d9919bbc6cd8f22fe7a7be01519a347d5/scikit_learn-1.7.2-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:36749fb62b3d961b1ce4fedf08fa57a1986cd409eff2d783bca5d4b9b5fce51c", size = 8653834, upload-time = "2025-09-09T08:20:22.073Z" },
+ { url = "https://files.pythonhosted.org/packages/58/0e/8c2a03d518fb6bd0b6b0d4b114c63d5f1db01ff0f9925d8eb10960d01c01/scikit_learn-1.7.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7a58814265dfc52b3295b1900cfb5701589d30a8bb026c7540f1e9d3499d5ec8", size = 9660938, upload-time = "2025-09-09T08:20:24.327Z" },
+ { url = "https://files.pythonhosted.org/packages/2b/75/4311605069b5d220e7cf5adabb38535bd96f0079313cdbb04b291479b22a/scikit_learn-1.7.2-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4a847fea807e278f821a0406ca01e387f97653e284ecbd9750e3ee7c90347f18", size = 9477818, upload-time = "2025-09-09T08:20:26.845Z" },
+ { url = "https://files.pythonhosted.org/packages/7f/9b/87961813c34adbca21a6b3f6b2bea344c43b30217a6d24cc437c6147f3e8/scikit_learn-1.7.2-cp310-cp310-win_amd64.whl", hash = "sha256:ca250e6836d10e6f402436d6463d6c0e4d8e0234cfb6a9a47835bd392b852ce5", size = 8886969, upload-time = "2025-09-09T08:20:29.329Z" },
+]
+
+[[package]]
+name = "scipy"
+version = "1.15.3"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "numpy" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/0f/37/6964b830433e654ec7485e45a00fc9a27cf868d622838f6b6d9c5ec0d532/scipy-1.15.3.tar.gz", hash = "sha256:eae3cf522bc7df64b42cad3925c876e1b0b6c35c1337c93e12c0f366f55b0eaf", size = 59419214, upload-time = "2025-05-08T16:13:05.955Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/78/2f/4966032c5f8cc7e6a60f1b2e0ad686293b9474b65246b0c642e3ef3badd0/scipy-1.15.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:a345928c86d535060c9c2b25e71e87c39ab2f22fc96e9636bd74d1dbf9de448c", size = 38702770, upload-time = "2025-05-08T16:04:20.849Z" },
+ { url = "https://files.pythonhosted.org/packages/a0/6e/0c3bf90fae0e910c274db43304ebe25a6b391327f3f10b5dcc638c090795/scipy-1.15.3-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:ad3432cb0f9ed87477a8d97f03b763fd1d57709f1bbde3c9369b1dff5503b253", size = 30094511, upload-time = "2025-05-08T16:04:27.103Z" },
+ { url = "https://files.pythonhosted.org/packages/ea/b1/4deb37252311c1acff7f101f6453f0440794f51b6eacb1aad4459a134081/scipy-1.15.3-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:aef683a9ae6eb00728a542b796f52a5477b78252edede72b8327a886ab63293f", size = 22368151, upload-time = "2025-05-08T16:04:31.731Z" },
+ { url = "https://files.pythonhosted.org/packages/38/7d/f457626e3cd3c29b3a49ca115a304cebb8cc6f31b04678f03b216899d3c6/scipy-1.15.3-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:1c832e1bd78dea67d5c16f786681b28dd695a8cb1fb90af2e27580d3d0967e92", size = 25121732, upload-time = "2025-05-08T16:04:36.596Z" },
+ { url = "https://files.pythonhosted.org/packages/db/0a/92b1de4a7adc7a15dcf5bddc6e191f6f29ee663b30511ce20467ef9b82e4/scipy-1.15.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:263961f658ce2165bbd7b99fa5135195c3a12d9bef045345016b8b50c315cb82", size = 35547617, upload-time = "2025-05-08T16:04:43.546Z" },
+ { url = "https://files.pythonhosted.org/packages/8e/6d/41991e503e51fc1134502694c5fa7a1671501a17ffa12716a4a9151af3df/scipy-1.15.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e2abc762b0811e09a0d3258abee2d98e0c703eee49464ce0069590846f31d40", size = 37662964, upload-time = "2025-05-08T16:04:49.431Z" },
+ { url = "https://files.pythonhosted.org/packages/25/e1/3df8f83cb15f3500478c889be8fb18700813b95e9e087328230b98d547ff/scipy-1.15.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ed7284b21a7a0c8f1b6e5977ac05396c0d008b89e05498c8b7e8f4a1423bba0e", size = 37238749, upload-time = "2025-05-08T16:04:55.215Z" },
+ { url = "https://files.pythonhosted.org/packages/93/3e/b3257cf446f2a3533ed7809757039016b74cd6f38271de91682aa844cfc5/scipy-1.15.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5380741e53df2c566f4d234b100a484b420af85deb39ea35a1cc1be84ff53a5c", size = 40022383, upload-time = "2025-05-08T16:05:01.914Z" },
+ { url = "https://files.pythonhosted.org/packages/d1/84/55bc4881973d3f79b479a5a2e2df61c8c9a04fcb986a213ac9c02cfb659b/scipy-1.15.3-cp310-cp310-win_amd64.whl", hash = "sha256:9d61e97b186a57350f6d6fd72640f9e99d5a4a2b8fbf4b9ee9a841eab327dc13", size = 41259201, upload-time = "2025-05-08T16:05:08.166Z" },
+]
+
+[[package]]
+name = "shellingham"
+version = "1.5.4"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/58/15/8b3609fd3830ef7b27b655beb4b4e9c62313a4e8da8c676e142cc210d58e/shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de", size = 10310, upload-time = "2023-10-24T04:13:40.426Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755, upload-time = "2023-10-24T04:13:38.866Z" },
+]
+
+[[package]]
+name = "six"
+version = "1.17.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" },
+]
+
+[[package]]
+name = "threadpoolctl"
+version = "3.6.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/b7/4d/08c89e34946fce2aec4fbb45c9016efd5f4d7f24af8e5d93296e935631d8/threadpoolctl-3.6.0.tar.gz", hash = "sha256:8ab8b4aa3491d812b623328249fab5302a68d2d71745c8a4c719a2fcaba9f44e", size = 21274, upload-time = "2025-03-13T13:49:23.031Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl", hash = "sha256:43a0b8fd5a2928500110039e43a5eed8480b918967083ea48dc3ab9f13c4a7fb", size = 18638, upload-time = "2025-03-13T13:49:21.846Z" },
+]
+
+[[package]]
+name = "tomli"
+version = "2.4.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/22/de/48c59722572767841493b26183a0d1cc411d54fd759c5607c4590b6563a6/tomli-2.4.1.tar.gz", hash = "sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f", size = 17543, upload-time = "2026-03-25T20:22:03.828Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/7b/61/cceae43728b7de99d9b847560c262873a1f6c98202171fd5ed62640b494b/tomli-2.4.1-py3-none-any.whl", hash = "sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe", size = 14583, upload-time = "2026-03-25T20:22:03.012Z" },
+]
+
+[[package]]
+name = "typer"
+version = "0.27.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "annotated-doc" },
+ { name = "colorama", marker = "sys_platform == 'win32'" },
+ { name = "rich" },
+ { name = "shellingham" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/37/78/fda3361b56efc27944f24225f6ecd13d96d6fcfe37bd0eb34e2f4c63f9fc/typer-0.27.0.tar.gz", hash = "sha256:629bd12ea5d13a17148125d9a264f949eb171fb3f120f9b04d85873cab054fa5", size = 203430, upload-time = "2026-07-15T19:21:07.007Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/40/03/26a383c9e58c213199d1aad1c3d353cfc22d4444ec6d2c0bf8ad02523843/typer-0.27.0-py3-none-any.whl", hash = "sha256:6f4b27631e47f077871b7dc30e933ec0131c1390fbe0e387ea5574b5bac9ccf1", size = 122716, upload-time = "2026-07-15T19:21:05.553Z" },
+]
+
+[[package]]
+name = "typing-extensions"
+version = "4.16.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f6/cc/6253133b5bb138fc3306cebfbda2c520f545d36b5be2c7255cc528bb45d6/typing_extensions-4.16.0.tar.gz", hash = "sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5", size = 113555, upload-time = "2026-07-02T08:40:05.92Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/49/d3/b8441a820a491ddfc024b0b0cf0393375b75ea13866d9c66727e54c2fc80/typing_extensions-4.16.0-py3-none-any.whl", hash = "sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8", size = 45571, upload-time = "2026-07-02T08:40:04.659Z" },
+]
+
+[[package]]
+name = "tzdata"
+version = "2026.3"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/92/ff/5a28bdfd8c3ebec42564ac7d0e54ca3db65044a9314a97f9564fa7a1e926/tzdata-2026.3.tar.gz", hash = "sha256:4a1518b8993086a7982523e071643f3c0e5f213e75b21318e78bcabfff9d1415", size = 198674, upload-time = "2026-07-10T08:50:37.887Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/e5/6d/b53b99a9f2766d095985947a5782f1702cabb129a34f7a802d7197af832f/tzdata-2026.3-py2.py3-none-any.whl", hash = "sha256:dc096730c87af6cab1b171c9d532be840741ff5d459015e7f6947bd7d7e54931", size = 348168, upload-time = "2026-07-10T08:50:36.46Z" },
+]
diff --git a/services/tune/current/ioc/AGEBD-CPCL-TUNE_main.subs b/services/tune/current/ioc/AGEBD-CPCL-TUNE_main.subs
new file mode 100644
index 0000000..378be70
--- /dev/null
+++ b/services/tune/current/ioc/AGEBD-CPCL-TUNE_main.subs
@@ -0,0 +1,4 @@
+file TUNE.template {
+ pattern { DEVICE }
+ { AGEBD-TUNE{{ agebd_env }} }
+}
diff --git a/services/tune/current/ioc/AGEBD-CPCL-TUNE_parameters.yaml b/services/tune/current/ioc/AGEBD-CPCL-TUNE_parameters.yaml
new file mode 100644
index 0000000..ff8e70f
--- /dev/null
+++ b/services/tune/current/ioc/AGEBD-CPCL-TUNE_parameters.yaml
@@ -0,0 +1,6 @@
+cpu_architecture: x86_64
+epics_version: 7.0.8
+ioc_host: sls-vserv-bd-01{{ agebd_env }}
+ioc_port: {{ ioc_port }}
+os: RHEL8
+os_id: rhel
diff --git a/services/tune/current/ioc/TUNE.template b/services/tune/current/ioc/TUNE.template
new file mode 100644
index 0000000..ad157d3
--- /dev/null
+++ b/services/tune/current/ioc/TUNE.template
@@ -0,0 +1,439 @@
+# HLA Service Control Parameters
+
+record(ao, "$(DEVICE):SVD-CLEAN-Neigenvalues") {
+ field(DESC, "Nr of EV in SVD")
+ field(VAL, "3")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-TbTFirstIndex") {
+ field(DESC, "Index of first TbT data point to use")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-TbTLastIndex") {
+ field(DESC, "Index of last TbT data point to use")
+ field(VAL, "511")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-NAveraging") {
+ field(DESC, "Nr. of samples to take for averaging")
+ field(VAL, "1")
+ field(PREC, "0")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-ZeroPaddingN") {
+ field(DESC, "Add zeropadding to obtain N datapoints")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-ROI-Xi") {
+ field(DESC, "First datapoint for hor. peak search")
+ field(VAL, "0.1")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-ROI-Xf") {
+ field(DESC, "Last datapoint for hor. peak search")
+ field(VAL, "0.5")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-ROI-Yi") {
+ field(DESC, "First datapoint for ver. peak search")
+ field(VAL, "0.1")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-ROI-Yf") {
+ field(DESC, "Last datapoint for ver. peak search")
+ field(VAL, "0.5")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-ROI-Zi") {
+ field(DESC, "First datapoint for long. peak search")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-ROI-Zf") {
+ field(DESC, "Last datapoint for long. peak search")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-HOR-PING-ISET") {
+ field(DESC, "default current value for x pinger")
+ field(VAL, "20")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-HOR-PING-DELAY") {
+ field(DESC, "default delay value for x pinger")
+ field(VAL, "80")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-VER-PING-ISET") {
+ field(DESC, "default current value for y pinger")
+ field(VAL, "20")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-VER-PING-DELAY") {
+ field(DESC, "default delay value for y pinger")
+ field(VAL, "80")
+ field(PINI, "YES")
+}
+
+
+# # HLA Service Output/Result Parameters
+
+record(ao, "$(DEVICE):HORIZONTAL-PEAK1-FREQ") {
+ field(DESC, "Horizontal tune frequency")
+}
+
+record(ao, "$(DEVICE):HORIZONTAL-PEAK1-AMP") {
+ field(DESC, "Horizontal tune amplitude")
+}
+
+record(ao, "$(DEVICE):HORIZONTAL-PEAK2-FREQ") {
+ field(DESC, "Horizontal sideband 1 frequency")
+}
+
+record(ao, "$(DEVICE):HORIZONTAL-PEAK2-AMP") {
+ field(DESC, "Horizontal sideband 1 amplitude")
+}
+
+record(ao, "$(DEVICE):HORIZONTAL-PEAK3-FREQ") {
+ field(DESC, "Horizontal sideband 2 frequency")
+}
+
+record(ao, "$(DEVICE):HORIZONTAL-PEAK3-AMP") {
+ field(DESC, "Horizontal sideband 2 amplitude")
+}
+
+record(ao, "$(DEVICE):VERTICAL-PEAK1-FREQ") {
+ field(DESC, "Vertical tune frequency")
+}
+
+record(ao, "$(DEVICE):VERTICAL-PEAK1-AMP") {
+ field(DESC, "Vertical tune amplitude")
+}
+
+record(ao, "$(DEVICE):VERTICAL-PEAK2-FREQ") {
+ field(DESC, "Vertical sideband 1 frequency")
+}
+
+record(ao, "$(DEVICE):VERTICAL-PEAK2-AMP") {
+ field(DESC, "Vertical sideband 1 amplitude")
+}
+
+record(ao, "$(DEVICE):VERTICAL-PEAK3-FREQ") {
+ field(DESC, "Vertical sideband 2 frequency")
+}
+
+record(ao, "$(DEVICE):VERTICAL-PEAK3-AMP") {
+ field(DESC, "Vertical sideband 2 amplitude")
+}
+
+record(ao, "$(DEVICE):LONGITUDINAL-PEAK1-FREQ") {
+ field(DESC, "Longitudinal tune frequency")
+}
+
+record(ao, "$(DEVICE):LONGITUDINAL-PEAK1-AMP") {
+ field(DESC, "Longitudinal tune amplitude")
+}
+
+record(ao, "$(DEVICE):LONGITUDINAL-PEAK2-FREQ") {
+ field(DESC, "Longitudinal sideband 1 frequency")
+}
+
+record(ao, "$(DEVICE):LONGITUDINAL-PEAK2-AMP") {
+ field(DESC, "Longitudinal sideband 1 amplitude")
+}
+
+record(ao, "$(DEVICE):LONGITUDINAL-PEAK3-FREQ") {
+ field(DESC, "Longitudinal sideband 2 frequency")
+}
+
+record(ao, "$(DEVICE):LONGITUDINAL-PEAK3-AMP") {
+ field(DESC, "Longitudinal sideband 2 amplitude")
+}
+
+record(waveform, "$(DEVICE):HORIZONTAL-SPEC-ALL") {
+ field(DESC, "Entire measured horizontal spectrum")
+ field(NELM, "16384")
+ field(FTVL, "FLOAT")
+}
+
+record(waveform, "$(DEVICE):HORIZONTAL-SPEC-ROI") {
+ field(DESC, "Entire measured horizontal spectrum")
+ field(NELM, "4096")
+ field(FTVL, "FLOAT")
+}
+
+record(waveform, "$(DEVICE):VERTICAL-SPEC-ALL") {
+ field(DESC, "Entire measured vertical spectrum")
+ field(NELM, "16384")
+ field(FTVL, "FLOAT")
+}
+
+record(waveform, "$(DEVICE):VERTICAL-SPEC-ROI") {
+ field(DESC, "Entire measured vertical spectrum")
+ field(NELM, "4096")
+ field(FTVL, "FLOAT")
+}
+
+record(waveform, "$(DEVICE):LONGITUDINAL-SPEC-ALL") {
+ field(DESC, "Entire measured longitudinal spectrum")
+ field(NELM, "16384")
+ field(FTVL, "FLOAT")
+}
+
+record(waveform, "$(DEVICE):LONGITUDINAL-SPEC-ROI") {
+ field(DESC, "Entire measured longitudinal spectrum")
+ field(NELM, "4096")
+ field(FTVL, "FLOAT")
+}
+
+
+record (ao,"$(DEVICE):Q1_NAFF"){
+ field (DESC, "Horizontal tune calculated using NAFF")
+ field (VAL, 0)
+ field (EGU, "")
+}
+
+record (ao,"$(DEVICE):Q2_NAFF"){
+ field (DESC, "Vertical tune calculated using NAFF")
+ field (VAL, 0)
+ field (EGU, "")
+}
+
+record (ao,"$(DEVICE):NPOINTS"){
+ field (DESC, "Number of points in pos/fft waveform")
+ field (VAL, 16384)
+ field (EGU, "")
+}
+
+record(waveform, "$(DEVICE):SPEC-SAMPLE-ALL") {
+ field(DESC, "FFT spectrum tune axis")
+ field(NELM, "16384")
+ field(FTVL, "FLOAT")
+}
+
+record(waveform, "$(DEVICE):OSCILLATION-X-ALL") {
+ field(DESC, "Entire measured horizontal oscillation")
+ field(NELM, "16384")
+ field(FTVL, "FLOAT")
+}
+
+record(waveform, "$(DEVICE):OSCILLATION-Y-ALL") {
+ field(DESC, "Entire measured vertical oscillation")
+ field(NELM, "16384")
+ field(FTVL, "FLOAT")
+}
+
+record(waveform, "$(DEVICE):OSCILLATION-SAMPLE-ALL") {
+ field(DESC, "Sample index for oscillations")
+ field(NELM, "16384")
+ field(FTVL, "FLOAT")
+}
+
+record (ao,"$(DEVICE):CONTROL-NAFF"){
+ field (DESC, "Control NAFF calc.")
+ field (VAL, 1)
+ field (EGU, "")
+}
+
+record (ao,"$(DEVICE):SINGLE-BPM"){
+ field (VAL, 0)
+}
+
+record (ao,"$(DEVICE):SVD-CLEAN"){
+ field (VAL, 0)
+}
+
+record (ao,"$(DEVICE):MEAS-TIME"){
+ field (DESC, "Time for measurement")
+ field (VAL, 0)
+ field (EGU, "ms")
+}
+
+record (ao,"$(DEVICE):DUMMY1"){
+ field (DESC, "Dummy PV with value 1")
+ field (VAL, 1)
+}
+
+record(stringout, "$(DEVICE):BPM-SELECT-SINGLE") {
+ field(DESC, "String defining selected BPM")
+ field(VAL, "ARS07-DBPM-0840")
+ field(PINI, "YES")
+}
+
+record(bo,"$(DEVICE):BPM-SELECT-BPM") {
+ field(DESC, "Select BPMs")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(bo,"$(DEVICE):BPM-SELECT-BPMA") {
+ field(DESC, "Select BPMAs")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(bo,"$(DEVICE):BPM-SELECT-BPM-01") {
+ field(DESC, "Select BPMs")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(bo,"$(DEVICE):BPM-SELECT-BPMA-01") {
+ field(DESC, "Select BPMAs")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(bo,"$(DEVICE):BPM-SELECT-BPM-02") {
+ field(DESC, "Select BPMs")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(bo,"$(DEVICE):BPM-SELECT-BPMA-02") {
+ field(DESC, "Select BPMAs")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(bo,"$(DEVICE):BPM-SELECT-BPM-03") {
+ field(DESC, "Select BPMs")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(bo,"$(DEVICE):BPM-SELECT-BPMA-03") {
+ field(DESC, "Select BPMAs")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(bo,"$(DEVICE):BPM-SELECT-BPM-04") {
+ field(DESC, "Select BPMs")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(bo,"$(DEVICE):BPM-SELECT-BPMA-04") {
+ field(DESC, "Select BPMAs")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(bo,"$(DEVICE):BPM-SELECT-BPM-05") {
+ field(DESC, "Select BPMs")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(bo,"$(DEVICE):BPM-SELECT-BPMA-05") {
+ field(DESC, "Select BPMAs")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(bo,"$(DEVICE):BPM-SELECT-BPM-06") {
+ field(DESC, "Select BPMs")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(bo,"$(DEVICE):BPM-SELECT-BPMA-06") {
+ field(DESC, "Select BPMAs")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(bo,"$(DEVICE):BPM-SELECT-BPM-07") {
+ field(DESC, "Select BPMs")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(bo,"$(DEVICE):BPM-SELECT-BPMA-07") {
+ field(DESC, "Select BPMAs")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(bo,"$(DEVICE):BPM-SELECT-BPM-08") {
+ field(DESC, "Select BPMs")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(bo,"$(DEVICE):BPM-SELECT-BPMA-08") {
+ field(DESC, "Select BPMAs")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(bo,"$(DEVICE):BPM-SELECT-BPM-09") {
+ field(DESC, "Select BPMs")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(bo,"$(DEVICE):BPM-SELECT-BPMA-09") {
+ field(DESC, "Select BPMAs")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(bo,"$(DEVICE):BPM-SELECT-BPM-10") {
+ field(DESC, "Select BPMs")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(bo,"$(DEVICE):BPM-SELECT-BPMA-10") {
+ field(DESC, "Select BPMAs")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(bo,"$(DEVICE):BPM-SELECT-BPM-11") {
+ field(DESC, "Select BPMs")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(bo,"$(DEVICE):BPM-SELECT-BPMA-11") {
+ field(DESC, "Select BPMAs")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(bo,"$(DEVICE):BPM-SELECT-BPM-12") {
+ field(DESC, "Select BPMs")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(bo,"$(DEVICE):BPM-SELECT-BPMA-12") {
+ field(DESC, "Select BPMAs")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record (ao,"$(DEVICE):NAFF-HARMONICS"){
+ field(DESC, "Number")
+ field(VAL, "5")
+ field(EGU, "")
+ field(PINI, "YES")
+ field(DRVH, "20")
+ field(DRVL, "1")
+}
diff --git a/services/tune/current/ioc/startup.script b/services/tune/current/ioc/startup.script
new file mode 100644
index 0000000..0fa52ff
--- /dev/null
+++ b/services/tune/current/ioc/startup.script
@@ -0,0 +1 @@
+epicsEnvSet("ENGINEER", "armborst")
diff --git a/services/tune/current/qt/A_BD_Tune.ui b/services/tune/current/qt/A_BD_Tune.ui
new file mode 100644
index 0000000..844a7bc
--- /dev/null
+++ b/services/tune/current/qt/A_BD_Tune.ui
@@ -0,0 +1,2300 @@
+
+
+ MainWindow
+
+
+
+ 0
+ 0
+ 950
+ 780
+
+
+
+
+ 1600
+ 800
+
+
+
+ MainWindow
+
+
+
+
+
+ 20
+ 400
+ 911
+ 331
+
+
+
+ 0
+
+
+
+ Oscillation plot
+
+
+
+
+ 10
+ 10
+ 421
+ 271
+
+
+
+ Horizontal beam oscillation
+
+
+ Turn
+
+
+ x [mm]
+
+
+ AGEBD-TUNE:OSCILLATION-SAMPLE-ALL;AGEBD-TUNE:OSCILLATION-X-ALL
+
+
+ caCartesianPlot::NoSymbol
+
+
+
+ 0
+ 255
+ 0
+
+
+
+
+
+
+ caCartesianPlot::Auto
+
+
+ caCartesianPlot::Auto
+
+
+ 0;0
+
+
+ 0;1
+
+
+
+
+
+ 460
+ 10
+ 431
+ 271
+
+
+
+ Vertical beam oscillation
+
+
+ Turn
+
+
+ y [mm]
+
+
+ AGEBD-TUNE:OSCILLATION-SAMPLE-ALL;AGEBD-TUNE:OSCILLATION-Y-ALL
+
+
+ caCartesianPlot::NoSymbol
+
+
+
+ 0
+ 255
+ 0
+
+
+
+
+
+
+ caCartesianPlot::Auto
+
+
+ caCartesianPlot::Auto
+
+
+ 0;0.5
+
+
+
+
+
+ Tune plot
+
+
+
+
+ 10
+ 10
+ 421
+ 271
+
+
+
+ Horizontal tune spectrum
+
+
+ Tune
+
+
+ Amplitude
+
+
+ AGEBD-TUNE:SPEC-SAMPLE-ALL;AGEBD-TUNE:HORIZONTAL-SPEC-ALL
+
+
+ caCartesianPlot::NoSymbol
+
+
+
+ 0
+ 255
+ 0
+
+
+
+
+
+
+ caCartesianPlot::Sticks
+
+
+ caCartesianPlot::User
+
+
+ caCartesianPlot::Auto
+
+
+ 0;0.5
+
+
+
+
+
+ 460
+ 10
+ 431
+ 271
+
+
+
+ Vertical tune spectrum
+
+
+ Tune
+
+
+ Amplitude
+
+
+ AGEBD-TUNE:SPEC-SAMPLE-ALL;AGEBD-TUNE:VERTICAL-SPEC-ALL
+
+
+ caCartesianPlot::NoSymbol
+
+
+
+ 0
+ 255
+ 0
+
+
+
+
+
+
+ caCartesianPlot::Sticks
+
+
+ caCartesianPlot::User
+
+
+ caCartesianPlot::Auto
+
+
+ 0;0.5
+
+
+
+
+
+
+
+ 20
+ 20
+ 141
+ 171
+
+
+
+ Tune loop control
+
+
+
+
+ 10
+ 30
+ 129
+ 132
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+ true
+
+
+ false
+
+
+ 28
+
+
+ 28
+
+
+ true
+
+
+ false
+
+
+ AGEBD-ALH:TUNE-ALIVE
+
+
+ caLed::Alarm
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+ true
+
+
+ false
+
+
+ 28
+
+
+ 28
+
+
+ true
+
+
+ false
+
+
+ AGEBD-ALH:TUNE-ONOFF-RB
+
+
+ caLed::Alarm
+
+
+
+ -
+
+
+ Program alive
+
+
+
+ -
+
+
+ Measurement
+running
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ Activate
+measurement
+
+
+ true
+
+
+ AGEBD-ALH:TUNE-ONOFF
+
+
+
+
+
+
+
+
+
+ 180
+ 20
+ 281
+ 141
+
+
+
+ Results
+
+
+
+
+ 10
+ 110
+ 111
+ 20
+
+
+
+
+ 10
+
+
+
+ Meas. time [ms]
+
+
+
+
+
+ 130
+ 110
+ 71
+ 20
+
+
+
+ AGEBD-TUNE:MEAS-TIME
+
+
+
+
+
+ 10
+ 30
+ 211
+ 71
+
+
+
+ -
+
+
+
+ 10
+
+
+
+ Q1
+
+
+
+ -
+
+
+ AGEBD-TUNE:VERTICAL-PEAK1-FREQ
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 100.000000000000000
+
+
+ -100.000000000000000
+
+
+
+ -
+
+
+
+ 10
+
+
+
+ Q2
+
+
+
+ -
+
+
+ AGEBD-TUNE:HORIZONTAL-PEAK1-FREQ
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ 100.000000000000000
+
+
+ -100.000000000000000
+
+
+
+ -
+
+
+
+ 10
+
+
+
+ FFT
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+
+ 10
+
+
+
+ NAFF
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ AGEBD-TUNE:Q1_NAFF
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 100.000000000000000
+
+
+ -100.000000000000000
+
+
+
+ -
+
+
+ AGEBD-TUNE:Q2_NAFF
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 100.000000000000000
+
+
+ -100.000000000000000
+
+
+
+
+
+
+
+
+
+ 20
+ 200
+ 911
+ 191
+
+
+
+ 2
+
+
+
+ Tune analysis settings
+
+
+
+
+ 190
+ 10
+ 91
+ 141
+
+
+
+ SVD cleaning
+
+
+
+
+ 10
+ 30
+ 71
+ 21
+
+
+
+
+ Arial
+ 11
+ 75
+ true
+
+
+
+ Enable
+
+
+ false
+
+
+ AGEBD-TUNE:SVD-CLEAN
+
+
+
+
+
+ 10
+ 90
+ 71
+ 41
+
+
+
+ 2
+
+
+ 0
+
+
+ AGEBD-TUNE:SVD-CLEAN-Neigenvalues
+
+
+ false
+
+
+ caNumeric::User
+
+
+ 115.000000000000000
+
+
+ 1.000000000000000
+
+
+
+
+
+ 10
+ 60
+ 81
+ 31
+
+
+
+
+ 10
+
+
+
+ # Singular
+values
+
+
+
+
+
+
+ 500
+ 10
+ 211
+ 121
+
+
+
+ Region of Interest
+
+
+
+
+ 10
+ 30
+ 191
+ 81
+
+
+
+ -
+
+
+
+ 45
+ 20
+
+
+
+
+ 9
+
+
+
+ 2
+
+
+ AGEBD-TUNE:CONTROL-ROI-Yi
+
+
+ caSpinbox::User
+
+
+ caSpinbox::User
+
+
+ 1.000000000000000
+
+
+ 0.000000000000000
+
+
+
+ -
+
+
+
+ 10
+
+
+
+ From
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+
+ 45
+ 20
+
+
+
+
+ 9
+
+
+
+ 2
+
+
+ 0.000000000000000
+
+
+ AGEBD-TUNE:CONTROL-ROI-Xf
+
+
+ caSpinbox::User
+
+
+ caSpinbox::User
+
+
+ 1.000000000000000
+
+
+ 0.000000000000000
+
+
+
+ -
+
+
+
+ 45
+ 20
+
+
+
+
+ 9
+
+
+
+ 2
+
+
+ AGEBD-TUNE:CONTROL-ROI-Xi
+
+
+ caSpinbox::User
+
+
+ caSpinbox::User
+
+
+ 1.000000000000000
+
+
+ 0.000000000000000
+
+
+
+ -
+
+
+
+ 10
+
+
+
+ Q1
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+
+ 10
+
+
+
+ Q2
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+
+ 10
+
+
+
+ To
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+
+ 45
+ 20
+
+
+
+
+ 9
+
+
+
+ 2
+
+
+ 0.000000000000000
+
+
+ AGEBD-TUNE:CONTROL-ROI-Yf
+
+
+ caSpinbox::User
+
+
+ caSpinbox::User
+
+
+ 1.000000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+
+
+
+
+ 290
+ 10
+ 191
+ 111
+
+
+
+ Turn selection
+
+
+
+
+ 10
+ 30
+ 171
+ 71
+
+
+
+ -
+
+
+
+ 45
+ 20
+
+
+
+
+ 9
+
+
+
+ 4
+
+
+ 0
+
+
+ false
+
+
+ AGEBD-TUNE:CONTROL-TbTLastIndex
+
+
+ caSpinbox::User
+
+
+ 4095.000000000000000
+
+
+ 1.000000000000000
+
+
+
+ -
+
+
+
+ 10
+
+
+
+ First turn
+
+
+
+ -
+
+
+
+ 10
+
+
+
+ Last turn
+
+
+
+ -
+
+
+
+ 45
+ 20
+
+
+
+
+ 9
+
+
+
+ 4
+
+
+ 0
+
+
+ false
+
+
+ AGEBD-TUNE:CONTROL-TbTFirstIndex
+
+
+ false
+
+
+ caSpinbox::User
+
+
+ 4094.000000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+
+
+
+
+ 20
+ 10
+ 141
+ 51
+
+
+
+ -
+
+
+ # samples
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ 1
+
+
+ 0
+
+
+ true
+
+
+ AGEBD-TUNE:CONTROL-NAveraging
+
+
+ caNumeric::Channel
+
+
+ true
+
+
+ caNumeric::User
+
+
+ 99.000000000000000
+
+
+ 1.000000000000000
+
+
+ caNumeric::on_top
+
+
+
+
+
+
+
+
+ 20
+ 60
+ 141
+ 91
+
+
+
+ -
+
+
+
+ Arial
+ 16
+ 75
+ true
+
+
+
+ Calc. NAFF
+
+
+ true
+
+
+ AGEBD-TUNE:CONTROL-NAFF
+
+
+
+ -
+
+
-
+
+
+
+ 9
+
+
+
+ # NAFF
+harmonics
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ 1
+
+
+ 0
+
+
+ true
+
+
+ AGEBD-TUNE:NAFF-HARMONICS
+
+
+ caNumeric::Channel
+
+
+ true
+
+
+ caNumeric::User
+
+
+ 99.000000000000000
+
+
+ 1.000000000000000
+
+
+ caNumeric::on_top
+
+
+
+
+
+
+
+
+
+
+ BPM select
+
+
+
+
+ 350
+ 50
+ 159
+ 29
+
+
+
+ Recommended:
+ARS07-DBPM-0840
+
+
+
+
+
+
+ 30
+ 40
+ 104
+ 24
+
+
+
+
+ 0
+ 0
+
+
+
+
+ Arial
+ 12
+ 50
+ false
+
+
+
+ Single BPM
+
+
+ false
+
+
+ AGEBD-TUNE:SINGLE-BPM
+
+
+
+
+
+ Other settings
+
+
+
+
+ 460
+ 0
+ 151
+ 121
+
+
+
+ BPM trigger
+
+
+
+
+ 10
+ 30
+ 131
+ 80
+
+
+
+ -
+
+
+ -Trigger on pinger
+
+
+ Restart analysis script
+
+
+ /opt/gfa/python-3.8/latest/bin/python /sls/diag/bin/s_di_bpm_cmd.py put_trig_on_pinger
+
+
+
+
+
+
+
+ -
+
+
+ -Trigger on extraction
+
+
+ Restart analysis script
+
+
+ /opt/gfa/python-3.8/latest/bin/python /sls/diag/bin/s_di_bpm_cmd.py put_trig_on_extraction
+
+
+
+
+
+
+
+ -
+
+
+ -Trigger on 3 Hz
+
+
+ Restart analysis script
+
+
+ /opt/gfa/python-3.8/latest/bin/python /sls/diag/bin/s_di_bpm_cmd.py put_trig_on_3hz
+
+
+
+
+
+
+
+
+
+
+
+
+ 10
+ 0
+ 441
+ 151
+
+
+
+ Pinger settings
+
+
+
+
+ 10
+ 30
+ 421
+ 114
+
+
+
+ -
+
+
+
+ Lucida Sans Typewriter
+ 10
+
+
+
+ ARS01-MKIK-0320:I-READ-POS
+
+
+
+ -
+
+
+
+ 20
+ 16777215
+
+
+
+
+
+
+ ARS01-MKIK-0290:CTRL-ON-OFF
+
+
+
+ -
+
+
+
+ 10
+
+
+
+ Pinger V
+
+
+
+ -
+
+
+
+ 10
+
+
+
+ Set current
+[A]
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+
+ 10
+
+
+
+ 4
+
+
+ false
+
+
+ ABOMA-VME-KY-EVR0:OUT3-Delay-SP
+
+
+
+ -
+
+
+
+ 150
+ 20
+
+
+
+
+ 10
+
+
+
+ 3
+
+
+ false
+
+
+ ARS01-MKIK-0320:I-SET
+
+
+
+ -
+
+
+
+ 10
+
+
+
+ Pinger H
+
+
+
+ -
+
+
+
+ Lucida Sans Typewriter
+ 10
+
+
+
+ ARS01-MKIK-0290:I-READ-POS
+
+
+
+ -
+
+
+
+ 10
+
+
+
+ Timing Delay
+[us]
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+
+ 20
+ 16777215
+
+
+
+
+
+
+ ARS01-MKIK-0320:CTRL-ON-OFF
+
+
+
+ -
+
+
+
+ 10
+
+
+
+ Read current
+[A]
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+
+ 10
+
+
+
+ 4
+
+
+ false
+
+
+ ABOMA-VME-KY-EVR0:OUT2-Delay-SP
+
+
+
+ -
+
+
+
+ 150
+ 20
+
+
+
+
+ 10
+
+
+
+ 3
+
+
+ false
+
+
+ ARS01-MKIK-0290:I-SET
+
+
+
+
+
+
+
+
+
+ 750
+ 30
+ 71
+ 31
+
+
+
+ ARS07-CECL-DBPM3-1:EEVR-EVENT0-ID
+
+
+
+
+
+ 620
+ 30
+ 121
+ 31
+
+
+
+
+ 10
+
+
+
+ BPM Trigger ID
+ARS07-DBPM-0840
+
+
+ Qt::AutoText
+
+
+ Qt::AlignCenter
+
+
+
+
+
+
+
+
+
+
+ caNumeric
+ QFrame
+
+
+
+ caMenu
+ QComboBox
+
+
+
+ caToggleButton
+ QCheckBox
+
+
+
+ caSpinbox
+ QFrame
+
+
+
+ caLed
+ QWidget
+
+
+
+ caLineEdit
+ QLineEdit
+
+
+
+ caCartesianPlot
+ QwtPlot
+
+
+
+ caShellCommand
+ QWidget
+
+
+
+ QwtPlot
+ QFrame
+
+
+
+
+
+
diff --git a/services/tune/current/systemd/AGEBD-SERVICE-TUNE.service b/services/tune/current/systemd/AGEBD-SERVICE-TUNE.service
new file mode 100644
index 0000000..f70014a
--- /dev/null
+++ b/services/tune/current/systemd/AGEBD-SERVICE-TUNE.service
@@ -0,0 +1,16 @@
+[Unit]
+Description=AGEBD-SERVICE-TUNE
+After=network.target
+
+[Service]
+Environment=AGEBD_ENV={{ agebd_env }}
+ExecStart=/sls/bd/hla/{{ agebd_env }}/bin/start_service.sh TUNE
+Restart=no
+
+[Install]
+WantedBy=default.target
+
+# https://www.freedesktop.org/software/systemd/man/latest/systemd.service.html
+# systemctl --user daemon-reload
+# systemctl --user enable /sls/bd/bin/systemd/AGEBD-SERVICE-TUNE.service
+# systemctl --user start AGEBD-SERVICE-TUNE
diff --git a/services/tunebump/current/app/pyproject.toml b/services/tunebump/current/app/pyproject.toml
new file mode 100644
index 0000000..e59c4d6
--- /dev/null
+++ b/services/tunebump/current/app/pyproject.toml
@@ -0,0 +1,49 @@
+[project]
+name = "agebd-tunebump"
+version = "0.1.0"
+description = "AGEBD-TUNEBUMP Service"
+requires-python = "==3.10.*"
+dependencies = [
+ "agebd",
+ "numpy>=2.2.6",
+ "scipy>=1.15.3",
+]
+
+[dependency-groups]
+dev = [
+ "pyepics>=3.5.8",
+ "pytest>=8.4.2",
+ "ruff>=0.15.20",
+]
+
+[tool.uv.sources]
+# Path is relative to where agebd package is deployed on hla
+# machines (see CI/CD in .gitea/workflows)
+agebd = { path = "../../../../packages/agebd", editable = true }
+
+[build-system]
+requires = ["hatchling"]
+build-backend = "hatchling.build"
+
+[tool.uv]
+package = true
+
+[tool.pytest.ini_options]
+pythonpath = ["src"]
+env = [
+ "AGEBD_ENV=local",
+]
+
+[tool.ruff]
+include = [
+ "src/**/*.py",
+ "tests/**/*.py",
+]
+line-length = 100
+
+[tool.ruff.lint]
+# use isort to sort imports
+extend-select = ["I"]
+
+[tool.ruff.lint.isort]
+known-first-party = ["agebd"]
diff --git a/services/tunebump/current/app/src/agebd_tunebump/__init__.py b/services/tunebump/current/app/src/agebd_tunebump/__init__.py
new file mode 100644
index 0000000..1800c27
--- /dev/null
+++ b/services/tunebump/current/app/src/agebd_tunebump/__init__.py
@@ -0,0 +1 @@
+from .service import PVs, Service
diff --git a/services/tunebump/current/app/src/agebd_tunebump/main.py b/services/tunebump/current/app/src/agebd_tunebump/main.py
new file mode 100644
index 0000000..092188a
--- /dev/null
+++ b/services/tunebump/current/app/src/agebd_tunebump/main.py
@@ -0,0 +1,31 @@
+import typer
+
+from agebd.enums import LogLevel
+from agebd.runner import CallbackRunner
+from agebd.utils import init_logging
+from agebd_tunebump import PVs, Service
+
+
+# TODO: remove: cicd test 10
+
+def main(
+ log_level: LogLevel = typer.Option(
+ LogLevel.INFO,
+ "--log-level",
+ "-l",
+ # Looks at the OS env variable first. If empty, falls back to "INFO"
+ envvar="AGEBD_LOG_LEVEL",
+ # help="Set log level: DEBUG, INFO, WARNING, ERROR, CRITICAL",
+ case_sensitive=False,
+ ),
+):
+ init_logging(log_level)
+ service_name = "TUNEBUMP"
+ pvs = PVs(service_name=service_name)
+ service = Service(name=service_name, pvs=pvs)
+ runner = CallbackRunner(service=service)
+ runner.start()
+
+
+if __name__ == "__main__":
+ typer.run(main)
diff --git a/services/tunebump/current/app/src/agebd_tunebump/service.py b/services/tunebump/current/app/src/agebd_tunebump/service.py
new file mode 100644
index 0000000..66cdcea
--- /dev/null
+++ b/services/tunebump/current/app/src/agebd_tunebump/service.py
@@ -0,0 +1,475 @@
+from datetime import datetime
+
+import numpy as np
+from epics import PV
+
+# TODO: how to package/deploy this to use it here?
+from OMFacility import Facility
+
+# TODO: how to package/deploy this to use it here?
+from OMSLS2Magnet import SLS2Magnet
+from scipy import signal
+
+from agebd.pv import get_pv_class
+from agebd.service.base import BaseService
+from agebd.service.pvs import BasePVs
+from agebd.utils import printgetversion
+
+__version__ = printgetversion(__file__)
+
+PV = get_pv_class()
+
+
+class PVs(BasePVs):
+ ## Service specific PVs from dedicated IOC
+ # just print new values or write to magnets
+ Write2Mag = PV("AGEBD-TUNEBUMP:WRITE2MAG.VAL")
+
+ anatune = {
+ "QX": {
+ "Spec": PV("AGEBD-TUNEBUMP:SPEC-X.VAL"),
+ "Freq": PV("AGEBD-TUNEBUMP:SPEC-FREQ-qX.VAL"),
+ "NormSpec": PV("AGEBD-TUNEBUMP:NORM-QX-AMP.VAL"),
+ "NormFreq": PV("AGEBD-TUNEBUMP:NORM-QX-FREQ.VAL"),
+ "Tune": PV("AGEBD-TUNEBUMP:QX.VAL"),
+ "TuneSB1": PV("AGEBD-TUNEBUMP:QX-SB1.VAL"),
+ "TuneSB2": PV("AGEBD-TUNEBUMP:QX-SB2.VAL"),
+ "Peak": PV("AGEBD-TUNEBUMP:QX-PEAKS.VAL"),
+ "PeakFreq": PV("AGEBD-TUNEBUMP:QX-PEAKS-FREQ.VAL"),
+ "Ulim": PV("AGEBD-TUNEBUMP:QX-ULIM.VAL"),
+ "Llim": PV("AGEBD-TUNEBUMP:QX-LLIM.VAL"),
+ },
+ "QY": {
+ "Spec": PV("AGEBD-TUNEBUMP:SPEC-Y.VAL"),
+ "Freq": PV("AGEBD-TUNEBUMP:SPEC-FREQ-qY.VAL"),
+ "NormSpec": PV("AGEBD-TUNEBUMP:NORM-QY-AMP.VAL"),
+ "NormFreq": PV("AGEBD-TUNEBUMP:NORM-QY-FREQ.VAL"),
+ "Tune": PV("AGEBD-TUNEBUMP:QY.VAL"),
+ "TuneSB1": PV("AGEBD-TUNEBUMP:QY-SB1.VAL"),
+ "TuneSB2": PV("AGEBD-TUNEBUMP:QY-SB2.VAL"),
+ "Peak": PV("AGEBD-TUNEBUMP:QY-PEAKS.VAL"),
+ "PeakFreq": PV("AGEBD-TUNEBUMP:QY-PEAKS-FREQ.VAL"),
+ "Ulim": PV("AGEBD-TUNEBUMP:QY-ULIM.VAL"),
+ "Llim": PV("AGEBD-TUNEBUMP:QY-LLIM.VAL"),
+ },
+ "QZ": {
+ "Spec": PV("AGEBD-TUNEBUMP:SPEC-Z.VAL"),
+ "Freq": PV("AGEBD-TUNEBUMP:SPEC-FREQ-qZ.VAL"),
+ "NormSpec": PV("AGEBD-TUNEBUMP:NORM-QZ-AMP.VAL"),
+ "NormFreq": PV("AGEBD-TUNEBUMP:NORM-QZ-FREQ.VAL"),
+ "Tune": PV("AGEBD-TUNEBUMP:QZ.VAL"),
+ "Peak": PV("AGEBD-TUNEBUMP:QZ-PEAKS.VAL"),
+ "PeakFreq": PV("AGEBD-TUNEBUMP:QZ-PEAKS-FREQ.VAL"),
+ "Ulim": PV("AGEBD-TUNEBUMP:QZ-ULIM.VAL"),
+ "Llim": PV("AGEBD-TUNEBUMP:QZ-LLIM.VAL"),
+ },
+ }
+
+ Qx_stepsize = PV("AGEBD-TUNEBUMP:QX-STEPSIZE")
+ Qx_stepup = PV("AGEBD-TUNEBUMP:QX-STEPUP")
+ Qx_stepdown = PV("AGEBD-TUNEBUMP:QX-STEPDOWN")
+ Qy_stepsize = PV("AGEBD-TUNEBUMP:QY-STEPSIZE")
+ Qy_stepup = PV("AGEBD-TUNEBUMP:QY-STEPUP")
+ Qy_stepdown = PV("AGEBD-TUNEBUMP:QY-STEPDOWN")
+
+ TuneBump_changelog = PV("AGEBD-TUNEBUMP:CHANGELOG")
+
+ ## Service specific PVs from other IOCs
+ # ordered dict of quads (Python > 3.7 required!)
+ quads = { # Quad PV base | F or D | pv link to ISET | MQCO Name for SLS2 Magnet Library
+ "ARS01-MOCT-1840-QA": ["F"],
+ "ARS01-MOCT-2360-QA": ["F"],
+ "ARS01-MOCT-2860-QA": ["F"],
+ "ARS01-MOCT-4130-QA": ["F"],
+ "ARS01-MOCT-4630-QA": ["F"],
+ "ARS01-MOCT-5150-QA": ["F"],
+ "ARS02-MOCT-1840-QA": ["F"],
+ "ARS02-MOCT-2360-QA": ["F"],
+ "ARS02-MOCT-2860-QA": ["F"],
+ "ARS02-MOCT-4130-QA": ["F"],
+ "ARS02-MOCT-4630-QA": ["F"],
+ "ARS02-MOCT-5150-QA": ["F"],
+ "ARS03-MOCT-1840-QA": ["F"],
+ "ARS03-MOCT-2360-QA": ["F"],
+ "ARS03-MOCT-2860-QA": ["F"],
+ "ARS03-MOCT-4130-QA": ["F"],
+ "ARS03-MOCT-4630-QA": ["F"],
+ "ARS03-MOCT-5150-QA": ["F"],
+ "ARS04-MOCT-1840-QA": ["F"],
+ "ARS04-MOCT-2360-QA": ["F"],
+ "ARS04-MOCT-2860-QA": ["F"],
+ "ARS04-MOCT-4130-QA": ["F"],
+ "ARS04-MOCT-4630-QA": ["F"],
+ "ARS04-MOCT-5150-QA": ["F"],
+ "ARS05-MOCT-1840-QA": ["F"],
+ "ARS05-MOCT-2360-QA": ["F"],
+ "ARS05-MOCT-2860-QA": ["F"],
+ "ARS05-MOCT-4130-QA": ["F"],
+ "ARS05-MOCT-4630-QA": ["F"],
+ "ARS05-MOCT-5150-QA": ["F"],
+ "ARS06-MOCT-1840-QA": ["F"],
+ "ARS06-MOCT-2360-QA": ["F"],
+ "ARS06-MOCT-2860-QA": ["F"],
+ "ARS06-MOCT-4130-QA": ["F"],
+ "ARS06-MOCT-4630-QA": ["F"],
+ "ARS06-MOCT-5150-QA": ["F"],
+ "ARS07-MOCT-1840-QA": ["F"],
+ "ARS07-MOCT-2360-QA": ["F"],
+ "ARS07-MOCT-2860-QA": ["F"],
+ "ARS07-MOCT-4130-QA": ["F"],
+ "ARS07-MOCT-4630-QA": ["F"],
+ "ARS07-MOCT-5150-QA": ["F"],
+ "ARS08-MOCT-1840-QA": ["F"],
+ "ARS08-MOCT-2360-QA": ["F"],
+ "ARS08-MOCT-2860-QA": ["F"],
+ "ARS08-MOCT-4130-QA": ["F"],
+ "ARS08-MOCT-4630-QA": ["F"],
+ "ARS08-MOCT-5150-QA": ["F"],
+ "ARS09-MOCT-1840-QA": ["F"],
+ "ARS09-MOCT-2360-QA": ["F"],
+ "ARS09-MOCT-2860-QA": ["F"],
+ "ARS09-MOCT-4130-QA": ["F"],
+ "ARS09-MOCT-4630-QA": ["F"],
+ "ARS09-MOCT-5150-QA": ["F"],
+ "ARS10-MOCT-1840-QA": ["F"],
+ "ARS10-MOCT-2360-QA": ["F"],
+ "ARS10-MOCT-2860-QA": ["F"],
+ "ARS10-MOCT-4130-QA": ["F"],
+ "ARS10-MOCT-4630-QA": ["F"],
+ "ARS10-MOCT-5150-QA": ["F"],
+ "ARS11-MOCT-1840-QA": ["F"],
+ "ARS11-MOCT-2360-QA": ["F"],
+ "ARS11-MOCT-2860-QA": ["F"],
+ "ARS11-MOCT-4130-QA": ["F"],
+ "ARS11-MOCT-4630-QA": ["F"],
+ "ARS11-MOCT-5150-QA": ["F"],
+ "ARS12-MOCT-1840-QA": ["F"],
+ "ARS12-MOCT-2360-QA": ["F"],
+ "ARS12-MOCT-2860-QA": ["F"],
+ "ARS12-MOCT-4130-QA": ["F"],
+ "ARS12-MOCT-4630-QA": ["F"],
+ "ARS12-MOCT-5150-QA": ["F"],
+ "ARS01-MOCT-1950-QA": ["D"],
+ "ARS01-MOCT-2230-QA": ["D"],
+ "ARS01-MOCT-2450-QA": ["D"],
+ "ARS01-MOCT-2730-QA": ["D"],
+ "ARS01-MOCT-2950-QA": ["D"],
+ "ARS01-MOCT-4040-QA": ["D"],
+ "ARS01-MOCT-4260-QA": ["D"],
+ "ARS01-MOCT-4540-QA": ["D"],
+ "ARS01-MOCT-4760-QA": ["D"],
+ "ARS01-MOCT-5040-QA": ["D"],
+ "ARS02-MOCT-1950-QA": ["D"],
+ "ARS02-MOCT-2230-QA": ["D"],
+ "ARS02-MOCT-2450-QA": ["D"],
+ "ARS02-MOCT-2730-QA": ["D"],
+ "ARS02-MOCT-2950-QA": ["D"],
+ "ARS02-MOCT-4040-QA": ["D"],
+ "ARS02-MOCT-4260-QA": ["D"],
+ "ARS02-MOCT-4540-QA": ["D"],
+ "ARS02-MOCT-4760-QA": ["D"],
+ "ARS02-MOCT-5040-QA": ["D"],
+ "ARS03-MOCT-1950-QA": ["D"],
+ "ARS03-MOCT-2230-QA": ["D"],
+ "ARS03-MOCT-2450-QA": ["D"],
+ "ARS03-MOCT-2730-QA": ["D"],
+ "ARS03-MOCT-2950-QA": ["D"],
+ "ARS03-MOCT-4040-QA": ["D"],
+ "ARS03-MOCT-4260-QA": ["D"],
+ "ARS03-MOCT-4540-QA": ["D"],
+ "ARS03-MOCT-4760-QA": ["D"],
+ "ARS03-MOCT-5040-QA": ["D"],
+ "ARS04-MOCT-1950-QA": ["D"],
+ "ARS04-MOCT-2230-QA": ["D"],
+ "ARS04-MOCT-2450-QA": ["D"],
+ "ARS04-MOCT-2730-QA": ["D"],
+ "ARS04-MOCT-2950-QA": ["D"],
+ "ARS04-MOCT-4040-QA": ["D"],
+ "ARS04-MOCT-4260-QA": ["D"],
+ "ARS04-MOCT-4540-QA": ["D"],
+ "ARS04-MOCT-4760-QA": ["D"],
+ "ARS04-MOCT-5040-QA": ["D"],
+ "ARS05-MOCT-1950-QA": ["D"],
+ "ARS05-MOCT-2230-QA": ["D"],
+ "ARS05-MOCT-2450-QA": ["D"],
+ "ARS05-MOCT-2730-QA": ["D"],
+ "ARS05-MOCT-2950-QA": ["D"],
+ "ARS05-MOCT-4040-QA": ["D"],
+ "ARS05-MOCT-4260-QA": ["D"],
+ "ARS05-MOCT-4540-QA": ["D"],
+ "ARS05-MOCT-4760-QA": ["D"],
+ "ARS05-MOCT-5040-QA": ["D"],
+ "ARS06-MOCT-1950-QA": ["D"],
+ "ARS06-MOCT-2230-QA": ["D"],
+ "ARS06-MOCT-2450-QA": ["D"],
+ "ARS06-MOCT-2730-QA": ["D"],
+ "ARS06-MOCT-2950-QA": ["D"],
+ "ARS06-MOCT-4040-QA": ["D"],
+ "ARS06-MOCT-4260-QA": ["D"],
+ "ARS06-MOCT-4540-QA": ["D"],
+ "ARS06-MOCT-4760-QA": ["D"],
+ "ARS06-MOCT-5040-QA": ["D"],
+ "ARS07-MOCT-1950-QA": ["D"],
+ "ARS07-MOCT-2230-QA": ["D"],
+ "ARS07-MOCT-2450-QA": ["D"],
+ "ARS07-MOCT-2730-QA": ["D"],
+ "ARS07-MOCT-2950-QA": ["D"],
+ "ARS07-MOCT-4040-QA": ["D"],
+ "ARS07-MOCT-4260-QA": ["D"],
+ "ARS07-MOCT-4540-QA": ["D"],
+ "ARS07-MOCT-4760-QA": ["D"],
+ "ARS07-MOCT-5040-QA": ["D"],
+ "ARS08-MOCT-1950-QA": ["D"],
+ "ARS08-MOCT-2230-QA": ["D"],
+ "ARS08-MOCT-2450-QA": ["D"],
+ "ARS08-MOCT-2730-QA": ["D"],
+ "ARS08-MOCT-2950-QA": ["D"],
+ "ARS08-MOCT-4040-QA": ["D"],
+ "ARS08-MOCT-4260-QA": ["D"],
+ "ARS08-MOCT-4540-QA": ["D"],
+ "ARS08-MOCT-4760-QA": ["D"],
+ "ARS08-MOCT-5040-QA": ["D"],
+ "ARS09-MOCT-1950-QA": ["D"],
+ "ARS09-MOCT-2230-QA": ["D"],
+ "ARS09-MOCT-2450-QA": ["D"],
+ "ARS09-MOCT-2730-QA": ["D"],
+ "ARS09-MOCT-2950-QA": ["D"],
+ "ARS09-MOCT-4040-QA": ["D"],
+ "ARS09-MOCT-4260-QA": ["D"],
+ "ARS09-MOCT-4540-QA": ["D"],
+ "ARS09-MOCT-4760-QA": ["D"],
+ "ARS09-MOCT-5040-QA": ["D"],
+ "ARS10-MOCT-1950-QA": ["D"],
+ "ARS10-MOCT-2230-QA": ["D"],
+ "ARS10-MOCT-2450-QA": ["D"],
+ "ARS10-MOCT-2730-QA": ["D"],
+ "ARS10-MOCT-2950-QA": ["D"],
+ "ARS10-MOCT-4040-QA": ["D"],
+ "ARS10-MOCT-4260-QA": ["D"],
+ "ARS10-MOCT-4540-QA": ["D"],
+ "ARS10-MOCT-4760-QA": ["D"],
+ "ARS10-MOCT-5040-QA": ["D"],
+ "ARS11-MOCT-1950-QA": ["D"],
+ "ARS11-MOCT-2230-QA": ["D"],
+ "ARS11-MOCT-2450-QA": ["D"],
+ "ARS11-MOCT-2730-QA": ["D"],
+ "ARS11-MOCT-2950-QA": ["D"],
+ "ARS11-MOCT-4040-QA": ["D"],
+ "ARS11-MOCT-4260-QA": ["D"],
+ "ARS11-MOCT-4540-QA": ["D"],
+ "ARS11-MOCT-4760-QA": ["D"],
+ "ARS11-MOCT-5040-QA": ["D"],
+ "ARS12-MOCT-1950-QA": ["D"],
+ "ARS12-MOCT-2230-QA": ["D"],
+ "ARS12-MOCT-2450-QA": ["D"],
+ "ARS12-MOCT-2730-QA": ["D"],
+ "ARS12-MOCT-2950-QA": ["D"],
+ "ARS12-MOCT-4040-QA": ["D"],
+ "ARS12-MOCT-4260-QA": ["D"],
+ "ARS12-MOCT-4540-QA": ["D"],
+ "ARS12-MOCT-4760-QA": ["D"],
+ "ARS12-MOCT-5040-QA": ["D"],
+ }
+
+ for key in quads:
+ quads[key].append(PV(key + ":I-SET.VAL"))
+
+ def __init__(self, service_name: str, pv_factory=PV):
+ super().__init__(service_name, pv_factory)
+ PV = pv_factory
+
+ # usually it is advisable to trigger the mainloop of a service on changes of certain PVs:
+ self.CallbackPV = PV("AGEBD-TUNEBUMP:CALLBACK", auto_monitor=True)
+
+
+class Service(BaseService[PVs]):
+ def __init__(
+ self,
+ name: str,
+ pvs: PVs,
+ version: str = __version__,
+ sleep_interval: float = 0.1,
+ ):
+ super().__init__(name, pvs, version, sleep_interval)
+
+ self.spects = pvs.anatune["QZ"]["Spec"].timestamp
+ self.freqvec = {}
+ for q in ["QX", "QY", "QZ"]:
+ self.freqvec[q] = pvs.anatune[q]["Freq"].get()
+
+ ## OnlineModel
+ # SLS 2.0 Machine Definition
+ self.S2 = Facility("/sls/bd/bin/MasterLayout.txt")
+ # load fully expanded machine element by element
+ self.S2.Layout("full")
+ # get individual short names for MQCO all magnets
+ # MQCO = S2.getElement_SN('MQCO')
+ # rather get them from the already sorted (by focus) PVs since sorting MQCOs from S2 by focusing requires MADX Model
+ for key in pvs.quads:
+ pvs.quads[key].append(key.replace("MOCT", "MQCO").rstrip("-QA"))
+ # SLS 2.0 Magnet Measurement Mapping Library
+ self.SM = SLS2Magnet()
+
+ # Nominal Tunes
+ self.Qx0 = 39.36999688
+ self.Qy0 = 15.21999988
+
+ self.dk = 0.01
+
+ # Tunes when dk=0.01 for Focusing knob
+ self.dQx_f = 39.38800899 - self.Qx0
+ self.dQy_f = 15.21560142 - self.Qy0
+
+ # Tunes when dk=0.01 for Defocusing knob
+ self.dQx_d = 39.38329945 - self.Qx0
+ self.dQy_d = 15.20693031 - self.Qy0
+
+ # Tune response matrix for dk=0.01
+ self.Qmat = np.array([[self.dQx_f, self.dQx_d], [self.dQy_f, self.dQy_d]])
+
+ # prepare dict of : Iset old and Iset new for all quads
+ self.quadsetpoints = {q: np.zeros(2) for q in pvs.quads}
+
+ def update(self):
+ pvs = self.pvs
+
+ if self.CallbackFired:
+ self.log = ["Tunebump service log, {:}".format(str(datetime.now())[:-7])]
+
+ self.dQx = 0
+ self.dQy = 0
+
+ for q in self.quadsetpoints:
+ self.quadsetpoints[q][0] = pvs.quads[q][1].get()
+
+ if pvs.Qx_stepup.get():
+ self.dQx = pvs.Qx_stepsize.get()
+
+ pvs.Qx_stepup.put(0)
+ self.log.append("Qx_stepup")
+
+ elif pvs.Qx_stepdown.get():
+ self.dQx = -pvs.Qx_stepsize.get()
+
+ pvs.Qx_stepdown.put(0)
+ self.log.append("Qx_stepdown")
+
+ if pvs.Qy_stepup.get():
+ self.dQy = pvs.Qy_stepsize.get()
+
+ pvs.Qy_stepup.put(0)
+ self.log.append("Qy_stepup")
+
+ elif pvs.Qy_stepdown.get():
+ self.dQy = -pvs.Qy_stepsize.get()
+
+ pvs.Qy_stepdown.put(0)
+ self.log.append("Qy_stepdown")
+
+ dKLF, dKLD = self.dQ2dKL(self.dQx, self.dQy)
+
+ for q in self.quadsetpoints:
+ if pvs.quads[q][0] == "F":
+ self.quadsetpoints[q][1] = self.Ii2If(
+ self.quadsetpoints[q][0], pvs.quads[q][2], dKLF
+ )
+
+ elif pvs.quads[q][0] == "D":
+ self.quadsetpoints[q][1] = self.Ii2If(
+ self.quadsetpoints[q][0], pvs.quads[q][2], dKLD
+ )
+
+ Isteps = [
+ self.quadsetpoints[q][1] - self.quadsetpoints[q][0] for q in self.quadsetpoints
+ ]
+ self.log.append(" MAX Istep = {:.6f}".format(np.nanmax(Isteps)))
+ self.log.append(" MIN Istep = {:.6f}".format(np.nanmin(Isteps)))
+
+ self.foc = "F"
+ self.log.append("-------------------------------------------")
+ self.log.append("focusing quads")
+ self.log.append("{:18} {:10} {:10}".format("Quad", "Iset_i", "Istep"))
+
+ Write2Mag = pvs.Write2Mag.get()
+
+ for q in self.quadsetpoints:
+ if Write2Mag:
+ pvs.quads[q][1].put(np.round(self.quadsetpoints[q][1], 6))
+
+ if pvs.quads[q][0] == "D" and self.foc == "F":
+ self.foc = "D"
+ self.log.append("-------------------------------------------")
+ self.log.append("defocusing quads")
+ self.log.append("{:18} {:10} {:10}".format("Quad", "Iset_i", "Istep"))
+
+ self.log.append(
+ "{:18} {:8.4f} {:8.4f}".format(
+ q,
+ self.quadsetpoints[q][0],
+ self.quadsetpoints[q][1] - self.quadsetpoints[q][0],
+ )
+ )
+
+ pvs.TuneBump_changelog.put("\n".join(self.log))
+ self.CallbackFired = 0
+
+ elif self.spects != pvs.anatune["QZ"]["Spec"].timestamp:
+ try:
+ for q in ["QX", "QY", "QZ"]:
+ spec = pvs.anatune[q]["Spec"].get()
+ self.spects = pvs.anatune[q]["Spec"].timestamp
+
+ freq = self.freqvec[q]
+ ulim = pvs.anatune[q]["Ulim"].get()
+ llim = pvs.anatune[q]["Llim"].get()
+ ind = np.where(np.logical_and(llim < freq, freq < ulim))[0]
+ freq = freq[ind]
+ spec = spec[ind]
+ spec = spec / np.max(spec)
+ peaks_wf = np.zeros(len(freq))
+
+ pvs.anatune[q]["NormSpec"].put(spec)
+ pvs.anatune[q]["NormFreq"].put(freq)
+
+ peaks, properties = signal.find_peaks(spec, height=0.03, distance=5)
+ sortind = np.argsort(properties["peak_heights"])[::-1]
+ peaks = peaks[sortind]
+
+ N = len(peaks)
+
+ if N > 0:
+ pvs.anatune[q]["Peak"].put(spec[peaks[:3]])
+ pvs.anatune[q]["PeakFreq"].put(freq[peaks[:3]])
+
+ pvs.anatune[q]["Tune"].put(freq[peaks[0]])
+
+ if q in ["QX", "QY"]:
+ if N > 1:
+ pvs.anatune[q]["TuneSB1"].put(freq[peaks[1]])
+ if N > 2:
+ pvs.anatune[q]["TuneSB2"].put(freq[peaks[2]])
+
+ except:
+ pass
+
+ # function to translate setcurrent of individual MQCO
+ def Ii2If(self, Ii, q, dKL):
+
+ qType = self.S2.getElement(q).TYPE
+
+ # Ii = pv.get()
+ KLi = self.SM.I2KL(qType, Ii)
+ KLf = KLi + dKL
+ If = self.SM.KL2I(qType, KLf)
+ # pv.put(If)
+
+ return If
+
+ def dQ2dKL(self, dQx, dQy):
+
+ dkF, dkD = np.dot(np.linalg.inv(self.Qmat), np.array([dQx, dQy])) * self.dk
+
+ dKLF = dkF * 0.05 # MQCO length is 5 cm
+ dKLD = dkD * 0.05 # MQCO length is 5 cm
+
+ return dKLF, dKLD
diff --git a/services/tunebump/current/app/tests/test_app.py b/services/tunebump/current/app/tests/test_app.py
new file mode 100644
index 0000000..ea2bb02
--- /dev/null
+++ b/services/tunebump/current/app/tests/test_app.py
@@ -0,0 +1,9 @@
+from agebd_tunebump import PVs, Service
+
+
+def test_app():
+ service_name = "DUMMY"
+ pvs = PVs(service_name=service_name)
+ service = Service(name=service_name, pvs=pvs)
+ service.CallbackFired = 1
+ service.update()
diff --git a/services/tunebump/current/app/uv.lock b/services/tunebump/current/app/uv.lock
new file mode 100644
index 0000000..37e64e0
--- /dev/null
+++ b/services/tunebump/current/app/uv.lock
@@ -0,0 +1,323 @@
+version = 1
+revision = 3
+requires-python = "==3.10.*"
+
+[[package]]
+name = "agebd"
+version = "0.1.0"
+source = { editable = "../../../../packages/agebd" }
+dependencies = [
+ { name = "h5py" },
+ { name = "typer" },
+]
+
+[package.metadata]
+requires-dist = [
+ { name = "h5py", specifier = ">=3.16.0" },
+ { name = "typer", specifier = ">=0.23.2" },
+]
+
+[package.metadata.requires-dev]
+dev = [
+ { name = "pyright", specifier = ">=1.1.410" },
+ { name = "pytest", specifier = ">=8.4.2" },
+ { name = "ruff", specifier = ">=0.15.19" },
+]
+
+[[package]]
+name = "agebd-tunebump"
+version = "0.1.0"
+source = { editable = "." }
+dependencies = [
+ { name = "agebd" },
+ { name = "numpy" },
+ { name = "scipy" },
+]
+
+[package.dev-dependencies]
+dev = [
+ { name = "pyepics" },
+ { name = "pytest" },
+ { name = "ruff" },
+]
+
+[package.metadata]
+requires-dist = [
+ { name = "agebd", editable = "../../../../packages/agebd" },
+ { name = "numpy", specifier = ">=2.2.6" },
+ { name = "scipy", specifier = ">=1.15.3" },
+]
+
+[package.metadata.requires-dev]
+dev = [
+ { name = "pyepics", specifier = ">=3.5.8" },
+ { name = "pytest", specifier = ">=8.4.2" },
+ { name = "ruff", specifier = ">=0.15.20" },
+]
+
+[[package]]
+name = "annotated-doc"
+version = "0.0.4"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/57/ba/046ceea27344560984e26a590f90bc7f4a75b06701f653222458922b558c/annotated_doc-0.0.4.tar.gz", hash = "sha256:fbcda96e87e9c92ad167c2e53839e57503ecfda18804ea28102353485033faa4", size = 7288, upload-time = "2025-11-10T22:07:42.062Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl", hash = "sha256:571ac1dc6991c450b25a9c2d84a3705e2ae7a53467b5d111c24fa8baabbed320", size = 5303, upload-time = "2025-11-10T22:07:40.673Z" },
+]
+
+[[package]]
+name = "colorama"
+version = "0.4.6"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" },
+]
+
+[[package]]
+name = "exceptiongroup"
+version = "1.3.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "typing-extensions" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" },
+]
+
+[[package]]
+name = "h5py"
+version = "3.16.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "numpy" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/db/33/acd0ce6863b6c0d7735007df01815403f5589a21ff8c2e1ee2587a38f548/h5py-3.16.0.tar.gz", hash = "sha256:a0dbaad796840ccaa67a4c144a0d0c8080073c34c76d5a6941d6818678ef2738", size = 446526, upload-time = "2026-03-06T13:49:08.07Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/3a/6b/231413e58a787a89b316bb0d1777da3c62257e4797e09afd8d17ad3549dc/h5py-3.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e06f864bedb2c8e7c1358e6c73af48519e317457c444d6f3d332bb4e8fa6d7d9", size = 3724137, upload-time = "2026-03-06T13:47:35.242Z" },
+ { url = "https://files.pythonhosted.org/packages/74/f9/557ce3aad0fe8471fb5279bab0fc56ea473858a022c4ce8a0b8f303d64e9/h5py-3.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ec86d4fffd87a0f4cb3d5796ceb5a50123a2a6d99b43e616e5504e66a953eca3", size = 3090112, upload-time = "2026-03-06T13:47:37.634Z" },
+ { url = "https://files.pythonhosted.org/packages/7a/f5/e15b3d0dc8a18e56409a839e6468d6fb589bc5207c917399c2e0706eeb44/h5py-3.16.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:86385ea895508220b8a7e45efa428aeafaa586bd737c7af9ee04661d8d84a10d", size = 4844847, upload-time = "2026-03-06T13:47:39.811Z" },
+ { url = "https://files.pythonhosted.org/packages/cb/92/a8851d936547efe30cc0ce5245feac01f3ec6171f7899bc3f775c72030b3/h5py-3.16.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:8975273c2c5921c25700193b408e28d6bdd0111c37468b2d4e25dcec4cd1d84d", size = 5065352, upload-time = "2026-03-06T13:47:41.489Z" },
+ { url = "https://files.pythonhosted.org/packages/2b/ae/f2adc5d0ca9626db3277a3d87516e124cbc5d0eea0bd79bc085702d04f2c/h5py-3.16.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:1677ad48b703f44efc9ea0c3ab284527f81bc4f318386aaaebc5fede6bbae56f", size = 4839173, upload-time = "2026-03-06T13:47:43.586Z" },
+ { url = "https://files.pythonhosted.org/packages/64/0b/e0c8c69da1d8838da023a50cd3080eae5d475691f7636b35eff20bb6ef20/h5py-3.16.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7c4dd4cf5f0a4e36083f73172f6cfc25a5710789269547f132a20975bfe2434c", size = 5076216, upload-time = "2026-03-06T13:47:45.315Z" },
+ { url = "https://files.pythonhosted.org/packages/66/35/d88fd6718832133c885004c61ceeeb24dbd6397ef877dbed6b3a64d6a286/h5py-3.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:bdef06507725b455fccba9c16529121a5e1fbf56aa375f7d9713d9e8ff42454d", size = 3183639, upload-time = "2026-03-06T13:47:47.041Z" },
+]
+
+[[package]]
+name = "iniconfig"
+version = "2.3.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" },
+]
+
+[[package]]
+name = "markdown-it-py"
+version = "4.2.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "mdurl" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/06/ff/7841249c247aa650a76b9ee4bbaeae59370dc8bfd2f6c01f3630c35eb134/markdown_it_py-4.2.0.tar.gz", hash = "sha256:04a21681d6fbb623de53f6f364d352309d4094dd4194040a10fd51833e418d49", size = 82454, upload-time = "2026-05-07T12:08:28.36Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl", hash = "sha256:9f7ebbcd14fe59494226453aed97c1070d83f8d24b6fc3a3bcf9a38092641c4a", size = 91687, upload-time = "2026-05-07T12:08:27.182Z" },
+]
+
+[[package]]
+name = "mdurl"
+version = "0.1.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" },
+]
+
+[[package]]
+name = "numpy"
+version = "2.2.6"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/76/21/7d2a95e4bba9dc13d043ee156a356c0a8f0c6309dff6b21b4d71a073b8a8/numpy-2.2.6.tar.gz", hash = "sha256:e29554e2bef54a90aa5cc07da6ce955accb83f21ab5de01a62c8478897b264fd", size = 20276440, upload-time = "2025-05-17T22:38:04.611Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/9a/3e/ed6db5be21ce87955c0cbd3009f2803f59fa08df21b5df06862e2d8e2bdd/numpy-2.2.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b412caa66f72040e6d268491a59f2c43bf03eb6c96dd8f0307829feb7fa2b6fb", size = 21165245, upload-time = "2025-05-17T21:27:58.555Z" },
+ { url = "https://files.pythonhosted.org/packages/22/c2/4b9221495b2a132cc9d2eb862e21d42a009f5a60e45fc44b00118c174bff/numpy-2.2.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e41fd67c52b86603a91c1a505ebaef50b3314de0213461c7a6e99c9a3beff90", size = 14360048, upload-time = "2025-05-17T21:28:21.406Z" },
+ { url = "https://files.pythonhosted.org/packages/fd/77/dc2fcfc66943c6410e2bf598062f5959372735ffda175b39906d54f02349/numpy-2.2.6-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:37e990a01ae6ec7fe7fa1c26c55ecb672dd98b19c3d0e1d1f326fa13cb38d163", size = 5340542, upload-time = "2025-05-17T21:28:30.931Z" },
+ { url = "https://files.pythonhosted.org/packages/7a/4f/1cb5fdc353a5f5cc7feb692db9b8ec2c3d6405453f982435efc52561df58/numpy-2.2.6-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:5a6429d4be8ca66d889b7cf70f536a397dc45ba6faeb5f8c5427935d9592e9cf", size = 6878301, upload-time = "2025-05-17T21:28:41.613Z" },
+ { url = "https://files.pythonhosted.org/packages/eb/17/96a3acd228cec142fcb8723bd3cc39c2a474f7dcf0a5d16731980bcafa95/numpy-2.2.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:efd28d4e9cd7d7a8d39074a4d44c63eda73401580c5c76acda2ce969e0a38e83", size = 14297320, upload-time = "2025-05-17T21:29:02.78Z" },
+ { url = "https://files.pythonhosted.org/packages/b4/63/3de6a34ad7ad6646ac7d2f55ebc6ad439dbbf9c4370017c50cf403fb19b5/numpy-2.2.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc7b73d02efb0e18c000e9ad8b83480dfcd5dfd11065997ed4c6747470ae8915", size = 16801050, upload-time = "2025-05-17T21:29:27.675Z" },
+ { url = "https://files.pythonhosted.org/packages/07/b6/89d837eddef52b3d0cec5c6ba0456c1bf1b9ef6a6672fc2b7873c3ec4e2e/numpy-2.2.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:74d4531beb257d2c3f4b261bfb0fc09e0f9ebb8842d82a7b4209415896adc680", size = 15807034, upload-time = "2025-05-17T21:29:51.102Z" },
+ { url = "https://files.pythonhosted.org/packages/01/c8/dc6ae86e3c61cfec1f178e5c9f7858584049b6093f843bca541f94120920/numpy-2.2.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8fc377d995680230e83241d8a96def29f204b5782f371c532579b4f20607a289", size = 18614185, upload-time = "2025-05-17T21:30:18.703Z" },
+ { url = "https://files.pythonhosted.org/packages/5b/c5/0064b1b7e7c89137b471ccec1fd2282fceaae0ab3a9550f2568782d80357/numpy-2.2.6-cp310-cp310-win32.whl", hash = "sha256:b093dd74e50a8cba3e873868d9e93a85b78e0daf2e98c6797566ad8044e8363d", size = 6527149, upload-time = "2025-05-17T21:30:29.788Z" },
+ { url = "https://files.pythonhosted.org/packages/a3/dd/4b822569d6b96c39d1215dbae0582fd99954dcbcf0c1a13c61783feaca3f/numpy-2.2.6-cp310-cp310-win_amd64.whl", hash = "sha256:f0fd6321b839904e15c46e0d257fdd101dd7f530fe03fd6359c1ea63738703f3", size = 12904620, upload-time = "2025-05-17T21:30:48.994Z" },
+ { url = "https://files.pythonhosted.org/packages/9e/3b/d94a75f4dbf1ef5d321523ecac21ef23a3cd2ac8b78ae2aac40873590229/numpy-2.2.6-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0b605b275d7bd0c640cad4e5d30fa701a8d59302e127e5f79138ad62762c3e3d", size = 21040391, upload-time = "2025-05-17T21:44:35.948Z" },
+ { url = "https://files.pythonhosted.org/packages/17/f4/09b2fa1b58f0fb4f7c7963a1649c64c4d315752240377ed74d9cd878f7b5/numpy-2.2.6-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:7befc596a7dc9da8a337f79802ee8adb30a552a94f792b9c9d18c840055907db", size = 6786754, upload-time = "2025-05-17T21:44:47.446Z" },
+ { url = "https://files.pythonhosted.org/packages/af/30/feba75f143bdc868a1cc3f44ccfa6c4b9ec522b36458e738cd00f67b573f/numpy-2.2.6-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce47521a4754c8f4593837384bd3424880629f718d87c5d44f8ed763edd63543", size = 16643476, upload-time = "2025-05-17T21:45:11.871Z" },
+ { url = "https://files.pythonhosted.org/packages/37/48/ac2a9584402fb6c0cd5b5d1a91dcf176b15760130dd386bbafdbfe3640bf/numpy-2.2.6-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d042d24c90c41b54fd506da306759e06e568864df8ec17ccc17e9e884634fd00", size = 12812666, upload-time = "2025-05-17T21:45:31.426Z" },
+]
+
+[[package]]
+name = "packaging"
+version = "26.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d7/f1/e7a6dd94a8d4a5626c03e4e99c87f241ba9e350cd9e6d75123f992427270/packaging-26.2.tar.gz", hash = "sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661", size = 228134, upload-time = "2026-04-24T20:15:23.917Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/df/b2/87e62e8c3e2f4b32e5fe99e0b86d576da1312593b39f47d8ceef365e95ed/packaging-26.2-py3-none-any.whl", hash = "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e", size = 100195, upload-time = "2026-04-24T20:15:22.081Z" },
+]
+
+[[package]]
+name = "pluggy"
+version = "1.6.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" },
+]
+
+[[package]]
+name = "pyepics"
+version = "3.5.10"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "numpy" },
+ { name = "pyparsing" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/69/57/29e1e9ef11ba2a3419f489946ae1d8190025a1e4f4e1c1686758bb2b6e0a/pyepics-3.5.10.tar.gz", hash = "sha256:f390cf9be40aba757b9528888114bc14d8db01086d0c93914720b1772460375b", size = 6150481, upload-time = "2026-05-20T18:44:36.336Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d6/36/e517fd83bd97d6bfe4105e0c6b322070c5cc36fb56a8fab2866e319f8804/pyepics-3.5.10-py3-none-any.whl", hash = "sha256:c9fac2c54f2b595268e66fc348cf5ec24e63718e7dbd07d73d1b37d4da6bfee1", size = 5332376, upload-time = "2026-05-20T18:44:34.242Z" },
+]
+
+[[package]]
+name = "pygments"
+version = "2.20.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" },
+]
+
+[[package]]
+name = "pyparsing"
+version = "3.3.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f3/91/9c6ee907786a473bf81c5f53cf703ba0957b23ab84c264080fb5a450416f/pyparsing-3.3.2.tar.gz", hash = "sha256:c777f4d763f140633dcb6d8a3eda953bf7a214dc4eff598413c070bcdc117cbc", size = 6851574, upload-time = "2026-01-21T03:57:59.36Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl", hash = "sha256:850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d", size = 122781, upload-time = "2026-01-21T03:57:55.912Z" },
+]
+
+[[package]]
+name = "pytest"
+version = "9.1.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "colorama", marker = "sys_platform == 'win32'" },
+ { name = "exceptiongroup" },
+ { name = "iniconfig" },
+ { name = "packaging" },
+ { name = "pluggy" },
+ { name = "pygments" },
+ { name = "tomli" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/e4/47/b9efed96c114afcfa3c9d3fe98a76a1d14c74a9e266d397cf6eb64be5e01/pytest-9.1.1.tar.gz", hash = "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313", size = 1636369, upload-time = "2026-06-19T10:58:32.857Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/24/25/1de2678b631f5a49215c6c96fff41ba892b0a34df68d6d80292b1b48aa7f/pytest-9.1.1-py3-none-any.whl", hash = "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c", size = 386536, upload-time = "2026-06-19T10:58:31.347Z" },
+]
+
+[[package]]
+name = "rich"
+version = "15.0.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "markdown-it-py" },
+ { name = "pygments" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/c0/8f/0722ca900cc807c13a6a0c696dacf35430f72e0ec571c4275d2371fca3e9/rich-15.0.0.tar.gz", hash = "sha256:edd07a4824c6b40189fb7ac9bc4c52536e9780fbbfbddf6f1e2502c31b068c36", size = 230680, upload-time = "2026-04-12T08:24:00.75Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl", hash = "sha256:33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb", size = 310654, upload-time = "2026-04-12T08:24:02.83Z" },
+]
+
+[[package]]
+name = "ruff"
+version = "0.15.21"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/0f/36/6f65aa9989acdec45d417192d8f4e7921931d8a6cf87ac74bce3eed98a8e/ruff-0.15.21.tar.gz", hash = "sha256:d0cfc841c572283c36548f82664a54ce6565567f1b0d5b4cf2caac693d8b7500", size = 4769401, upload-time = "2026-07-09T20:01:34.005Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d0/c6/ede15cac6839f3dbce52565c8f5164a8210e669c7bc4decb03e5bdf47d0d/ruff-0.15.21-py3-none-linux_armv6l.whl", hash = "sha256:63ea0e965e5d73c90e95b2434beeafc70820536717f561b32ab6e777cb9bdf5d", size = 10854342, upload-time = "2026-07-09T20:00:53.998Z" },
+ { url = "https://files.pythonhosted.org/packages/28/9d/d825b07ee7ea9e2d61df92a860033c94e06e7300d50a1c2653aac27d24fe/ruff-0.15.21-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:0f212c5d7d54c01bbfe6dcab02b724a39300f3e34ed7acbe995ccb320a2c58bd", size = 11139539, upload-time = "2026-07-09T20:00:57.809Z" },
+ { url = "https://files.pythonhosted.org/packages/f5/de/3b107712e642f063c7a9e0887c427b22cb44097de5aab36c05f2e280670c/ruff-0.15.21-py3-none-macosx_11_0_arm64.whl", hash = "sha256:e6312e41bc96791299614995ea3a977c5857c3b5662b1ecef6755b02b87cb646", size = 10595437, upload-time = "2026-07-09T20:01:00.006Z" },
+ { url = "https://files.pythonhosted.org/packages/9a/6f/b4523cc90ba239ede441447a19d0c968846a3012e5a0b0c5b62831a3d5e3/ruff-0.15.21-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01d65b4831c6b2a4ba8ee6faa84049d44d982b7a706e622c4094c509e51673be", size = 10990053, upload-time = "2026-07-09T20:01:02.187Z" },
+ { url = "https://files.pythonhosted.org/packages/92/cc/c6a9872a5375f0628875481cf2f66b13d7d865bf3ca2e57f91c7e762d976/ruff-0.15.21-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2c5a913a589120ce67933d5d05fd6ddbcc2481c6a054980ee767f7414c72b4fd", size = 10666096, upload-time = "2026-07-09T20:01:04.299Z" },
+ { url = "https://files.pythonhosted.org/packages/ab/97/c621f7a17e097f1790fa3af6374138823b330b2d03fc38337945daca212c/ruff-0.15.21-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ef04b681d02ad4dc9620f00f83ac5c22f652d0e9a9cfe431d219b16ad5ccc41", size = 11537011, upload-time = "2026-07-09T20:01:06.771Z" },
+ { url = "https://files.pythonhosted.org/packages/ea/51/d928727e476e25ccc57c6f449ffd80241a651a973ad949d39cfb2a771d28/ruff-0.15.21-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:16d090c0740916594157e75b80d666eab8e78083b39b3b0e1d698f4670a17b86", size = 12347101, upload-time = "2026-07-09T20:01:08.859Z" },
+ { url = "https://files.pythonhosted.org/packages/1e/88/8cd62026802b16018ad06931d87997cf795ba2a6239ab659606c87d96bf0/ruff-0.15.21-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3a10e74757dd65004d779b73e2f3c5210156d9980b41224d50d2ebcf1db51e67", size = 11572001, upload-time = "2026-07-09T20:01:11.092Z" },
+ { url = "https://files.pythonhosted.org/packages/b2/97/f63084cf55444fc110e8cb985ebfcc592af47f597d44453d778cb81bc156/ruff-0.15.21-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bab0905d2f29e0d9fbc3c373ed23db0095edaa3f71f1f4f519ec15134d9e85c8", size = 11549239, upload-time = "2026-07-09T20:01:13.27Z" },
+ { url = "https://files.pythonhosted.org/packages/9d/77/f107da4a2874b7715914b03f09ba9c54424de3ff8a1cc5d015d3ee2ce0ac/ruff-0.15.21-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:00eca240af5789fec6fe7df74c088cc1f9644ed83027113468efba7c92b94075", size = 11535340, upload-time = "2026-07-09T20:01:15.206Z" },
+ { url = "https://files.pythonhosted.org/packages/d5/e9/601deb322d3303a7bf212b0100ead6f2ee3f6a044d89c30f2f92bf83c731/ruff-0.15.21-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:262ab31557a75141325e32d3357f3597645a7f084e732b6b054dde428ecd9341", size = 10964048, upload-time = "2026-07-09T20:01:17.723Z" },
+ { url = "https://files.pythonhosted.org/packages/ea/2e/0f2176d1e99c15192caea19c8c3a0a955246b4cb4de795042eeb616345cd/ruff-0.15.21-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:659c4e7a4212f83306045ec7c5e5a356d16d9a6ef4ae0c7a4d872914fc655d9d", size = 10667055, upload-time = "2026-07-09T20:01:19.73Z" },
+ { url = "https://files.pythonhosted.org/packages/48/60/abd74a02e0c4214f12a68becfd30af7165cfdcb0e661ecdc60bbb949c09a/ruff-0.15.21-py3-none-musllinux_1_2_i686.whl", hash = "sha256:9e866eab611a5f959d36df2d10e446973a3610bc42b0c15b31dc27977d59c233", size = 11242043, upload-time = "2026-07-09T20:01:21.947Z" },
+ { url = "https://files.pythonhosted.org/packages/b2/c6/583075d8ccabb4b229345edcaf1545eb3d8d6be90f686a479d7e94088bbf/ruff-0.15.21-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e89bc93c0d3803ba870b55c29671bad9dc6d94bb1eb181b056b52eb05b52854f", size = 11648064, upload-time = "2026-07-09T20:01:24.023Z" },
+ { url = "https://files.pythonhosted.org/packages/3a/3c/37d0ecb729a7cc2d393ea7dce316fc585680f35d93b8d62139d7d0a3700c/ruff-0.15.21-py3-none-win32.whl", hash = "sha256:01f8d5be84823c172b389e123174f781f9daf86d6c58719d603f941932195cdd", size = 10896555, upload-time = "2026-07-09T20:01:26.941Z" },
+ { url = "https://files.pythonhosted.org/packages/c0/b8/e43466b2a6067ce91e669068f6e28d6c719a920f014b070d5c8731725de3/ruff-0.15.21-py3-none-win_amd64.whl", hash = "sha256:d4b8d9a2f0f12b816b50447f6eccb9f4bb01a6b82c86b50fb3b5354b458dc6d3", size = 12038772, upload-time = "2026-07-09T20:01:29.497Z" },
+ { url = "https://files.pythonhosted.org/packages/dd/75/e90ab9aeece218a9fc5a5bc3ec97d0ee6bb3c4ff95869463c1de58e29a1c/ruff-0.15.21-py3-none-win_arm64.whl", hash = "sha256:6e83115d4b9377c1cbc13abf0e051f069fab0ef815ea0504a8a008cee24dd0a8", size = 11375265, upload-time = "2026-07-09T20:01:31.772Z" },
+]
+
+[[package]]
+name = "scipy"
+version = "1.15.3"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "numpy" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/0f/37/6964b830433e654ec7485e45a00fc9a27cf868d622838f6b6d9c5ec0d532/scipy-1.15.3.tar.gz", hash = "sha256:eae3cf522bc7df64b42cad3925c876e1b0b6c35c1337c93e12c0f366f55b0eaf", size = 59419214, upload-time = "2025-05-08T16:13:05.955Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/78/2f/4966032c5f8cc7e6a60f1b2e0ad686293b9474b65246b0c642e3ef3badd0/scipy-1.15.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:a345928c86d535060c9c2b25e71e87c39ab2f22fc96e9636bd74d1dbf9de448c", size = 38702770, upload-time = "2025-05-08T16:04:20.849Z" },
+ { url = "https://files.pythonhosted.org/packages/a0/6e/0c3bf90fae0e910c274db43304ebe25a6b391327f3f10b5dcc638c090795/scipy-1.15.3-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:ad3432cb0f9ed87477a8d97f03b763fd1d57709f1bbde3c9369b1dff5503b253", size = 30094511, upload-time = "2025-05-08T16:04:27.103Z" },
+ { url = "https://files.pythonhosted.org/packages/ea/b1/4deb37252311c1acff7f101f6453f0440794f51b6eacb1aad4459a134081/scipy-1.15.3-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:aef683a9ae6eb00728a542b796f52a5477b78252edede72b8327a886ab63293f", size = 22368151, upload-time = "2025-05-08T16:04:31.731Z" },
+ { url = "https://files.pythonhosted.org/packages/38/7d/f457626e3cd3c29b3a49ca115a304cebb8cc6f31b04678f03b216899d3c6/scipy-1.15.3-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:1c832e1bd78dea67d5c16f786681b28dd695a8cb1fb90af2e27580d3d0967e92", size = 25121732, upload-time = "2025-05-08T16:04:36.596Z" },
+ { url = "https://files.pythonhosted.org/packages/db/0a/92b1de4a7adc7a15dcf5bddc6e191f6f29ee663b30511ce20467ef9b82e4/scipy-1.15.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:263961f658ce2165bbd7b99fa5135195c3a12d9bef045345016b8b50c315cb82", size = 35547617, upload-time = "2025-05-08T16:04:43.546Z" },
+ { url = "https://files.pythonhosted.org/packages/8e/6d/41991e503e51fc1134502694c5fa7a1671501a17ffa12716a4a9151af3df/scipy-1.15.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e2abc762b0811e09a0d3258abee2d98e0c703eee49464ce0069590846f31d40", size = 37662964, upload-time = "2025-05-08T16:04:49.431Z" },
+ { url = "https://files.pythonhosted.org/packages/25/e1/3df8f83cb15f3500478c889be8fb18700813b95e9e087328230b98d547ff/scipy-1.15.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ed7284b21a7a0c8f1b6e5977ac05396c0d008b89e05498c8b7e8f4a1423bba0e", size = 37238749, upload-time = "2025-05-08T16:04:55.215Z" },
+ { url = "https://files.pythonhosted.org/packages/93/3e/b3257cf446f2a3533ed7809757039016b74cd6f38271de91682aa844cfc5/scipy-1.15.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5380741e53df2c566f4d234b100a484b420af85deb39ea35a1cc1be84ff53a5c", size = 40022383, upload-time = "2025-05-08T16:05:01.914Z" },
+ { url = "https://files.pythonhosted.org/packages/d1/84/55bc4881973d3f79b479a5a2e2df61c8c9a04fcb986a213ac9c02cfb659b/scipy-1.15.3-cp310-cp310-win_amd64.whl", hash = "sha256:9d61e97b186a57350f6d6fd72640f9e99d5a4a2b8fbf4b9ee9a841eab327dc13", size = 41259201, upload-time = "2025-05-08T16:05:08.166Z" },
+]
+
+[[package]]
+name = "shellingham"
+version = "1.5.4"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/58/15/8b3609fd3830ef7b27b655beb4b4e9c62313a4e8da8c676e142cc210d58e/shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de", size = 10310, upload-time = "2023-10-24T04:13:40.426Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755, upload-time = "2023-10-24T04:13:38.866Z" },
+]
+
+[[package]]
+name = "tomli"
+version = "2.4.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/22/de/48c59722572767841493b26183a0d1cc411d54fd759c5607c4590b6563a6/tomli-2.4.1.tar.gz", hash = "sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f", size = 17543, upload-time = "2026-03-25T20:22:03.828Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/7b/61/cceae43728b7de99d9b847560c262873a1f6c98202171fd5ed62640b494b/tomli-2.4.1-py3-none-any.whl", hash = "sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe", size = 14583, upload-time = "2026-03-25T20:22:03.012Z" },
+]
+
+[[package]]
+name = "typer"
+version = "0.27.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "annotated-doc" },
+ { name = "colorama", marker = "sys_platform == 'win32'" },
+ { name = "rich" },
+ { name = "shellingham" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/37/78/fda3361b56efc27944f24225f6ecd13d96d6fcfe37bd0eb34e2f4c63f9fc/typer-0.27.0.tar.gz", hash = "sha256:629bd12ea5d13a17148125d9a264f949eb171fb3f120f9b04d85873cab054fa5", size = 203430, upload-time = "2026-07-15T19:21:07.007Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/40/03/26a383c9e58c213199d1aad1c3d353cfc22d4444ec6d2c0bf8ad02523843/typer-0.27.0-py3-none-any.whl", hash = "sha256:6f4b27631e47f077871b7dc30e933ec0131c1390fbe0e387ea5574b5bac9ccf1", size = 122716, upload-time = "2026-07-15T19:21:05.553Z" },
+]
+
+[[package]]
+name = "typing-extensions"
+version = "4.16.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f6/cc/6253133b5bb138fc3306cebfbda2c520f545d36b5be2c7255cc528bb45d6/typing_extensions-4.16.0.tar.gz", hash = "sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5", size = 113555, upload-time = "2026-07-02T08:40:05.92Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/49/d3/b8441a820a491ddfc024b0b0cf0393375b75ea13866d9c66727e54c2fc80/typing_extensions-4.16.0-py3-none-any.whl", hash = "sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8", size = 45571, upload-time = "2026-07-02T08:40:04.659Z" },
+]
diff --git a/services/tunebump/current/ioc/AGEBD-CPCL-TUNEBUMP_main.subs b/services/tunebump/current/ioc/AGEBD-CPCL-TUNEBUMP_main.subs
new file mode 100644
index 0000000..cf91d27
--- /dev/null
+++ b/services/tunebump/current/ioc/AGEBD-CPCL-TUNEBUMP_main.subs
@@ -0,0 +1,4 @@
+file TUNEBUMP.template {
+ pattern { DEVICE }
+ { AGEBD-TUNEBUMP{{ agebd_env }} }
+}
diff --git a/services/tunebump/current/ioc/AGEBD-CPCL-TUNEBUMP_parameters.yaml b/services/tunebump/current/ioc/AGEBD-CPCL-TUNEBUMP_parameters.yaml
new file mode 100644
index 0000000..ff8e70f
--- /dev/null
+++ b/services/tunebump/current/ioc/AGEBD-CPCL-TUNEBUMP_parameters.yaml
@@ -0,0 +1,6 @@
+cpu_architecture: x86_64
+epics_version: 7.0.8
+ioc_host: sls-vserv-bd-01{{ agebd_env }}
+ioc_port: {{ ioc_port }}
+os: RHEL8
+os_id: rhel
diff --git a/services/tunebump/current/ioc/TUNEBUMP.template b/services/tunebump/current/ioc/TUNEBUMP.template
new file mode 100644
index 0000000..b2bb298
--- /dev/null
+++ b/services/tunebump/current/ioc/TUNEBUMP.template
@@ -0,0 +1,493 @@
+####################################
+## USED BPMs
+####################################
+# HORIZONTAL ARS01-DBPM-0760 (Im FOFB)
+# ARS07-DBPM-0840 (BPMA)
+# ----------------------------------
+# VERTICAL ARS09-DBPM-0570 (Im FOFB)
+# ARS07-DBPM-5530 (BPMA)
+# ----------------------------------
+# LONGITUDINAL ARS02-DBPM-2910 (Im FOFB)
+#
+####################################
+
+
+record(bo, "$(DEVICE):WRITE2MAG") {
+ field(DESC, "Only print or apply setpoints")
+ field(VAL, "1")
+ field(PINI, "YES")
+}
+
+record(waveform,"$(DEVICE):CHANGELOG") {
+ field(DESC, "overview of to be applied changes")
+ field(FTVL, "UCHAR")
+ field(NELM, "$(SIZE=60000)")
+ field(PINI, "YES")
+}
+
+record(calcout, "$(DEVICE):CALLBACK"){
+ field(DESC, "1 if a tune step has been requested")
+ field(ASG, "READONLY")
+ field(PINI, "YES")
+ field(VAL, "0")
+ field(CALC, "A + B + C + D")
+ field(INPA, "$(DEVICE):QX-STEPUP")
+ field(INPB, "$(DEVICE):QX-STEPDOWN")
+ field(INPC, "$(DEVICE):QY-STEPUP")
+ field(INPD, "$(DEVICE):QY-STEPDOWN")
+}
+
+record(ao, "$(DEVICE):QX-STEPSIZE"){
+ field(DESC, "hor. tune step size, e.g. 0.0001")
+ field(VAL, "0.0001")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):QX-FIT"){
+ field(DESC, "hor. tune from fit")
+ field(VAL, "0.0")
+ field(PINI, "YES")
+}
+
+record(bo, "$(DEVICE):QX-STEPUP"){
+ field(DESC, "request hor. tune step up")
+ field(FLNK, "$(DEVICE):CALLBACK")
+ field(VAL, "0")
+ field(PINI, "YES")
+ field(HIGH, "1")
+}
+
+record(bo, "$(DEVICE):QX-STEPDOWN"){
+ field(DESC, "request hor. tune step down")
+ field(FLNK, "$(DEVICE):CALLBACK")
+ field(VAL, "0")
+ field(PINI, "YES")
+ field(HIGH, "1")
+}
+
+record(ao, "$(DEVICE):QY-STEPSIZE"){
+ field(DESC, "ver. tune step size, e.g. 0.0001")
+ field(VAL, "0.0001")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):QY-FIT"){
+ field(DESC, "ver. tune from fit")
+ field(VAL, "0.0")
+ field(PINI, "YES")
+}
+
+record(bo, "$(DEVICE):QY-STEPUP"){
+ field(DESC, "request ver. tune step up")
+ field(FLNK, "$(DEVICE):CALLBACK")
+ field(VAL, "0")
+ field(PINI, "YES")
+ field(HIGH, "1")
+}
+
+record(bo, "$(DEVICE):QY-STEPDOWN"){
+ field(DESC, "request ver. tune step down")
+ field(FLNK, "$(DEVICE):CALLBACK")
+ field(VAL, "0")
+ field(PINI, "YES")
+ field(HIGH, "1")
+}
+
+
+## spectra
+
+record (waveform, "$(DEVICE):SIGN-X"){
+ field (DESC, "Copy of ARS07-DBPM-0840:DAQ-BEAM-STG0-X")
+ field (FTVL, "FLOAT")
+ field (NELM, "16384")
+ field (INP, "ARS07-DBPM-0840:DAQ-BEAM-STG0-X CP MS")
+ field (FLNK, "$(DEVICE):SPEC-X")
+ field (PREC, "6")
+}
+
+record (waveform, "$(DEVICE):SPEC-X"){
+ field (FTVL, "FLOAT")
+ field (DTYP, "FFT spsd")
+ field (NELM, "8193")
+ field (INP, "$(DEVICE):SIGN-X MS")
+ field (FLNK, "$(DEVICE):SPEC-FREQ-qX")
+ field (PREC, "3")
+}
+
+record(calcout, "$(DEVICE):OVERSAMPLE-2-qxVEC"){
+ field(DESC, "Sampling Rate")
+ field(CALC, "0.5 * A / (299792458 / 288 / 1000)")
+ field(INPA, "ARS07-DBPM-0840:DWC-STG0-RATE CP")
+ field(OUT, "$(DEVICE):SPEC-FREQ-qX.HOPR PP")
+}
+
+record (waveform, "$(DEVICE):SPEC-FREQ-qX"){
+ field (FTVL, "FLOAT")
+ field (DTYP, "sequence")
+ field (NELM, "8193")
+ field (LOPR, "0")
+ field (HOPR, "0.5")
+ field (PREC, "3")
+ field (PINI, "YES")
+}
+
+record (waveform, "$(DEVICE):SIGN-Y"){
+ field (DESC, "Copy of ARS07-DBPM-5530:DAQ-BEAM-STG0-Y")
+ field (FTVL, "FLOAT")
+ field (NELM, "16384")
+ field (INP, "ARS07-DBPM-5530:DAQ-BEAM-STG0-Y CP MS")
+ field (FLNK, "$(DEVICE):SPEC-Y")
+ field (PREC, "6")
+}
+
+record (waveform, "$(DEVICE):SPEC-Y"){
+ field (FTVL, "FLOAT")
+ field (DTYP, "FFT spsd")
+ field (NELM, "8192")
+ field (INP, "$(DEVICE):SIGN-Y MS")
+ field (FLNK, "$(DEVICE):SPEC-FREQ-qY")
+ field (PREC, "3")
+}
+
+record(calcout, "$(DEVICE):OVERSAMPLE-2-qYVEC"){
+ field(DESC, "Sampling Rate")
+ field(CALC, "0.5 * A / (299792458 / 288 / 1000)")
+ field(INPA, "ARS07-DBPM-5530:DWC-STG0-RATE CP")
+ field(OUT, "$(DEVICE):SPEC-FREQ-qY.HOPR PP")
+}
+
+record (waveform, "$(DEVICE):SPEC-FREQ-qY"){
+ field (FTVL, "FLOAT")
+ field (DTYP, "sequence")
+ field (NELM, "8192")
+ field (LOPR, "0")
+ field (HOPR, "0.5")
+ field (PREC, "3")
+ field (PINI, "YES")
+}
+
+record (waveform, "$(DEVICE):SIGN-Z"){
+ field (DESC, "Copy of ARS02-DBPM-2910:DAQ-BEAM-STG1-X")
+ field (FTVL, "FLOAT")
+ field (NELM, "16384")
+ field (INP, "ARS02-DBPM-2910:DAQ-BEAM-STG1-X CP MS")
+ field (FLNK, "$(DEVICE):SPEC-Z")
+ field (PREC, "6")
+}
+
+record (waveform, "$(DEVICE):SPEC-Z"){
+ field (FTVL, "FLOAT")
+ field (DTYP, "FFT spsd")
+ field (NELM, "8192")
+ field (INP, "$(DEVICE):SIGN-Z MS")
+ field (FLNK, "$(DEVICE):SPEC-FREQ-qZ")
+ field (PREC, "3")
+}
+
+record(calcout, "$(DEVICE):OVERSAMPLE-2-qZVEC"){
+ field(DESC, "Sampling Rate")
+ field(CALC, "0.5 * A / (299792458 / 288 / 1000)")
+ field(INPA, "ARS02-DBPM-2910:DWC-STG1-RATE CP")
+ field(OUT, "$(DEVICE):SPEC-FREQ-qZ.HOPR PP")
+}
+
+record (waveform, "$(DEVICE):SPEC-FREQ-qZ"){
+ field (FTVL, "FLOAT")
+ field (DTYP, "sequence")
+ field (NELM, "8192")
+ field (LOPR, "0")
+ field (HOPR, "0.5")
+ field (PREC, "3")
+ field (PINI, "YES")
+}
+
+record(ao, "$(DEVICE):REF-QX") {
+ field(DESC, "PV for the hor. reference tune")
+ field(PREC, "3")
+ field(ASG, "READONLY")
+ field(VAL, "39.37")
+}
+
+record(ao, "$(DEVICE):QX") {
+ field(DESC, "PV for the measured hor. tune")
+ field(PREC, "3")
+ field(ASG, "PROTECTED")
+ field(FLNK, "$(DEVICE):QX-FREQ")
+ field(HIHI, "0.40")
+ field(HHSV, "MAJOR")
+ field(HIGH, "0.38")
+ field(HSV, "MINOR")
+ field(LOW, "0.36")
+ field(LSV, "MINOR")
+ field(LOLO, "0.34")
+ field(LLSV, "MAJOR")
+}
+
+record(calcout, "$(DEVICE):QX-FREQ") {
+ field(DESC, "Freq hor. tune")
+ field(EGU, "kHz")
+ field(PREC, "3")
+ field(ASG, "READONLY")
+ field(PINI, "YES")
+ field(VAL, "0")
+ field(CALC, "A * B / 480 / 1000")
+ field(INPA, "$(DEVICE):QX")
+ field(INPB, "AGERF-MO01:FREQ-GET")
+}
+
+record(ao, "$(DEVICE):QX-SB1") {
+ field(DESC, "PV for the measured hor. tune")
+ field(PREC, "3")
+ field(ASG, "PROTECTED")
+ field(FLNK, "$(DEVICE):QX-SB1-DIFF")
+}
+
+record(calcout, "$(DEVICE):QX-SB1-DIFF") {
+ field(DESC, "PV for the measured hor. tune")
+ field(PREC, "3")
+ field(ASG, "READONLY")
+ field(PINI, "YES")
+ field(VAL, "0")
+ field(CALC, "ABS(A - B)")
+ field(INPA, "$(DEVICE):QX")
+ field(INPB, "$(DEVICE):QX-SB1")
+}
+
+record(ao, "$(DEVICE):QX-SB2") {
+ field(DESC, "PV for the measured hor. tune")
+ field(PREC, "3")
+ field(ASG, "PROTECTED")
+ field(FLNK, "$(DEVICE):QX-SB2-DIFF")
+}
+
+record(calcout, "$(DEVICE):QX-SB2-DIFF") {
+ field(DESC, "PV for the measured hor. tune")
+ field(PREC, "3")
+ field(ASG, "READONLY")
+ field(PINI, "YES")
+ field(VAL, "0")
+ field(CALC, "ABS(A - B)")
+ field(INPA, "$(DEVICE):QX")
+ field(INPB, "$(DEVICE):QX-SB2")
+}
+
+record(ao, "$(DEVICE):QX-ULIM") {
+ field(DESC, "upper limit qx search range")
+ field(PREC, "3")
+ field(ASG, "PROTECTED")
+ field(VAL, "0.44")
+}
+record(ao, "$(DEVICE):QX-LLIM") {
+ field(DESC, "lower limit qx search range")
+ field(PREC, "3")
+ field(ASG, "PROTECTED")
+ field(VAL, "0.30")
+}
+
+record(waveform, "$(DEVICE):NORM-QX-AMP") {
+ field(DESC, "normalized, hor. spectrum")
+ field(NELM, "8192")
+ field(FTVL, "FLOAT")
+}
+
+record(waveform, "$(DEVICE):NORM-QX-FREQ") {
+ field(DESC, "normalized, hor. spectrum")
+ field(NELM, "8192")
+ field(FTVL, "FLOAT")
+}
+
+record(waveform, "$(DEVICE):QX-PEAKS-FREQ") {
+ field(DESC, "peaks in hor. spectrum")
+ field(NELM, "8192")
+ field(FTVL, "FLOAT")
+}
+
+record(waveform, "$(DEVICE):QX-PEAKS") {
+ field(DESC, "peaks in hor. spectrum")
+ field(NELM, "8192")
+ field(FTVL, "FLOAT")
+}
+
+record(ao, "$(DEVICE):REF-QY") {
+ field(DESC, "PV for the ver. reference tune")
+ field(PREC, "3")
+ field(ASG, "READONLY")
+ field(VAL, "15.22")
+}
+
+record(ao, "$(DEVICE):QY") {
+ field(DESC, "PV for the measured ver. tune")
+ field(PREC, "3")
+ field(ASG, "PROTECTED")
+ field(FLNK, "$(DEVICE):QY-FREQ")
+ field(HIHI, "0.25")
+ field(HHSV, "MAJOR")
+ field(HIGH, "0.23")
+ field(HSV, "MINOR")
+ field(LOW, "0.21")
+ field(LSV, "MINOR")
+ field(LOLO, "0.19")
+ field(LLSV, "MAJOR")
+}
+
+record(calcout, "$(DEVICE):QY-FREQ") {
+ field(DESC, "Freq ver. tune")
+ field(EGU, "kHz")
+ field(PREC, "3")
+ field(ASG, "READONLY")
+ field(PINI, "YES")
+ field(VAL, "0")
+ field(CALC, "A * B / 480 / 1000")
+ field(INPA, "$(DEVICE):QY")
+ field(INPB, "AGERF-MO01:FREQ-GET")
+}
+
+record(ao, "$(DEVICE):QY-SB1") {
+ field(DESC, "PV for the measured ver. tune")
+ field(PREC, "3")
+ field(ASG, "PROTECTED")
+ field(FLNK, "$(DEVICE):QY-SB1-DIFF")
+}
+
+record(calcout, "$(DEVICE):QY-SB1-DIFF") {
+ field(DESC, "PV for the measured ver. tune")
+ field(PREC, "3")
+ field(ASG, "READONLY")
+ field(PINI, "YES")
+ field(VAL, "0")
+ field(CALC, "ABS(A - B)")
+ field(INPA, "$(DEVICE):QY")
+ field(INPB, "$(DEVICE):QY-SB1")
+}
+
+record(ao, "$(DEVICE):QY-SB2") {
+ field(DESC, "PV for the measured ver. tune")
+ field(PREC, "3")
+ field(ASG, "PROTECTED")
+ field(FLNK, "$(DEVICE):QY-SB2-DIFF")
+}
+
+record(calcout, "$(DEVICE):QY-SB2-DIFF") {
+ field(DESC, "PV for the measured ver. tune")
+ field(PREC, "3")
+ field(ASG, "READONLY")
+ field(PINI, "YES")
+ field(VAL, "0")
+ field(CALC, "ABS(A - B)")
+ field(INPA, "$(DEVICE):QY")
+ field(INPB, "$(DEVICE):QY-SB2")
+}
+
+record(ao, "$(DEVICE):QY-ULIM") {
+ field(DESC, "upper limit qy search range")
+ field(PREC, "3")
+ field(ASG, "PROTECTED")
+ field(VAL, "0.29")
+}
+record(ao, "$(DEVICE):QY-LLIM") {
+ field(DESC, "lower limit qy search range")
+ field(PREC, "3")
+ field(ASG, "PROTECTED")
+ field(VAL, "0.15")
+}
+
+record(waveform, "$(DEVICE):NORM-QY-AMP") {
+ field(DESC, "normalized, ver. spectrum")
+ field(NELM, "8192")
+ field(FTVL, "FLOAT")
+}
+
+record(waveform, "$(DEVICE):NORM-QY-FREQ") {
+ field(DESC, "normalized, ver. spectrum")
+ field(NELM, "8192")
+ field(FTVL, "FLOAT")
+}
+
+record(waveform, "$(DEVICE):QY-PEAKS-FREQ") {
+ field(DESC, "peaks in ver. spectrum")
+ field(NELM, "8192")
+ field(FTVL, "FLOAT")
+}
+
+record(waveform, "$(DEVICE):QY-PEAKS") {
+ field(DESC, "peaks in ver. spectrum")
+ field(NELM, "8192")
+ field(FTVL, "FLOAT")
+}
+
+record(ao, "$(DEVICE):REF-QZ") {
+ field(DESC, "PV for the long. reference tune, no 3HC")
+ field(PREC, "3")
+ field(ASG, "READONLY")
+ field(VAL, "0.0027")
+}
+
+record(ao, "$(DEVICE):QZ") {
+ field(DESC, "PV for the measured long. tune")
+ field(PREC, "3")
+ field(ASG, "PROTECTED")
+ field(FLNK, "$(DEVICE):QZ-FREQ")
+ field(HIHI, "0.004")
+ field(HHSV, "MAJOR")
+ field(HIGH, "0.003")
+ field(HSV, "MINOR")
+ field(LOW, "0.001")
+ field(LSV, "MINOR")
+ field(LOLO, "0.0005")
+ field(LLSV, "MAJOR")
+}
+
+record(calcout, "$(DEVICE):QZ-FREQ") {
+ field(DESC, "Freq ver. tune")
+ field(EGU, "kHz")
+ field(PREC, "3")
+ field(ASG, "READONLY")
+ field(PINI, "YES")
+ field(VAL, "0")
+ field(CALC, "A * B / 480 / 1000")
+ field(INPA, "$(DEVICE):QZ")
+ field(INPB, "AGERF-MO01:FREQ-GET")
+}
+
+record(ao, "$(DEVICE):QZ-ULIM") {
+ field(DESC, "upper limit qz search range")
+ field(PREC, "3")
+ field(ASG, "PROTECTED")
+ field(VAL, "0.0025")
+}
+record(ao, "$(DEVICE):QZ-LLIM") {
+ field(DESC, "lower limit qz search range")
+ field(PREC, "3")
+ field(ASG, "PROTECTED")
+ field(VAL, "0.0005")
+}
+
+record(waveform, "$(DEVICE):NORM-QZ-AMP") {
+ field(DESC, "normalized, long. spectrum")
+ field(NELM, "8192")
+ field(FTVL, "FLOAT")
+}
+
+record(waveform, "$(DEVICE):NORM-QZ-FREQ") {
+ field(DESC, "normalized, long. spectrum")
+ field(NELM, "8192")
+ field(FTVL, "FLOAT")
+}
+
+record(waveform, "$(DEVICE):QZ-PEAKS-FREQ") {
+ field(DESC, "peaks in long. spectrum")
+ field(NELM, "8192")
+ field(FTVL, "FLOAT")
+}
+
+record(waveform, "$(DEVICE):QZ-PEAKS") {
+ field(DESC, "peaks in long. spectrum")
+ field(NELM, "8192")
+ field(FTVL, "FLOAT")
+}
+
+record(bo, "$(DEVICE):MEAS-VALID") {
+ field(DESC, "reflects validity of tune measurement")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
\ No newline at end of file
diff --git a/services/tunebump/current/ioc/startup.script b/services/tunebump/current/ioc/startup.script
new file mode 100644
index 0000000..5c6f31b
--- /dev/null
+++ b/services/tunebump/current/ioc/startup.script
@@ -0,0 +1,4 @@
+epicsEnvSet("ENGINEER", "armborst")
+require fft
+require array
+require SynApps
diff --git a/services/tunebump/current/qt/A_BD_TuneBump.ui b/services/tunebump/current/qt/A_BD_TuneBump.ui
new file mode 100644
index 0000000..22fe977
--- /dev/null
+++ b/services/tunebump/current/qt/A_BD_TuneBump.ui
@@ -0,0 +1,6779 @@
+
+
+ MainWindow
+
+
+
+ 0
+ 0
+ 605
+ 960
+
+
+
+ MainWindow
+
+
+ /*################################################*/
+/*# Settings for new templates/forms #*/
+/*################################################*/
+QMainWindow#MainWindow, QWidget#Form, QDialog#Dialog{
+ background: rgba(236, 236, 236, 255);
+}
+
+QMainWindow#MainWindow[transparent=true], QWidget#Form[transparent=true], QDialog#Dialog[transparent=true]{
+ background: rgba(0, 0, 0, 0);
+}
+
+/*-----------------------------------------------*/
+/* Title */
+/*-----------------------------------------------*/
+/* Operation panels */
+caLabel[statusTip="Operation"]{
+ color: rgba(0, 0, 0, 255);
+ font: bold 18pt;
+ font-family: Sans Serif;
+ padding: 1px;
+ margin: 0px;
+ qproperty-alignment: AlignLeft;
+ qproperty-frameShape: StyledPanel;
+ /*qproperty-geometry: rect(-2 0 1600 33);*/
+ background: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1,
+ stop:0 rgba(218, 218, 218, 255),
+ stop:0.5 rgba(200, 200, 200, 255),
+ stop:1 rgba(218, 218, 218, 255));
+}
+
+ QGroupBox {
+ background: rgba(225,225,225,255);
+ border: 2px solid black;
+ border-radius: 5px;
+ margin-top: 1ex; /* leave space at the top for the title */
+ }
+
+
+
+
+
+ 810
+ 120
+ 70
+ 20
+
+
+
+
+
+
+ 810
+ 60
+ 70
+ 20
+
+
+
+ Reload
+
+
+ RELOAD
+
+
+ A
+
+
+ AGEBD-ALH:TUNEBUMP-GUIRELOAD
+
+
+ caCalc::TriggerZeroToOne
+
+
+
+
+
+ 340
+ 60
+ 40
+ 30
+
+
+
+ <<
+
+
+ false
+
+
+ AGEBD-TUNEBUMP:QX-STEPDOWN
+
+
+ <<
+
+
+
+ 160
+ 160
+ 160
+
+
+
+
+
+
+ 1
+
+
+ caMessageButton::as_is
+
+
+
+
+
+ 390
+ 60
+ 150
+ 30
+
+
+
+ 1
+
+
+ 4
+
+
+ AGEBD-TUNEBUMP:QX-STEPSIZE
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caSpinbox::as_is
+
+
+
+
+
+ 390
+ 160
+ 150
+ 30
+
+
+
+ 1
+
+
+ 4
+
+
+ AGEBD-TUNEBUMP:QY-STEPSIZE
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caSpinbox::as_is
+
+
+
+
+
+ 390
+ 35
+ 150
+ 20
+
+
+
+
+ 12
+ 75
+ true
+
+
+
+ Step Size
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 340
+ 160
+ 40
+ 30
+
+
+
+ <<
+
+
+ false
+
+
+ AGEBD-TUNEBUMP:QY-STEPDOWN
+
+
+ <<
+
+
+
+ 160
+ 160
+ 160
+
+
+
+
+
+
+ 1
+
+
+ caMessageButton::as_is
+
+
+
+
+
+ 10
+ 60
+ 50
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ Qx
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 42
+ 99
+ 228
+
+
+
+
+
+
+ 10
+ 160
+ 50
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ Qy
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 139
+ 26
+ 150
+
+
+
+
+
+
+ 550
+ 160
+ 40
+ 30
+
+
+
+ >>
+
+
+ false
+
+
+ AGEBD-TUNEBUMP:QY-STEPUP
+
+
+ >>
+
+
+
+ 160
+ 160
+ 160
+
+
+
+
+
+
+ 1
+
+
+ caMessageButton::as_is
+
+
+
+
+
+ 547
+ 60
+ 40
+ 30
+
+
+
+ >>
+
+
+ false
+
+
+ AGEBD-TUNEBUMP:QX-STEPUP
+
+
+ >>
+
+
+
+ 160
+ 160
+ 160
+
+
+
+
+
+
+ 1
+
+
+ caMessageButton::as_is
+
+
+
+
+
+ 0
+ 0
+ 600
+ 32
+
+
+
+
+ Sans Serif
+ 18
+ 75
+ false
+ true
+
+
+
+ Operation
+
+
+ Tune Shift
+
+
+ Qt::AlignLeading
+
+
+
+ 218
+ 218
+ 218
+
+
+
+ caLabel::Default
+
+
+
+
+
+ 0
+ 300
+ 605
+ 660
+
+
+
+ 0
+
+
+
+ Meas
+
+
+
+
+ 5
+ 210
+ 590
+ 200
+
+
+
+ Vertical Tune (nominal: Qy = 15.22)
+
+
+ AGEBD-TUNEBUMP:NORM-QY-FREQ;AGEBD-TUNEBUMP:NORM-QY-AMP
+
+
+
+ 139
+ 26
+ 150
+
+
+
+ AGEBD-TUNEBUMP:QY-PEAKS-FREQ;AGEBD-TUNEBUMP:QY-PEAKS
+
+
+ caCartesianPlot::Sticks
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+ 139
+ 26
+ 150
+
+
+
+ caCartesianPlot::User
+
+
+ caCartesianPlot::Auto
+
+
+ 0.15;0.29
+
+
+ false
+
+
+ 14
+
+
+ caCartesianPlot::linear
+
+
+
+
+
+ 5
+ 415
+ 590
+ 200
+
+
+
+ Synchrotron Tune (nominal: 0.0027)
+
+
+ AGEBD-TUNEBUMP:NORM-QZ-FREQ;AGEBD-TUNEBUMP:NORM-QZ-AMP
+
+
+
+ 205
+ 97
+ 0
+
+
+
+ AGEBD-TUNEBUMP:QZ-PEAKS-FREQ;AGEBD-TUNEBUMP:QZ-PEAKS
+
+
+ caCartesianPlot::Sticks
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+ 205
+ 97
+ 0
+
+
+
+ caCartesianPlot::Auto
+
+
+ caCartesianPlot::Auto
+
+
+ 0.0005;0.0025
+
+
+ false
+
+
+ 10
+
+
+ caCartesianPlot::linear
+
+
+
+
+
+ 5
+ 5
+ 590
+ 200
+
+
+
+ Horizontal Tune (nominal: Qx = 39.37)
+
+
+ AGEBD-TUNEBUMP:NORM-QX-FREQ;AGEBD-TUNEBUMP:NORM-QX-AMP
+
+
+
+ 42
+ 99
+ 228
+
+
+
+ AGEBD-TUNEBUMP:QX-PEAKS-FREQ;AGEBD-TUNEBUMP:QX-PEAKS
+
+
+ caCartesianPlot::Sticks
+
+
+ caCartesianPlot::NoSymbol
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+ 42
+ 99
+ 228
+
+
+
+ caCartesianPlot::Auto
+
+
+ caCartesianPlot::Auto
+
+
+ 0.3;0.44
+
+
+
+
+
+ false
+
+
+ false
+
+
+ 14
+
+
+ caCartesianPlot::linear
+
+
+
+
+
+ FFT
+
+
+
+
+ 0
+ 415
+ 590
+ 200
+
+
+
+ Tune Z
+
+
+ AGEBD-TUNEBUMP:SPEC-FREQ-qZ;AGEBD-TUNEBUMP:SPEC-Z
+
+
+
+ 205
+ 97
+ 0
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+ caCartesianPlot::User
+
+
+ caCartesianPlot::Auto
+
+
+ 0.0005;0.0025
+
+
+ 10
+
+
+ caCartesianPlot::log10
+
+
+
+
+
+ 0
+ 210
+ 590
+ 200
+
+
+
+ Tune Y
+
+
+ AGEBD-TUNEBUMP:SPEC-FREQ-qY;AGEBD-TUNEBUMP:SPEC-Y
+
+
+
+ 139
+ 26
+ 150
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+ caCartesianPlot::User
+
+
+ caCartesianPlot::Auto
+
+
+ 0.15;0.29
+
+
+ 14
+
+
+ caCartesianPlot::log10
+
+
+
+
+
+ 0
+ 5
+ 590
+ 200
+
+
+
+ Tune X
+
+
+ AGEBD-TUNEBUMP:SPEC-FREQ-qX;AGEBD-TUNEBUMP:SPEC-X
+
+
+
+ 42
+ 99
+ 228
+
+
+
+
+
+
+ caCartesianPlot::Sticks
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+ caCartesianPlot::User
+
+
+ caCartesianPlot::Auto
+
+
+ 0.3;0.44
+
+
+ 0:1
+
+
+ 14
+
+
+ caCartesianPlot::log10
+
+
+
+
+
+ Raw
+
+
+
+
+ 0
+ 210
+ 590
+ 200
+
+
+
+ Vertical TbT data
+
+
+ ;AGEBD-TUNEBUMP:SIGN-Y
+
+
+
+ 139
+ 26
+ 150
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+ caCartesianPlot::User
+
+
+ caCartesianPlot::Auto
+
+
+ 0;16384
+
+
+
+
+
+ 14
+
+
+ caCartesianPlot::linear
+
+
+
+
+
+ 0
+ 415
+ 590
+ 200
+
+
+
+ Longitudinal Stage 1 Data
+
+
+ ;AGEBD-TUNEBUMP:SIGN-Z
+
+
+
+ 205
+ 97
+ 0
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+ caCartesianPlot::User
+
+
+ caCartesianPlot::Auto
+
+
+ 0;16384
+
+
+
+
+
+ 10
+
+
+ caCartesianPlot::linear
+
+
+
+
+
+ 0
+ 5
+ 590
+ 200
+
+
+
+ Horizontal TbT data
+
+
+ ;AGEBD-TUNEBUMP:SIGN-X
+
+
+
+ 42
+ 99
+ 228
+
+
+
+
+
+
+ caCartesianPlot::Sticks
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+ caCartesianPlot::User
+
+
+ caCartesianPlot::Auto
+
+
+ 0;16384
+
+
+
+
+
+ 14
+
+
+ caCartesianPlot::linear
+
+
+
+
+
+ Settings
+
+
+
+
+ 10
+ 260
+ 371
+ 51
+
+
+
+
+ 19
+ 75
+ true
+
+
+
+ Pinger Settings (ca. 10 A)
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 440
+ 320
+ 150
+ 40
+
+
+
+ 3
+
+
+ 2
+
+
+ ARS01-MKIK-0320:I-SET
+
+
+ caSpinbox::User
+
+
+ caSpinbox::User
+
+
+ 300.000000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 140
+ 320
+ 150
+ 40
+
+
+
+ 3
+
+
+ 2
+
+
+ ARS01-MKIK-0290:I-SET
+
+
+ caSpinbox::User
+
+
+ caSpinbox::User
+
+
+ 300.000000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 160
+ 490
+ 291
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ Enable Energy Stabelization:
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 10
+ 450
+ 581
+ 30
+
+
+
+
+ 12
+ 75
+ true
+
+
+
+ Defined by FOFB Mean Horizontal Corrector Integral Setpoint:
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+
+
+ 250
+ 530
+ 110
+ 30
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ ARSGE-CECL-FOFB1:MCOX-INTEGRAL-ERR
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Alarm_Static
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 30
+ 490
+ 110
+ 30
+
+
+
+ 1
+
+
+ 4
+
+
+ ARSGE-CECL-FOFB1:MCOX-INTEGRAL-REF-DEFAULT
+
+
+ caSpinbox::User
+
+
+ caSpinbox::User
+
+
+ 1.000000000000000
+
+
+ -1.000000000000000
+
+
+
+
+
+ 10
+ 10
+ 400
+ 40
+
+
+
+
+ 24
+ 75
+ true
+
+
+
+ Qx Search Range
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 42
+ 99
+ 228
+
+
+
+
+
+
+ 10
+ 130
+ 400
+ 40
+
+
+
+
+ 25
+ 75
+ true
+
+
+
+ Qy Search Range
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 139
+ 26
+ 150
+
+
+
+
+
+
+ 10
+ 60
+ 121
+ 40
+
+
+
+
+ 16
+ 50
+ false
+
+
+
+ Lower limit
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 310
+ 60
+ 121
+ 40
+
+
+
+
+ 16
+ 50
+ false
+
+
+
+ Upper limit
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 440
+ 60
+ 150
+ 40
+
+
+
+ 1
+
+
+ 2
+
+
+ AGEBD-TUNEBUMP:QX-ULIM
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 140
+ 60
+ 150
+ 40
+
+
+
+ 1
+
+
+ 2
+
+
+ AGEBD-TUNEBUMP:QX-LLIM
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 440
+ 180
+ 150
+ 40
+
+
+
+ 1
+
+
+ 2
+
+
+ AGEBD-TUNEBUMP:QY-ULIM
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 310
+ 180
+ 121
+ 40
+
+
+
+
+ 16
+ 50
+ false
+
+
+
+ Upper limit
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 140
+ 180
+ 150
+ 40
+
+
+
+ 1
+
+
+ 2
+
+
+ AGEBD-TUNEBUMP:QY-LLIM
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 10
+ 180
+ 121
+ 40
+
+
+
+
+ 16
+ 50
+ false
+
+
+
+ Lower limit
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 10
+ 320
+ 121
+ 40
+
+
+
+
+ 17
+ 50
+ false
+
+
+
+ Horizontal
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 310
+ 320
+ 121
+ 40
+
+
+
+
+ 24
+ 50
+ false
+
+
+
+ Vertical
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 10
+ 390
+ 371
+ 51
+
+
+
+
+ 22
+ 75
+ true
+
+
+
+ Beam Energy Setpoint
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+
+
+ 450
+ 490
+ 31
+ 30
+
+
+
+ ARSGE-CECL-FOFB1:MCOX-INTEGRAL-REF-DEFAULT-EN
+
+
+
+
+
+ 160
+ 530
+ 91
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ ERROR:
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ BPMs
+
+
+
+
+ 10
+ 20
+ 400
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ Horizontal Tune BPM
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 42
+ 99
+ 228
+
+
+
+
+
+
+ 10
+ 140
+ 400
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ Vertical Tune BPM
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 139
+ 26
+ 150
+
+
+
+
+
+
+ 10
+ 270
+ 400
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ Longitudinal Tune BPM
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 205
+ 97
+ 0
+
+
+
+
+
+
+ 10
+ 180
+ 580
+ 30
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEBUMP:SIGN-Y.INP
+
+
+
+ 139
+ 26
+ 150
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 10
+ 60
+ 580
+ 30
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEBUMP:SIGN-X.INP
+
+
+
+ 42
+ 99
+ 228
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 10
+ 310
+ 580
+ 30
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEBUMP:SIGN-Z.INP
+
+
+
+ 205
+ 97
+ 0
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+
+
+
+
+
+
+ FeedBack QX
+
+
+
+
+ 400
+ 210
+ 150
+ 40
+
+
+
+ 1
+
+
+ 3
+
+
+ AGEBD-TUNEFBX:CONTROL-KP
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 10
+ 10
+ 400
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ Horizontal Tune Feedback
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 42
+ 99
+ 228
+
+
+
+
+
+
+ 310
+ 210
+ 80
+ 40
+
+
+
+
+ 25
+ 50
+ false
+
+
+
+ <html><head/><body><p>K<span style=" vertical-align:sub;">P</span></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 310
+ 260
+ 80
+ 40
+
+
+
+
+ 25
+ 50
+ false
+
+
+
+ <html><head/><body><p>K<span style=" vertical-align:sub;">I</span></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 310
+ 310
+ 80
+ 40
+
+
+
+
+ 25
+ 50
+ false
+
+
+
+ <html><head/><body><p>K<span style=" vertical-align:sub;">D</span></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 400
+ 260
+ 150
+ 40
+
+
+
+ 1
+
+
+ 3
+
+
+ AGEBD-TUNEFBX:CONTROL-KI
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 400
+ 310
+ 150
+ 40
+
+
+
+ 1
+
+
+ 3
+
+
+ AGEBD-TUNEFBX:CONTROL-KD
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 120
+ 60
+ 171
+ 40
+
+
+
+ 1
+
+
+ 2
+
+
+ AGEBD-TUNEFBX:CONTROL-QX
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 20
+ 60
+ 80
+ 40
+
+
+
+
+ 23
+ 50
+ false
+
+
+
+ <html><head/><body><p>Q<span style=" vertical-align:sub;">X,set</span></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 120
+ 110
+ 171
+ 40
+
+
+
+ 1
+
+
+ 2
+
+
+ AGEBD-TUNEFBX:CONTROL-QXMAX
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 20
+ 110
+ 80
+ 40
+
+
+
+
+ 17
+ 50
+ false
+
+
+
+ <html><head/><body><p>Q<span style=" vertical-align:sub;">X,DRVH</span></p><p><br/></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 120
+ 160
+ 171
+ 40
+
+
+
+ 1
+
+
+ 2
+
+
+ AGEBD-TUNEFBX:CONTROL-QXMIN
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 20
+ 160
+ 80
+ 40
+
+
+
+
+ 17
+ 50
+ false
+
+
+
+ <html><head/><body><p>Q<span style=" vertical-align:sub;">X,DRVL</span></p><p><br/></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 20
+ 260
+ 80
+ 40
+
+
+
+
+ 25
+ 50
+ false
+
+
+
+ <html><head/><body><p>I<span style=" vertical-align:sub;">min</span></p><p><br/></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 120
+ 260
+ 171
+ 40
+
+
+
+ 3
+
+
+ 1
+
+
+ AGEBD-TUNEFBX:CONTROL-MIN-CURR
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 20
+ 210
+ 80
+ 40
+
+
+
+
+ 16
+ 50
+ false
+
+
+
+ <html><head/><body><p>Q<span style=" vertical-align:sub;">OKrange</span></p><p><br/></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 120
+ 210
+ 171
+ 40
+
+
+
+ 1
+
+
+ 4
+
+
+ true
+
+
+ AGEBD-TUNEFBX:CONTROL-QX-OKRNG
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 400
+ 60
+ 150
+ 40
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEFBX:DELTAQ
+
+
+
+ 139
+ 26
+ 150
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 310
+ 60
+ 80
+ 40
+
+
+
+
+ 25
+ 50
+ false
+
+
+
+ <html><head/><body><p>ΔQ</p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 20
+ 380
+ 571
+ 240
+
+
+
+
+ 10
+ 75
+ true
+
+
+
+ Accumulated Tune Steps
+
+
+
+
+
+
+
+
+ AGEBD-TUNEFBX:QSTEPS
+
+
+ caStripPlot::Second
+
+
+ 600.000000000000000
+
+
+ caStripPlot::High
+
+
+ caStripPlot::linear
+
+
+ caStripPlot::autoScale
+
+
+ 0.000000000000000
+
+
+ 0.000000001000000
+
+
+ caStripPlot::Channel
+
+
+ caStripPlot::Channel
+
+
+
+ 42
+ 99
+ 228
+
+
+
+ 0.000000410000000
+
+
+ 0.000000001000000
+
+
+ caStripPlot::User
+
+
+ caStripPlot::User
+
+
+
+ 252
+ 192
+ 11
+
+
+
+ 0.000000410000000
+
+
+ 0.000000001000000
+
+
+ caStripPlot::User
+
+
+ caStripPlot::User
+
+
+
+ 252
+ 192
+ 11
+
+
+
+ 0.000000410000000
+
+
+ 0.000000001000000
+
+
+ caStripPlot::User
+
+
+ caStripPlot::User
+
+
+
+ 239
+ 41
+ 41
+
+
+
+ 0.000000410000000
+
+
+ 0.000000001000000
+
+
+ caStripPlot::User
+
+
+ caStripPlot::User
+
+
+
+ 239
+ 41
+ 41
+
+
+
+ 0.000000410000000
+
+
+ 0.000000001000000
+
+
+ caStripPlot::User
+
+
+ caStripPlot::User
+
+
+
+ 255
+ 0
+ 255
+
+
+
+ 0.000000100000000
+
+
+ 0.000000001000000
+
+
+
+ 218
+ 218
+ 218
+
+
+
+ true
+
+
+ false
+
+
+
+
+
+ 390
+ 10
+ 160
+ 30
+
+
+
+ AGEBD-ALH:TUNEFBX-ONOFF
+
+
+ caChoice::Column
+
+
+ 1
+
+
+
+
+
+ 120
+ 350
+ 30
+ 30
+
+
+
+ AGEBD-TUNEFBX:CHECK1
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 170
+ 350
+ 30
+ 30
+
+
+
+ AGEBD-TUNEFBX:CHECK2
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 400
+ 350
+ 20
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ +
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 320
+ 350
+ 30
+ 30
+
+
+
+ AGEBD-TUNEFBX:CHECK5
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 470
+ 350
+ 30
+ 30
+
+
+
+ AGEBD-TUNEFBX:CHECK8
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 350
+ 350
+ 20
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ +
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 220
+ 350
+ 30
+ 30
+
+
+
+ AGEBD-TUNEFBX:CHECK3
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 250
+ 350
+ 20
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ +
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 370
+ 350
+ 30
+ 30
+
+
+
+ AGEBD-TUNEFBX:CHECK6
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 270
+ 350
+ 30
+ 30
+
+
+
+ AGEBD-TUNEFBX:CHECK4
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 450
+ 350
+ 20
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ +
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 420
+ 350
+ 30
+ 30
+
+
+
+ AGEBD-TUNEFBX:CHECK7
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 300
+ 350
+ 20
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ +
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 500
+ 350
+ 20
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ =
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 520
+ 350
+ 30
+ 30
+
+
+
+ true
+
+
+ true
+
+
+ AGEBD-TUNEFBX:CHECKALL
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 200
+ 350
+ 20
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ +
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 150
+ 350
+ 20
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ +
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 310
+ 110
+ 80
+ 40
+
+
+
+
+ 20
+ 50
+ false
+
+
+
+ <html><head/><body><p>ΔQ<span style=" vertical-align:sub;">max</span></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 310
+ 160
+ 80
+ 40
+
+
+
+
+ 21
+ 50
+ false
+
+
+
+ <html><head/><body><p>ΔQ<span style=" vertical-align:sub;">min</span></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 400
+ 110
+ 150
+ 40
+
+
+
+ 1
+
+
+ 3
+
+
+ AGEBD-TUNEFBX:DELTAQ-ULIM
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 400
+ 160
+ 150
+ 40
+
+
+
+ 1
+
+
+ 3
+
+
+ AGEBD-TUNEFBX:DELTAQ-LLIM
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 40
+ 355
+ 80
+ 20
+
+
+
+
+ 11
+ 50
+ false
+
+
+
+ <html><head/><body><p>Conditions<br/></p></body></html>
+
+
+ Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ Feedback QY
+
+
+
+
+ 10
+ 10
+ 400
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ Vertical Tune Feedback
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 139
+ 26
+ 150
+
+
+
+
+
+
+ 120
+ 60
+ 171
+ 40
+
+
+
+ 1
+
+
+ 2
+
+
+ AGEBD-TUNEFBY:CONTROL-QY
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 310
+ 210
+ 80
+ 40
+
+
+
+
+ 25
+ 50
+ false
+
+
+
+ <html><head/><body><p>K<span style=" vertical-align:sub;">P</span></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 120
+ 210
+ 171
+ 40
+
+
+
+ 1
+
+
+ 4
+
+
+ true
+
+
+ AGEBD-TUNEFBY:CONTROL-QY-OKRNG
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 200
+ 350
+ 20
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ +
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 400
+ 260
+ 150
+ 40
+
+
+
+ 1
+
+
+ 3
+
+
+ AGEBD-TUNEFBY:CONTROL-KI
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 310
+ 60
+ 80
+ 40
+
+
+
+
+ 25
+ 50
+ false
+
+
+
+ <html><head/><body><p>ΔQ</p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 310
+ 310
+ 80
+ 40
+
+
+
+
+ 25
+ 50
+ false
+
+
+
+ <html><head/><body><p>K<span style=" vertical-align:sub;">D</span></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 270
+ 350
+ 30
+ 30
+
+
+
+ AGEBD-TUNEFBY:CHECK4
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 400
+ 210
+ 150
+ 40
+
+
+
+ 1
+
+
+ 3
+
+
+ AGEBD-TUNEFBY:CONTROL-KP
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 120
+ 110
+ 171
+ 40
+
+
+
+ 1
+
+
+ 2
+
+
+ AGEBD-TUNEFBY:CONTROL-QYMAX
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 250
+ 350
+ 20
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ +
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 300
+ 350
+ 20
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ +
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 20
+ 160
+ 80
+ 40
+
+
+
+
+ 18
+ 50
+ false
+
+
+
+ <html><head/><body><p>Q<span style=" vertical-align:sub;">Y,DRVL</span></p><p><br/></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 400
+ 310
+ 150
+ 40
+
+
+
+ 1
+
+
+ 3
+
+
+ AGEBD-TUNEFBY:CONTROL-KD
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 220
+ 350
+ 30
+ 30
+
+
+
+ AGEBD-TUNEFBY:CHECK3
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 350
+ 350
+ 20
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ +
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 150
+ 350
+ 20
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ +
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 20
+ 60
+ 80
+ 40
+
+
+
+
+ 24
+ 50
+ false
+
+
+
+ <html><head/><body><p>Q<span style=" vertical-align:sub;">Y,set</span></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 20
+ 210
+ 80
+ 40
+
+
+
+
+ 16
+ 50
+ false
+
+
+
+ <html><head/><body><p>Q<span style=" vertical-align:sub;">OKrange</span></p><p><br/></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 400
+ 60
+ 150
+ 40
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEFBY:DELTAQ
+
+
+
+ 139
+ 26
+ 150
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 500
+ 350
+ 20
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ =
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 520
+ 350
+ 33
+ 30
+
+
+
+ true
+
+
+ 18
+
+
+ 18
+
+
+ true
+
+
+ AGEBD-TUNEFBY:CHECKALL
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 320
+ 350
+ 30
+ 30
+
+
+
+ AGEBD-TUNEFBY:CHECK5
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 170
+ 350
+ 30
+ 30
+
+
+
+ AGEBD-TUNEFBY:CHECK2
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 310
+ 260
+ 80
+ 40
+
+
+
+
+ 25
+ 50
+ false
+
+
+
+ <html><head/><body><p>K<span style=" vertical-align:sub;">I</span></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 120
+ 160
+ 171
+ 40
+
+
+
+ 1
+
+
+ 2
+
+
+ AGEBD-TUNEFBY:CONTROL-QYMIN
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 120
+ 350
+ 30
+ 30
+
+
+
+ AGEBD-TUNEFBY:CHECK1
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 40
+ 355
+ 80
+ 20
+
+
+
+
+ 11
+ 50
+ false
+
+
+
+ <html><head/><body><p>Conditions<br/></p></body></html>
+
+
+ Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 390
+ 10
+ 160
+ 30
+
+
+
+ AGEBD-ALH:TUNEFBY-ONOFF
+
+
+ caChoice::Column
+
+
+ 1
+
+
+
+
+
+ 370
+ 350
+ 30
+ 30
+
+
+
+ AGEBD-TUNEFBY:CHECK6
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 20
+ 380
+ 571
+ 240
+
+
+
+
+ 10
+ 75
+ true
+
+
+
+ Accumulated Tune Steps
+
+
+
+
+
+
+
+
+ AGEBD-TUNEFBY:QSTEPS
+
+
+ caStripPlot::Second
+
+
+ 600.000000000000000
+
+
+ caStripPlot::High
+
+
+ caStripPlot::linear
+
+
+ caStripPlot::autoScale
+
+
+ 0.000000000000000
+
+
+ 0.000000001000000
+
+
+ caStripPlot::Channel
+
+
+ caStripPlot::Channel
+
+
+
+ 42
+ 99
+ 228
+
+
+
+ 0.000000410000000
+
+
+ 0.000000001000000
+
+
+ caStripPlot::User
+
+
+ caStripPlot::User
+
+
+
+ 252
+ 192
+ 11
+
+
+
+ 0.000000410000000
+
+
+ 0.000000001000000
+
+
+ caStripPlot::User
+
+
+ caStripPlot::User
+
+
+
+ 252
+ 192
+ 11
+
+
+
+ 0.000000410000000
+
+
+ 0.000000001000000
+
+
+ caStripPlot::User
+
+
+ caStripPlot::User
+
+
+
+ 239
+ 41
+ 41
+
+
+
+ 0.000000410000000
+
+
+ 0.000000001000000
+
+
+ caStripPlot::User
+
+
+ caStripPlot::User
+
+
+
+ 239
+ 41
+ 41
+
+
+
+ 0.000000410000000
+
+
+ 0.000000001000000
+
+
+ caStripPlot::User
+
+
+ caStripPlot::User
+
+
+
+ 255
+ 0
+ 255
+
+
+
+ 0.000000100000000
+
+
+ 0.000000001000000
+
+
+
+ 218
+ 218
+ 218
+
+
+
+ true
+
+
+ false
+
+
+
+
+
+ 20
+ 260
+ 80
+ 40
+
+
+
+
+ 25
+ 50
+ false
+
+
+
+ <html><head/><body><p>I<span style=" vertical-align:sub;">min</span></p><p><br/></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 20
+ 110
+ 80
+ 40
+
+
+
+
+ 17
+ 50
+ false
+
+
+
+ <html><head/><body><p>Q<span style=" vertical-align:sub;">Y,DRVH</span></p><p><br/></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 120
+ 260
+ 171
+ 40
+
+
+
+ 3
+
+
+ 1
+
+
+ AGEBD-TUNEFBY:CONTROL-MIN-CURR
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 400
+ 350
+ 20
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ +
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 420
+ 350
+ 30
+ 30
+
+
+
+ AGEBD-TUNEFBY:CHECK7
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 470
+ 350
+ 30
+ 30
+
+
+
+ AGEBD-TUNEFBY:CHECK8
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 450
+ 350
+ 20
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ +
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 310
+ 160
+ 80
+ 40
+
+
+
+
+ 21
+ 50
+ false
+
+
+
+ <html><head/><body><p>ΔQ<span style=" vertical-align:sub;">min</span></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 400
+ 110
+ 150
+ 40
+
+
+
+ 1
+
+
+ 3
+
+
+ AGEBD-TUNEFBY:DELTAQ-ULIM
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 400
+ 160
+ 150
+ 40
+
+
+
+ 1
+
+
+ 3
+
+
+ AGEBD-TUNEFBY:DELTAQ-LLIM
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 310
+ 110
+ 80
+ 40
+
+
+
+
+ 20
+ 50
+ false
+
+
+
+ <html><head/><body><p>ΔQ<span style=" vertical-align:sub;">max</span></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ Debug
+
+
+
+
+ 250
+ 20
+ 31
+ 30
+
+
+
+ AGEBD-TUNEBUMP:WRITE2MAG
+
+
+
+
+
+ 10
+ 20
+ 231
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ Apply MQCO Setpoints
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 4
+ 50
+ 595
+ 575
+
+
+
+
+ Monospace
+ 10
+ PreferDefault
+
+
+
+ Qt::ScrollBarAlwaysOn
+
+
+ Qt::ScrollBarAsNeeded
+
+
+ AGEBD-TUNEBUMP:CHANGELOG
+
+
+ caMultiLineString::None
+
+
+
+
+
+
+
+ 60
+ 60
+ 100
+ 30
+
+
+
+
+ Lucida Sans Typewriter
+ 16
+
+
+
+ true
+
+
+
+
+
+
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEBUMP:QX
+
+
+
+ 42
+ 99
+ 228
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caLineEdit::Static
+
+
+ true
+
+
+
+ 42
+ 99
+ 228
+
+
+
+ 1
+
+
+ caLineEdit::onBackground
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::None
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 60
+ 160
+ 100
+ 30
+
+
+
+
+ Lucida Sans Typewriter
+ 16
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEBUMP:QY
+
+
+
+ 139
+ 26
+ 150
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caLineEdit::Static
+
+
+ true
+
+
+
+ 139
+ 26
+ 150
+
+
+
+ 1
+
+
+ caLineEdit::onBackground
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::None
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 110
+ 100
+ 121
+ 20
+
+
+
+
+ 12
+ 75
+ true
+
+
+
+ Sideband 1
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 250
+ 100
+ 110
+ 20
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEBUMP:QX-SB1
+
+
+
+ 42
+ 99
+ 228
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 480
+ 100
+ 110
+ 20
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEBUMP:QX-SB1-DIFF
+
+
+
+ 42
+ 99
+ 228
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 110
+ 130
+ 121
+ 20
+
+
+
+
+ 12
+ 75
+ true
+
+
+
+ Sideband 2
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 250
+ 130
+ 110
+ 20
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEBUMP:QX-SB2
+
+
+
+ 42
+ 99
+ 228
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 480
+ 130
+ 110
+ 20
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEBUMP:QX-SB2-DIFF
+
+
+
+ 42
+ 99
+ 228
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 380
+ 100
+ 91
+ 20
+
+
+
+
+ 12
+ 75
+ true
+
+
+
+ Distance
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 380
+ 130
+ 91
+ 20
+
+
+
+
+ 12
+ 75
+ true
+
+
+
+ Distance
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 380
+ 200
+ 91
+ 20
+
+
+
+
+ 12
+ 75
+ true
+
+
+
+ Distance
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 250
+ 200
+ 110
+ 20
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEBUMP:QY-SB1
+
+
+
+ 139
+ 26
+ 150
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 110
+ 200
+ 121
+ 20
+
+
+
+
+ 12
+ 75
+ true
+
+
+
+ Sideband 1
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 380
+ 230
+ 91
+ 20
+
+
+
+
+ 12
+ 75
+ true
+
+
+
+ Distance
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 110
+ 230
+ 121
+ 20
+
+
+
+
+ 12
+ 75
+ true
+
+
+
+ Sideband 2
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 250
+ 230
+ 110
+ 20
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEBUMP:QY-SB2
+
+
+
+ 139
+ 26
+ 150
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 480
+ 200
+ 110
+ 20
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEBUMP:QY-SB1-DIFF
+
+
+
+ 139
+ 26
+ 150
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 480
+ 230
+ 110
+ 20
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEBUMP:QY-SB2-DIFF
+
+
+
+ 139
+ 26
+ 150
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 170
+ 60
+ 160
+ 30
+
+
+
+
+ Lucida Sans Typewriter
+ 16
+
+
+
+ true
+
+
+
+
+
+
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEBUMP:QX-FREQ
+
+
+
+ 42
+ 99
+ 228
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caLineEdit::Static
+
+
+ true
+
+
+
+ 42
+ 99
+ 228
+
+
+
+ 1
+
+
+ caLineEdit::onBackground
+
+
+ 3
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::None
+
+
+ true
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 170
+ 160
+ 160
+ 30
+
+
+
+
+ Lucida Sans Typewriter
+ 16
+
+
+
+ true
+
+
+
+
+
+
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEBUMP:QY-FREQ
+
+
+
+ 139
+ 26
+ 150
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caLineEdit::Static
+
+
+ true
+
+
+
+ 139
+ 26
+ 150
+
+
+
+ 1
+
+
+ caLineEdit::onBackground
+
+
+ 3
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::None
+
+
+ true
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 10
+ 260
+ 50
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ Qz
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 205
+ 97
+ 0
+
+
+
+
+
+
+ 60
+ 260
+ 100
+ 30
+
+
+
+
+ Lucida Sans Typewriter
+ 16
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEBUMP:QZ
+
+
+
+ 205
+ 97
+ 0
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caLineEdit::Static
+
+
+ true
+
+
+
+ 205
+ 97
+ 0
+
+
+
+ 1
+
+
+ caLineEdit::onBackground
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::None
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 170
+ 260
+ 160
+ 30
+
+
+
+
+ Lucida Sans Typewriter
+ 16
+
+
+
+ true
+
+
+
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEBUMP:QZ-FREQ
+
+
+
+ 205
+ 97
+ 0
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caLineEdit::Static
+
+
+ true
+
+
+
+ 205
+ 97
+ 0
+
+
+
+ 1
+
+
+ caLineEdit::onBackground
+
+
+ 3
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::None
+
+
+ true
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 340
+ 60
+ 250
+ 30
+
+
+
+
+ Sans Serif
+ 18
+
+
+
+ Feedback ON
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ caLabel::Calc
+
+
+ A
+
+
+ AGEBD-ALH:TUNEFBX-ONOFF
+
+
+
+
+
+ 340
+ 160
+ 250
+ 30
+
+
+
+
+ Sans Serif
+ 18
+
+
+
+ Feedback ON
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ caLabel::Calc
+
+
+ A
+
+
+ AGEBD-ALH:TUNEFBY-ONOFF
+
+
+ calabel_3
+ wmsignalpropagator
+ cacalc_2
+ camessagebutton_14
+ caspinbox
+ caspinbox_2
+ calabel_12
+ camessagebutton_15
+ calabel_13
+ calabel_14
+ camessagebutton_16
+ camessagebutton_17
+ tabWidget
+ caLineEdit_39
+ caLineEdit_40
+ calabel_18
+ caLineEdit_43
+ caLineEdit_45
+ calabel_19
+ caLineEdit_48
+ caLineEdit_49
+ calabel_20
+ calabel_21
+ calabel_22
+ caLineEdit_44
+ calabel_23
+ calabel_24
+ calabel_25
+ caLineEdit_50
+ caLineEdit_46
+ caLineEdit_51
+ caLineEdit_42
+ caLineEdit_54
+ calabel_33
+ caLineEdit_55
+ caLineEdit_56
+ calabel
+ calabel_2
+
+
+
+
+ caMenu
+ QComboBox
+
+
+
+ caChoice
+ QWidget
+
+
+
+ caMessageButton
+ QPushButton
+
+
+
+ caToggleButton
+ QCheckBox
+
+
+
+ caSpinbox
+ QFrame
+
+
+
+ caLabel
+ QLabel
+
+
+
+ caLed
+ QWidget
+
+
+
+ caLineEdit
+ QLineEdit
+
+
+
+ caMultiLineString
+ QPlainTextEdit
+
+
+
+ caCartesianPlot
+ QwtPlot
+
+
+
+ caStripPlot
+ QwtPlot
+
+ 1
+
+
+ caCalc
+ QLabel
+
+
+
+ wmSignalPropagator
+ QLabel
+
+
+
+ QwtPlot
+ QFrame
+
+
+
+
+
+
+ cacalc_2
+ emitSignal(bool)
+ wmsignalpropagator
+ reloadwindow()
+
+
+ 598
+ 89
+
+
+ 608
+ 152
+
+
+
+
+
diff --git a/services/tunebump/current/systemd/AGEBD-SERVICE-TUNEBUMP.service b/services/tunebump/current/systemd/AGEBD-SERVICE-TUNEBUMP.service
new file mode 100644
index 0000000..09eeef8
--- /dev/null
+++ b/services/tunebump/current/systemd/AGEBD-SERVICE-TUNEBUMP.service
@@ -0,0 +1,16 @@
+[Unit]
+Description=AGEBD-SERVICE-TUNEBUMP
+After=network.target
+
+[Service]
+Environment=AGEBD_ENV={{ agebd_env }}
+ExecStart=/sls/bd/hla/{{ agebd_env }}/bin/start_service.sh TUNEBUMP
+Restart=no
+
+[Install]
+WantedBy=default.target
+
+# https://www.freedesktop.org/software/systemd/man/latest/systemd.service.html
+# systemctl --user daemon-reload
+# systemctl --user enable /sls/bd/bin/systemd/AGEBD-SERVICE-TUNEBUMP.service
+# systemctl --user start AGEBD-SERVICE-TUNEBUMP
diff --git a/services/tunefbx/current/app/pyproject.toml b/services/tunefbx/current/app/pyproject.toml
new file mode 100644
index 0000000..1d0f61b
--- /dev/null
+++ b/services/tunefbx/current/app/pyproject.toml
@@ -0,0 +1,48 @@
+[project]
+name = "agebd-tunefbx"
+version = "0.1.0"
+description = "AGEBD-TUNEFBX Service"
+requires-python = "==3.10.*"
+dependencies = [
+ "agebd",
+ "numpy>=2.2.6",
+]
+
+[dependency-groups]
+dev = [
+ "pyepics>=3.5.8",
+ "pytest>=8.4.2",
+ "ruff>=0.15.20",
+]
+
+[tool.uv.sources]
+# Path is relative to where agebd package is deployed on hla
+# machines (see CI/CD in .gitea/workflows)
+agebd = { path = "../../../../packages/agebd", editable = true }
+
+[build-system]
+requires = ["hatchling"]
+build-backend = "hatchling.build"
+
+[tool.uv]
+package = true
+
+[tool.pytest.ini_options]
+pythonpath = ["src"]
+env = [
+ "AGEBD_ENV=local",
+]
+
+[tool.ruff]
+include = [
+ "src/**/*.py",
+ "tests/**/*.py",
+]
+line-length = 100
+
+[tool.ruff.lint]
+# use isort to sort imports
+extend-select = ["I"]
+
+[tool.ruff.lint.isort]
+known-first-party = ["agebd"]
diff --git a/services/tunefbx/current/app/src/agebd_tunefbx/__init__.py b/services/tunefbx/current/app/src/agebd_tunefbx/__init__.py
new file mode 100644
index 0000000..1800c27
--- /dev/null
+++ b/services/tunefbx/current/app/src/agebd_tunefbx/__init__.py
@@ -0,0 +1 @@
+from .service import PVs, Service
diff --git a/services/tunefbx/current/app/src/agebd_tunefbx/main.py b/services/tunefbx/current/app/src/agebd_tunefbx/main.py
new file mode 100644
index 0000000..a589168
--- /dev/null
+++ b/services/tunefbx/current/app/src/agebd_tunefbx/main.py
@@ -0,0 +1,31 @@
+import typer
+
+from agebd.enums import LogLevel
+from agebd.runner import CallbackRunner
+from agebd.utils import init_logging
+from agebd_tunefbx import PVs, Service
+
+
+# TODO: remove: cicd test 10
+
+def main(
+ log_level: LogLevel = typer.Option(
+ LogLevel.INFO,
+ "--log-level",
+ "-l",
+ # Looks at the OS env variable first. If empty, falls back to "INFO"
+ envvar="AGEBD_LOG_LEVEL",
+ # help="Set log level: DEBUG, INFO, WARNING, ERROR, CRITICAL",
+ case_sensitive=False,
+ ),
+):
+ init_logging(log_level)
+ service_name = "TUNEFBX"
+ pvs = PVs(service_name=service_name)
+ service = Service(name=service_name, pvs=pvs)
+ runner = CallbackRunner(service=service)
+ runner.start()
+
+
+if __name__ == "__main__":
+ typer.run(main)
diff --git a/services/tunefbx/current/app/src/agebd_tunefbx/service.py b/services/tunefbx/current/app/src/agebd_tunefbx/service.py
new file mode 100644
index 0000000..fda5c79
--- /dev/null
+++ b/services/tunefbx/current/app/src/agebd_tunefbx/service.py
@@ -0,0 +1,221 @@
+from time import perf_counter
+
+import numpy as np
+from epics import dbr
+
+from agebd.pv import get_pv_class
+from agebd.service.base import BaseService
+from agebd.service.pvs import BasePVs
+from agebd.utils import printgetversion
+
+__version__ = printgetversion(__file__)
+
+PV = get_pv_class()
+
+
+class PVs(BasePVs):
+ ## Service specific PVs from dedicated IOC
+ kp = PV("AGEBD-TUNEFBX:CONTROL-KP.VAL")
+ ki = PV("AGEBD-TUNEFBX:CONTROL-KI.VAL")
+ kd = PV("AGEBD-TUNEFBX:CONTROL-KD.VAL")
+ qx_ref = PV("AGEBD-TUNEFBX:CONTROL-QX.VAL")
+ qx_okrng = PV("AGEBD-TUNEFBX:CONTROL-QX-OKRNG.VAL")
+ qx_drvh = PV("AGEBD-TUNEFBX:CONTROL-QXMAX.VAL")
+ qx_drvl = PV("AGEBD-TUNEFBX:CONTROL-QXMIN.VAL")
+ mincur = PV("AGEBD-TUNEFBX:CONTROL-MIN-CURR.VAL")
+ dq = PV("AGEBD-TUNEFBX:DELTAQ.VAL")
+ dq_ulim = PV("AGEBD-TUNEFBX:DELTAQ-ULIM.VAL")
+ dq_llim = PV("AGEBD-TUNEFBX:DELTAQ-LLIM.VAL")
+ check1 = PV("AGEBD-TUNEFBX:CHECK1.VAL")
+ check2 = PV("AGEBD-TUNEFBX:CHECK2.VAL")
+ check3 = PV("AGEBD-TUNEFBX:CHECK3.VAL")
+ check4 = PV("AGEBD-TUNEFBX:CHECK4.VAL")
+ check5 = PV("AGEBD-TUNEFBX:CHECK5.VAL")
+ check6 = PV("AGEBD-TUNEFBX:CHECK6.VAL")
+ check7 = PV("AGEBD-TUNEFBX:CHECK7.VAL")
+ check8 = PV("AGEBD-TUNEFBX:CHECK8.VAL")
+
+ # Output PVs
+ qx_stepdec = PV("AGEBD-TUNEBUMP:QX-STEPDOWN.VAL")
+ qx_stepinc = PV("AGEBD-TUNEBUMP:QX-STEPUP.VAL")
+ qx_stepsiz = PV("AGEBD-TUNEBUMP:QX-STEPSIZE.VAL")
+
+ ## Service specific PVs from other IOCs
+ inj_active = PV("AGEBD-PARAMS:INJECTION-ACTIVE.VAL")
+ dump_valve = PV("ARS01-VVPG-0210:PLC_STATUS.VAL")
+ hor_pinger_trig = PV("AGETI-CVME-MASTER-TMA:Evt-SR-Pinger-H-Ena-Sel.VAL")
+ ver_pinger_trig = PV("AGETI-CVME-MASTER-TMA:Evt-SR-Pinger-V-Ena-Sel.VAL")
+ bpm_qx_pilot_int = PV("ARS07-DBPM-0840:PILOT-INT-SWITCH.VAL") # must be: 0 No Pilot
+ bpm_qx_pilot_ext = PV("ARS07-DBPM-0840:PILOT-EXT-SWITCH.VAL") # must be: 0 No Pilot
+ bpm_qx_chopper = PV("ARS07-DBPM-0840:CHOPPER-MODE.VAL") # must be: 0 Periodic
+ cur = PV("ARS07-DPCT-0000:CURR.VAL")
+
+ def __init__(self, service_name: str, pv_factory=PV):
+ super().__init__(service_name, pv_factory)
+ PV = pv_factory
+
+ # usually it is advisable to trigger the mainloop of a service on changes of certain PVs:
+ self.CallbackPV = PV("AGEBD-TUNEBUMP:QX.VAL", auto_monitor=dbr.DBE_VALUE)
+
+
+class PID:
+ # Proportional-Integral-Derivative (PID) controller class
+ # PID setup procedure:
+ # 1. set integral and derivative gains ki, kd to 0
+ # 2. set proportional gain kp to low, stable value
+ # 3. increase kp and create a disturbance, e.g., by changing the setpoint
+ # 4. increase kp until feedback parameter oscillates
+ # 5. set kp to 40 % of the critical value triggering oscillation
+ # 6. slowly increase ki to eliminate the steady state error
+ # 7. adjust it until setpoint is reached accurately without overshoot
+ # 8. tune kd to minimize oscillations and overshoots (caution: high kd can amplify noise)
+
+ def __init__(self, kp, ki, kd, setpoint):
+
+ # Proportional Gain >> The "present" term. It provides a response proportional to the current error. Increasing kp makes the system respond faster, but if pushed too high, it will cause violent overshoot and oscillation.
+ self.kp = kp
+ # Integral Gain >> The "past" term. It accumulates the errors over time to eliminate steady-state error. However, high ki values can cause sluggishness or instability (e.g., integral windup).
+ self.ki = ki
+ # Derivative Gain >> The "future" term. It measures the rate of change of the error, acting as a damping factor to reduce overshoot and smooth out rapid, unwanted movements
+ self.kd = kd
+ self.setpoint = setpoint
+ self.integral = 0
+ self.prev_error = 0
+
+ def update(self, measurement, dt):
+
+ error = self.setpoint - measurement
+ self.integral += error * dt
+ derivative = (error - self.prev_error) / dt if dt > 0 else 0
+
+ self.prev_error = error
+
+ # Calculate the final output using Kp, Ki, and Kd which is written to actuator
+ output = (self.kp * error) + (self.ki * self.integral) + (self.kd * derivative)
+
+ return output
+
+
+class Service(BaseService[PVs]):
+ def __init__(
+ self,
+ name: str,
+ pvs: PVs,
+ version: str = __version__,
+ sleep_interval: float = 0.1,
+ ):
+ super().__init__(name, pvs, version, sleep_interval)
+
+ self.control = 0.0
+ self.dq_llim = 0.0
+ self.dq_ulim = 0.0
+
+ self.qx_okrng = pvs.qx_okrng.get()
+
+ self.PID = PID(pvs.kp.get(), pvs.ki.get(), pvs.kd.get(), pvs.qx_ref.get())
+ # start stop watch
+ self.t0 = perf_counter()
+
+ def update(self):
+ pvs = self.pvs
+ # when callback is fired, this code will be executed
+ if self.CallbackFired:
+ #######################################################################################
+ #######################################################################################
+ # here goes all the code that your service is supposed to be
+ # running every time when the callback is fired
+
+ # update PID settings
+ self.PID.setpoint = pvs.qx_ref.get()
+ self.PID.kp = pvs.kp.get()
+ self.PID.ki = pvs.ki.get()
+ self.PID.kd = pvs.kd.get()
+
+ self.qx_okrng = pvs.qx_okrng.get()
+
+ ############
+ ## CHECKS ##
+ ############
+ # 1. measured tune within drivelimits
+ self.check1 = (
+ pvs.qx_drvl.get() < self.CallbackValue and self.CallbackValue < pvs.qx_drvh.get()
+ )
+ pvs.check1.put(self.check1)
+
+ # 2. measured tune outside ok range limits
+ self.check2 = self.CallbackValue < (
+ self.PID.setpoint - self.qx_okrng
+ ) or self.CallbackValue > (self.PID.setpoint + self.qx_okrng)
+ pvs.check2.put(self.check2)
+
+ # 3. injection not active
+ self.check3 = not pvs.inj_active.get()
+ pvs.check3.put(self.check3)
+
+ # 4. stored beam current above threshold
+ self.check4 = pvs.cur.get() > pvs.mincur.get()
+ pvs.check4.put(self.check4)
+
+ # 5. bpm setup correctly for tune measurement
+ self.check5 = (
+ pvs.bpm_qx_pilot_int.get() == 0
+ and pvs.bpm_qx_pilot_ext.get() == 0
+ and pvs.bpm_qx_chopper.get() == 1
+ )
+ pvs.check5.put(self.check5)
+
+ # 6. pingers are on
+ self.check6 = pvs.hor_pinger_trig.get() and pvs.ver_pinger_trig.get()
+ pvs.check6.put(self.check6)
+
+ # 7. dt corresponds to 3.125 Hz, i.e., min. 2 consecutive valid measurements
+ t1 = perf_counter()
+ self.dt = t1 - self.t0
+ self.t0 = t1
+ self.check7 = self.dt < 1.1 / 3.125
+ pvs.check7.put(self.check7)
+
+ # check all checks before PID call
+ self.checkall = (
+ self.check1
+ and self.check2
+ and self.check3
+ and self.check4
+ and self.check5
+ and self.check6
+ and self.check7
+ )
+
+ if self.checkall:
+ # 8. PID calculated step within limits
+ self.control = self.PID.update(self.CallbackValue, self.dt)
+ self.dq_llim = pvs.dq_llim.get()
+ self.dq_ulim = pvs.dq_ulim.get()
+
+ self.check8 = self.control > self.dq_llim and self.control < self.dq_ulim
+ pvs.check8.put(self.check8)
+
+ if self.check8:
+ pvs.dq.put(self.control)
+ pvs.qx_stepsiz.put(np.abs(self.control))
+ if self.control < 0:
+ pvs.qx_stepdec.put(1)
+ else:
+ pvs.qx_stepinc.put(1)
+
+ #######################################################################################
+ #######################################################################################
+
+ # callback done
+ self.CallbackFired = 0
+
+ #######################################################################################
+ #######################################################################################
+ # here goes all the code that your service
+ # is supposed to be running in any case, e.g.,
+ # update some pvs/vals
+
+ # maybe sleep to limit the update loop execution rate
+ # sleep(1)
+ #######################################################################################
+ #######################################################################################
diff --git a/services/tunefbx/current/app/tests/test_app.py b/services/tunefbx/current/app/tests/test_app.py
new file mode 100644
index 0000000..b0158a0
--- /dev/null
+++ b/services/tunefbx/current/app/tests/test_app.py
@@ -0,0 +1,9 @@
+from agebd_tunefbx import PVs, Service
+
+
+def test_app():
+ service_name = "DUMMY"
+ pvs = PVs(service_name=service_name)
+ service = Service(name=service_name, pvs=pvs)
+ service.CallbackFired = 1
+ service.update()
diff --git a/services/tunefbx/current/app/uv.lock b/services/tunefbx/current/app/uv.lock
new file mode 100644
index 0000000..d4cd5b5
--- /dev/null
+++ b/services/tunefbx/current/app/uv.lock
@@ -0,0 +1,301 @@
+version = 1
+revision = 3
+requires-python = "==3.10.*"
+
+[[package]]
+name = "agebd"
+version = "0.1.0"
+source = { editable = "../../../../packages/agebd" }
+dependencies = [
+ { name = "h5py" },
+ { name = "typer" },
+]
+
+[package.metadata]
+requires-dist = [
+ { name = "h5py", specifier = ">=3.16.0" },
+ { name = "typer", specifier = ">=0.23.2" },
+]
+
+[package.metadata.requires-dev]
+dev = [
+ { name = "pyright", specifier = ">=1.1.410" },
+ { name = "pytest", specifier = ">=8.4.2" },
+ { name = "ruff", specifier = ">=0.15.19" },
+]
+
+[[package]]
+name = "agebd-tunefbx"
+version = "0.1.0"
+source = { editable = "." }
+dependencies = [
+ { name = "agebd" },
+ { name = "numpy" },
+]
+
+[package.dev-dependencies]
+dev = [
+ { name = "pyepics" },
+ { name = "pytest" },
+ { name = "ruff" },
+]
+
+[package.metadata]
+requires-dist = [
+ { name = "agebd", editable = "../../../../packages/agebd" },
+ { name = "numpy", specifier = ">=2.2.6" },
+]
+
+[package.metadata.requires-dev]
+dev = [
+ { name = "pyepics", specifier = ">=3.5.8" },
+ { name = "pytest", specifier = ">=8.4.2" },
+ { name = "ruff", specifier = ">=0.15.20" },
+]
+
+[[package]]
+name = "annotated-doc"
+version = "0.0.4"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/57/ba/046ceea27344560984e26a590f90bc7f4a75b06701f653222458922b558c/annotated_doc-0.0.4.tar.gz", hash = "sha256:fbcda96e87e9c92ad167c2e53839e57503ecfda18804ea28102353485033faa4", size = 7288, upload-time = "2025-11-10T22:07:42.062Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl", hash = "sha256:571ac1dc6991c450b25a9c2d84a3705e2ae7a53467b5d111c24fa8baabbed320", size = 5303, upload-time = "2025-11-10T22:07:40.673Z" },
+]
+
+[[package]]
+name = "colorama"
+version = "0.4.6"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" },
+]
+
+[[package]]
+name = "exceptiongroup"
+version = "1.3.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "typing-extensions" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" },
+]
+
+[[package]]
+name = "h5py"
+version = "3.16.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "numpy" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/db/33/acd0ce6863b6c0d7735007df01815403f5589a21ff8c2e1ee2587a38f548/h5py-3.16.0.tar.gz", hash = "sha256:a0dbaad796840ccaa67a4c144a0d0c8080073c34c76d5a6941d6818678ef2738", size = 446526, upload-time = "2026-03-06T13:49:08.07Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/3a/6b/231413e58a787a89b316bb0d1777da3c62257e4797e09afd8d17ad3549dc/h5py-3.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e06f864bedb2c8e7c1358e6c73af48519e317457c444d6f3d332bb4e8fa6d7d9", size = 3724137, upload-time = "2026-03-06T13:47:35.242Z" },
+ { url = "https://files.pythonhosted.org/packages/74/f9/557ce3aad0fe8471fb5279bab0fc56ea473858a022c4ce8a0b8f303d64e9/h5py-3.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ec86d4fffd87a0f4cb3d5796ceb5a50123a2a6d99b43e616e5504e66a953eca3", size = 3090112, upload-time = "2026-03-06T13:47:37.634Z" },
+ { url = "https://files.pythonhosted.org/packages/7a/f5/e15b3d0dc8a18e56409a839e6468d6fb589bc5207c917399c2e0706eeb44/h5py-3.16.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:86385ea895508220b8a7e45efa428aeafaa586bd737c7af9ee04661d8d84a10d", size = 4844847, upload-time = "2026-03-06T13:47:39.811Z" },
+ { url = "https://files.pythonhosted.org/packages/cb/92/a8851d936547efe30cc0ce5245feac01f3ec6171f7899bc3f775c72030b3/h5py-3.16.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:8975273c2c5921c25700193b408e28d6bdd0111c37468b2d4e25dcec4cd1d84d", size = 5065352, upload-time = "2026-03-06T13:47:41.489Z" },
+ { url = "https://files.pythonhosted.org/packages/2b/ae/f2adc5d0ca9626db3277a3d87516e124cbc5d0eea0bd79bc085702d04f2c/h5py-3.16.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:1677ad48b703f44efc9ea0c3ab284527f81bc4f318386aaaebc5fede6bbae56f", size = 4839173, upload-time = "2026-03-06T13:47:43.586Z" },
+ { url = "https://files.pythonhosted.org/packages/64/0b/e0c8c69da1d8838da023a50cd3080eae5d475691f7636b35eff20bb6ef20/h5py-3.16.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7c4dd4cf5f0a4e36083f73172f6cfc25a5710789269547f132a20975bfe2434c", size = 5076216, upload-time = "2026-03-06T13:47:45.315Z" },
+ { url = "https://files.pythonhosted.org/packages/66/35/d88fd6718832133c885004c61ceeeb24dbd6397ef877dbed6b3a64d6a286/h5py-3.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:bdef06507725b455fccba9c16529121a5e1fbf56aa375f7d9713d9e8ff42454d", size = 3183639, upload-time = "2026-03-06T13:47:47.041Z" },
+]
+
+[[package]]
+name = "iniconfig"
+version = "2.3.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" },
+]
+
+[[package]]
+name = "markdown-it-py"
+version = "4.2.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "mdurl" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/06/ff/7841249c247aa650a76b9ee4bbaeae59370dc8bfd2f6c01f3630c35eb134/markdown_it_py-4.2.0.tar.gz", hash = "sha256:04a21681d6fbb623de53f6f364d352309d4094dd4194040a10fd51833e418d49", size = 82454, upload-time = "2026-05-07T12:08:28.36Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl", hash = "sha256:9f7ebbcd14fe59494226453aed97c1070d83f8d24b6fc3a3bcf9a38092641c4a", size = 91687, upload-time = "2026-05-07T12:08:27.182Z" },
+]
+
+[[package]]
+name = "mdurl"
+version = "0.1.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" },
+]
+
+[[package]]
+name = "numpy"
+version = "2.2.6"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/76/21/7d2a95e4bba9dc13d043ee156a356c0a8f0c6309dff6b21b4d71a073b8a8/numpy-2.2.6.tar.gz", hash = "sha256:e29554e2bef54a90aa5cc07da6ce955accb83f21ab5de01a62c8478897b264fd", size = 20276440, upload-time = "2025-05-17T22:38:04.611Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/9a/3e/ed6db5be21ce87955c0cbd3009f2803f59fa08df21b5df06862e2d8e2bdd/numpy-2.2.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b412caa66f72040e6d268491a59f2c43bf03eb6c96dd8f0307829feb7fa2b6fb", size = 21165245, upload-time = "2025-05-17T21:27:58.555Z" },
+ { url = "https://files.pythonhosted.org/packages/22/c2/4b9221495b2a132cc9d2eb862e21d42a009f5a60e45fc44b00118c174bff/numpy-2.2.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e41fd67c52b86603a91c1a505ebaef50b3314de0213461c7a6e99c9a3beff90", size = 14360048, upload-time = "2025-05-17T21:28:21.406Z" },
+ { url = "https://files.pythonhosted.org/packages/fd/77/dc2fcfc66943c6410e2bf598062f5959372735ffda175b39906d54f02349/numpy-2.2.6-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:37e990a01ae6ec7fe7fa1c26c55ecb672dd98b19c3d0e1d1f326fa13cb38d163", size = 5340542, upload-time = "2025-05-17T21:28:30.931Z" },
+ { url = "https://files.pythonhosted.org/packages/7a/4f/1cb5fdc353a5f5cc7feb692db9b8ec2c3d6405453f982435efc52561df58/numpy-2.2.6-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:5a6429d4be8ca66d889b7cf70f536a397dc45ba6faeb5f8c5427935d9592e9cf", size = 6878301, upload-time = "2025-05-17T21:28:41.613Z" },
+ { url = "https://files.pythonhosted.org/packages/eb/17/96a3acd228cec142fcb8723bd3cc39c2a474f7dcf0a5d16731980bcafa95/numpy-2.2.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:efd28d4e9cd7d7a8d39074a4d44c63eda73401580c5c76acda2ce969e0a38e83", size = 14297320, upload-time = "2025-05-17T21:29:02.78Z" },
+ { url = "https://files.pythonhosted.org/packages/b4/63/3de6a34ad7ad6646ac7d2f55ebc6ad439dbbf9c4370017c50cf403fb19b5/numpy-2.2.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc7b73d02efb0e18c000e9ad8b83480dfcd5dfd11065997ed4c6747470ae8915", size = 16801050, upload-time = "2025-05-17T21:29:27.675Z" },
+ { url = "https://files.pythonhosted.org/packages/07/b6/89d837eddef52b3d0cec5c6ba0456c1bf1b9ef6a6672fc2b7873c3ec4e2e/numpy-2.2.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:74d4531beb257d2c3f4b261bfb0fc09e0f9ebb8842d82a7b4209415896adc680", size = 15807034, upload-time = "2025-05-17T21:29:51.102Z" },
+ { url = "https://files.pythonhosted.org/packages/01/c8/dc6ae86e3c61cfec1f178e5c9f7858584049b6093f843bca541f94120920/numpy-2.2.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8fc377d995680230e83241d8a96def29f204b5782f371c532579b4f20607a289", size = 18614185, upload-time = "2025-05-17T21:30:18.703Z" },
+ { url = "https://files.pythonhosted.org/packages/5b/c5/0064b1b7e7c89137b471ccec1fd2282fceaae0ab3a9550f2568782d80357/numpy-2.2.6-cp310-cp310-win32.whl", hash = "sha256:b093dd74e50a8cba3e873868d9e93a85b78e0daf2e98c6797566ad8044e8363d", size = 6527149, upload-time = "2025-05-17T21:30:29.788Z" },
+ { url = "https://files.pythonhosted.org/packages/a3/dd/4b822569d6b96c39d1215dbae0582fd99954dcbcf0c1a13c61783feaca3f/numpy-2.2.6-cp310-cp310-win_amd64.whl", hash = "sha256:f0fd6321b839904e15c46e0d257fdd101dd7f530fe03fd6359c1ea63738703f3", size = 12904620, upload-time = "2025-05-17T21:30:48.994Z" },
+ { url = "https://files.pythonhosted.org/packages/9e/3b/d94a75f4dbf1ef5d321523ecac21ef23a3cd2ac8b78ae2aac40873590229/numpy-2.2.6-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0b605b275d7bd0c640cad4e5d30fa701a8d59302e127e5f79138ad62762c3e3d", size = 21040391, upload-time = "2025-05-17T21:44:35.948Z" },
+ { url = "https://files.pythonhosted.org/packages/17/f4/09b2fa1b58f0fb4f7c7963a1649c64c4d315752240377ed74d9cd878f7b5/numpy-2.2.6-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:7befc596a7dc9da8a337f79802ee8adb30a552a94f792b9c9d18c840055907db", size = 6786754, upload-time = "2025-05-17T21:44:47.446Z" },
+ { url = "https://files.pythonhosted.org/packages/af/30/feba75f143bdc868a1cc3f44ccfa6c4b9ec522b36458e738cd00f67b573f/numpy-2.2.6-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce47521a4754c8f4593837384bd3424880629f718d87c5d44f8ed763edd63543", size = 16643476, upload-time = "2025-05-17T21:45:11.871Z" },
+ { url = "https://files.pythonhosted.org/packages/37/48/ac2a9584402fb6c0cd5b5d1a91dcf176b15760130dd386bbafdbfe3640bf/numpy-2.2.6-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d042d24c90c41b54fd506da306759e06e568864df8ec17ccc17e9e884634fd00", size = 12812666, upload-time = "2025-05-17T21:45:31.426Z" },
+]
+
+[[package]]
+name = "packaging"
+version = "26.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d7/f1/e7a6dd94a8d4a5626c03e4e99c87f241ba9e350cd9e6d75123f992427270/packaging-26.2.tar.gz", hash = "sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661", size = 228134, upload-time = "2026-04-24T20:15:23.917Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/df/b2/87e62e8c3e2f4b32e5fe99e0b86d576da1312593b39f47d8ceef365e95ed/packaging-26.2-py3-none-any.whl", hash = "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e", size = 100195, upload-time = "2026-04-24T20:15:22.081Z" },
+]
+
+[[package]]
+name = "pluggy"
+version = "1.6.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" },
+]
+
+[[package]]
+name = "pyepics"
+version = "3.5.10"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "numpy" },
+ { name = "pyparsing" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/69/57/29e1e9ef11ba2a3419f489946ae1d8190025a1e4f4e1c1686758bb2b6e0a/pyepics-3.5.10.tar.gz", hash = "sha256:f390cf9be40aba757b9528888114bc14d8db01086d0c93914720b1772460375b", size = 6150481, upload-time = "2026-05-20T18:44:36.336Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d6/36/e517fd83bd97d6bfe4105e0c6b322070c5cc36fb56a8fab2866e319f8804/pyepics-3.5.10-py3-none-any.whl", hash = "sha256:c9fac2c54f2b595268e66fc348cf5ec24e63718e7dbd07d73d1b37d4da6bfee1", size = 5332376, upload-time = "2026-05-20T18:44:34.242Z" },
+]
+
+[[package]]
+name = "pygments"
+version = "2.20.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" },
+]
+
+[[package]]
+name = "pyparsing"
+version = "3.3.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f3/91/9c6ee907786a473bf81c5f53cf703ba0957b23ab84c264080fb5a450416f/pyparsing-3.3.2.tar.gz", hash = "sha256:c777f4d763f140633dcb6d8a3eda953bf7a214dc4eff598413c070bcdc117cbc", size = 6851574, upload-time = "2026-01-21T03:57:59.36Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl", hash = "sha256:850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d", size = 122781, upload-time = "2026-01-21T03:57:55.912Z" },
+]
+
+[[package]]
+name = "pytest"
+version = "9.1.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "colorama", marker = "sys_platform == 'win32'" },
+ { name = "exceptiongroup" },
+ { name = "iniconfig" },
+ { name = "packaging" },
+ { name = "pluggy" },
+ { name = "pygments" },
+ { name = "tomli" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/e4/47/b9efed96c114afcfa3c9d3fe98a76a1d14c74a9e266d397cf6eb64be5e01/pytest-9.1.1.tar.gz", hash = "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313", size = 1636369, upload-time = "2026-06-19T10:58:32.857Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/24/25/1de2678b631f5a49215c6c96fff41ba892b0a34df68d6d80292b1b48aa7f/pytest-9.1.1-py3-none-any.whl", hash = "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c", size = 386536, upload-time = "2026-06-19T10:58:31.347Z" },
+]
+
+[[package]]
+name = "rich"
+version = "15.0.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "markdown-it-py" },
+ { name = "pygments" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/c0/8f/0722ca900cc807c13a6a0c696dacf35430f72e0ec571c4275d2371fca3e9/rich-15.0.0.tar.gz", hash = "sha256:edd07a4824c6b40189fb7ac9bc4c52536e9780fbbfbddf6f1e2502c31b068c36", size = 230680, upload-time = "2026-04-12T08:24:00.75Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl", hash = "sha256:33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb", size = 310654, upload-time = "2026-04-12T08:24:02.83Z" },
+]
+
+[[package]]
+name = "ruff"
+version = "0.15.21"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/0f/36/6f65aa9989acdec45d417192d8f4e7921931d8a6cf87ac74bce3eed98a8e/ruff-0.15.21.tar.gz", hash = "sha256:d0cfc841c572283c36548f82664a54ce6565567f1b0d5b4cf2caac693d8b7500", size = 4769401, upload-time = "2026-07-09T20:01:34.005Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d0/c6/ede15cac6839f3dbce52565c8f5164a8210e669c7bc4decb03e5bdf47d0d/ruff-0.15.21-py3-none-linux_armv6l.whl", hash = "sha256:63ea0e965e5d73c90e95b2434beeafc70820536717f561b32ab6e777cb9bdf5d", size = 10854342, upload-time = "2026-07-09T20:00:53.998Z" },
+ { url = "https://files.pythonhosted.org/packages/28/9d/d825b07ee7ea9e2d61df92a860033c94e06e7300d50a1c2653aac27d24fe/ruff-0.15.21-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:0f212c5d7d54c01bbfe6dcab02b724a39300f3e34ed7acbe995ccb320a2c58bd", size = 11139539, upload-time = "2026-07-09T20:00:57.809Z" },
+ { url = "https://files.pythonhosted.org/packages/f5/de/3b107712e642f063c7a9e0887c427b22cb44097de5aab36c05f2e280670c/ruff-0.15.21-py3-none-macosx_11_0_arm64.whl", hash = "sha256:e6312e41bc96791299614995ea3a977c5857c3b5662b1ecef6755b02b87cb646", size = 10595437, upload-time = "2026-07-09T20:01:00.006Z" },
+ { url = "https://files.pythonhosted.org/packages/9a/6f/b4523cc90ba239ede441447a19d0c968846a3012e5a0b0c5b62831a3d5e3/ruff-0.15.21-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01d65b4831c6b2a4ba8ee6faa84049d44d982b7a706e622c4094c509e51673be", size = 10990053, upload-time = "2026-07-09T20:01:02.187Z" },
+ { url = "https://files.pythonhosted.org/packages/92/cc/c6a9872a5375f0628875481cf2f66b13d7d865bf3ca2e57f91c7e762d976/ruff-0.15.21-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2c5a913a589120ce67933d5d05fd6ddbcc2481c6a054980ee767f7414c72b4fd", size = 10666096, upload-time = "2026-07-09T20:01:04.299Z" },
+ { url = "https://files.pythonhosted.org/packages/ab/97/c621f7a17e097f1790fa3af6374138823b330b2d03fc38337945daca212c/ruff-0.15.21-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ef04b681d02ad4dc9620f00f83ac5c22f652d0e9a9cfe431d219b16ad5ccc41", size = 11537011, upload-time = "2026-07-09T20:01:06.771Z" },
+ { url = "https://files.pythonhosted.org/packages/ea/51/d928727e476e25ccc57c6f449ffd80241a651a973ad949d39cfb2a771d28/ruff-0.15.21-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:16d090c0740916594157e75b80d666eab8e78083b39b3b0e1d698f4670a17b86", size = 12347101, upload-time = "2026-07-09T20:01:08.859Z" },
+ { url = "https://files.pythonhosted.org/packages/1e/88/8cd62026802b16018ad06931d87997cf795ba2a6239ab659606c87d96bf0/ruff-0.15.21-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3a10e74757dd65004d779b73e2f3c5210156d9980b41224d50d2ebcf1db51e67", size = 11572001, upload-time = "2026-07-09T20:01:11.092Z" },
+ { url = "https://files.pythonhosted.org/packages/b2/97/f63084cf55444fc110e8cb985ebfcc592af47f597d44453d778cb81bc156/ruff-0.15.21-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bab0905d2f29e0d9fbc3c373ed23db0095edaa3f71f1f4f519ec15134d9e85c8", size = 11549239, upload-time = "2026-07-09T20:01:13.27Z" },
+ { url = "https://files.pythonhosted.org/packages/9d/77/f107da4a2874b7715914b03f09ba9c54424de3ff8a1cc5d015d3ee2ce0ac/ruff-0.15.21-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:00eca240af5789fec6fe7df74c088cc1f9644ed83027113468efba7c92b94075", size = 11535340, upload-time = "2026-07-09T20:01:15.206Z" },
+ { url = "https://files.pythonhosted.org/packages/d5/e9/601deb322d3303a7bf212b0100ead6f2ee3f6a044d89c30f2f92bf83c731/ruff-0.15.21-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:262ab31557a75141325e32d3357f3597645a7f084e732b6b054dde428ecd9341", size = 10964048, upload-time = "2026-07-09T20:01:17.723Z" },
+ { url = "https://files.pythonhosted.org/packages/ea/2e/0f2176d1e99c15192caea19c8c3a0a955246b4cb4de795042eeb616345cd/ruff-0.15.21-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:659c4e7a4212f83306045ec7c5e5a356d16d9a6ef4ae0c7a4d872914fc655d9d", size = 10667055, upload-time = "2026-07-09T20:01:19.73Z" },
+ { url = "https://files.pythonhosted.org/packages/48/60/abd74a02e0c4214f12a68becfd30af7165cfdcb0e661ecdc60bbb949c09a/ruff-0.15.21-py3-none-musllinux_1_2_i686.whl", hash = "sha256:9e866eab611a5f959d36df2d10e446973a3610bc42b0c15b31dc27977d59c233", size = 11242043, upload-time = "2026-07-09T20:01:21.947Z" },
+ { url = "https://files.pythonhosted.org/packages/b2/c6/583075d8ccabb4b229345edcaf1545eb3d8d6be90f686a479d7e94088bbf/ruff-0.15.21-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e89bc93c0d3803ba870b55c29671bad9dc6d94bb1eb181b056b52eb05b52854f", size = 11648064, upload-time = "2026-07-09T20:01:24.023Z" },
+ { url = "https://files.pythonhosted.org/packages/3a/3c/37d0ecb729a7cc2d393ea7dce316fc585680f35d93b8d62139d7d0a3700c/ruff-0.15.21-py3-none-win32.whl", hash = "sha256:01f8d5be84823c172b389e123174f781f9daf86d6c58719d603f941932195cdd", size = 10896555, upload-time = "2026-07-09T20:01:26.941Z" },
+ { url = "https://files.pythonhosted.org/packages/c0/b8/e43466b2a6067ce91e669068f6e28d6c719a920f014b070d5c8731725de3/ruff-0.15.21-py3-none-win_amd64.whl", hash = "sha256:d4b8d9a2f0f12b816b50447f6eccb9f4bb01a6b82c86b50fb3b5354b458dc6d3", size = 12038772, upload-time = "2026-07-09T20:01:29.497Z" },
+ { url = "https://files.pythonhosted.org/packages/dd/75/e90ab9aeece218a9fc5a5bc3ec97d0ee6bb3c4ff95869463c1de58e29a1c/ruff-0.15.21-py3-none-win_arm64.whl", hash = "sha256:6e83115d4b9377c1cbc13abf0e051f069fab0ef815ea0504a8a008cee24dd0a8", size = 11375265, upload-time = "2026-07-09T20:01:31.772Z" },
+]
+
+[[package]]
+name = "shellingham"
+version = "1.5.4"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/58/15/8b3609fd3830ef7b27b655beb4b4e9c62313a4e8da8c676e142cc210d58e/shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de", size = 10310, upload-time = "2023-10-24T04:13:40.426Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755, upload-time = "2023-10-24T04:13:38.866Z" },
+]
+
+[[package]]
+name = "tomli"
+version = "2.4.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/22/de/48c59722572767841493b26183a0d1cc411d54fd759c5607c4590b6563a6/tomli-2.4.1.tar.gz", hash = "sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f", size = 17543, upload-time = "2026-03-25T20:22:03.828Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/7b/61/cceae43728b7de99d9b847560c262873a1f6c98202171fd5ed62640b494b/tomli-2.4.1-py3-none-any.whl", hash = "sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe", size = 14583, upload-time = "2026-03-25T20:22:03.012Z" },
+]
+
+[[package]]
+name = "typer"
+version = "0.27.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "annotated-doc" },
+ { name = "colorama", marker = "sys_platform == 'win32'" },
+ { name = "rich" },
+ { name = "shellingham" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/37/78/fda3361b56efc27944f24225f6ecd13d96d6fcfe37bd0eb34e2f4c63f9fc/typer-0.27.0.tar.gz", hash = "sha256:629bd12ea5d13a17148125d9a264f949eb171fb3f120f9b04d85873cab054fa5", size = 203430, upload-time = "2026-07-15T19:21:07.007Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/40/03/26a383c9e58c213199d1aad1c3d353cfc22d4444ec6d2c0bf8ad02523843/typer-0.27.0-py3-none-any.whl", hash = "sha256:6f4b27631e47f077871b7dc30e933ec0131c1390fbe0e387ea5574b5bac9ccf1", size = 122716, upload-time = "2026-07-15T19:21:05.553Z" },
+]
+
+[[package]]
+name = "typing-extensions"
+version = "4.16.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f6/cc/6253133b5bb138fc3306cebfbda2c520f545d36b5be2c7255cc528bb45d6/typing_extensions-4.16.0.tar.gz", hash = "sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5", size = 113555, upload-time = "2026-07-02T08:40:05.92Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/49/d3/b8441a820a491ddfc024b0b0cf0393375b75ea13866d9c66727e54c2fc80/typing_extensions-4.16.0-py3-none-any.whl", hash = "sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8", size = 45571, upload-time = "2026-07-02T08:40:04.659Z" },
+]
diff --git a/services/tunefbx/current/ioc/AGEBD-CPCL-TUNEFBX_main.subs b/services/tunefbx/current/ioc/AGEBD-CPCL-TUNEFBX_main.subs
new file mode 100644
index 0000000..eaabe8c
--- /dev/null
+++ b/services/tunefbx/current/ioc/AGEBD-CPCL-TUNEFBX_main.subs
@@ -0,0 +1,4 @@
+file TUNEFBX.template {
+ pattern { DEVICE }
+ { AGEBD-TUNEFBX{{ agebd_env }} }
+}
diff --git a/services/tunefbx/current/ioc/AGEBD-CPCL-TUNEFBX_parameters.yaml b/services/tunefbx/current/ioc/AGEBD-CPCL-TUNEFBX_parameters.yaml
new file mode 100644
index 0000000..ff8e70f
--- /dev/null
+++ b/services/tunefbx/current/ioc/AGEBD-CPCL-TUNEFBX_parameters.yaml
@@ -0,0 +1,6 @@
+cpu_architecture: x86_64
+epics_version: 7.0.8
+ioc_host: sls-vserv-bd-01{{ agebd_env }}
+ioc_port: {{ ioc_port }}
+os: RHEL8
+os_id: rhel
diff --git a/services/tunefbx/current/ioc/TUNEFBX.template b/services/tunefbx/current/ioc/TUNEFBX.template
new file mode 100644
index 0000000..b11ca9a
--- /dev/null
+++ b/services/tunefbx/current/ioc/TUNEFBX.template
@@ -0,0 +1,185 @@
+record(ao, "$(DEVICE):CONTROL-KP") {
+ field(DESC, "PID Proportional Gain")
+ field(ASG, "PROTECTED")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-KI") {
+ field(DESC, "PID Integral Gain")
+ field(ASG, "PROTECTED")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-KD") {
+ field(DESC, "PID Derivative Gain")
+ field(ASG, "PROTECTED")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-QX") {
+ field(DESC, "PID Setpoint for QX")
+ field(ASG, "PROTECTED")
+ field(VAL, "0.37")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-QX-OKRNG") {
+ field(DESC, "PID THRESHOLD")
+ field(ASG, "PROTECTED")
+ field(VAL, "0.0005")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-QXMIN") {
+ field(DESC, "PID LOWER LIMIT")
+ field(ASG, "PROTECTED")
+ field(VAL, "0.31")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-QXMAX") {
+ field(DESC, "PID UPPER LIMIT")
+ field(ASG, "PROTECTED")
+ field(VAL, "0.43")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-MIN-CURR") {
+ field(DESC, "PID MIN CURR")
+ field(ASG, "PROTECTED")
+ field(VAL, "400")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):DELTAQ") {
+ field(DESC, "PID SETPOINT for archive")
+ field(ASG, "PROTECTED")
+ field(FLNK, "$(DEVICE):QSTEPS")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):DELTAQ-ULIM") {
+ field(DESC, "PID SETPOINT upper limit")
+ field(ASG, "PROTECTED")
+ field(FLNK, "$(DEVICE):QSTEPS")
+ field(VAL, "0.001")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):DELTAQ-LLIM") {
+ field(DESC, "PID SETPOINT lower limit")
+ field(ASG, "PROTECTED")
+ field(FLNK, "$(DEVICE):QSTEPS")
+ field(VAL, "-0.001")
+ field(PINI, "YES")
+}
+
+record(calc, "$(DEVICE):QSTEPS") {
+ field(DESC, "PID SETPOINT accumulated")
+ field(ASG, "READONLY")
+ field(PREC, "4")
+ field(VAL, "0")
+ field(PINI, "YES")
+ field(CALC, "VAL + A")
+ field(INPA, "$(DEVICE):DELTAQ")
+}
+
+record(bo, "$(DEVICE):CHECK1") {
+ field(DESC, "measured tune realistic")
+ field(FLNK, "$(DEVICE):CHECKALL")
+ field(ASG, "PROTECTED")
+ field(ZSV, "MINOR")
+ field(OSV, "NO_ALARM")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(bo, "$(DEVICE):CHECK2") {
+ field(DESC, "measured tune okrng")
+ field(FLNK, "$(DEVICE):CHECKALL")
+ field(ASG, "PROTECTED")
+ field(ZSV, "MINOR")
+ field(OSV, "NO_ALARM")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(bo, "$(DEVICE):CHECK3") {
+ field(DESC, "injection not active")
+ field(FLNK, "$(DEVICE):CHECKALL")
+ field(ASG, "PROTECTED")
+ field(ZSV, "MINOR")
+ field(OSV, "NO_ALARM")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(bo, "$(DEVICE):CHECK4") {
+ field(DESC, "current above min")
+ field(FLNK, "$(DEVICE):CHECKALL")
+ field(ASG, "PROTECTED")
+ field(ZSV, "MINOR")
+ field(OSV, "NO_ALARM")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(bo, "$(DEVICE):CHECK5") {
+ field(DESC, "tune bpm config")
+ field(FLNK, "$(DEVICE):CHECKALL")
+ field(ASG, "PROTECTED")
+ field(ZSV, "MINOR")
+ field(OSV, "NO_ALARM")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(bo, "$(DEVICE):CHECK6") {
+ field(DESC, "pingers on")
+ field(FLNK, "$(DEVICE):CHECKALL")
+ field(ASG, "PROTECTED")
+ field(ZSV, "MINOR")
+ field(OSV, "NO_ALARM")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(bo, "$(DEVICE):CHECK7") {
+ field(DESC, "dt corresponds to 3.125 Hz")
+ field(FLNK, "$(DEVICE):CHECKALL")
+ field(ASG, "PROTECTED")
+ field(ZSV, "MINOR")
+ field(OSV, "NO_ALARM")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(bo, "$(DEVICE):CHECK8") {
+ field(DESC, "calculated step within limits")
+ field(FLNK, "$(DEVICE):CHECKALL")
+ field(ASG, "PROTECTED")
+ field(ZSV, "MINOR")
+ field(OSV, "NO_ALARM")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(calc, "$(DEVICE):CHECKALL") {
+ field(DESC, "Check SUM, written by IOC")
+ field(ASG, "READONLY")
+ field(LOLO, "0.1")
+ field(LLSV, "MINOR")
+ field(CALC, "A & B & C & D & E & F & G & H")
+ field(INPA, "$(DEVICE):CHECK1")
+ field(INPB, "$(DEVICE):CHECK2")
+ field(INPC, "$(DEVICE):CHECK3")
+ field(INPD, "$(DEVICE):CHECK4")
+ field(INPE, "$(DEVICE):CHECK5")
+ field(INPF, "$(DEVICE):CHECK6")
+ field(INPG, "$(DEVICE):CHECK7")
+ field(INPH, "$(DEVICE):CHECK8")
+}
\ No newline at end of file
diff --git a/services/tunefbx/current/ioc/startup.script b/services/tunefbx/current/ioc/startup.script
new file mode 100644
index 0000000..0fa52ff
--- /dev/null
+++ b/services/tunefbx/current/ioc/startup.script
@@ -0,0 +1 @@
+epicsEnvSet("ENGINEER", "armborst")
diff --git a/services/tunefbx/current/qt/A_BD_TuneBump.ui b/services/tunefbx/current/qt/A_BD_TuneBump.ui
new file mode 100644
index 0000000..22fe977
--- /dev/null
+++ b/services/tunefbx/current/qt/A_BD_TuneBump.ui
@@ -0,0 +1,6779 @@
+
+
+ MainWindow
+
+
+
+ 0
+ 0
+ 605
+ 960
+
+
+
+ MainWindow
+
+
+ /*################################################*/
+/*# Settings for new templates/forms #*/
+/*################################################*/
+QMainWindow#MainWindow, QWidget#Form, QDialog#Dialog{
+ background: rgba(236, 236, 236, 255);
+}
+
+QMainWindow#MainWindow[transparent=true], QWidget#Form[transparent=true], QDialog#Dialog[transparent=true]{
+ background: rgba(0, 0, 0, 0);
+}
+
+/*-----------------------------------------------*/
+/* Title */
+/*-----------------------------------------------*/
+/* Operation panels */
+caLabel[statusTip="Operation"]{
+ color: rgba(0, 0, 0, 255);
+ font: bold 18pt;
+ font-family: Sans Serif;
+ padding: 1px;
+ margin: 0px;
+ qproperty-alignment: AlignLeft;
+ qproperty-frameShape: StyledPanel;
+ /*qproperty-geometry: rect(-2 0 1600 33);*/
+ background: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1,
+ stop:0 rgba(218, 218, 218, 255),
+ stop:0.5 rgba(200, 200, 200, 255),
+ stop:1 rgba(218, 218, 218, 255));
+}
+
+ QGroupBox {
+ background: rgba(225,225,225,255);
+ border: 2px solid black;
+ border-radius: 5px;
+ margin-top: 1ex; /* leave space at the top for the title */
+ }
+
+
+
+
+
+ 810
+ 120
+ 70
+ 20
+
+
+
+
+
+
+ 810
+ 60
+ 70
+ 20
+
+
+
+ Reload
+
+
+ RELOAD
+
+
+ A
+
+
+ AGEBD-ALH:TUNEBUMP-GUIRELOAD
+
+
+ caCalc::TriggerZeroToOne
+
+
+
+
+
+ 340
+ 60
+ 40
+ 30
+
+
+
+ <<
+
+
+ false
+
+
+ AGEBD-TUNEBUMP:QX-STEPDOWN
+
+
+ <<
+
+
+
+ 160
+ 160
+ 160
+
+
+
+
+
+
+ 1
+
+
+ caMessageButton::as_is
+
+
+
+
+
+ 390
+ 60
+ 150
+ 30
+
+
+
+ 1
+
+
+ 4
+
+
+ AGEBD-TUNEBUMP:QX-STEPSIZE
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caSpinbox::as_is
+
+
+
+
+
+ 390
+ 160
+ 150
+ 30
+
+
+
+ 1
+
+
+ 4
+
+
+ AGEBD-TUNEBUMP:QY-STEPSIZE
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caSpinbox::as_is
+
+
+
+
+
+ 390
+ 35
+ 150
+ 20
+
+
+
+
+ 12
+ 75
+ true
+
+
+
+ Step Size
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 340
+ 160
+ 40
+ 30
+
+
+
+ <<
+
+
+ false
+
+
+ AGEBD-TUNEBUMP:QY-STEPDOWN
+
+
+ <<
+
+
+
+ 160
+ 160
+ 160
+
+
+
+
+
+
+ 1
+
+
+ caMessageButton::as_is
+
+
+
+
+
+ 10
+ 60
+ 50
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ Qx
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 42
+ 99
+ 228
+
+
+
+
+
+
+ 10
+ 160
+ 50
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ Qy
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 139
+ 26
+ 150
+
+
+
+
+
+
+ 550
+ 160
+ 40
+ 30
+
+
+
+ >>
+
+
+ false
+
+
+ AGEBD-TUNEBUMP:QY-STEPUP
+
+
+ >>
+
+
+
+ 160
+ 160
+ 160
+
+
+
+
+
+
+ 1
+
+
+ caMessageButton::as_is
+
+
+
+
+
+ 547
+ 60
+ 40
+ 30
+
+
+
+ >>
+
+
+ false
+
+
+ AGEBD-TUNEBUMP:QX-STEPUP
+
+
+ >>
+
+
+
+ 160
+ 160
+ 160
+
+
+
+
+
+
+ 1
+
+
+ caMessageButton::as_is
+
+
+
+
+
+ 0
+ 0
+ 600
+ 32
+
+
+
+
+ Sans Serif
+ 18
+ 75
+ false
+ true
+
+
+
+ Operation
+
+
+ Tune Shift
+
+
+ Qt::AlignLeading
+
+
+
+ 218
+ 218
+ 218
+
+
+
+ caLabel::Default
+
+
+
+
+
+ 0
+ 300
+ 605
+ 660
+
+
+
+ 0
+
+
+
+ Meas
+
+
+
+
+ 5
+ 210
+ 590
+ 200
+
+
+
+ Vertical Tune (nominal: Qy = 15.22)
+
+
+ AGEBD-TUNEBUMP:NORM-QY-FREQ;AGEBD-TUNEBUMP:NORM-QY-AMP
+
+
+
+ 139
+ 26
+ 150
+
+
+
+ AGEBD-TUNEBUMP:QY-PEAKS-FREQ;AGEBD-TUNEBUMP:QY-PEAKS
+
+
+ caCartesianPlot::Sticks
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+ 139
+ 26
+ 150
+
+
+
+ caCartesianPlot::User
+
+
+ caCartesianPlot::Auto
+
+
+ 0.15;0.29
+
+
+ false
+
+
+ 14
+
+
+ caCartesianPlot::linear
+
+
+
+
+
+ 5
+ 415
+ 590
+ 200
+
+
+
+ Synchrotron Tune (nominal: 0.0027)
+
+
+ AGEBD-TUNEBUMP:NORM-QZ-FREQ;AGEBD-TUNEBUMP:NORM-QZ-AMP
+
+
+
+ 205
+ 97
+ 0
+
+
+
+ AGEBD-TUNEBUMP:QZ-PEAKS-FREQ;AGEBD-TUNEBUMP:QZ-PEAKS
+
+
+ caCartesianPlot::Sticks
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+ 205
+ 97
+ 0
+
+
+
+ caCartesianPlot::Auto
+
+
+ caCartesianPlot::Auto
+
+
+ 0.0005;0.0025
+
+
+ false
+
+
+ 10
+
+
+ caCartesianPlot::linear
+
+
+
+
+
+ 5
+ 5
+ 590
+ 200
+
+
+
+ Horizontal Tune (nominal: Qx = 39.37)
+
+
+ AGEBD-TUNEBUMP:NORM-QX-FREQ;AGEBD-TUNEBUMP:NORM-QX-AMP
+
+
+
+ 42
+ 99
+ 228
+
+
+
+ AGEBD-TUNEBUMP:QX-PEAKS-FREQ;AGEBD-TUNEBUMP:QX-PEAKS
+
+
+ caCartesianPlot::Sticks
+
+
+ caCartesianPlot::NoSymbol
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+ 42
+ 99
+ 228
+
+
+
+ caCartesianPlot::Auto
+
+
+ caCartesianPlot::Auto
+
+
+ 0.3;0.44
+
+
+
+
+
+ false
+
+
+ false
+
+
+ 14
+
+
+ caCartesianPlot::linear
+
+
+
+
+
+ FFT
+
+
+
+
+ 0
+ 415
+ 590
+ 200
+
+
+
+ Tune Z
+
+
+ AGEBD-TUNEBUMP:SPEC-FREQ-qZ;AGEBD-TUNEBUMP:SPEC-Z
+
+
+
+ 205
+ 97
+ 0
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+ caCartesianPlot::User
+
+
+ caCartesianPlot::Auto
+
+
+ 0.0005;0.0025
+
+
+ 10
+
+
+ caCartesianPlot::log10
+
+
+
+
+
+ 0
+ 210
+ 590
+ 200
+
+
+
+ Tune Y
+
+
+ AGEBD-TUNEBUMP:SPEC-FREQ-qY;AGEBD-TUNEBUMP:SPEC-Y
+
+
+
+ 139
+ 26
+ 150
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+ caCartesianPlot::User
+
+
+ caCartesianPlot::Auto
+
+
+ 0.15;0.29
+
+
+ 14
+
+
+ caCartesianPlot::log10
+
+
+
+
+
+ 0
+ 5
+ 590
+ 200
+
+
+
+ Tune X
+
+
+ AGEBD-TUNEBUMP:SPEC-FREQ-qX;AGEBD-TUNEBUMP:SPEC-X
+
+
+
+ 42
+ 99
+ 228
+
+
+
+
+
+
+ caCartesianPlot::Sticks
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+ caCartesianPlot::User
+
+
+ caCartesianPlot::Auto
+
+
+ 0.3;0.44
+
+
+ 0:1
+
+
+ 14
+
+
+ caCartesianPlot::log10
+
+
+
+
+
+ Raw
+
+
+
+
+ 0
+ 210
+ 590
+ 200
+
+
+
+ Vertical TbT data
+
+
+ ;AGEBD-TUNEBUMP:SIGN-Y
+
+
+
+ 139
+ 26
+ 150
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+ caCartesianPlot::User
+
+
+ caCartesianPlot::Auto
+
+
+ 0;16384
+
+
+
+
+
+ 14
+
+
+ caCartesianPlot::linear
+
+
+
+
+
+ 0
+ 415
+ 590
+ 200
+
+
+
+ Longitudinal Stage 1 Data
+
+
+ ;AGEBD-TUNEBUMP:SIGN-Z
+
+
+
+ 205
+ 97
+ 0
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+ caCartesianPlot::User
+
+
+ caCartesianPlot::Auto
+
+
+ 0;16384
+
+
+
+
+
+ 10
+
+
+ caCartesianPlot::linear
+
+
+
+
+
+ 0
+ 5
+ 590
+ 200
+
+
+
+ Horizontal TbT data
+
+
+ ;AGEBD-TUNEBUMP:SIGN-X
+
+
+
+ 42
+ 99
+ 228
+
+
+
+
+
+
+ caCartesianPlot::Sticks
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+ caCartesianPlot::User
+
+
+ caCartesianPlot::Auto
+
+
+ 0;16384
+
+
+
+
+
+ 14
+
+
+ caCartesianPlot::linear
+
+
+
+
+
+ Settings
+
+
+
+
+ 10
+ 260
+ 371
+ 51
+
+
+
+
+ 19
+ 75
+ true
+
+
+
+ Pinger Settings (ca. 10 A)
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 440
+ 320
+ 150
+ 40
+
+
+
+ 3
+
+
+ 2
+
+
+ ARS01-MKIK-0320:I-SET
+
+
+ caSpinbox::User
+
+
+ caSpinbox::User
+
+
+ 300.000000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 140
+ 320
+ 150
+ 40
+
+
+
+ 3
+
+
+ 2
+
+
+ ARS01-MKIK-0290:I-SET
+
+
+ caSpinbox::User
+
+
+ caSpinbox::User
+
+
+ 300.000000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 160
+ 490
+ 291
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ Enable Energy Stabelization:
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 10
+ 450
+ 581
+ 30
+
+
+
+
+ 12
+ 75
+ true
+
+
+
+ Defined by FOFB Mean Horizontal Corrector Integral Setpoint:
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+
+
+ 250
+ 530
+ 110
+ 30
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ ARSGE-CECL-FOFB1:MCOX-INTEGRAL-ERR
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Alarm_Static
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 30
+ 490
+ 110
+ 30
+
+
+
+ 1
+
+
+ 4
+
+
+ ARSGE-CECL-FOFB1:MCOX-INTEGRAL-REF-DEFAULT
+
+
+ caSpinbox::User
+
+
+ caSpinbox::User
+
+
+ 1.000000000000000
+
+
+ -1.000000000000000
+
+
+
+
+
+ 10
+ 10
+ 400
+ 40
+
+
+
+
+ 24
+ 75
+ true
+
+
+
+ Qx Search Range
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 42
+ 99
+ 228
+
+
+
+
+
+
+ 10
+ 130
+ 400
+ 40
+
+
+
+
+ 25
+ 75
+ true
+
+
+
+ Qy Search Range
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 139
+ 26
+ 150
+
+
+
+
+
+
+ 10
+ 60
+ 121
+ 40
+
+
+
+
+ 16
+ 50
+ false
+
+
+
+ Lower limit
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 310
+ 60
+ 121
+ 40
+
+
+
+
+ 16
+ 50
+ false
+
+
+
+ Upper limit
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 440
+ 60
+ 150
+ 40
+
+
+
+ 1
+
+
+ 2
+
+
+ AGEBD-TUNEBUMP:QX-ULIM
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 140
+ 60
+ 150
+ 40
+
+
+
+ 1
+
+
+ 2
+
+
+ AGEBD-TUNEBUMP:QX-LLIM
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 440
+ 180
+ 150
+ 40
+
+
+
+ 1
+
+
+ 2
+
+
+ AGEBD-TUNEBUMP:QY-ULIM
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 310
+ 180
+ 121
+ 40
+
+
+
+
+ 16
+ 50
+ false
+
+
+
+ Upper limit
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 140
+ 180
+ 150
+ 40
+
+
+
+ 1
+
+
+ 2
+
+
+ AGEBD-TUNEBUMP:QY-LLIM
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 10
+ 180
+ 121
+ 40
+
+
+
+
+ 16
+ 50
+ false
+
+
+
+ Lower limit
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 10
+ 320
+ 121
+ 40
+
+
+
+
+ 17
+ 50
+ false
+
+
+
+ Horizontal
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 310
+ 320
+ 121
+ 40
+
+
+
+
+ 24
+ 50
+ false
+
+
+
+ Vertical
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 10
+ 390
+ 371
+ 51
+
+
+
+
+ 22
+ 75
+ true
+
+
+
+ Beam Energy Setpoint
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+
+
+ 450
+ 490
+ 31
+ 30
+
+
+
+ ARSGE-CECL-FOFB1:MCOX-INTEGRAL-REF-DEFAULT-EN
+
+
+
+
+
+ 160
+ 530
+ 91
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ ERROR:
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ BPMs
+
+
+
+
+ 10
+ 20
+ 400
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ Horizontal Tune BPM
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 42
+ 99
+ 228
+
+
+
+
+
+
+ 10
+ 140
+ 400
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ Vertical Tune BPM
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 139
+ 26
+ 150
+
+
+
+
+
+
+ 10
+ 270
+ 400
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ Longitudinal Tune BPM
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 205
+ 97
+ 0
+
+
+
+
+
+
+ 10
+ 180
+ 580
+ 30
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEBUMP:SIGN-Y.INP
+
+
+
+ 139
+ 26
+ 150
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 10
+ 60
+ 580
+ 30
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEBUMP:SIGN-X.INP
+
+
+
+ 42
+ 99
+ 228
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 10
+ 310
+ 580
+ 30
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEBUMP:SIGN-Z.INP
+
+
+
+ 205
+ 97
+ 0
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+
+
+
+
+
+
+ FeedBack QX
+
+
+
+
+ 400
+ 210
+ 150
+ 40
+
+
+
+ 1
+
+
+ 3
+
+
+ AGEBD-TUNEFBX:CONTROL-KP
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 10
+ 10
+ 400
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ Horizontal Tune Feedback
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 42
+ 99
+ 228
+
+
+
+
+
+
+ 310
+ 210
+ 80
+ 40
+
+
+
+
+ 25
+ 50
+ false
+
+
+
+ <html><head/><body><p>K<span style=" vertical-align:sub;">P</span></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 310
+ 260
+ 80
+ 40
+
+
+
+
+ 25
+ 50
+ false
+
+
+
+ <html><head/><body><p>K<span style=" vertical-align:sub;">I</span></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 310
+ 310
+ 80
+ 40
+
+
+
+
+ 25
+ 50
+ false
+
+
+
+ <html><head/><body><p>K<span style=" vertical-align:sub;">D</span></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 400
+ 260
+ 150
+ 40
+
+
+
+ 1
+
+
+ 3
+
+
+ AGEBD-TUNEFBX:CONTROL-KI
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 400
+ 310
+ 150
+ 40
+
+
+
+ 1
+
+
+ 3
+
+
+ AGEBD-TUNEFBX:CONTROL-KD
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 120
+ 60
+ 171
+ 40
+
+
+
+ 1
+
+
+ 2
+
+
+ AGEBD-TUNEFBX:CONTROL-QX
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 20
+ 60
+ 80
+ 40
+
+
+
+
+ 23
+ 50
+ false
+
+
+
+ <html><head/><body><p>Q<span style=" vertical-align:sub;">X,set</span></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 120
+ 110
+ 171
+ 40
+
+
+
+ 1
+
+
+ 2
+
+
+ AGEBD-TUNEFBX:CONTROL-QXMAX
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 20
+ 110
+ 80
+ 40
+
+
+
+
+ 17
+ 50
+ false
+
+
+
+ <html><head/><body><p>Q<span style=" vertical-align:sub;">X,DRVH</span></p><p><br/></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 120
+ 160
+ 171
+ 40
+
+
+
+ 1
+
+
+ 2
+
+
+ AGEBD-TUNEFBX:CONTROL-QXMIN
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 20
+ 160
+ 80
+ 40
+
+
+
+
+ 17
+ 50
+ false
+
+
+
+ <html><head/><body><p>Q<span style=" vertical-align:sub;">X,DRVL</span></p><p><br/></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 20
+ 260
+ 80
+ 40
+
+
+
+
+ 25
+ 50
+ false
+
+
+
+ <html><head/><body><p>I<span style=" vertical-align:sub;">min</span></p><p><br/></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 120
+ 260
+ 171
+ 40
+
+
+
+ 3
+
+
+ 1
+
+
+ AGEBD-TUNEFBX:CONTROL-MIN-CURR
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 20
+ 210
+ 80
+ 40
+
+
+
+
+ 16
+ 50
+ false
+
+
+
+ <html><head/><body><p>Q<span style=" vertical-align:sub;">OKrange</span></p><p><br/></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 120
+ 210
+ 171
+ 40
+
+
+
+ 1
+
+
+ 4
+
+
+ true
+
+
+ AGEBD-TUNEFBX:CONTROL-QX-OKRNG
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 400
+ 60
+ 150
+ 40
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEFBX:DELTAQ
+
+
+
+ 139
+ 26
+ 150
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 310
+ 60
+ 80
+ 40
+
+
+
+
+ 25
+ 50
+ false
+
+
+
+ <html><head/><body><p>ΔQ</p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 20
+ 380
+ 571
+ 240
+
+
+
+
+ 10
+ 75
+ true
+
+
+
+ Accumulated Tune Steps
+
+
+
+
+
+
+
+
+ AGEBD-TUNEFBX:QSTEPS
+
+
+ caStripPlot::Second
+
+
+ 600.000000000000000
+
+
+ caStripPlot::High
+
+
+ caStripPlot::linear
+
+
+ caStripPlot::autoScale
+
+
+ 0.000000000000000
+
+
+ 0.000000001000000
+
+
+ caStripPlot::Channel
+
+
+ caStripPlot::Channel
+
+
+
+ 42
+ 99
+ 228
+
+
+
+ 0.000000410000000
+
+
+ 0.000000001000000
+
+
+ caStripPlot::User
+
+
+ caStripPlot::User
+
+
+
+ 252
+ 192
+ 11
+
+
+
+ 0.000000410000000
+
+
+ 0.000000001000000
+
+
+ caStripPlot::User
+
+
+ caStripPlot::User
+
+
+
+ 252
+ 192
+ 11
+
+
+
+ 0.000000410000000
+
+
+ 0.000000001000000
+
+
+ caStripPlot::User
+
+
+ caStripPlot::User
+
+
+
+ 239
+ 41
+ 41
+
+
+
+ 0.000000410000000
+
+
+ 0.000000001000000
+
+
+ caStripPlot::User
+
+
+ caStripPlot::User
+
+
+
+ 239
+ 41
+ 41
+
+
+
+ 0.000000410000000
+
+
+ 0.000000001000000
+
+
+ caStripPlot::User
+
+
+ caStripPlot::User
+
+
+
+ 255
+ 0
+ 255
+
+
+
+ 0.000000100000000
+
+
+ 0.000000001000000
+
+
+
+ 218
+ 218
+ 218
+
+
+
+ true
+
+
+ false
+
+
+
+
+
+ 390
+ 10
+ 160
+ 30
+
+
+
+ AGEBD-ALH:TUNEFBX-ONOFF
+
+
+ caChoice::Column
+
+
+ 1
+
+
+
+
+
+ 120
+ 350
+ 30
+ 30
+
+
+
+ AGEBD-TUNEFBX:CHECK1
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 170
+ 350
+ 30
+ 30
+
+
+
+ AGEBD-TUNEFBX:CHECK2
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 400
+ 350
+ 20
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ +
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 320
+ 350
+ 30
+ 30
+
+
+
+ AGEBD-TUNEFBX:CHECK5
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 470
+ 350
+ 30
+ 30
+
+
+
+ AGEBD-TUNEFBX:CHECK8
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 350
+ 350
+ 20
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ +
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 220
+ 350
+ 30
+ 30
+
+
+
+ AGEBD-TUNEFBX:CHECK3
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 250
+ 350
+ 20
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ +
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 370
+ 350
+ 30
+ 30
+
+
+
+ AGEBD-TUNEFBX:CHECK6
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 270
+ 350
+ 30
+ 30
+
+
+
+ AGEBD-TUNEFBX:CHECK4
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 450
+ 350
+ 20
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ +
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 420
+ 350
+ 30
+ 30
+
+
+
+ AGEBD-TUNEFBX:CHECK7
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 300
+ 350
+ 20
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ +
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 500
+ 350
+ 20
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ =
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 520
+ 350
+ 30
+ 30
+
+
+
+ true
+
+
+ true
+
+
+ AGEBD-TUNEFBX:CHECKALL
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 200
+ 350
+ 20
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ +
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 150
+ 350
+ 20
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ +
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 310
+ 110
+ 80
+ 40
+
+
+
+
+ 20
+ 50
+ false
+
+
+
+ <html><head/><body><p>ΔQ<span style=" vertical-align:sub;">max</span></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 310
+ 160
+ 80
+ 40
+
+
+
+
+ 21
+ 50
+ false
+
+
+
+ <html><head/><body><p>ΔQ<span style=" vertical-align:sub;">min</span></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 400
+ 110
+ 150
+ 40
+
+
+
+ 1
+
+
+ 3
+
+
+ AGEBD-TUNEFBX:DELTAQ-ULIM
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 400
+ 160
+ 150
+ 40
+
+
+
+ 1
+
+
+ 3
+
+
+ AGEBD-TUNEFBX:DELTAQ-LLIM
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 40
+ 355
+ 80
+ 20
+
+
+
+
+ 11
+ 50
+ false
+
+
+
+ <html><head/><body><p>Conditions<br/></p></body></html>
+
+
+ Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ Feedback QY
+
+
+
+
+ 10
+ 10
+ 400
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ Vertical Tune Feedback
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 139
+ 26
+ 150
+
+
+
+
+
+
+ 120
+ 60
+ 171
+ 40
+
+
+
+ 1
+
+
+ 2
+
+
+ AGEBD-TUNEFBY:CONTROL-QY
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 310
+ 210
+ 80
+ 40
+
+
+
+
+ 25
+ 50
+ false
+
+
+
+ <html><head/><body><p>K<span style=" vertical-align:sub;">P</span></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 120
+ 210
+ 171
+ 40
+
+
+
+ 1
+
+
+ 4
+
+
+ true
+
+
+ AGEBD-TUNEFBY:CONTROL-QY-OKRNG
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 200
+ 350
+ 20
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ +
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 400
+ 260
+ 150
+ 40
+
+
+
+ 1
+
+
+ 3
+
+
+ AGEBD-TUNEFBY:CONTROL-KI
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 310
+ 60
+ 80
+ 40
+
+
+
+
+ 25
+ 50
+ false
+
+
+
+ <html><head/><body><p>ΔQ</p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 310
+ 310
+ 80
+ 40
+
+
+
+
+ 25
+ 50
+ false
+
+
+
+ <html><head/><body><p>K<span style=" vertical-align:sub;">D</span></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 270
+ 350
+ 30
+ 30
+
+
+
+ AGEBD-TUNEFBY:CHECK4
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 400
+ 210
+ 150
+ 40
+
+
+
+ 1
+
+
+ 3
+
+
+ AGEBD-TUNEFBY:CONTROL-KP
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 120
+ 110
+ 171
+ 40
+
+
+
+ 1
+
+
+ 2
+
+
+ AGEBD-TUNEFBY:CONTROL-QYMAX
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 250
+ 350
+ 20
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ +
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 300
+ 350
+ 20
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ +
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 20
+ 160
+ 80
+ 40
+
+
+
+
+ 18
+ 50
+ false
+
+
+
+ <html><head/><body><p>Q<span style=" vertical-align:sub;">Y,DRVL</span></p><p><br/></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 400
+ 310
+ 150
+ 40
+
+
+
+ 1
+
+
+ 3
+
+
+ AGEBD-TUNEFBY:CONTROL-KD
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 220
+ 350
+ 30
+ 30
+
+
+
+ AGEBD-TUNEFBY:CHECK3
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 350
+ 350
+ 20
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ +
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 150
+ 350
+ 20
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ +
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 20
+ 60
+ 80
+ 40
+
+
+
+
+ 24
+ 50
+ false
+
+
+
+ <html><head/><body><p>Q<span style=" vertical-align:sub;">Y,set</span></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 20
+ 210
+ 80
+ 40
+
+
+
+
+ 16
+ 50
+ false
+
+
+
+ <html><head/><body><p>Q<span style=" vertical-align:sub;">OKrange</span></p><p><br/></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 400
+ 60
+ 150
+ 40
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEFBY:DELTAQ
+
+
+
+ 139
+ 26
+ 150
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 500
+ 350
+ 20
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ =
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 520
+ 350
+ 33
+ 30
+
+
+
+ true
+
+
+ 18
+
+
+ 18
+
+
+ true
+
+
+ AGEBD-TUNEFBY:CHECKALL
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 320
+ 350
+ 30
+ 30
+
+
+
+ AGEBD-TUNEFBY:CHECK5
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 170
+ 350
+ 30
+ 30
+
+
+
+ AGEBD-TUNEFBY:CHECK2
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 310
+ 260
+ 80
+ 40
+
+
+
+
+ 25
+ 50
+ false
+
+
+
+ <html><head/><body><p>K<span style=" vertical-align:sub;">I</span></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 120
+ 160
+ 171
+ 40
+
+
+
+ 1
+
+
+ 2
+
+
+ AGEBD-TUNEFBY:CONTROL-QYMIN
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 120
+ 350
+ 30
+ 30
+
+
+
+ AGEBD-TUNEFBY:CHECK1
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 40
+ 355
+ 80
+ 20
+
+
+
+
+ 11
+ 50
+ false
+
+
+
+ <html><head/><body><p>Conditions<br/></p></body></html>
+
+
+ Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 390
+ 10
+ 160
+ 30
+
+
+
+ AGEBD-ALH:TUNEFBY-ONOFF
+
+
+ caChoice::Column
+
+
+ 1
+
+
+
+
+
+ 370
+ 350
+ 30
+ 30
+
+
+
+ AGEBD-TUNEFBY:CHECK6
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 20
+ 380
+ 571
+ 240
+
+
+
+
+ 10
+ 75
+ true
+
+
+
+ Accumulated Tune Steps
+
+
+
+
+
+
+
+
+ AGEBD-TUNEFBY:QSTEPS
+
+
+ caStripPlot::Second
+
+
+ 600.000000000000000
+
+
+ caStripPlot::High
+
+
+ caStripPlot::linear
+
+
+ caStripPlot::autoScale
+
+
+ 0.000000000000000
+
+
+ 0.000000001000000
+
+
+ caStripPlot::Channel
+
+
+ caStripPlot::Channel
+
+
+
+ 42
+ 99
+ 228
+
+
+
+ 0.000000410000000
+
+
+ 0.000000001000000
+
+
+ caStripPlot::User
+
+
+ caStripPlot::User
+
+
+
+ 252
+ 192
+ 11
+
+
+
+ 0.000000410000000
+
+
+ 0.000000001000000
+
+
+ caStripPlot::User
+
+
+ caStripPlot::User
+
+
+
+ 252
+ 192
+ 11
+
+
+
+ 0.000000410000000
+
+
+ 0.000000001000000
+
+
+ caStripPlot::User
+
+
+ caStripPlot::User
+
+
+
+ 239
+ 41
+ 41
+
+
+
+ 0.000000410000000
+
+
+ 0.000000001000000
+
+
+ caStripPlot::User
+
+
+ caStripPlot::User
+
+
+
+ 239
+ 41
+ 41
+
+
+
+ 0.000000410000000
+
+
+ 0.000000001000000
+
+
+ caStripPlot::User
+
+
+ caStripPlot::User
+
+
+
+ 255
+ 0
+ 255
+
+
+
+ 0.000000100000000
+
+
+ 0.000000001000000
+
+
+
+ 218
+ 218
+ 218
+
+
+
+ true
+
+
+ false
+
+
+
+
+
+ 20
+ 260
+ 80
+ 40
+
+
+
+
+ 25
+ 50
+ false
+
+
+
+ <html><head/><body><p>I<span style=" vertical-align:sub;">min</span></p><p><br/></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 20
+ 110
+ 80
+ 40
+
+
+
+
+ 17
+ 50
+ false
+
+
+
+ <html><head/><body><p>Q<span style=" vertical-align:sub;">Y,DRVH</span></p><p><br/></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 120
+ 260
+ 171
+ 40
+
+
+
+ 3
+
+
+ 1
+
+
+ AGEBD-TUNEFBY:CONTROL-MIN-CURR
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 400
+ 350
+ 20
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ +
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 420
+ 350
+ 30
+ 30
+
+
+
+ AGEBD-TUNEFBY:CHECK7
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 470
+ 350
+ 30
+ 30
+
+
+
+ AGEBD-TUNEFBY:CHECK8
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 450
+ 350
+ 20
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ +
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 310
+ 160
+ 80
+ 40
+
+
+
+
+ 21
+ 50
+ false
+
+
+
+ <html><head/><body><p>ΔQ<span style=" vertical-align:sub;">min</span></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 400
+ 110
+ 150
+ 40
+
+
+
+ 1
+
+
+ 3
+
+
+ AGEBD-TUNEFBY:DELTAQ-ULIM
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 400
+ 160
+ 150
+ 40
+
+
+
+ 1
+
+
+ 3
+
+
+ AGEBD-TUNEFBY:DELTAQ-LLIM
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 310
+ 110
+ 80
+ 40
+
+
+
+
+ 20
+ 50
+ false
+
+
+
+ <html><head/><body><p>ΔQ<span style=" vertical-align:sub;">max</span></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ Debug
+
+
+
+
+ 250
+ 20
+ 31
+ 30
+
+
+
+ AGEBD-TUNEBUMP:WRITE2MAG
+
+
+
+
+
+ 10
+ 20
+ 231
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ Apply MQCO Setpoints
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 4
+ 50
+ 595
+ 575
+
+
+
+
+ Monospace
+ 10
+ PreferDefault
+
+
+
+ Qt::ScrollBarAlwaysOn
+
+
+ Qt::ScrollBarAsNeeded
+
+
+ AGEBD-TUNEBUMP:CHANGELOG
+
+
+ caMultiLineString::None
+
+
+
+
+
+
+
+ 60
+ 60
+ 100
+ 30
+
+
+
+
+ Lucida Sans Typewriter
+ 16
+
+
+
+ true
+
+
+
+
+
+
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEBUMP:QX
+
+
+
+ 42
+ 99
+ 228
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caLineEdit::Static
+
+
+ true
+
+
+
+ 42
+ 99
+ 228
+
+
+
+ 1
+
+
+ caLineEdit::onBackground
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::None
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 60
+ 160
+ 100
+ 30
+
+
+
+
+ Lucida Sans Typewriter
+ 16
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEBUMP:QY
+
+
+
+ 139
+ 26
+ 150
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caLineEdit::Static
+
+
+ true
+
+
+
+ 139
+ 26
+ 150
+
+
+
+ 1
+
+
+ caLineEdit::onBackground
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::None
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 110
+ 100
+ 121
+ 20
+
+
+
+
+ 12
+ 75
+ true
+
+
+
+ Sideband 1
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 250
+ 100
+ 110
+ 20
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEBUMP:QX-SB1
+
+
+
+ 42
+ 99
+ 228
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 480
+ 100
+ 110
+ 20
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEBUMP:QX-SB1-DIFF
+
+
+
+ 42
+ 99
+ 228
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 110
+ 130
+ 121
+ 20
+
+
+
+
+ 12
+ 75
+ true
+
+
+
+ Sideband 2
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 250
+ 130
+ 110
+ 20
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEBUMP:QX-SB2
+
+
+
+ 42
+ 99
+ 228
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 480
+ 130
+ 110
+ 20
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEBUMP:QX-SB2-DIFF
+
+
+
+ 42
+ 99
+ 228
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 380
+ 100
+ 91
+ 20
+
+
+
+
+ 12
+ 75
+ true
+
+
+
+ Distance
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 380
+ 130
+ 91
+ 20
+
+
+
+
+ 12
+ 75
+ true
+
+
+
+ Distance
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 380
+ 200
+ 91
+ 20
+
+
+
+
+ 12
+ 75
+ true
+
+
+
+ Distance
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 250
+ 200
+ 110
+ 20
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEBUMP:QY-SB1
+
+
+
+ 139
+ 26
+ 150
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 110
+ 200
+ 121
+ 20
+
+
+
+
+ 12
+ 75
+ true
+
+
+
+ Sideband 1
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 380
+ 230
+ 91
+ 20
+
+
+
+
+ 12
+ 75
+ true
+
+
+
+ Distance
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 110
+ 230
+ 121
+ 20
+
+
+
+
+ 12
+ 75
+ true
+
+
+
+ Sideband 2
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 250
+ 230
+ 110
+ 20
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEBUMP:QY-SB2
+
+
+
+ 139
+ 26
+ 150
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 480
+ 200
+ 110
+ 20
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEBUMP:QY-SB1-DIFF
+
+
+
+ 139
+ 26
+ 150
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 480
+ 230
+ 110
+ 20
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEBUMP:QY-SB2-DIFF
+
+
+
+ 139
+ 26
+ 150
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 170
+ 60
+ 160
+ 30
+
+
+
+
+ Lucida Sans Typewriter
+ 16
+
+
+
+ true
+
+
+
+
+
+
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEBUMP:QX-FREQ
+
+
+
+ 42
+ 99
+ 228
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caLineEdit::Static
+
+
+ true
+
+
+
+ 42
+ 99
+ 228
+
+
+
+ 1
+
+
+ caLineEdit::onBackground
+
+
+ 3
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::None
+
+
+ true
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 170
+ 160
+ 160
+ 30
+
+
+
+
+ Lucida Sans Typewriter
+ 16
+
+
+
+ true
+
+
+
+
+
+
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEBUMP:QY-FREQ
+
+
+
+ 139
+ 26
+ 150
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caLineEdit::Static
+
+
+ true
+
+
+
+ 139
+ 26
+ 150
+
+
+
+ 1
+
+
+ caLineEdit::onBackground
+
+
+ 3
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::None
+
+
+ true
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 10
+ 260
+ 50
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ Qz
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 205
+ 97
+ 0
+
+
+
+
+
+
+ 60
+ 260
+ 100
+ 30
+
+
+
+
+ Lucida Sans Typewriter
+ 16
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEBUMP:QZ
+
+
+
+ 205
+ 97
+ 0
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caLineEdit::Static
+
+
+ true
+
+
+
+ 205
+ 97
+ 0
+
+
+
+ 1
+
+
+ caLineEdit::onBackground
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::None
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 170
+ 260
+ 160
+ 30
+
+
+
+
+ Lucida Sans Typewriter
+ 16
+
+
+
+ true
+
+
+
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEBUMP:QZ-FREQ
+
+
+
+ 205
+ 97
+ 0
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caLineEdit::Static
+
+
+ true
+
+
+
+ 205
+ 97
+ 0
+
+
+
+ 1
+
+
+ caLineEdit::onBackground
+
+
+ 3
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::None
+
+
+ true
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 340
+ 60
+ 250
+ 30
+
+
+
+
+ Sans Serif
+ 18
+
+
+
+ Feedback ON
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ caLabel::Calc
+
+
+ A
+
+
+ AGEBD-ALH:TUNEFBX-ONOFF
+
+
+
+
+
+ 340
+ 160
+ 250
+ 30
+
+
+
+
+ Sans Serif
+ 18
+
+
+
+ Feedback ON
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ caLabel::Calc
+
+
+ A
+
+
+ AGEBD-ALH:TUNEFBY-ONOFF
+
+
+ calabel_3
+ wmsignalpropagator
+ cacalc_2
+ camessagebutton_14
+ caspinbox
+ caspinbox_2
+ calabel_12
+ camessagebutton_15
+ calabel_13
+ calabel_14
+ camessagebutton_16
+ camessagebutton_17
+ tabWidget
+ caLineEdit_39
+ caLineEdit_40
+ calabel_18
+ caLineEdit_43
+ caLineEdit_45
+ calabel_19
+ caLineEdit_48
+ caLineEdit_49
+ calabel_20
+ calabel_21
+ calabel_22
+ caLineEdit_44
+ calabel_23
+ calabel_24
+ calabel_25
+ caLineEdit_50
+ caLineEdit_46
+ caLineEdit_51
+ caLineEdit_42
+ caLineEdit_54
+ calabel_33
+ caLineEdit_55
+ caLineEdit_56
+ calabel
+ calabel_2
+
+
+
+
+ caMenu
+ QComboBox
+
+
+
+ caChoice
+ QWidget
+
+
+
+ caMessageButton
+ QPushButton
+
+
+
+ caToggleButton
+ QCheckBox
+
+
+
+ caSpinbox
+ QFrame
+
+
+
+ caLabel
+ QLabel
+
+
+
+ caLed
+ QWidget
+
+
+
+ caLineEdit
+ QLineEdit
+
+
+
+ caMultiLineString
+ QPlainTextEdit
+
+
+
+ caCartesianPlot
+ QwtPlot
+
+
+
+ caStripPlot
+ QwtPlot
+
+ 1
+
+
+ caCalc
+ QLabel
+
+
+
+ wmSignalPropagator
+ QLabel
+
+
+
+ QwtPlot
+ QFrame
+
+
+
+
+
+
+ cacalc_2
+ emitSignal(bool)
+ wmsignalpropagator
+ reloadwindow()
+
+
+ 598
+ 89
+
+
+ 608
+ 152
+
+
+
+
+
diff --git a/services/tunefbx/current/systemd/AGEBD-SERVICE-TUNEFBX.service b/services/tunefbx/current/systemd/AGEBD-SERVICE-TUNEFBX.service
new file mode 100644
index 0000000..84b2c61
--- /dev/null
+++ b/services/tunefbx/current/systemd/AGEBD-SERVICE-TUNEFBX.service
@@ -0,0 +1,16 @@
+[Unit]
+Description=AGEBD-SERVICE-TUNEFBX
+After=network.target
+
+[Service]
+Environment=AGEBD_ENV={{ agebd_env }}
+ExecStart=/sls/bd/hla/{{ agebd_env }}/bin/start_service.sh TUNEFBX
+Restart=no
+
+[Install]
+WantedBy=default.target
+
+# https://www.freedesktop.org/software/systemd/man/latest/systemd.service.html
+# systemctl --user daemon-reload
+# systemctl --user enable /sls/bd/bin/systemd/AGEBD-SERVICE-TUNEFBX.service
+# systemctl --user start AGEBD-SERVICE-TUNEFBX
diff --git a/services/tunefby/current/app/pyproject.toml b/services/tunefby/current/app/pyproject.toml
new file mode 100644
index 0000000..cdd7fc7
--- /dev/null
+++ b/services/tunefby/current/app/pyproject.toml
@@ -0,0 +1,48 @@
+[project]
+name = "agebd-tunefby"
+version = "0.1.0"
+description = "AGEBD-TUNEFBY Service"
+requires-python = "==3.10.*"
+dependencies = [
+ "agebd",
+ "numpy>=2.2.6",
+]
+
+[dependency-groups]
+dev = [
+ "pyepics>=3.5.8",
+ "pytest>=8.4.2",
+ "ruff>=0.15.20",
+]
+
+[tool.uv.sources]
+# Path is relative to where agebd package is deployed on hla
+# machines (see CI/CD in .gitea/workflows)
+agebd = { path = "../../../../packages/agebd", editable = true }
+
+[build-system]
+requires = ["hatchling"]
+build-backend = "hatchling.build"
+
+[tool.uv]
+package = true
+
+[tool.pytest.ini_options]
+pythonpath = ["src"]
+env = [
+ "AGEBD_ENV=local",
+]
+
+[tool.ruff]
+include = [
+ "src/**/*.py",
+ "tests/**/*.py",
+]
+line-length = 100
+
+[tool.ruff.lint]
+# use isort to sort imports
+extend-select = ["I"]
+
+[tool.ruff.lint.isort]
+known-first-party = ["agebd"]
diff --git a/services/tunefby/current/app/src/agebd_tunefby/__init__.py b/services/tunefby/current/app/src/agebd_tunefby/__init__.py
new file mode 100644
index 0000000..1800c27
--- /dev/null
+++ b/services/tunefby/current/app/src/agebd_tunefby/__init__.py
@@ -0,0 +1 @@
+from .service import PVs, Service
diff --git a/services/tunefby/current/app/src/agebd_tunefby/main.py b/services/tunefby/current/app/src/agebd_tunefby/main.py
new file mode 100644
index 0000000..ff69b86
--- /dev/null
+++ b/services/tunefby/current/app/src/agebd_tunefby/main.py
@@ -0,0 +1,31 @@
+import typer
+
+from agebd.enums import LogLevel
+from agebd.runner import CallbackRunner
+from agebd.utils import init_logging
+from agebd_tunefby import PVs, Service
+
+
+# TODO: remove: cicd test 10
+
+def main(
+ log_level: LogLevel = typer.Option(
+ LogLevel.INFO,
+ "--log-level",
+ "-l",
+ # Looks at the OS env variable first. If empty, falls back to "INFO"
+ envvar="AGEBD_LOG_LEVEL",
+ # help="Set log level: DEBUG, INFO, WARNING, ERROR, CRITICAL",
+ case_sensitive=False,
+ ),
+):
+ init_logging(log_level)
+ service_name = "TUNEFBY"
+ pvs = PVs(service_name=service_name)
+ service = Service(name=service_name, pvs=pvs)
+ runner = CallbackRunner(service=service)
+ runner.start()
+
+
+if __name__ == "__main__":
+ typer.run(main)
diff --git a/services/tunefby/current/app/src/agebd_tunefby/service.py b/services/tunefby/current/app/src/agebd_tunefby/service.py
new file mode 100644
index 0000000..160777d
--- /dev/null
+++ b/services/tunefby/current/app/src/agebd_tunefby/service.py
@@ -0,0 +1,218 @@
+from time import perf_counter
+
+import numpy as np
+from epics import dbr
+
+from agebd.pv import get_pv_class
+from agebd.service.base import BaseService
+from agebd.service.pvs import BasePVs
+from agebd.utils import printgetversion
+
+__version__ = printgetversion(__file__)
+
+PV = get_pv_class()
+
+
+class PVs(BasePVs):
+ ## Service specific PVs from dedicated IOC
+ kp = PV("AGEBD-TUNEFBY:CONTROL-KP.VAL")
+ ki = PV("AGEBD-TUNEFBY:CONTROL-KI.VAL")
+ kd = PV("AGEBD-TUNEFBY:CONTROL-KD.VAL")
+ qy_ref = PV("AGEBD-TUNEFBY:CONTROL-QY.VAL")
+ qy_okrng = PV("AGEBD-TUNEFBY:CONTROL-QY-OKRNG.VAL")
+ qy_drvh = PV("AGEBD-TUNEFBY:CONTROL-QYMAX.VAL")
+ qy_drvl = PV("AGEBD-TUNEFBY:CONTROL-QYMIN.VAL")
+ mincur = PV("AGEBD-TUNEFBY:CONTROL-MIN-CURR.VAL")
+ dq = PV("AGEBD-TUNEFBY:DELTAQ.VAL")
+ dq_ulim = PV("AGEBD-TUNEFBY:DELTAQ-ULIM.VAL")
+ dq_llim = PV("AGEBD-TUNEFBY:DELTAQ-LLIM.VAL")
+ check1 = PV("AGEBD-TUNEFBY:CHECK1.VAL")
+ check2 = PV("AGEBD-TUNEFBY:CHECK2.VAL")
+ check3 = PV("AGEBD-TUNEFBY:CHECK3.VAL")
+ check4 = PV("AGEBD-TUNEFBY:CHECK4.VAL")
+ check5 = PV("AGEBD-TUNEFBY:CHECK5.VAL")
+ check6 = PV("AGEBD-TUNEFBY:CHECK6.VAL")
+ check7 = PV("AGEBD-TUNEFBY:CHECK7.VAL")
+ check8 = PV("AGEBD-TUNEFBY:CHECK8.VAL")
+
+ # Output PVs
+ qy_stepdec = PV("AGEBD-TUNEBUMP:QY-STEPDOWN.VAL")
+ qy_stepinc = PV("AGEBD-TUNEBUMP:QY-STEPUP.VAL")
+ qy_stepsiz = PV("AGEBD-TUNEBUMP:QY-STEPSIZE.VAL")
+
+ ## Service specific PVs from other IOCs
+ inj_active = PV("AGEBD-PARAMS:INJECTION-ACTIVE.VAL")
+ dump_valve = PV("ARS01-VVPG-0210:PLC_STATUS.VAL")
+ hor_pinger_trig = PV("AGETI-CVME-MASTER-TMA:Evt-SR-Pinger-H-Ena-Sel.VAL")
+ ver_pinger_trig = PV("AGETI-CVME-MASTER-TMA:Evt-SR-Pinger-V-Ena-Sel.VAL")
+ cur = PV("ARS07-DPCT-0000:CURR.VAL")
+ bpm_qy_pilot_int = PV("ARS07-DBPM-5530:PILOT-INT-SWITCH.VAL") # must be: 0 No Pilot
+ bpm_qy_pilot_ext = PV("ARS07-DBPM-5530:PILOT-EXT-SWITCH.VAL") # must be: 0 No Pilot
+ bpm_qy_chopper = PV("ARS07-DBPM-5530:CHOPPER-MODE.VAL") # must be: 0 Periodic
+
+ def __init__(self, service_name: str, pv_factory=PV):
+ super().__init__(service_name, pv_factory)
+ PV = pv_factory
+
+ # usually it is advisable to trigger the mainloop of a service on changes of certain PVs:
+ self.CallbackPV = PV("AGEBD-TUNEBUMP:QY.VAL", auto_monitor=dbr.DBE_VALUE)
+
+
+class PID:
+ # Proportional-Integral-Derivative (PID) controller class
+ # PID setup procedure:
+ # 1. set integral and derivative gains ki, kd to 0
+ # 2. set proportional gain kp to low, stable value
+ # 3. increase kp and create a disturbance, e.g., by changing the setpoint
+ # 4. increase kp until feedback parameter oscillates
+ # 5. set kp to 40 % of the critical value triggering oscillation
+ # 6. slowly increase ki to eliminate the steady state error
+ # 7. adjust it until setpoint is reached accurately without overshoot
+ # 8. tune kd to minimize oscillations and overshoots (caution: high kd can amplify noise)
+
+ def __init__(self, kp, ki, kd, setpoint):
+
+ # Proportional Gain >> The "present" term. It provides a response proportional to the current error. Increasing kp makes the system respond faster, but if pushed too high, it will cause violent overshoot and oscillation.
+ self.kp = kp
+ # Integral Gain >> The "past" term. It accumulates the errors over time to eliminate steady-state error. However, high ki values can cause sluggishness or instability (e.g., integral windup).
+ self.ki = ki
+ # Derivative Gain >> The "future" term. It measures the rate of change of the error, acting as a damping factor to reduce overshoot and smooth out rapid, unwanted movements
+ self.kd = kd
+ self.setpoint = setpoint
+ self.integral = 0
+ self.prev_error = 0
+
+ def update(self, measurement, dt):
+
+ error = self.setpoint - measurement
+ self.integral += error * dt
+ derivative = (error - self.prev_error) / dt if dt > 0 else 0
+
+ self.prev_error = error
+
+ # Calculate the final output using Kp, Ki, and Kd which is written to actuator
+ output = (self.kp * error) + (self.ki * self.integral) + (self.kd * derivative)
+
+ return output
+
+
+class Service(BaseService[PVs]):
+ def __init__(
+ self,
+ name: str,
+ pvs: PVs,
+ version: str = __version__,
+ sleep_interval: float = 0.1,
+ ):
+ super().__init__(name, pvs, version, sleep_interval)
+
+ self.qy_okrng = pvs.qy_okrng.get()
+
+ self.PID = PID(pvs.kp.get(), pvs.ki.get(), pvs.kd.get(), pvs.qy_ref.get())
+ # start stop watch
+ self.t0 = perf_counter()
+
+ def update(self):
+ pvs = self.pvs
+
+ # when callback is fired, this code will be executed
+ if self.CallbackFired:
+ #######################################################################################
+ #######################################################################################
+ # here goes all the code that your service is supposed to be
+ # running every time when the callback is fired
+
+ # update PID settings
+ self.PID.setpoint = pvs.qy_ref.get()
+ self.PID.kp = pvs.kp.get()
+ self.PID.ki = pvs.ki.get()
+ self.PID.kd = pvs.kd.get()
+
+ self.qy_okrng = pvs.qy_okrng.get()
+
+ ############
+ ## CHECKS ##
+ ############
+ # 1. measured tune within drivelimits
+ self.check1 = (
+ pvs.qy_drvl.get() < self.CallbackValue and self.CallbackValue < pvs.qy_drvh.get()
+ )
+ pvs.check1.put(self.check1)
+
+ # 2. measured tune outside ok range limits
+ self.check2 = self.CallbackValue < (
+ self.PID.setpoint - self.qy_okrng
+ ) or self.CallbackValue > (self.PID.setpoint + self.qy_okrng)
+ pvs.check2.put(self.check2)
+
+ # 3. injection not active
+ self.check3 = not pvs.inj_active.get()
+ pvs.check3.put(self.check3)
+
+ # 4. stored beam current above threshold
+ self.check4 = pvs.cur.get() > pvs.mincur.get()
+ pvs.check4.put(self.check4)
+
+ # 5. bpm setup correctly for tune measurement
+ self.check5 = (
+ pvs.bpm_qy_pilot_int.get() == 0
+ and pvs.bpm_qy_pilot_ext.get() == 0
+ and pvs.bpm_qy_chopper.get() == 1
+ )
+ pvs.check5.put(self.check5)
+
+ # 6. pingers are on
+ self.check6 = pvs.hor_pinger_trig.get() and pvs.ver_pinger_trig.get()
+ pvs.check6.put(self.check6)
+
+ # 7. dt corresponds to 3.125 Hz, i.e., min. 2 consecutive valid measurements
+ t1 = perf_counter()
+ self.dt = t1 - self.t0
+ self.t0 = t1
+ self.check7 = self.dt < 1.1 / 3.125
+ pvs.check7.put(self.check7)
+
+ # check all checks before PID call
+ self.checkall = (
+ self.check1
+ and self.check2
+ and self.check3
+ and self.check4
+ and self.check5
+ and self.check6
+ and self.check7
+ )
+
+ if self.checkall:
+ # 8. PID calculated step within limits
+ self.control = self.PID.update(self.CallbackValue, self.dt)
+ self.dq_llim = pvs.dq_llim.get()
+ self.dq_ulim = pvs.dq_ulim.get()
+
+ self.check8 = self.control > self.dq_llim and self.control < self.dq_ulim
+ pvs.check8.put(self.check8)
+
+ if self.check8:
+ pvs.dq.put(self.control)
+ pvs.qy_stepsiz.put(np.abs(self.control))
+ if self.control < 0:
+ pvs.qy_stepdec.put(1)
+ else:
+ pvs.qy_stepinc.put(1)
+
+ #######################################################################################
+ #######################################################################################
+
+ # callback done
+ self.CallbackFired = 0
+
+ #######################################################################################
+ #######################################################################################
+ # here goes all the code that your service
+ # is supposed to be running in any case, e.g.,
+ # update some pvs/vals
+
+ # maybe sleep to limit the update loop execution rate
+ # sleep(1)
+ #######################################################################################
+ #######################################################################################
diff --git a/services/tunefby/current/app/tests/test_app.py b/services/tunefby/current/app/tests/test_app.py
new file mode 100644
index 0000000..d8727c2
--- /dev/null
+++ b/services/tunefby/current/app/tests/test_app.py
@@ -0,0 +1,9 @@
+from agebd_tunefby import PVs, Service
+
+
+def test_app():
+ service_name = "DUMMY"
+ pvs = PVs(service_name=service_name)
+ service = Service(name=service_name, pvs=pvs)
+ service.CallbackFired = 1
+ service.update()
diff --git a/services/tunefby/current/app/uv.lock b/services/tunefby/current/app/uv.lock
new file mode 100644
index 0000000..c4be5c0
--- /dev/null
+++ b/services/tunefby/current/app/uv.lock
@@ -0,0 +1,301 @@
+version = 1
+revision = 3
+requires-python = "==3.10.*"
+
+[[package]]
+name = "agebd"
+version = "0.1.0"
+source = { editable = "../../../../packages/agebd" }
+dependencies = [
+ { name = "h5py" },
+ { name = "typer" },
+]
+
+[package.metadata]
+requires-dist = [
+ { name = "h5py", specifier = ">=3.16.0" },
+ { name = "typer", specifier = ">=0.23.2" },
+]
+
+[package.metadata.requires-dev]
+dev = [
+ { name = "pyright", specifier = ">=1.1.410" },
+ { name = "pytest", specifier = ">=8.4.2" },
+ { name = "ruff", specifier = ">=0.15.19" },
+]
+
+[[package]]
+name = "agebd-tunefby"
+version = "0.1.0"
+source = { editable = "." }
+dependencies = [
+ { name = "agebd" },
+ { name = "numpy" },
+]
+
+[package.dev-dependencies]
+dev = [
+ { name = "pyepics" },
+ { name = "pytest" },
+ { name = "ruff" },
+]
+
+[package.metadata]
+requires-dist = [
+ { name = "agebd", editable = "../../../../packages/agebd" },
+ { name = "numpy", specifier = ">=2.2.6" },
+]
+
+[package.metadata.requires-dev]
+dev = [
+ { name = "pyepics", specifier = ">=3.5.8" },
+ { name = "pytest", specifier = ">=8.4.2" },
+ { name = "ruff", specifier = ">=0.15.20" },
+]
+
+[[package]]
+name = "annotated-doc"
+version = "0.0.4"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/57/ba/046ceea27344560984e26a590f90bc7f4a75b06701f653222458922b558c/annotated_doc-0.0.4.tar.gz", hash = "sha256:fbcda96e87e9c92ad167c2e53839e57503ecfda18804ea28102353485033faa4", size = 7288, upload-time = "2025-11-10T22:07:42.062Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl", hash = "sha256:571ac1dc6991c450b25a9c2d84a3705e2ae7a53467b5d111c24fa8baabbed320", size = 5303, upload-time = "2025-11-10T22:07:40.673Z" },
+]
+
+[[package]]
+name = "colorama"
+version = "0.4.6"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" },
+]
+
+[[package]]
+name = "exceptiongroup"
+version = "1.3.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "typing-extensions" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" },
+]
+
+[[package]]
+name = "h5py"
+version = "3.16.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "numpy" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/db/33/acd0ce6863b6c0d7735007df01815403f5589a21ff8c2e1ee2587a38f548/h5py-3.16.0.tar.gz", hash = "sha256:a0dbaad796840ccaa67a4c144a0d0c8080073c34c76d5a6941d6818678ef2738", size = 446526, upload-time = "2026-03-06T13:49:08.07Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/3a/6b/231413e58a787a89b316bb0d1777da3c62257e4797e09afd8d17ad3549dc/h5py-3.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e06f864bedb2c8e7c1358e6c73af48519e317457c444d6f3d332bb4e8fa6d7d9", size = 3724137, upload-time = "2026-03-06T13:47:35.242Z" },
+ { url = "https://files.pythonhosted.org/packages/74/f9/557ce3aad0fe8471fb5279bab0fc56ea473858a022c4ce8a0b8f303d64e9/h5py-3.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ec86d4fffd87a0f4cb3d5796ceb5a50123a2a6d99b43e616e5504e66a953eca3", size = 3090112, upload-time = "2026-03-06T13:47:37.634Z" },
+ { url = "https://files.pythonhosted.org/packages/7a/f5/e15b3d0dc8a18e56409a839e6468d6fb589bc5207c917399c2e0706eeb44/h5py-3.16.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:86385ea895508220b8a7e45efa428aeafaa586bd737c7af9ee04661d8d84a10d", size = 4844847, upload-time = "2026-03-06T13:47:39.811Z" },
+ { url = "https://files.pythonhosted.org/packages/cb/92/a8851d936547efe30cc0ce5245feac01f3ec6171f7899bc3f775c72030b3/h5py-3.16.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:8975273c2c5921c25700193b408e28d6bdd0111c37468b2d4e25dcec4cd1d84d", size = 5065352, upload-time = "2026-03-06T13:47:41.489Z" },
+ { url = "https://files.pythonhosted.org/packages/2b/ae/f2adc5d0ca9626db3277a3d87516e124cbc5d0eea0bd79bc085702d04f2c/h5py-3.16.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:1677ad48b703f44efc9ea0c3ab284527f81bc4f318386aaaebc5fede6bbae56f", size = 4839173, upload-time = "2026-03-06T13:47:43.586Z" },
+ { url = "https://files.pythonhosted.org/packages/64/0b/e0c8c69da1d8838da023a50cd3080eae5d475691f7636b35eff20bb6ef20/h5py-3.16.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7c4dd4cf5f0a4e36083f73172f6cfc25a5710789269547f132a20975bfe2434c", size = 5076216, upload-time = "2026-03-06T13:47:45.315Z" },
+ { url = "https://files.pythonhosted.org/packages/66/35/d88fd6718832133c885004c61ceeeb24dbd6397ef877dbed6b3a64d6a286/h5py-3.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:bdef06507725b455fccba9c16529121a5e1fbf56aa375f7d9713d9e8ff42454d", size = 3183639, upload-time = "2026-03-06T13:47:47.041Z" },
+]
+
+[[package]]
+name = "iniconfig"
+version = "2.3.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" },
+]
+
+[[package]]
+name = "markdown-it-py"
+version = "4.2.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "mdurl" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/06/ff/7841249c247aa650a76b9ee4bbaeae59370dc8bfd2f6c01f3630c35eb134/markdown_it_py-4.2.0.tar.gz", hash = "sha256:04a21681d6fbb623de53f6f364d352309d4094dd4194040a10fd51833e418d49", size = 82454, upload-time = "2026-05-07T12:08:28.36Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl", hash = "sha256:9f7ebbcd14fe59494226453aed97c1070d83f8d24b6fc3a3bcf9a38092641c4a", size = 91687, upload-time = "2026-05-07T12:08:27.182Z" },
+]
+
+[[package]]
+name = "mdurl"
+version = "0.1.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" },
+]
+
+[[package]]
+name = "numpy"
+version = "2.2.6"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/76/21/7d2a95e4bba9dc13d043ee156a356c0a8f0c6309dff6b21b4d71a073b8a8/numpy-2.2.6.tar.gz", hash = "sha256:e29554e2bef54a90aa5cc07da6ce955accb83f21ab5de01a62c8478897b264fd", size = 20276440, upload-time = "2025-05-17T22:38:04.611Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/9a/3e/ed6db5be21ce87955c0cbd3009f2803f59fa08df21b5df06862e2d8e2bdd/numpy-2.2.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b412caa66f72040e6d268491a59f2c43bf03eb6c96dd8f0307829feb7fa2b6fb", size = 21165245, upload-time = "2025-05-17T21:27:58.555Z" },
+ { url = "https://files.pythonhosted.org/packages/22/c2/4b9221495b2a132cc9d2eb862e21d42a009f5a60e45fc44b00118c174bff/numpy-2.2.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e41fd67c52b86603a91c1a505ebaef50b3314de0213461c7a6e99c9a3beff90", size = 14360048, upload-time = "2025-05-17T21:28:21.406Z" },
+ { url = "https://files.pythonhosted.org/packages/fd/77/dc2fcfc66943c6410e2bf598062f5959372735ffda175b39906d54f02349/numpy-2.2.6-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:37e990a01ae6ec7fe7fa1c26c55ecb672dd98b19c3d0e1d1f326fa13cb38d163", size = 5340542, upload-time = "2025-05-17T21:28:30.931Z" },
+ { url = "https://files.pythonhosted.org/packages/7a/4f/1cb5fdc353a5f5cc7feb692db9b8ec2c3d6405453f982435efc52561df58/numpy-2.2.6-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:5a6429d4be8ca66d889b7cf70f536a397dc45ba6faeb5f8c5427935d9592e9cf", size = 6878301, upload-time = "2025-05-17T21:28:41.613Z" },
+ { url = "https://files.pythonhosted.org/packages/eb/17/96a3acd228cec142fcb8723bd3cc39c2a474f7dcf0a5d16731980bcafa95/numpy-2.2.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:efd28d4e9cd7d7a8d39074a4d44c63eda73401580c5c76acda2ce969e0a38e83", size = 14297320, upload-time = "2025-05-17T21:29:02.78Z" },
+ { url = "https://files.pythonhosted.org/packages/b4/63/3de6a34ad7ad6646ac7d2f55ebc6ad439dbbf9c4370017c50cf403fb19b5/numpy-2.2.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc7b73d02efb0e18c000e9ad8b83480dfcd5dfd11065997ed4c6747470ae8915", size = 16801050, upload-time = "2025-05-17T21:29:27.675Z" },
+ { url = "https://files.pythonhosted.org/packages/07/b6/89d837eddef52b3d0cec5c6ba0456c1bf1b9ef6a6672fc2b7873c3ec4e2e/numpy-2.2.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:74d4531beb257d2c3f4b261bfb0fc09e0f9ebb8842d82a7b4209415896adc680", size = 15807034, upload-time = "2025-05-17T21:29:51.102Z" },
+ { url = "https://files.pythonhosted.org/packages/01/c8/dc6ae86e3c61cfec1f178e5c9f7858584049b6093f843bca541f94120920/numpy-2.2.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8fc377d995680230e83241d8a96def29f204b5782f371c532579b4f20607a289", size = 18614185, upload-time = "2025-05-17T21:30:18.703Z" },
+ { url = "https://files.pythonhosted.org/packages/5b/c5/0064b1b7e7c89137b471ccec1fd2282fceaae0ab3a9550f2568782d80357/numpy-2.2.6-cp310-cp310-win32.whl", hash = "sha256:b093dd74e50a8cba3e873868d9e93a85b78e0daf2e98c6797566ad8044e8363d", size = 6527149, upload-time = "2025-05-17T21:30:29.788Z" },
+ { url = "https://files.pythonhosted.org/packages/a3/dd/4b822569d6b96c39d1215dbae0582fd99954dcbcf0c1a13c61783feaca3f/numpy-2.2.6-cp310-cp310-win_amd64.whl", hash = "sha256:f0fd6321b839904e15c46e0d257fdd101dd7f530fe03fd6359c1ea63738703f3", size = 12904620, upload-time = "2025-05-17T21:30:48.994Z" },
+ { url = "https://files.pythonhosted.org/packages/9e/3b/d94a75f4dbf1ef5d321523ecac21ef23a3cd2ac8b78ae2aac40873590229/numpy-2.2.6-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0b605b275d7bd0c640cad4e5d30fa701a8d59302e127e5f79138ad62762c3e3d", size = 21040391, upload-time = "2025-05-17T21:44:35.948Z" },
+ { url = "https://files.pythonhosted.org/packages/17/f4/09b2fa1b58f0fb4f7c7963a1649c64c4d315752240377ed74d9cd878f7b5/numpy-2.2.6-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:7befc596a7dc9da8a337f79802ee8adb30a552a94f792b9c9d18c840055907db", size = 6786754, upload-time = "2025-05-17T21:44:47.446Z" },
+ { url = "https://files.pythonhosted.org/packages/af/30/feba75f143bdc868a1cc3f44ccfa6c4b9ec522b36458e738cd00f67b573f/numpy-2.2.6-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce47521a4754c8f4593837384bd3424880629f718d87c5d44f8ed763edd63543", size = 16643476, upload-time = "2025-05-17T21:45:11.871Z" },
+ { url = "https://files.pythonhosted.org/packages/37/48/ac2a9584402fb6c0cd5b5d1a91dcf176b15760130dd386bbafdbfe3640bf/numpy-2.2.6-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d042d24c90c41b54fd506da306759e06e568864df8ec17ccc17e9e884634fd00", size = 12812666, upload-time = "2025-05-17T21:45:31.426Z" },
+]
+
+[[package]]
+name = "packaging"
+version = "26.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d7/f1/e7a6dd94a8d4a5626c03e4e99c87f241ba9e350cd9e6d75123f992427270/packaging-26.2.tar.gz", hash = "sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661", size = 228134, upload-time = "2026-04-24T20:15:23.917Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/df/b2/87e62e8c3e2f4b32e5fe99e0b86d576da1312593b39f47d8ceef365e95ed/packaging-26.2-py3-none-any.whl", hash = "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e", size = 100195, upload-time = "2026-04-24T20:15:22.081Z" },
+]
+
+[[package]]
+name = "pluggy"
+version = "1.6.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" },
+]
+
+[[package]]
+name = "pyepics"
+version = "3.5.10"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "numpy" },
+ { name = "pyparsing" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/69/57/29e1e9ef11ba2a3419f489946ae1d8190025a1e4f4e1c1686758bb2b6e0a/pyepics-3.5.10.tar.gz", hash = "sha256:f390cf9be40aba757b9528888114bc14d8db01086d0c93914720b1772460375b", size = 6150481, upload-time = "2026-05-20T18:44:36.336Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d6/36/e517fd83bd97d6bfe4105e0c6b322070c5cc36fb56a8fab2866e319f8804/pyepics-3.5.10-py3-none-any.whl", hash = "sha256:c9fac2c54f2b595268e66fc348cf5ec24e63718e7dbd07d73d1b37d4da6bfee1", size = 5332376, upload-time = "2026-05-20T18:44:34.242Z" },
+]
+
+[[package]]
+name = "pygments"
+version = "2.20.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" },
+]
+
+[[package]]
+name = "pyparsing"
+version = "3.3.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f3/91/9c6ee907786a473bf81c5f53cf703ba0957b23ab84c264080fb5a450416f/pyparsing-3.3.2.tar.gz", hash = "sha256:c777f4d763f140633dcb6d8a3eda953bf7a214dc4eff598413c070bcdc117cbc", size = 6851574, upload-time = "2026-01-21T03:57:59.36Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl", hash = "sha256:850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d", size = 122781, upload-time = "2026-01-21T03:57:55.912Z" },
+]
+
+[[package]]
+name = "pytest"
+version = "9.1.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "colorama", marker = "sys_platform == 'win32'" },
+ { name = "exceptiongroup" },
+ { name = "iniconfig" },
+ { name = "packaging" },
+ { name = "pluggy" },
+ { name = "pygments" },
+ { name = "tomli" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/e4/47/b9efed96c114afcfa3c9d3fe98a76a1d14c74a9e266d397cf6eb64be5e01/pytest-9.1.1.tar.gz", hash = "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313", size = 1636369, upload-time = "2026-06-19T10:58:32.857Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/24/25/1de2678b631f5a49215c6c96fff41ba892b0a34df68d6d80292b1b48aa7f/pytest-9.1.1-py3-none-any.whl", hash = "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c", size = 386536, upload-time = "2026-06-19T10:58:31.347Z" },
+]
+
+[[package]]
+name = "rich"
+version = "15.0.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "markdown-it-py" },
+ { name = "pygments" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/c0/8f/0722ca900cc807c13a6a0c696dacf35430f72e0ec571c4275d2371fca3e9/rich-15.0.0.tar.gz", hash = "sha256:edd07a4824c6b40189fb7ac9bc4c52536e9780fbbfbddf6f1e2502c31b068c36", size = 230680, upload-time = "2026-04-12T08:24:00.75Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl", hash = "sha256:33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb", size = 310654, upload-time = "2026-04-12T08:24:02.83Z" },
+]
+
+[[package]]
+name = "ruff"
+version = "0.15.21"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/0f/36/6f65aa9989acdec45d417192d8f4e7921931d8a6cf87ac74bce3eed98a8e/ruff-0.15.21.tar.gz", hash = "sha256:d0cfc841c572283c36548f82664a54ce6565567f1b0d5b4cf2caac693d8b7500", size = 4769401, upload-time = "2026-07-09T20:01:34.005Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d0/c6/ede15cac6839f3dbce52565c8f5164a8210e669c7bc4decb03e5bdf47d0d/ruff-0.15.21-py3-none-linux_armv6l.whl", hash = "sha256:63ea0e965e5d73c90e95b2434beeafc70820536717f561b32ab6e777cb9bdf5d", size = 10854342, upload-time = "2026-07-09T20:00:53.998Z" },
+ { url = "https://files.pythonhosted.org/packages/28/9d/d825b07ee7ea9e2d61df92a860033c94e06e7300d50a1c2653aac27d24fe/ruff-0.15.21-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:0f212c5d7d54c01bbfe6dcab02b724a39300f3e34ed7acbe995ccb320a2c58bd", size = 11139539, upload-time = "2026-07-09T20:00:57.809Z" },
+ { url = "https://files.pythonhosted.org/packages/f5/de/3b107712e642f063c7a9e0887c427b22cb44097de5aab36c05f2e280670c/ruff-0.15.21-py3-none-macosx_11_0_arm64.whl", hash = "sha256:e6312e41bc96791299614995ea3a977c5857c3b5662b1ecef6755b02b87cb646", size = 10595437, upload-time = "2026-07-09T20:01:00.006Z" },
+ { url = "https://files.pythonhosted.org/packages/9a/6f/b4523cc90ba239ede441447a19d0c968846a3012e5a0b0c5b62831a3d5e3/ruff-0.15.21-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01d65b4831c6b2a4ba8ee6faa84049d44d982b7a706e622c4094c509e51673be", size = 10990053, upload-time = "2026-07-09T20:01:02.187Z" },
+ { url = "https://files.pythonhosted.org/packages/92/cc/c6a9872a5375f0628875481cf2f66b13d7d865bf3ca2e57f91c7e762d976/ruff-0.15.21-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2c5a913a589120ce67933d5d05fd6ddbcc2481c6a054980ee767f7414c72b4fd", size = 10666096, upload-time = "2026-07-09T20:01:04.299Z" },
+ { url = "https://files.pythonhosted.org/packages/ab/97/c621f7a17e097f1790fa3af6374138823b330b2d03fc38337945daca212c/ruff-0.15.21-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ef04b681d02ad4dc9620f00f83ac5c22f652d0e9a9cfe431d219b16ad5ccc41", size = 11537011, upload-time = "2026-07-09T20:01:06.771Z" },
+ { url = "https://files.pythonhosted.org/packages/ea/51/d928727e476e25ccc57c6f449ffd80241a651a973ad949d39cfb2a771d28/ruff-0.15.21-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:16d090c0740916594157e75b80d666eab8e78083b39b3b0e1d698f4670a17b86", size = 12347101, upload-time = "2026-07-09T20:01:08.859Z" },
+ { url = "https://files.pythonhosted.org/packages/1e/88/8cd62026802b16018ad06931d87997cf795ba2a6239ab659606c87d96bf0/ruff-0.15.21-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3a10e74757dd65004d779b73e2f3c5210156d9980b41224d50d2ebcf1db51e67", size = 11572001, upload-time = "2026-07-09T20:01:11.092Z" },
+ { url = "https://files.pythonhosted.org/packages/b2/97/f63084cf55444fc110e8cb985ebfcc592af47f597d44453d778cb81bc156/ruff-0.15.21-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bab0905d2f29e0d9fbc3c373ed23db0095edaa3f71f1f4f519ec15134d9e85c8", size = 11549239, upload-time = "2026-07-09T20:01:13.27Z" },
+ { url = "https://files.pythonhosted.org/packages/9d/77/f107da4a2874b7715914b03f09ba9c54424de3ff8a1cc5d015d3ee2ce0ac/ruff-0.15.21-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:00eca240af5789fec6fe7df74c088cc1f9644ed83027113468efba7c92b94075", size = 11535340, upload-time = "2026-07-09T20:01:15.206Z" },
+ { url = "https://files.pythonhosted.org/packages/d5/e9/601deb322d3303a7bf212b0100ead6f2ee3f6a044d89c30f2f92bf83c731/ruff-0.15.21-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:262ab31557a75141325e32d3357f3597645a7f084e732b6b054dde428ecd9341", size = 10964048, upload-time = "2026-07-09T20:01:17.723Z" },
+ { url = "https://files.pythonhosted.org/packages/ea/2e/0f2176d1e99c15192caea19c8c3a0a955246b4cb4de795042eeb616345cd/ruff-0.15.21-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:659c4e7a4212f83306045ec7c5e5a356d16d9a6ef4ae0c7a4d872914fc655d9d", size = 10667055, upload-time = "2026-07-09T20:01:19.73Z" },
+ { url = "https://files.pythonhosted.org/packages/48/60/abd74a02e0c4214f12a68becfd30af7165cfdcb0e661ecdc60bbb949c09a/ruff-0.15.21-py3-none-musllinux_1_2_i686.whl", hash = "sha256:9e866eab611a5f959d36df2d10e446973a3610bc42b0c15b31dc27977d59c233", size = 11242043, upload-time = "2026-07-09T20:01:21.947Z" },
+ { url = "https://files.pythonhosted.org/packages/b2/c6/583075d8ccabb4b229345edcaf1545eb3d8d6be90f686a479d7e94088bbf/ruff-0.15.21-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e89bc93c0d3803ba870b55c29671bad9dc6d94bb1eb181b056b52eb05b52854f", size = 11648064, upload-time = "2026-07-09T20:01:24.023Z" },
+ { url = "https://files.pythonhosted.org/packages/3a/3c/37d0ecb729a7cc2d393ea7dce316fc585680f35d93b8d62139d7d0a3700c/ruff-0.15.21-py3-none-win32.whl", hash = "sha256:01f8d5be84823c172b389e123174f781f9daf86d6c58719d603f941932195cdd", size = 10896555, upload-time = "2026-07-09T20:01:26.941Z" },
+ { url = "https://files.pythonhosted.org/packages/c0/b8/e43466b2a6067ce91e669068f6e28d6c719a920f014b070d5c8731725de3/ruff-0.15.21-py3-none-win_amd64.whl", hash = "sha256:d4b8d9a2f0f12b816b50447f6eccb9f4bb01a6b82c86b50fb3b5354b458dc6d3", size = 12038772, upload-time = "2026-07-09T20:01:29.497Z" },
+ { url = "https://files.pythonhosted.org/packages/dd/75/e90ab9aeece218a9fc5a5bc3ec97d0ee6bb3c4ff95869463c1de58e29a1c/ruff-0.15.21-py3-none-win_arm64.whl", hash = "sha256:6e83115d4b9377c1cbc13abf0e051f069fab0ef815ea0504a8a008cee24dd0a8", size = 11375265, upload-time = "2026-07-09T20:01:31.772Z" },
+]
+
+[[package]]
+name = "shellingham"
+version = "1.5.4"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/58/15/8b3609fd3830ef7b27b655beb4b4e9c62313a4e8da8c676e142cc210d58e/shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de", size = 10310, upload-time = "2023-10-24T04:13:40.426Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755, upload-time = "2023-10-24T04:13:38.866Z" },
+]
+
+[[package]]
+name = "tomli"
+version = "2.4.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/22/de/48c59722572767841493b26183a0d1cc411d54fd759c5607c4590b6563a6/tomli-2.4.1.tar.gz", hash = "sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f", size = 17543, upload-time = "2026-03-25T20:22:03.828Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/7b/61/cceae43728b7de99d9b847560c262873a1f6c98202171fd5ed62640b494b/tomli-2.4.1-py3-none-any.whl", hash = "sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe", size = 14583, upload-time = "2026-03-25T20:22:03.012Z" },
+]
+
+[[package]]
+name = "typer"
+version = "0.27.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "annotated-doc" },
+ { name = "colorama", marker = "sys_platform == 'win32'" },
+ { name = "rich" },
+ { name = "shellingham" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/37/78/fda3361b56efc27944f24225f6ecd13d96d6fcfe37bd0eb34e2f4c63f9fc/typer-0.27.0.tar.gz", hash = "sha256:629bd12ea5d13a17148125d9a264f949eb171fb3f120f9b04d85873cab054fa5", size = 203430, upload-time = "2026-07-15T19:21:07.007Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/40/03/26a383c9e58c213199d1aad1c3d353cfc22d4444ec6d2c0bf8ad02523843/typer-0.27.0-py3-none-any.whl", hash = "sha256:6f4b27631e47f077871b7dc30e933ec0131c1390fbe0e387ea5574b5bac9ccf1", size = 122716, upload-time = "2026-07-15T19:21:05.553Z" },
+]
+
+[[package]]
+name = "typing-extensions"
+version = "4.16.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f6/cc/6253133b5bb138fc3306cebfbda2c520f545d36b5be2c7255cc528bb45d6/typing_extensions-4.16.0.tar.gz", hash = "sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5", size = 113555, upload-time = "2026-07-02T08:40:05.92Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/49/d3/b8441a820a491ddfc024b0b0cf0393375b75ea13866d9c66727e54c2fc80/typing_extensions-4.16.0-py3-none-any.whl", hash = "sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8", size = 45571, upload-time = "2026-07-02T08:40:04.659Z" },
+]
diff --git a/services/tunefby/current/ioc/AGEBD-CPCL-TUNEFBY_main.subs b/services/tunefby/current/ioc/AGEBD-CPCL-TUNEFBY_main.subs
new file mode 100644
index 0000000..8e1d851
--- /dev/null
+++ b/services/tunefby/current/ioc/AGEBD-CPCL-TUNEFBY_main.subs
@@ -0,0 +1,4 @@
+file TUNEFBY.template {
+ pattern { DEVICE }
+ { AGEBD-TUNEFBY{{ agebd_env }} }
+}
diff --git a/services/tunefby/current/ioc/AGEBD-CPCL-TUNEFBY_parameters.yaml b/services/tunefby/current/ioc/AGEBD-CPCL-TUNEFBY_parameters.yaml
new file mode 100644
index 0000000..ff8e70f
--- /dev/null
+++ b/services/tunefby/current/ioc/AGEBD-CPCL-TUNEFBY_parameters.yaml
@@ -0,0 +1,6 @@
+cpu_architecture: x86_64
+epics_version: 7.0.8
+ioc_host: sls-vserv-bd-01{{ agebd_env }}
+ioc_port: {{ ioc_port }}
+os: RHEL8
+os_id: rhel
diff --git a/services/tunefby/current/ioc/TUNEFBY.template b/services/tunefby/current/ioc/TUNEFBY.template
new file mode 100644
index 0000000..756df39
--- /dev/null
+++ b/services/tunefby/current/ioc/TUNEFBY.template
@@ -0,0 +1,185 @@
+record(ao, "$(DEVICE):CONTROL-KP") {
+ field(DESC, "PID Proportional Gain")
+ field(ASG, "PROTECTED")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-KI") {
+ field(DESC, "PID Integral Gain")
+ field(ASG, "PROTECTED")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-KD") {
+ field(DESC, "PID Derivative Gain")
+ field(ASG, "PROTECTED")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-QY") {
+ field(DESC, "PID Setpoint for QY")
+ field(ASG, "PROTECTED")
+ field(VAL, "0.22")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-QY-OKRNG") {
+ field(DESC, "PID THRESHOLD")
+ field(ASG, "PROTECTED")
+ field(VAL, "0.0005")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-QYMIN") {
+ field(DESC, "PID LOWER LIMIT")
+ field(ASG, "PROTECTED")
+ field(VAL, "0.15")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-QYMAX") {
+ field(DESC, "PID UPPER LIMIT")
+ field(ASG, "PROTECTED")
+ field(VAL, "0.28")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):CONTROL-MIN-CURR") {
+ field(DESC, "PID MIN CURR")
+ field(ASG, "PROTECTED")
+ field(VAL, "400")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):DELTAQ") {
+ field(DESC, "PID SETPOINT for archive")
+ field(ASG, "PROTECTED")
+ field(FLNK, "$(DEVICE):QSTEPS")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):DELTAQ-ULIM") {
+ field(DESC, "PID SETPOINT upper limit")
+ field(ASG, "PROTECTED")
+ field(FLNK, "$(DEVICE):QSTEPS")
+ field(VAL, "0.001")
+ field(PINI, "YES")
+}
+
+record(ao, "$(DEVICE):DELTAQ-LLIM") {
+ field(DESC, "PID SETPOINT lower limit")
+ field(ASG, "PROTECTED")
+ field(FLNK, "$(DEVICE):QSTEPS")
+ field(VAL, "-0.001")
+ field(PINI, "YES")
+}
+
+record(calc, "$(DEVICE):QSTEPS") {
+ field(DESC, "PID SETPOINT accumulated")
+ field(ASG, "READONLY")
+ field(PREC, "4")
+ field(VAL, "0")
+ field(PINI, "YES")
+ field(CALC, "VAL + A")
+ field(INPA, "$(DEVICE):DELTAQ")
+}
+
+record(bo, "$(DEVICE):CHECK1") {
+ field(DESC, "measured tune realistic")
+ field(FLNK, "$(DEVICE):CHECKALL")
+ field(ASG, "PROTECTED")
+ field(ZSV, "MINOR")
+ field(OSV, "NO_ALARM")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(bo, "$(DEVICE):CHECK2") {
+ field(DESC, "measured tune okrng")
+ field(FLNK, "$(DEVICE):CHECKALL")
+ field(ASG, "PROTECTED")
+ field(ZSV, "MINOR")
+ field(OSV, "NO_ALARM")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(bo, "$(DEVICE):CHECK3") {
+ field(DESC, "injection not active")
+ field(FLNK, "$(DEVICE):CHECKALL")
+ field(ASG, "PROTECTED")
+ field(ZSV, "MINOR")
+ field(OSV, "NO_ALARM")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(bo, "$(DEVICE):CHECK4") {
+ field(DESC, "current above min")
+ field(FLNK, "$(DEVICE):CHECKALL")
+ field(ASG, "PROTECTED")
+ field(ZSV, "MINOR")
+ field(OSV, "NO_ALARM")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(bo, "$(DEVICE):CHECK5") {
+ field(DESC, "tune bpm config")
+ field(FLNK, "$(DEVICE):CHECKALL")
+ field(ASG, "PROTECTED")
+ field(ZSV, "MINOR")
+ field(OSV, "NO_ALARM")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(bo, "$(DEVICE):CHECK6") {
+ field(DESC, "pingers on")
+ field(FLNK, "$(DEVICE):CHECKALL")
+ field(ASG, "PROTECTED")
+ field(ZSV, "MINOR")
+ field(OSV, "NO_ALARM")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(bo, "$(DEVICE):CHECK7") {
+ field(DESC, "dt corresponds to 3.125 Hz")
+ field(FLNK, "$(DEVICE):CHECKALL")
+ field(ASG, "PROTECTED")
+ field(ZSV, "MINOR")
+ field(OSV, "NO_ALARM")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(bo, "$(DEVICE):CHECK8") {
+ field(DESC, "calculated step within limits")
+ field(FLNK, "$(DEVICE):CHECKALL")
+ field(ASG, "PROTECTED")
+ field(ZSV, "MINOR")
+ field(OSV, "NO_ALARM")
+ field(VAL, "0")
+ field(PINI, "YES")
+}
+
+record(calc, "$(DEVICE):CHECKALL") {
+ field(DESC, "Check SUM, written by IOC")
+ field(ASG, "READONLY")
+ field(LOLO, "0.1")
+ field(LLSV, "MINOR")
+ field(CALC, "A & B & C & D & E & F & G & H")
+ field(INPA, "$(DEVICE):CHECK1")
+ field(INPB, "$(DEVICE):CHECK2")
+ field(INPC, "$(DEVICE):CHECK3")
+ field(INPD, "$(DEVICE):CHECK4")
+ field(INPE, "$(DEVICE):CHECK5")
+ field(INPF, "$(DEVICE):CHECK6")
+ field(INPG, "$(DEVICE):CHECK7")
+ field(INPH, "$(DEVICE):CHECK8")
+}
\ No newline at end of file
diff --git a/services/tunefby/current/ioc/startup.script b/services/tunefby/current/ioc/startup.script
new file mode 100644
index 0000000..0fa52ff
--- /dev/null
+++ b/services/tunefby/current/ioc/startup.script
@@ -0,0 +1 @@
+epicsEnvSet("ENGINEER", "armborst")
diff --git a/services/tunefby/current/qt/A_BD_TuneBump.ui b/services/tunefby/current/qt/A_BD_TuneBump.ui
new file mode 100644
index 0000000..22fe977
--- /dev/null
+++ b/services/tunefby/current/qt/A_BD_TuneBump.ui
@@ -0,0 +1,6779 @@
+
+
+ MainWindow
+
+
+
+ 0
+ 0
+ 605
+ 960
+
+
+
+ MainWindow
+
+
+ /*################################################*/
+/*# Settings for new templates/forms #*/
+/*################################################*/
+QMainWindow#MainWindow, QWidget#Form, QDialog#Dialog{
+ background: rgba(236, 236, 236, 255);
+}
+
+QMainWindow#MainWindow[transparent=true], QWidget#Form[transparent=true], QDialog#Dialog[transparent=true]{
+ background: rgba(0, 0, 0, 0);
+}
+
+/*-----------------------------------------------*/
+/* Title */
+/*-----------------------------------------------*/
+/* Operation panels */
+caLabel[statusTip="Operation"]{
+ color: rgba(0, 0, 0, 255);
+ font: bold 18pt;
+ font-family: Sans Serif;
+ padding: 1px;
+ margin: 0px;
+ qproperty-alignment: AlignLeft;
+ qproperty-frameShape: StyledPanel;
+ /*qproperty-geometry: rect(-2 0 1600 33);*/
+ background: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1,
+ stop:0 rgba(218, 218, 218, 255),
+ stop:0.5 rgba(200, 200, 200, 255),
+ stop:1 rgba(218, 218, 218, 255));
+}
+
+ QGroupBox {
+ background: rgba(225,225,225,255);
+ border: 2px solid black;
+ border-radius: 5px;
+ margin-top: 1ex; /* leave space at the top for the title */
+ }
+
+
+
+
+
+ 810
+ 120
+ 70
+ 20
+
+
+
+
+
+
+ 810
+ 60
+ 70
+ 20
+
+
+
+ Reload
+
+
+ RELOAD
+
+
+ A
+
+
+ AGEBD-ALH:TUNEBUMP-GUIRELOAD
+
+
+ caCalc::TriggerZeroToOne
+
+
+
+
+
+ 340
+ 60
+ 40
+ 30
+
+
+
+ <<
+
+
+ false
+
+
+ AGEBD-TUNEBUMP:QX-STEPDOWN
+
+
+ <<
+
+
+
+ 160
+ 160
+ 160
+
+
+
+
+
+
+ 1
+
+
+ caMessageButton::as_is
+
+
+
+
+
+ 390
+ 60
+ 150
+ 30
+
+
+
+ 1
+
+
+ 4
+
+
+ AGEBD-TUNEBUMP:QX-STEPSIZE
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caSpinbox::as_is
+
+
+
+
+
+ 390
+ 160
+ 150
+ 30
+
+
+
+ 1
+
+
+ 4
+
+
+ AGEBD-TUNEBUMP:QY-STEPSIZE
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caSpinbox::as_is
+
+
+
+
+
+ 390
+ 35
+ 150
+ 20
+
+
+
+
+ 12
+ 75
+ true
+
+
+
+ Step Size
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 340
+ 160
+ 40
+ 30
+
+
+
+ <<
+
+
+ false
+
+
+ AGEBD-TUNEBUMP:QY-STEPDOWN
+
+
+ <<
+
+
+
+ 160
+ 160
+ 160
+
+
+
+
+
+
+ 1
+
+
+ caMessageButton::as_is
+
+
+
+
+
+ 10
+ 60
+ 50
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ Qx
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 42
+ 99
+ 228
+
+
+
+
+
+
+ 10
+ 160
+ 50
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ Qy
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 139
+ 26
+ 150
+
+
+
+
+
+
+ 550
+ 160
+ 40
+ 30
+
+
+
+ >>
+
+
+ false
+
+
+ AGEBD-TUNEBUMP:QY-STEPUP
+
+
+ >>
+
+
+
+ 160
+ 160
+ 160
+
+
+
+
+
+
+ 1
+
+
+ caMessageButton::as_is
+
+
+
+
+
+ 547
+ 60
+ 40
+ 30
+
+
+
+ >>
+
+
+ false
+
+
+ AGEBD-TUNEBUMP:QX-STEPUP
+
+
+ >>
+
+
+
+ 160
+ 160
+ 160
+
+
+
+
+
+
+ 1
+
+
+ caMessageButton::as_is
+
+
+
+
+
+ 0
+ 0
+ 600
+ 32
+
+
+
+
+ Sans Serif
+ 18
+ 75
+ false
+ true
+
+
+
+ Operation
+
+
+ Tune Shift
+
+
+ Qt::AlignLeading
+
+
+
+ 218
+ 218
+ 218
+
+
+
+ caLabel::Default
+
+
+
+
+
+ 0
+ 300
+ 605
+ 660
+
+
+
+ 0
+
+
+
+ Meas
+
+
+
+
+ 5
+ 210
+ 590
+ 200
+
+
+
+ Vertical Tune (nominal: Qy = 15.22)
+
+
+ AGEBD-TUNEBUMP:NORM-QY-FREQ;AGEBD-TUNEBUMP:NORM-QY-AMP
+
+
+
+ 139
+ 26
+ 150
+
+
+
+ AGEBD-TUNEBUMP:QY-PEAKS-FREQ;AGEBD-TUNEBUMP:QY-PEAKS
+
+
+ caCartesianPlot::Sticks
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+ 139
+ 26
+ 150
+
+
+
+ caCartesianPlot::User
+
+
+ caCartesianPlot::Auto
+
+
+ 0.15;0.29
+
+
+ false
+
+
+ 14
+
+
+ caCartesianPlot::linear
+
+
+
+
+
+ 5
+ 415
+ 590
+ 200
+
+
+
+ Synchrotron Tune (nominal: 0.0027)
+
+
+ AGEBD-TUNEBUMP:NORM-QZ-FREQ;AGEBD-TUNEBUMP:NORM-QZ-AMP
+
+
+
+ 205
+ 97
+ 0
+
+
+
+ AGEBD-TUNEBUMP:QZ-PEAKS-FREQ;AGEBD-TUNEBUMP:QZ-PEAKS
+
+
+ caCartesianPlot::Sticks
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+ 205
+ 97
+ 0
+
+
+
+ caCartesianPlot::Auto
+
+
+ caCartesianPlot::Auto
+
+
+ 0.0005;0.0025
+
+
+ false
+
+
+ 10
+
+
+ caCartesianPlot::linear
+
+
+
+
+
+ 5
+ 5
+ 590
+ 200
+
+
+
+ Horizontal Tune (nominal: Qx = 39.37)
+
+
+ AGEBD-TUNEBUMP:NORM-QX-FREQ;AGEBD-TUNEBUMP:NORM-QX-AMP
+
+
+
+ 42
+ 99
+ 228
+
+
+
+ AGEBD-TUNEBUMP:QX-PEAKS-FREQ;AGEBD-TUNEBUMP:QX-PEAKS
+
+
+ caCartesianPlot::Sticks
+
+
+ caCartesianPlot::NoSymbol
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+ 42
+ 99
+ 228
+
+
+
+ caCartesianPlot::Auto
+
+
+ caCartesianPlot::Auto
+
+
+ 0.3;0.44
+
+
+
+
+
+ false
+
+
+ false
+
+
+ 14
+
+
+ caCartesianPlot::linear
+
+
+
+
+
+ FFT
+
+
+
+
+ 0
+ 415
+ 590
+ 200
+
+
+
+ Tune Z
+
+
+ AGEBD-TUNEBUMP:SPEC-FREQ-qZ;AGEBD-TUNEBUMP:SPEC-Z
+
+
+
+ 205
+ 97
+ 0
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+ caCartesianPlot::User
+
+
+ caCartesianPlot::Auto
+
+
+ 0.0005;0.0025
+
+
+ 10
+
+
+ caCartesianPlot::log10
+
+
+
+
+
+ 0
+ 210
+ 590
+ 200
+
+
+
+ Tune Y
+
+
+ AGEBD-TUNEBUMP:SPEC-FREQ-qY;AGEBD-TUNEBUMP:SPEC-Y
+
+
+
+ 139
+ 26
+ 150
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+ caCartesianPlot::User
+
+
+ caCartesianPlot::Auto
+
+
+ 0.15;0.29
+
+
+ 14
+
+
+ caCartesianPlot::log10
+
+
+
+
+
+ 0
+ 5
+ 590
+ 200
+
+
+
+ Tune X
+
+
+ AGEBD-TUNEBUMP:SPEC-FREQ-qX;AGEBD-TUNEBUMP:SPEC-X
+
+
+
+ 42
+ 99
+ 228
+
+
+
+
+
+
+ caCartesianPlot::Sticks
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+ caCartesianPlot::User
+
+
+ caCartesianPlot::Auto
+
+
+ 0.3;0.44
+
+
+ 0:1
+
+
+ 14
+
+
+ caCartesianPlot::log10
+
+
+
+
+
+ Raw
+
+
+
+
+ 0
+ 210
+ 590
+ 200
+
+
+
+ Vertical TbT data
+
+
+ ;AGEBD-TUNEBUMP:SIGN-Y
+
+
+
+ 139
+ 26
+ 150
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+ caCartesianPlot::User
+
+
+ caCartesianPlot::Auto
+
+
+ 0;16384
+
+
+
+
+
+ 14
+
+
+ caCartesianPlot::linear
+
+
+
+
+
+ 0
+ 415
+ 590
+ 200
+
+
+
+ Longitudinal Stage 1 Data
+
+
+ ;AGEBD-TUNEBUMP:SIGN-Z
+
+
+
+ 205
+ 97
+ 0
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+ caCartesianPlot::User
+
+
+ caCartesianPlot::Auto
+
+
+ 0;16384
+
+
+
+
+
+ 10
+
+
+ caCartesianPlot::linear
+
+
+
+
+
+ 0
+ 5
+ 590
+ 200
+
+
+
+ Horizontal TbT data
+
+
+ ;AGEBD-TUNEBUMP:SIGN-X
+
+
+
+ 42
+ 99
+ 228
+
+
+
+
+
+
+ caCartesianPlot::Sticks
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+ caCartesianPlot::User
+
+
+ caCartesianPlot::Auto
+
+
+ 0;16384
+
+
+
+
+
+ 14
+
+
+ caCartesianPlot::linear
+
+
+
+
+
+ Settings
+
+
+
+
+ 10
+ 260
+ 371
+ 51
+
+
+
+
+ 19
+ 75
+ true
+
+
+
+ Pinger Settings (ca. 10 A)
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 440
+ 320
+ 150
+ 40
+
+
+
+ 3
+
+
+ 2
+
+
+ ARS01-MKIK-0320:I-SET
+
+
+ caSpinbox::User
+
+
+ caSpinbox::User
+
+
+ 300.000000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 140
+ 320
+ 150
+ 40
+
+
+
+ 3
+
+
+ 2
+
+
+ ARS01-MKIK-0290:I-SET
+
+
+ caSpinbox::User
+
+
+ caSpinbox::User
+
+
+ 300.000000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 160
+ 490
+ 291
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ Enable Energy Stabelization:
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 10
+ 450
+ 581
+ 30
+
+
+
+
+ 12
+ 75
+ true
+
+
+
+ Defined by FOFB Mean Horizontal Corrector Integral Setpoint:
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+
+
+ 250
+ 530
+ 110
+ 30
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ ARSGE-CECL-FOFB1:MCOX-INTEGRAL-ERR
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Alarm_Static
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 30
+ 490
+ 110
+ 30
+
+
+
+ 1
+
+
+ 4
+
+
+ ARSGE-CECL-FOFB1:MCOX-INTEGRAL-REF-DEFAULT
+
+
+ caSpinbox::User
+
+
+ caSpinbox::User
+
+
+ 1.000000000000000
+
+
+ -1.000000000000000
+
+
+
+
+
+ 10
+ 10
+ 400
+ 40
+
+
+
+
+ 24
+ 75
+ true
+
+
+
+ Qx Search Range
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 42
+ 99
+ 228
+
+
+
+
+
+
+ 10
+ 130
+ 400
+ 40
+
+
+
+
+ 25
+ 75
+ true
+
+
+
+ Qy Search Range
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 139
+ 26
+ 150
+
+
+
+
+
+
+ 10
+ 60
+ 121
+ 40
+
+
+
+
+ 16
+ 50
+ false
+
+
+
+ Lower limit
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 310
+ 60
+ 121
+ 40
+
+
+
+
+ 16
+ 50
+ false
+
+
+
+ Upper limit
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 440
+ 60
+ 150
+ 40
+
+
+
+ 1
+
+
+ 2
+
+
+ AGEBD-TUNEBUMP:QX-ULIM
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 140
+ 60
+ 150
+ 40
+
+
+
+ 1
+
+
+ 2
+
+
+ AGEBD-TUNEBUMP:QX-LLIM
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 440
+ 180
+ 150
+ 40
+
+
+
+ 1
+
+
+ 2
+
+
+ AGEBD-TUNEBUMP:QY-ULIM
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 310
+ 180
+ 121
+ 40
+
+
+
+
+ 16
+ 50
+ false
+
+
+
+ Upper limit
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 140
+ 180
+ 150
+ 40
+
+
+
+ 1
+
+
+ 2
+
+
+ AGEBD-TUNEBUMP:QY-LLIM
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 10
+ 180
+ 121
+ 40
+
+
+
+
+ 16
+ 50
+ false
+
+
+
+ Lower limit
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 10
+ 320
+ 121
+ 40
+
+
+
+
+ 17
+ 50
+ false
+
+
+
+ Horizontal
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 310
+ 320
+ 121
+ 40
+
+
+
+
+ 24
+ 50
+ false
+
+
+
+ Vertical
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 10
+ 390
+ 371
+ 51
+
+
+
+
+ 22
+ 75
+ true
+
+
+
+ Beam Energy Setpoint
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+
+
+ 450
+ 490
+ 31
+ 30
+
+
+
+ ARSGE-CECL-FOFB1:MCOX-INTEGRAL-REF-DEFAULT-EN
+
+
+
+
+
+ 160
+ 530
+ 91
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ ERROR:
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ BPMs
+
+
+
+
+ 10
+ 20
+ 400
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ Horizontal Tune BPM
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 42
+ 99
+ 228
+
+
+
+
+
+
+ 10
+ 140
+ 400
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ Vertical Tune BPM
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 139
+ 26
+ 150
+
+
+
+
+
+
+ 10
+ 270
+ 400
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ Longitudinal Tune BPM
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 205
+ 97
+ 0
+
+
+
+
+
+
+ 10
+ 180
+ 580
+ 30
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEBUMP:SIGN-Y.INP
+
+
+
+ 139
+ 26
+ 150
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 10
+ 60
+ 580
+ 30
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEBUMP:SIGN-X.INP
+
+
+
+ 42
+ 99
+ 228
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 10
+ 310
+ 580
+ 30
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEBUMP:SIGN-Z.INP
+
+
+
+ 205
+ 97
+ 0
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+
+
+
+
+
+
+ FeedBack QX
+
+
+
+
+ 400
+ 210
+ 150
+ 40
+
+
+
+ 1
+
+
+ 3
+
+
+ AGEBD-TUNEFBX:CONTROL-KP
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 10
+ 10
+ 400
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ Horizontal Tune Feedback
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 42
+ 99
+ 228
+
+
+
+
+
+
+ 310
+ 210
+ 80
+ 40
+
+
+
+
+ 25
+ 50
+ false
+
+
+
+ <html><head/><body><p>K<span style=" vertical-align:sub;">P</span></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 310
+ 260
+ 80
+ 40
+
+
+
+
+ 25
+ 50
+ false
+
+
+
+ <html><head/><body><p>K<span style=" vertical-align:sub;">I</span></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 310
+ 310
+ 80
+ 40
+
+
+
+
+ 25
+ 50
+ false
+
+
+
+ <html><head/><body><p>K<span style=" vertical-align:sub;">D</span></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 400
+ 260
+ 150
+ 40
+
+
+
+ 1
+
+
+ 3
+
+
+ AGEBD-TUNEFBX:CONTROL-KI
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 400
+ 310
+ 150
+ 40
+
+
+
+ 1
+
+
+ 3
+
+
+ AGEBD-TUNEFBX:CONTROL-KD
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 120
+ 60
+ 171
+ 40
+
+
+
+ 1
+
+
+ 2
+
+
+ AGEBD-TUNEFBX:CONTROL-QX
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 20
+ 60
+ 80
+ 40
+
+
+
+
+ 23
+ 50
+ false
+
+
+
+ <html><head/><body><p>Q<span style=" vertical-align:sub;">X,set</span></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 120
+ 110
+ 171
+ 40
+
+
+
+ 1
+
+
+ 2
+
+
+ AGEBD-TUNEFBX:CONTROL-QXMAX
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 20
+ 110
+ 80
+ 40
+
+
+
+
+ 17
+ 50
+ false
+
+
+
+ <html><head/><body><p>Q<span style=" vertical-align:sub;">X,DRVH</span></p><p><br/></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 120
+ 160
+ 171
+ 40
+
+
+
+ 1
+
+
+ 2
+
+
+ AGEBD-TUNEFBX:CONTROL-QXMIN
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 20
+ 160
+ 80
+ 40
+
+
+
+
+ 17
+ 50
+ false
+
+
+
+ <html><head/><body><p>Q<span style=" vertical-align:sub;">X,DRVL</span></p><p><br/></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 20
+ 260
+ 80
+ 40
+
+
+
+
+ 25
+ 50
+ false
+
+
+
+ <html><head/><body><p>I<span style=" vertical-align:sub;">min</span></p><p><br/></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 120
+ 260
+ 171
+ 40
+
+
+
+ 3
+
+
+ 1
+
+
+ AGEBD-TUNEFBX:CONTROL-MIN-CURR
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 20
+ 210
+ 80
+ 40
+
+
+
+
+ 16
+ 50
+ false
+
+
+
+ <html><head/><body><p>Q<span style=" vertical-align:sub;">OKrange</span></p><p><br/></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 120
+ 210
+ 171
+ 40
+
+
+
+ 1
+
+
+ 4
+
+
+ true
+
+
+ AGEBD-TUNEFBX:CONTROL-QX-OKRNG
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 400
+ 60
+ 150
+ 40
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEFBX:DELTAQ
+
+
+
+ 139
+ 26
+ 150
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 310
+ 60
+ 80
+ 40
+
+
+
+
+ 25
+ 50
+ false
+
+
+
+ <html><head/><body><p>ΔQ</p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 20
+ 380
+ 571
+ 240
+
+
+
+
+ 10
+ 75
+ true
+
+
+
+ Accumulated Tune Steps
+
+
+
+
+
+
+
+
+ AGEBD-TUNEFBX:QSTEPS
+
+
+ caStripPlot::Second
+
+
+ 600.000000000000000
+
+
+ caStripPlot::High
+
+
+ caStripPlot::linear
+
+
+ caStripPlot::autoScale
+
+
+ 0.000000000000000
+
+
+ 0.000000001000000
+
+
+ caStripPlot::Channel
+
+
+ caStripPlot::Channel
+
+
+
+ 42
+ 99
+ 228
+
+
+
+ 0.000000410000000
+
+
+ 0.000000001000000
+
+
+ caStripPlot::User
+
+
+ caStripPlot::User
+
+
+
+ 252
+ 192
+ 11
+
+
+
+ 0.000000410000000
+
+
+ 0.000000001000000
+
+
+ caStripPlot::User
+
+
+ caStripPlot::User
+
+
+
+ 252
+ 192
+ 11
+
+
+
+ 0.000000410000000
+
+
+ 0.000000001000000
+
+
+ caStripPlot::User
+
+
+ caStripPlot::User
+
+
+
+ 239
+ 41
+ 41
+
+
+
+ 0.000000410000000
+
+
+ 0.000000001000000
+
+
+ caStripPlot::User
+
+
+ caStripPlot::User
+
+
+
+ 239
+ 41
+ 41
+
+
+
+ 0.000000410000000
+
+
+ 0.000000001000000
+
+
+ caStripPlot::User
+
+
+ caStripPlot::User
+
+
+
+ 255
+ 0
+ 255
+
+
+
+ 0.000000100000000
+
+
+ 0.000000001000000
+
+
+
+ 218
+ 218
+ 218
+
+
+
+ true
+
+
+ false
+
+
+
+
+
+ 390
+ 10
+ 160
+ 30
+
+
+
+ AGEBD-ALH:TUNEFBX-ONOFF
+
+
+ caChoice::Column
+
+
+ 1
+
+
+
+
+
+ 120
+ 350
+ 30
+ 30
+
+
+
+ AGEBD-TUNEFBX:CHECK1
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 170
+ 350
+ 30
+ 30
+
+
+
+ AGEBD-TUNEFBX:CHECK2
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 400
+ 350
+ 20
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ +
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 320
+ 350
+ 30
+ 30
+
+
+
+ AGEBD-TUNEFBX:CHECK5
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 470
+ 350
+ 30
+ 30
+
+
+
+ AGEBD-TUNEFBX:CHECK8
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 350
+ 350
+ 20
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ +
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 220
+ 350
+ 30
+ 30
+
+
+
+ AGEBD-TUNEFBX:CHECK3
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 250
+ 350
+ 20
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ +
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 370
+ 350
+ 30
+ 30
+
+
+
+ AGEBD-TUNEFBX:CHECK6
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 270
+ 350
+ 30
+ 30
+
+
+
+ AGEBD-TUNEFBX:CHECK4
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 450
+ 350
+ 20
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ +
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 420
+ 350
+ 30
+ 30
+
+
+
+ AGEBD-TUNEFBX:CHECK7
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 300
+ 350
+ 20
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ +
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 500
+ 350
+ 20
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ =
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 520
+ 350
+ 30
+ 30
+
+
+
+ true
+
+
+ true
+
+
+ AGEBD-TUNEFBX:CHECKALL
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 200
+ 350
+ 20
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ +
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 150
+ 350
+ 20
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ +
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 310
+ 110
+ 80
+ 40
+
+
+
+
+ 20
+ 50
+ false
+
+
+
+ <html><head/><body><p>ΔQ<span style=" vertical-align:sub;">max</span></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 310
+ 160
+ 80
+ 40
+
+
+
+
+ 21
+ 50
+ false
+
+
+
+ <html><head/><body><p>ΔQ<span style=" vertical-align:sub;">min</span></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 400
+ 110
+ 150
+ 40
+
+
+
+ 1
+
+
+ 3
+
+
+ AGEBD-TUNEFBX:DELTAQ-ULIM
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 400
+ 160
+ 150
+ 40
+
+
+
+ 1
+
+
+ 3
+
+
+ AGEBD-TUNEFBX:DELTAQ-LLIM
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 40
+ 355
+ 80
+ 20
+
+
+
+
+ 11
+ 50
+ false
+
+
+
+ <html><head/><body><p>Conditions<br/></p></body></html>
+
+
+ Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ Feedback QY
+
+
+
+
+ 10
+ 10
+ 400
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ Vertical Tune Feedback
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 139
+ 26
+ 150
+
+
+
+
+
+
+ 120
+ 60
+ 171
+ 40
+
+
+
+ 1
+
+
+ 2
+
+
+ AGEBD-TUNEFBY:CONTROL-QY
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 310
+ 210
+ 80
+ 40
+
+
+
+
+ 25
+ 50
+ false
+
+
+
+ <html><head/><body><p>K<span style=" vertical-align:sub;">P</span></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 120
+ 210
+ 171
+ 40
+
+
+
+ 1
+
+
+ 4
+
+
+ true
+
+
+ AGEBD-TUNEFBY:CONTROL-QY-OKRNG
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 200
+ 350
+ 20
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ +
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 400
+ 260
+ 150
+ 40
+
+
+
+ 1
+
+
+ 3
+
+
+ AGEBD-TUNEFBY:CONTROL-KI
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 310
+ 60
+ 80
+ 40
+
+
+
+
+ 25
+ 50
+ false
+
+
+
+ <html><head/><body><p>ΔQ</p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 310
+ 310
+ 80
+ 40
+
+
+
+
+ 25
+ 50
+ false
+
+
+
+ <html><head/><body><p>K<span style=" vertical-align:sub;">D</span></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 270
+ 350
+ 30
+ 30
+
+
+
+ AGEBD-TUNEFBY:CHECK4
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 400
+ 210
+ 150
+ 40
+
+
+
+ 1
+
+
+ 3
+
+
+ AGEBD-TUNEFBY:CONTROL-KP
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 120
+ 110
+ 171
+ 40
+
+
+
+ 1
+
+
+ 2
+
+
+ AGEBD-TUNEFBY:CONTROL-QYMAX
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 250
+ 350
+ 20
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ +
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 300
+ 350
+ 20
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ +
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 20
+ 160
+ 80
+ 40
+
+
+
+
+ 18
+ 50
+ false
+
+
+
+ <html><head/><body><p>Q<span style=" vertical-align:sub;">Y,DRVL</span></p><p><br/></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 400
+ 310
+ 150
+ 40
+
+
+
+ 1
+
+
+ 3
+
+
+ AGEBD-TUNEFBY:CONTROL-KD
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 220
+ 350
+ 30
+ 30
+
+
+
+ AGEBD-TUNEFBY:CHECK3
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 350
+ 350
+ 20
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ +
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 150
+ 350
+ 20
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ +
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 20
+ 60
+ 80
+ 40
+
+
+
+
+ 24
+ 50
+ false
+
+
+
+ <html><head/><body><p>Q<span style=" vertical-align:sub;">Y,set</span></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 20
+ 210
+ 80
+ 40
+
+
+
+
+ 16
+ 50
+ false
+
+
+
+ <html><head/><body><p>Q<span style=" vertical-align:sub;">OKrange</span></p><p><br/></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 400
+ 60
+ 150
+ 40
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEFBY:DELTAQ
+
+
+
+ 139
+ 26
+ 150
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 500
+ 350
+ 20
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ =
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 520
+ 350
+ 33
+ 30
+
+
+
+ true
+
+
+ 18
+
+
+ 18
+
+
+ true
+
+
+ AGEBD-TUNEFBY:CHECKALL
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 320
+ 350
+ 30
+ 30
+
+
+
+ AGEBD-TUNEFBY:CHECK5
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 170
+ 350
+ 30
+ 30
+
+
+
+ AGEBD-TUNEFBY:CHECK2
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 310
+ 260
+ 80
+ 40
+
+
+
+
+ 25
+ 50
+ false
+
+
+
+ <html><head/><body><p>K<span style=" vertical-align:sub;">I</span></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 120
+ 160
+ 171
+ 40
+
+
+
+ 1
+
+
+ 2
+
+
+ AGEBD-TUNEFBY:CONTROL-QYMIN
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 120
+ 350
+ 30
+ 30
+
+
+
+ AGEBD-TUNEFBY:CHECK1
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 40
+ 355
+ 80
+ 20
+
+
+
+
+ 11
+ 50
+ false
+
+
+
+ <html><head/><body><p>Conditions<br/></p></body></html>
+
+
+ Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 390
+ 10
+ 160
+ 30
+
+
+
+ AGEBD-ALH:TUNEFBY-ONOFF
+
+
+ caChoice::Column
+
+
+ 1
+
+
+
+
+
+ 370
+ 350
+ 30
+ 30
+
+
+
+ AGEBD-TUNEFBY:CHECK6
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 20
+ 380
+ 571
+ 240
+
+
+
+
+ 10
+ 75
+ true
+
+
+
+ Accumulated Tune Steps
+
+
+
+
+
+
+
+
+ AGEBD-TUNEFBY:QSTEPS
+
+
+ caStripPlot::Second
+
+
+ 600.000000000000000
+
+
+ caStripPlot::High
+
+
+ caStripPlot::linear
+
+
+ caStripPlot::autoScale
+
+
+ 0.000000000000000
+
+
+ 0.000000001000000
+
+
+ caStripPlot::Channel
+
+
+ caStripPlot::Channel
+
+
+
+ 42
+ 99
+ 228
+
+
+
+ 0.000000410000000
+
+
+ 0.000000001000000
+
+
+ caStripPlot::User
+
+
+ caStripPlot::User
+
+
+
+ 252
+ 192
+ 11
+
+
+
+ 0.000000410000000
+
+
+ 0.000000001000000
+
+
+ caStripPlot::User
+
+
+ caStripPlot::User
+
+
+
+ 252
+ 192
+ 11
+
+
+
+ 0.000000410000000
+
+
+ 0.000000001000000
+
+
+ caStripPlot::User
+
+
+ caStripPlot::User
+
+
+
+ 239
+ 41
+ 41
+
+
+
+ 0.000000410000000
+
+
+ 0.000000001000000
+
+
+ caStripPlot::User
+
+
+ caStripPlot::User
+
+
+
+ 239
+ 41
+ 41
+
+
+
+ 0.000000410000000
+
+
+ 0.000000001000000
+
+
+ caStripPlot::User
+
+
+ caStripPlot::User
+
+
+
+ 255
+ 0
+ 255
+
+
+
+ 0.000000100000000
+
+
+ 0.000000001000000
+
+
+
+ 218
+ 218
+ 218
+
+
+
+ true
+
+
+ false
+
+
+
+
+
+ 20
+ 260
+ 80
+ 40
+
+
+
+
+ 25
+ 50
+ false
+
+
+
+ <html><head/><body><p>I<span style=" vertical-align:sub;">min</span></p><p><br/></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 20
+ 110
+ 80
+ 40
+
+
+
+
+ 17
+ 50
+ false
+
+
+
+ <html><head/><body><p>Q<span style=" vertical-align:sub;">Y,DRVH</span></p><p><br/></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 120
+ 260
+ 171
+ 40
+
+
+
+ 3
+
+
+ 1
+
+
+ AGEBD-TUNEFBY:CONTROL-MIN-CURR
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 400
+ 350
+ 20
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ +
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 420
+ 350
+ 30
+ 30
+
+
+
+ AGEBD-TUNEFBY:CHECK7
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 470
+ 350
+ 30
+ 30
+
+
+
+ AGEBD-TUNEFBY:CHECK8
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ 0
+
+
+ 1
+
+
+
+
+
+ 450
+ 350
+ 20
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ +
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 310
+ 160
+ 80
+ 40
+
+
+
+
+ 21
+ 50
+ false
+
+
+
+ <html><head/><body><p>ΔQ<span style=" vertical-align:sub;">min</span></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 400
+ 110
+ 150
+ 40
+
+
+
+ 1
+
+
+ 3
+
+
+ AGEBD-TUNEFBY:DELTAQ-ULIM
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 400
+ 160
+ 150
+ 40
+
+
+
+ 1
+
+
+ 3
+
+
+ AGEBD-TUNEFBY:DELTAQ-LLIM
+
+
+ caSpinbox::User
+
+
+ true
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+ 310
+ 110
+ 80
+ 40
+
+
+
+
+ 20
+ 50
+ false
+
+
+
+ <html><head/><body><p>ΔQ<span style=" vertical-align:sub;">max</span></p></body></html>
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ Debug
+
+
+
+
+ 250
+ 20
+ 31
+ 30
+
+
+
+ AGEBD-TUNEBUMP:WRITE2MAG
+
+
+
+
+
+ 10
+ 20
+ 231
+ 30
+
+
+
+
+ 15
+ 50
+ false
+
+
+
+ Apply MQCO Setpoints
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ESimpleLabel::None
+
+
+
+
+
+ 4
+ 50
+ 595
+ 575
+
+
+
+
+ Monospace
+ 10
+ PreferDefault
+
+
+
+ Qt::ScrollBarAlwaysOn
+
+
+ Qt::ScrollBarAsNeeded
+
+
+ AGEBD-TUNEBUMP:CHANGELOG
+
+
+ caMultiLineString::None
+
+
+
+
+
+
+
+ 60
+ 60
+ 100
+ 30
+
+
+
+
+ Lucida Sans Typewriter
+ 16
+
+
+
+ true
+
+
+
+
+
+
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEBUMP:QX
+
+
+
+ 42
+ 99
+ 228
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caLineEdit::Static
+
+
+ true
+
+
+
+ 42
+ 99
+ 228
+
+
+
+ 1
+
+
+ caLineEdit::onBackground
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::None
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 60
+ 160
+ 100
+ 30
+
+
+
+
+ Lucida Sans Typewriter
+ 16
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEBUMP:QY
+
+
+
+ 139
+ 26
+ 150
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caLineEdit::Static
+
+
+ true
+
+
+
+ 139
+ 26
+ 150
+
+
+
+ 1
+
+
+ caLineEdit::onBackground
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::None
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 110
+ 100
+ 121
+ 20
+
+
+
+
+ 12
+ 75
+ true
+
+
+
+ Sideband 1
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 250
+ 100
+ 110
+ 20
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEBUMP:QX-SB1
+
+
+
+ 42
+ 99
+ 228
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 480
+ 100
+ 110
+ 20
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEBUMP:QX-SB1-DIFF
+
+
+
+ 42
+ 99
+ 228
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 110
+ 130
+ 121
+ 20
+
+
+
+
+ 12
+ 75
+ true
+
+
+
+ Sideband 2
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 250
+ 130
+ 110
+ 20
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEBUMP:QX-SB2
+
+
+
+ 42
+ 99
+ 228
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 480
+ 130
+ 110
+ 20
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEBUMP:QX-SB2-DIFF
+
+
+
+ 42
+ 99
+ 228
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 380
+ 100
+ 91
+ 20
+
+
+
+
+ 12
+ 75
+ true
+
+
+
+ Distance
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 380
+ 130
+ 91
+ 20
+
+
+
+
+ 12
+ 75
+ true
+
+
+
+ Distance
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 380
+ 200
+ 91
+ 20
+
+
+
+
+ 12
+ 75
+ true
+
+
+
+ Distance
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 250
+ 200
+ 110
+ 20
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEBUMP:QY-SB1
+
+
+
+ 139
+ 26
+ 150
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 110
+ 200
+ 121
+ 20
+
+
+
+
+ 12
+ 75
+ true
+
+
+
+ Sideband 1
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 380
+ 230
+ 91
+ 20
+
+
+
+
+ 12
+ 75
+ true
+
+
+
+ Distance
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 110
+ 230
+ 121
+ 20
+
+
+
+
+ 12
+ 75
+ true
+
+
+
+ Sideband 2
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+ 255
+ 252
+ 255
+
+
+
+
+
+
+ 250
+ 230
+ 110
+ 20
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEBUMP:QY-SB2
+
+
+
+ 139
+ 26
+ 150
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 480
+ 200
+ 110
+ 20
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEBUMP:QY-SB1-DIFF
+
+
+
+ 139
+ 26
+ 150
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 480
+ 230
+ 110
+ 20
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEBUMP:QY-SB2-DIFF
+
+
+
+ 139
+ 26
+ 150
+
+
+
+
+ 255
+ 255
+ 225
+
+
+
+ caLineEdit::Static
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::Height
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 170
+ 60
+ 160
+ 30
+
+
+
+
+ Lucida Sans Typewriter
+ 16
+
+
+
+ true
+
+
+
+
+
+
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEBUMP:QX-FREQ
+
+
+
+ 42
+ 99
+ 228
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caLineEdit::Static
+
+
+ true
+
+
+
+ 42
+ 99
+ 228
+
+
+
+ 1
+
+
+ caLineEdit::onBackground
+
+
+ 3
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::None
+
+
+ true
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 170
+ 160
+ 160
+ 30
+
+
+
+
+ Lucida Sans Typewriter
+ 16
+
+
+
+ true
+
+
+
+
+
+
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEBUMP:QY-FREQ
+
+
+
+ 139
+ 26
+ 150
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caLineEdit::Static
+
+
+ true
+
+
+
+ 139
+ 26
+ 150
+
+
+
+ 1
+
+
+ caLineEdit::onBackground
+
+
+ 3
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::None
+
+
+ true
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 10
+ 260
+ 50
+ 30
+
+
+
+
+ 18
+ 75
+ true
+
+
+
+ Qz
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ 205
+ 97
+ 0
+
+
+
+
+
+
+ 60
+ 260
+ 100
+ 30
+
+
+
+
+ Lucida Sans Typewriter
+ 16
+
+
+
+ true
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEBUMP:QZ
+
+
+
+ 205
+ 97
+ 0
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caLineEdit::Static
+
+
+ true
+
+
+
+ 205
+ 97
+ 0
+
+
+
+ 1
+
+
+ caLineEdit::onBackground
+
+
+ 4
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::None
+
+
+ false
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 170
+ 260
+ 160
+ 30
+
+
+
+
+ Lucida Sans Typewriter
+ 16
+
+
+
+ true
+
+
+
+
+
+ Qt::AlignAbsolute|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ AGEBD-TUNEBUMP:QZ-FREQ
+
+
+
+ 205
+ 97
+ 0
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+ caLineEdit::Static
+
+
+ true
+
+
+
+ 205
+ 97
+ 0
+
+
+
+ 1
+
+
+ caLineEdit::onBackground
+
+
+ 3
+
+
+ caLineEdit::User
+
+
+ caLineEdit::Channel
+
+
+ 0.100000000000000
+
+
+ 0.000000000000000
+
+
+ caLineEdit::None
+
+
+ true
+
+
+ caLineEdit::decimal
+
+
+
+
+
+ 340
+ 60
+ 250
+ 30
+
+
+
+
+ Sans Serif
+ 18
+
+
+
+ Feedback ON
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ caLabel::Calc
+
+
+ A
+
+
+ AGEBD-ALH:TUNEFBX-ONOFF
+
+
+
+
+
+ 340
+ 160
+ 250
+ 30
+
+
+
+
+ Sans Serif
+ 18
+
+
+
+ Feedback ON
+
+
+ Qt::AlignCenter
+
+
+
+ 0
+ 205
+ 0
+
+
+
+ caLabel::Calc
+
+
+ A
+
+
+ AGEBD-ALH:TUNEFBY-ONOFF
+
+
+ calabel_3
+ wmsignalpropagator
+ cacalc_2
+ camessagebutton_14
+ caspinbox
+ caspinbox_2
+ calabel_12
+ camessagebutton_15
+ calabel_13
+ calabel_14
+ camessagebutton_16
+ camessagebutton_17
+ tabWidget
+ caLineEdit_39
+ caLineEdit_40
+ calabel_18
+ caLineEdit_43
+ caLineEdit_45
+ calabel_19
+ caLineEdit_48
+ caLineEdit_49
+ calabel_20
+ calabel_21
+ calabel_22
+ caLineEdit_44
+ calabel_23
+ calabel_24
+ calabel_25
+ caLineEdit_50
+ caLineEdit_46
+ caLineEdit_51
+ caLineEdit_42
+ caLineEdit_54
+ calabel_33
+ caLineEdit_55
+ caLineEdit_56
+ calabel
+ calabel_2
+
+
+
+
+ caMenu
+ QComboBox
+
+
+
+ caChoice
+ QWidget
+
+
+
+ caMessageButton
+ QPushButton
+
+
+
+ caToggleButton
+ QCheckBox
+
+
+
+ caSpinbox
+ QFrame
+
+
+
+ caLabel
+ QLabel
+
+
+
+ caLed
+ QWidget
+
+
+
+ caLineEdit
+ QLineEdit
+
+
+
+ caMultiLineString
+ QPlainTextEdit
+
+
+
+ caCartesianPlot
+ QwtPlot
+
+
+
+ caStripPlot
+ QwtPlot
+
+ 1
+
+
+ caCalc
+ QLabel
+
+
+
+ wmSignalPropagator
+ QLabel
+
+
+
+ QwtPlot
+ QFrame
+
+
+
+
+
+
+ cacalc_2
+ emitSignal(bool)
+ wmsignalpropagator
+ reloadwindow()
+
+
+ 598
+ 89
+
+
+ 608
+ 152
+
+
+
+
+
diff --git a/services/tunefby/current/systemd/AGEBD-SERVICE-TUNEFBY.service b/services/tunefby/current/systemd/AGEBD-SERVICE-TUNEFBY.service
new file mode 100644
index 0000000..3cbbb68
--- /dev/null
+++ b/services/tunefby/current/systemd/AGEBD-SERVICE-TUNEFBY.service
@@ -0,0 +1,16 @@
+[Unit]
+Description=AGEBD-SERVICE-TUNEFBY
+After=network.target
+
+[Service]
+Environment=AGEBD_ENV={{ agebd_env }}
+ExecStart=/sls/bd/hla/{{ agebd_env }}/bin/start_service.sh TUNEFBY
+Restart=no
+
+[Install]
+WantedBy=default.target
+
+# https://www.freedesktop.org/software/systemd/man/latest/systemd.service.html
+# systemctl --user daemon-reload
+# systemctl --user enable /sls/bd/bin/systemd/AGEBD-SERVICE-TUNEFBY.service
+# systemctl --user start AGEBD-SERVICE-TUNEFBY