Compare commits
57 Commits
ci/securit
...
docs/csaxs
| Author | SHA1 | Date | |
|---|---|---|---|
| ca40a8eb3d | |||
| f476b210f1 | |||
|
|
fad8b516a6 | ||
| a9ff092a66 | |||
| 37d80e9a7b | |||
| ed335dc308 | |||
| 78d2dd2436 | |||
|
|
bf2e6baba5 | ||
| fcf9ee4545 | |||
|
|
53a200928f | ||
|
|
1572dd4484 | ||
|
|
f72be7ab70 | ||
|
|
8aee3e3c0d | ||
|
|
6a517d3ac5 | ||
|
|
b6b2850853 | ||
|
|
5841a56255 | ||
|
|
333b4f1dd2 | ||
|
|
97e09cf622 | ||
|
|
174c0689bc | ||
|
|
a3899bf7a5 | ||
|
|
d4c12a3c9c | ||
|
|
8f0ed4e250 | ||
|
|
0359f1f431 | ||
|
|
b45070332d | ||
|
|
35e4ea0916 | ||
| ae86fbd329 | |||
| a195be64e7 | |||
| e980bf2ee6 | |||
| ce876f58d6 | |||
|
|
b0a1c32b47 | ||
| 11ed6e112f | |||
| 8a24692e82 | |||
| 1d266c5da9 | |||
| 7d93154761 | |||
| c85c6ec5ab | |||
|
|
d567e49b53 | ||
| 73ce61dd96 | |||
| 8410b3ceec | |||
| 477567e61a | |||
| 7da1bddef8 | |||
| 5007b182ca | |||
| 063308042d | |||
| 0180e4a3f9 | |||
| fc37892ea1 | |||
|
|
d6f88b599a | ||
|
|
ab2270683f | ||
|
|
7b6652f867 | ||
|
|
cb525e8778 | ||
| 21c3e3cab4 | |||
| adfdb6fe5d | |||
| 73d9a967d6 | |||
| 787e0afcec | |||
| 74d941c249 | |||
| f601593c77 | |||
|
|
e0d93cd84e | ||
| 803dffb9cd | |||
|
|
3cbafa51be |
109
.gitlab-ci.yml
109
.gitlab-ci.yml
@@ -1,105 +1,8 @@
|
|||||||
# This file is a template, and might need editing before it works on your project.
|
|
||||||
# Official language image. Look for the different tagged releases at:
|
|
||||||
# https://hub.docker.com/r/library/python/tags/
|
|
||||||
image: $CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX/python:3.10
|
|
||||||
|
|
||||||
workflow:
|
|
||||||
rules:
|
|
||||||
- if: $CI_PIPELINE_SOURCE == "schedule"
|
|
||||||
- if: $CI_PIPELINE_SOURCE == "web"
|
|
||||||
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
|
||||||
- if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS
|
|
||||||
when: never
|
|
||||||
- if: $CI_COMMIT_BRANCH
|
|
||||||
|
|
||||||
include:
|
include:
|
||||||
- template: Security/Secret-Detection.gitlab-ci.yml
|
- project: bec/awi_utils
|
||||||
|
file: /templates/plugin-repo-template.yml
|
||||||
|
inputs:
|
||||||
|
name: "csaxs"
|
||||||
|
target: "csaxs_bec"
|
||||||
|
branch: $CHILD_PIPELINE_BRANCH
|
||||||
|
|
||||||
|
|
||||||
#commands to run in the Docker container before starting each job.
|
|
||||||
before_script:
|
|
||||||
- pip install -e .[dev]
|
|
||||||
|
|
||||||
# different stages in the pipeline
|
|
||||||
stages:
|
|
||||||
- Formatter
|
|
||||||
- test # must be called test for security/secret-detection to work
|
|
||||||
- AdditionalTests
|
|
||||||
- Deploy
|
|
||||||
|
|
||||||
pylint:
|
|
||||||
stage: Formatter
|
|
||||||
script:
|
|
||||||
- pip install pylint pylint-exit anybadge
|
|
||||||
- pip install -e .[dev]
|
|
||||||
- mkdir ./pylint
|
|
||||||
- pylint ./csaxs_bec --output-format=text --output=./pylint/pylint.log | tee ./pylint/pylint.log || pylint-exit $?
|
|
||||||
- PYLINT_SCORE=$(sed -n 's/^Your code has been rated at \([-0-9.]*\)\/.*/\1/p' ./pylint/pylint.log)
|
|
||||||
- anybadge --label=Pylint --file=pylint/pylint.svg --value=$PYLINT_SCORE 2=red 4=orange 8=yellow 10=green
|
|
||||||
- echo "Pylint score is $PYLINT_SCORE"
|
|
||||||
artifacts:
|
|
||||||
paths:
|
|
||||||
- ./pylint/
|
|
||||||
expire_in: 1 week
|
|
||||||
|
|
||||||
pylint-check:
|
|
||||||
stage: Formatter
|
|
||||||
needs: []
|
|
||||||
allow_failure: true
|
|
||||||
before_script:
|
|
||||||
- pip install pylint pylint-exit anybadge
|
|
||||||
- apt-get update
|
|
||||||
- apt-get install -y bc
|
|
||||||
script:
|
|
||||||
# Identify changed Python files
|
|
||||||
- if [ "$CI_PIPELINE_SOURCE" == "merge_request_event" ]; then
|
|
||||||
TARGET_BRANCH_COMMIT_SHA=$(git rev-parse $CI_MERGE_REQUEST_TARGET_BRANCH_NAME);
|
|
||||||
CHANGED_FILES=$(git diff --name-only $SOURCE_BRANCH_COMMIT_SHA $TARGET_BRANCH_COMMIT_SHA | grep '\.py$' || true);
|
|
||||||
else
|
|
||||||
CHANGED_FILES=$(git diff --name-only $CI_COMMIT_BEFORE_SHA $CI_COMMIT_SHA | grep '\.py$' || true);
|
|
||||||
fi
|
|
||||||
- if [ -z "$CHANGED_FILES" ]; then echo "No Python files changed."; exit 0; fi
|
|
||||||
|
|
||||||
# Run pylint only on changed files
|
|
||||||
- mkdir ./pylint
|
|
||||||
- pylint $CHANGED_FILES --output-format=text . | tee ./pylint/pylint_changed_files.log || pylint-exit $?
|
|
||||||
- PYLINT_SCORE=$(sed -n 's/^Your code has been rated at \([-0-9.]*\)\/.*/\1/p' ./pylint/pylint_changed_files.log)
|
|
||||||
- echo "Pylint score is $PYLINT_SCORE"
|
|
||||||
|
|
||||||
# Fail the job if the pylint score is below 9
|
|
||||||
- if [ "$(echo "$PYLINT_SCORE < 9" | bc)" -eq 1 ]; then echo "Your pylint score is below the acceptable threshold (9)."; exit 1; fi
|
|
||||||
artifacts:
|
|
||||||
paths:
|
|
||||||
- ./pylint/
|
|
||||||
expire_in: 1 week
|
|
||||||
|
|
||||||
secret_detection:
|
|
||||||
before_script:
|
|
||||||
- ''
|
|
||||||
|
|
||||||
config_test:
|
|
||||||
stage: test
|
|
||||||
script:
|
|
||||||
- ophyd_test --config ./csaxs_bec/device_configs/ --output ./config_tests
|
|
||||||
artifacts:
|
|
||||||
paths:
|
|
||||||
- ./config_tests
|
|
||||||
when: on_failure
|
|
||||||
expire_in: "30 days"
|
|
||||||
allow_failure: true
|
|
||||||
|
|
||||||
|
|
||||||
pytest:
|
|
||||||
stage: test
|
|
||||||
script:
|
|
||||||
- pip install coverage
|
|
||||||
- coverage run --source=./csaxs_bec -m pytest -v --junitxml=report.xml --random-order --full-trace ./tests
|
|
||||||
- coverage report
|
|
||||||
- coverage xml
|
|
||||||
coverage: '/(?i)total.*? (100(?:\.0+)?\%|[1-9]?\d(?:\.\d+)?\%)$/'
|
|
||||||
artifacts:
|
|
||||||
reports:
|
|
||||||
junit: report.xml
|
|
||||||
coverage_report:
|
|
||||||
coverage_format: cobertura
|
|
||||||
path: coverage.xml
|
|
||||||
|
|||||||
@@ -3,8 +3,9 @@ from __future__ import annotations
|
|||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
from bec_lib import MessageEndpoints, RedisConnector, bec_logger, messages
|
from bec_lib import bec_logger, messages
|
||||||
from bec_lib.redis_connector import MessageObject
|
from bec_lib.endpoints import MessageEndpoints
|
||||||
|
from bec_lib.redis_connector import MessageObject, RedisConnector
|
||||||
|
|
||||||
logger = bec_logger.logger
|
logger = bec_logger.logger
|
||||||
|
|
||||||
@@ -27,7 +28,7 @@ class PilatusConverter:
|
|||||||
message (MessageObject): Message object
|
message (MessageObject): Message object
|
||||||
parent (PilatusConverter): Parent object
|
parent (PilatusConverter): Parent object
|
||||||
"""
|
"""
|
||||||
msg = messages.MessageReader.loads(message.value)
|
msg = message.value
|
||||||
print(msg)
|
print(msg)
|
||||||
if not msg:
|
if not msg:
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -13,6 +13,166 @@ umv = builtins.__dict__.get("umv")
|
|||||||
bec = builtins.__dict__.get("bec")
|
bec = builtins.__dict__.get("bec")
|
||||||
|
|
||||||
|
|
||||||
|
class LamNIInitError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class LaMNIInitStagesMixin:
|
||||||
|
def lamni_init_stages(self):
|
||||||
|
user_input = input("Starting initialization of LamNI stages. OK? [y/n]")
|
||||||
|
if user_input == "y":
|
||||||
|
print("staring...")
|
||||||
|
dev.lsamrot.enabled = True
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
|
||||||
|
if self.check_all_axes_of_lamni_referenced():
|
||||||
|
user_input = input("Continue anyways? [y/n]")
|
||||||
|
if user_input == "y":
|
||||||
|
print("ok then...")
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
|
||||||
|
axis_id_lsamrot = dev.lsamrot._config["deviceConfig"].get("axis_Id")
|
||||||
|
if dev.lsamrot.controller.get_motor_limit_switch(axis_id_lsamrot)[1] == False:
|
||||||
|
user_input = input("The rotation stage will be moved to one limit [y/n]")
|
||||||
|
if user_input == "y":
|
||||||
|
print("starting...")
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.drive_axis_to_limit(dev.lsamrot, "forward")
|
||||||
|
dev.lsamrot.enabled = False
|
||||||
|
print("Now hard reboot the controller and run the initialization routine again.")
|
||||||
|
print("The controller will be disabled in bec. To enable dev.lsamrot.enabled=True")
|
||||||
|
return
|
||||||
|
|
||||||
|
user_input = input(
|
||||||
|
"Init of loptz. Can the stage move to the upstream limit without collision?? [y/n]"
|
||||||
|
)
|
||||||
|
if user_input == "y":
|
||||||
|
print("ok then...")
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
|
||||||
|
print("Referencing loptz")
|
||||||
|
self.drive_axis_to_limit(dev.loptz, "forward")
|
||||||
|
self.find_reference_mark(dev.loptz)
|
||||||
|
|
||||||
|
print("Referencing loptx")
|
||||||
|
self.drive_axis_to_limit(dev.loptx, "reverse")
|
||||||
|
self.find_reference_mark(dev.loptx)
|
||||||
|
|
||||||
|
print("Referencing lopty")
|
||||||
|
self.drive_axis_to_limit(dev.lopty, "forward")
|
||||||
|
self.find_reference_mark(dev.lopty)
|
||||||
|
|
||||||
|
print("Referencing lsamx")
|
||||||
|
self.drive_axis_to_limit(dev.lsamx, "forward")
|
||||||
|
self.find_reference_mark(dev.lsamx)
|
||||||
|
|
||||||
|
print("Referencing lsamy")
|
||||||
|
self.drive_axis_to_limit(dev.lsamy, "reverse")
|
||||||
|
self.find_reference_mark(dev.lsamy)
|
||||||
|
|
||||||
|
# the dual encoder requires the reference mark to pass on both encoders
|
||||||
|
print("Referencing lsamrot")
|
||||||
|
self.drive_axis_to_limit(dev.lsamrot, "reverse")
|
||||||
|
time.sleep(0.1)
|
||||||
|
self.find_reference_mark(dev.lsamrot)
|
||||||
|
|
||||||
|
user_input = input("Init of leye. Can the stage move to -x limit without collision? [y/n]")
|
||||||
|
if user_input == "y":
|
||||||
|
print("starting...")
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
|
||||||
|
print("Referencing leyex")
|
||||||
|
self.drive_axis_to_limit(dev.leyex, "forward")
|
||||||
|
print("Referencing leyey")
|
||||||
|
self.drive_axis_to_limit(dev.leyey, "forward")
|
||||||
|
|
||||||
|
# set_lm lsamx 6 14
|
||||||
|
# set_lm lsamy 6 14
|
||||||
|
# set_lm lsamrot -3 362
|
||||||
|
# set_lm loptx -1 -0.2
|
||||||
|
# set_lm lopty 3.0 3.6
|
||||||
|
# set_lm loptz 82 87
|
||||||
|
# set_lm leyex 0 25
|
||||||
|
# set_lm leyey 0.5 50
|
||||||
|
|
||||||
|
print("Init of Smaract stages")
|
||||||
|
dev.losax.controller.find_reference_mark(2, 0, 1000, 1)
|
||||||
|
time.sleep(1)
|
||||||
|
dev.losax.controller.find_reference_mark(0, 0, 1000, 1)
|
||||||
|
time.sleep(1)
|
||||||
|
dev.losax.controller.find_reference_mark(1, 0, 1000, 1)
|
||||||
|
time.sleep(1)
|
||||||
|
# dev.losax.controller.find_reference_mark(3, 1, 1000, 1)
|
||||||
|
# time.sleep(1)
|
||||||
|
# dev.losax.controller.find_reference_mark(4, 1, 1000, 1)
|
||||||
|
# time.sleep(1)
|
||||||
|
|
||||||
|
# set_lm losax -1.5 0.25
|
||||||
|
# set_lm losay -2.5 4.1
|
||||||
|
# set_lm losaz -4.1 -0.5
|
||||||
|
# set_lm lcsy -1.5 5
|
||||||
|
|
||||||
|
self._align_setup()
|
||||||
|
|
||||||
|
def find_reference_mark(self, device):
|
||||||
|
axis_id = device._config["deviceConfig"].get("axis_Id")
|
||||||
|
axis_id_numeric = self.axis_id_to_numeric(axis_id)
|
||||||
|
device.controller.find_reference(axis_id_numeric)
|
||||||
|
|
||||||
|
def drive_axis_to_limit(self, device, direction):
|
||||||
|
axis_id = device._config["deviceConfig"].get("axis_Id")
|
||||||
|
axis_id_numeric = self.axis_id_to_numeric(axis_id)
|
||||||
|
device.controller.drive_axis_to_limit(axis_id_numeric, direction)
|
||||||
|
|
||||||
|
def axis_id_to_numeric(self, axis_id) -> int:
|
||||||
|
return ord(axis_id.lower()) - 97
|
||||||
|
|
||||||
|
def _align_setup(self):
|
||||||
|
user_input = input("Start moving stages to default initial positions? [y/n]")
|
||||||
|
if user_input == "y":
|
||||||
|
print("Start moving stages...")
|
||||||
|
else:
|
||||||
|
print("Stopping.")
|
||||||
|
return
|
||||||
|
|
||||||
|
lsamx_center = dev.lsamx.user_parameter.get("center")
|
||||||
|
if lsamx_center is None:
|
||||||
|
raise LamNIInitError(
|
||||||
|
"Could not find a lsamx center position. Please check your device config."
|
||||||
|
)
|
||||||
|
lsamy_center = dev.lsamy.user_parameter.get("center")
|
||||||
|
if lsamy_center is None:
|
||||||
|
raise LamNIInitError(
|
||||||
|
"Could not find a lsamy center position. Please check your device config."
|
||||||
|
)
|
||||||
|
umv(dev.lsamx, lsamx_center, dev.lsamy, lsamy_center, dev.loptx, -0.3, dev.lopty, 0)
|
||||||
|
umv(dev.losax, -1)
|
||||||
|
umv(dev.loptz, 82.25)
|
||||||
|
umv(dev.lsamrot, -1)
|
||||||
|
umv(dev.lsamrot, 0)
|
||||||
|
|
||||||
|
time.sleep(2)
|
||||||
|
dev.rtx.controller.feedback_disable_and_even_reset_lamni_angle_interferometer()
|
||||||
|
|
||||||
|
def check_all_axes_of_lamni_referenced(self):
|
||||||
|
if (
|
||||||
|
dev.losax.controller.axis_is_referenced(0)
|
||||||
|
& dev.losax.controller.axis_is_referenced(1)
|
||||||
|
& dev.losax.controller.axis_is_referenced(2)
|
||||||
|
& dev.lsamx.controller.all_axes_referenced()
|
||||||
|
):
|
||||||
|
print("All axes of LamNI are referenced.")
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
class LamNIOpticsMixin:
|
class LamNIOpticsMixin:
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _get_user_param_safe(device, var):
|
def _get_user_param_safe(device, var):
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ from typeguard import typechecked
|
|||||||
|
|
||||||
from csaxs_bec.bec_ipython_client.plugins.cSAXS import epics_get, epics_put, fshopen
|
from csaxs_bec.bec_ipython_client.plugins.cSAXS import epics_get, epics_put, fshopen
|
||||||
|
|
||||||
from .lamni_optics_mixin import LamNIOpticsMixin
|
from .lamni_optics_mixin import LaMNIInitStagesMixin, LamNIOpticsMixin
|
||||||
|
|
||||||
logger = bec_logger.logger
|
logger = bec_logger.logger
|
||||||
bec = builtins.__dict__.get("bec")
|
bec = builtins.__dict__.get("bec")
|
||||||
@@ -32,7 +32,7 @@ class XrayEyeAlign:
|
|||||||
self.lamni = lamni
|
self.lamni = lamni
|
||||||
self.device_manager = client.device_manager
|
self.device_manager = client.device_manager
|
||||||
self.scans = client.scans
|
self.scans = client.scans
|
||||||
self.xeye = self.device_manager.devices.xeye
|
# self.xeye = self.device_manager.devices.xeye
|
||||||
self.alignment_values = defaultdict(list)
|
self.alignment_values = defaultdict(list)
|
||||||
self._reset_init_values()
|
self._reset_init_values()
|
||||||
self.corr_pos_x = []
|
self.corr_pos_x = []
|
||||||
@@ -511,7 +511,7 @@ class LamNI(LamNIOpticsMixin):
|
|||||||
super().__init__()
|
super().__init__()
|
||||||
self.client = client
|
self.client = client
|
||||||
self.align = XrayEyeAlign(client, self)
|
self.align = XrayEyeAlign(client, self)
|
||||||
|
self.init = LaMNIInitStagesMixin()
|
||||||
self.check_shutter = True
|
self.check_shutter = True
|
||||||
self.check_light_available = True
|
self.check_light_available = True
|
||||||
self.check_fofb = True
|
self.check_fofb = True
|
||||||
@@ -586,6 +586,27 @@ class LamNI(LamNIOpticsMixin):
|
|||||||
def tomo_circfov(self, val: float):
|
def tomo_circfov(self, val: float):
|
||||||
self.client.set_global_var("tomo_circfov", val)
|
self.client.set_global_var("tomo_circfov", val)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def tomo_type(self):
|
||||||
|
val = self.client.get_global_var("tomo_type")
|
||||||
|
if val is None:
|
||||||
|
return 1
|
||||||
|
return val
|
||||||
|
|
||||||
|
@tomo_type.setter
|
||||||
|
def tomo_type(self, val: float):
|
||||||
|
if val == 1:
|
||||||
|
# equally spaced tomography with 8 sub tomograms
|
||||||
|
self.client.set_global_var("tomo_type", val)
|
||||||
|
# elif val == 2:
|
||||||
|
# # golden ratio tomography (sorted bunches)
|
||||||
|
# self.client.set_global_var("tomo_type", val)
|
||||||
|
# elif val == 3:
|
||||||
|
# # equally spaced tomography with starting angles shifted by golden ratio
|
||||||
|
# self.client.set_global_var("tomo_type", val)
|
||||||
|
else:
|
||||||
|
raise ValueError("Unknown tomo_type.")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def tomo_countingtime(self):
|
def tomo_countingtime(self):
|
||||||
val = self.client.get_global_var("tomo_countingtime")
|
val = self.client.get_global_var("tomo_countingtime")
|
||||||
@@ -948,25 +969,63 @@ class LamNI(LamNIOpticsMixin):
|
|||||||
# _tomo_shift_angles (potential global variable)
|
# _tomo_shift_angles (potential global variable)
|
||||||
_tomo_shift_angles = 0
|
_tomo_shift_angles = 0
|
||||||
angle_end = start_angle + 360
|
angle_end = start_angle + 360
|
||||||
for angle in np.linspace(
|
angles = np.linspace(
|
||||||
start_angle + _tomo_shift_angles,
|
start_angle + _tomo_shift_angles,
|
||||||
angle_end,
|
angle_end,
|
||||||
num=int(360 / self.tomo_angle_stepsize) + 1,
|
num=int(360 / self.tomo_angle_stepsize) + 1,
|
||||||
endpoint=True,
|
endpoint=True,
|
||||||
):
|
)
|
||||||
successful = False
|
|
||||||
error_caught = False
|
# reverse even sub-tomograms
|
||||||
if 0 <= angle < 360.05:
|
if not (subtomo_number % 2):
|
||||||
print(f"Starting LamNI scan for angle {angle}")
|
angles = np.flip(angles)
|
||||||
while not successful:
|
for angle in angles:
|
||||||
self._start_beam_check()
|
self.progress["subtomo"] = subtomo_number
|
||||||
if not self.special_angles:
|
self.progress["subtomo_projection"] = angles.index(angle)
|
||||||
self._current_special_angles = []
|
self.progress["subtomo_total_projections"] = 180 / self.tomo_angle_stepsize
|
||||||
if self._current_special_angles:
|
self.progress["projection"] = (subtomo_number - 1) * self.progress[
|
||||||
next_special_angle = self._current_special_angles[0]
|
"subtomo_total_projections"
|
||||||
if np.isclose(angle, next_special_angle, atol=0.5):
|
] + self.progress["subtomo_projection"]
|
||||||
self._current_special_angles.pop(0)
|
self.progress["total_projections"] = 180 / self.tomo_angle_stepsize * 8
|
||||||
num_repeats = self.special_angle_repeats
|
self.progress["angle"] = angle
|
||||||
|
self._tomo_scan_at_angle(angle, subtomo_number)
|
||||||
|
|
||||||
|
def _print_progress(self):
|
||||||
|
print("\x1b[95mProgress report:")
|
||||||
|
print(f"Tomo type: ....................... {self.progress['tomo_type']}")
|
||||||
|
print(f"Projection: ...................... {self.progress['projection']}")
|
||||||
|
print(f"Total projections expected ....... {self.progress['total_projections']}")
|
||||||
|
print(f"Angle: ........................... {self.progress['angle']}")
|
||||||
|
print(f"Current subtomo: ................. {self.progress['subtomo']}")
|
||||||
|
print(f"Current projection within subtomo: {self.progress['subtomo_projection']}\x1b[0m")
|
||||||
|
|
||||||
|
def _tomo_scan_at_angle(self, angle, subtomo_number):
|
||||||
|
successful = False
|
||||||
|
error_caught = False
|
||||||
|
if 0 <= angle < 360.05:
|
||||||
|
print(f"Starting LamNI scan for angle {angle} in subtomo {subtomo_number}")
|
||||||
|
self._print_progress()
|
||||||
|
while not successful:
|
||||||
|
self._start_beam_check()
|
||||||
|
if not self.special_angles:
|
||||||
|
self._current_special_angles = []
|
||||||
|
if self._current_special_angles:
|
||||||
|
next_special_angle = self._current_special_angles[0]
|
||||||
|
if np.isclose(angle, next_special_angle, atol=0.5):
|
||||||
|
self._current_special_angles.pop(0)
|
||||||
|
num_repeats = self.special_angle_repeats
|
||||||
|
else:
|
||||||
|
num_repeats = 1
|
||||||
|
try:
|
||||||
|
start_scan_number = bec.queue.next_scan_number
|
||||||
|
for i in range(num_repeats):
|
||||||
|
self._at_each_angle(angle)
|
||||||
|
error_caught = False
|
||||||
|
except AlarmBase as exc:
|
||||||
|
if exc.alarm_type == "TimeoutError":
|
||||||
|
bec.queue.request_queue_reset()
|
||||||
|
time.sleep(2)
|
||||||
|
error_caught = True
|
||||||
else:
|
else:
|
||||||
num_repeats = 1
|
num_repeats = 1
|
||||||
try:
|
try:
|
||||||
@@ -1006,7 +1065,7 @@ class LamNI(LamNIOpticsMixin):
|
|||||||
scans = builtins.__dict__.get("scans")
|
scans = builtins.__dict__.get("scans")
|
||||||
self._current_special_angles = self.special_angles.copy()
|
self._current_special_angles = self.special_angles.copy()
|
||||||
|
|
||||||
if subtomo_start == 1 and start_angle is None:
|
if self.tomo_type == 1 and subtomo_start == 1 and start_angle is None:
|
||||||
# pylint: disable=undefined-variable
|
# pylint: disable=undefined-variable
|
||||||
self.tomo_id = self.add_sample_database(
|
self.tomo_id = self.add_sample_database(
|
||||||
self.sample_name,
|
self.sample_name,
|
||||||
|
|||||||
@@ -309,6 +309,7 @@ class FlomniInitStagesMixin:
|
|||||||
else:
|
else:
|
||||||
print("Stopping.")
|
print("Stopping.")
|
||||||
return
|
return
|
||||||
|
dev.rtx.controller.feedback_disable()
|
||||||
# positions for optics out and 50 mm distance to sample
|
# positions for optics out and 50 mm distance to sample
|
||||||
umv(dev.ftrackz, 4.73, dev.ftracky, 2.5170, dev.foptx, -14.3, dev.fopty, 3.87)
|
umv(dev.ftrackz, 4.73, dev.ftracky, 2.5170, dev.foptx, -14.3, dev.fopty, 3.87)
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ bpm4i:
|
|||||||
softwareTrigger: false
|
softwareTrigger: false
|
||||||
mokev:
|
mokev:
|
||||||
description: Monochromator energy in keV
|
description: Monochromator energy in keV
|
||||||
deviceClass: csaxs_bec.devices.epics.devices.specMotors.EnergyKev
|
deviceClass: csaxs_bec.devices.epics.specMotors.EnergyKev
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
read_pv: X12SA-OP-MO:ROX2
|
read_pv: X12SA-OP-MO:ROX2
|
||||||
deviceTags:
|
deviceTags:
|
||||||
@@ -29,7 +29,7 @@ mokev:
|
|||||||
softwareTrigger: false
|
softwareTrigger: false
|
||||||
mcs:
|
mcs:
|
||||||
description: Mcs scalar card for transmission readout
|
description: Mcs scalar card for transmission readout
|
||||||
deviceClass: csaxs_bec.devices.epics.devices.MCScSAXS
|
deviceClass: csaxs_bec.devices.epics.mcs_csaxs.MCScSAXS
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
prefix: 'X12SA-MCS:'
|
prefix: 'X12SA-MCS:'
|
||||||
mcs_config:
|
mcs_config:
|
||||||
@@ -43,7 +43,7 @@ mcs:
|
|||||||
softwareTrigger: false
|
softwareTrigger: false
|
||||||
eiger9m:
|
eiger9m:
|
||||||
description: Eiger9m HPC area detector 9M
|
description: Eiger9m HPC area detector 9M
|
||||||
deviceClass: csaxs_bec.devices.epics.devices.Eiger9McSAXS
|
deviceClass: csaxs_bec.devices.epics.eiger9m_csaxs.Eiger9McSAXS
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
prefix: 'X12SA-ES-EIGER9M:'
|
prefix: 'X12SA-ES-EIGER9M:'
|
||||||
deviceTags:
|
deviceTags:
|
||||||
@@ -55,7 +55,7 @@ eiger9m:
|
|||||||
softwareTrigger: false
|
softwareTrigger: false
|
||||||
ddg_detectors:
|
ddg_detectors:
|
||||||
description: DelayGenerator for detector triggering
|
description: DelayGenerator for detector triggering
|
||||||
deviceClass: csaxs_bec.devices.epics.devices.DelayGeneratorcSAXS
|
deviceClass: csaxs_bec.devices.epics.delay_generator_csaxs.DelayGeneratorcSAXS
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
prefix: 'delaygen:DG1:'
|
prefix: 'delaygen:DG1:'
|
||||||
ddg_config:
|
ddg_config:
|
||||||
@@ -82,7 +82,7 @@ ddg_detectors:
|
|||||||
softwareTrigger: false
|
softwareTrigger: false
|
||||||
ddg_mcs:
|
ddg_mcs:
|
||||||
description: DelayGenerator for mcs triggering
|
description: DelayGenerator for mcs triggering
|
||||||
deviceClass: csaxs_bec.devices.epics.devices.DelayGeneratorcSAXS
|
deviceClass: csaxs_bec.devices.epics.delay_generator_csaxs.DelayGeneratorcSAXS
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
prefix: 'delaygen:DG2:'
|
prefix: 'delaygen:DG2:'
|
||||||
ddg_config:
|
ddg_config:
|
||||||
@@ -111,7 +111,7 @@ ddg_mcs:
|
|||||||
softwareTrigger: false
|
softwareTrigger: false
|
||||||
ddg_fsh:
|
ddg_fsh:
|
||||||
description: DelayGenerator for fast shutter control
|
description: DelayGenerator for fast shutter control
|
||||||
deviceClass: csaxs_bec.devices.epics.devices.DelayGeneratorcSAXS
|
deviceClass: csaxs_bec.devices.epics.delay_generator_csaxs.DelayGeneratorcSAXS
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
prefix: 'delaygen:DG3:'
|
prefix: 'delaygen:DG3:'
|
||||||
ddg_config:
|
ddg_config:
|
||||||
@@ -138,7 +138,7 @@ ddg_fsh:
|
|||||||
softwareTrigger: false
|
softwareTrigger: false
|
||||||
falcon:
|
falcon:
|
||||||
description: Falcon detector x-ray fluoresence
|
description: Falcon detector x-ray fluoresence
|
||||||
deviceClass: csaxs_bec.devices.epics.devices.FalconcSAXS
|
deviceClass: csaxs_bec.devices.epics.falcon_csaxs.FalconcSAXS
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
prefix: 'X12SA-SITORO:'
|
prefix: 'X12SA-SITORO:'
|
||||||
deviceTags:
|
deviceTags:
|
||||||
@@ -150,7 +150,7 @@ falcon:
|
|||||||
softwareTrigger: false
|
softwareTrigger: false
|
||||||
pilatus_2:
|
pilatus_2:
|
||||||
description: Pilatus2 HPC area detector 300k
|
description: Pilatus2 HPC area detector 300k
|
||||||
deviceClass: csaxs_bec.devices.epics.devices.PilatuscSAXS
|
deviceClass: csaxs_bec.devices.epics.pilatus_csaxs.PilatuscSAXS
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
prefix: 'X12SA-ES-PILATUS300K:'
|
prefix: 'X12SA-ES-PILATUS300K:'
|
||||||
deviceTags:
|
deviceTags:
|
||||||
@@ -162,7 +162,7 @@ pilatus_2:
|
|||||||
softwareTrigger: false
|
softwareTrigger: false
|
||||||
samx:
|
samx:
|
||||||
description: SGalil motor stage
|
description: SGalil motor stage
|
||||||
deviceClass: csaxs_bec.devices.galil.SGalilMotor
|
deviceClass: csaxs_bec.devices.omny.galil.SGalilMotor
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
axis_Id: "E"
|
axis_Id: "E"
|
||||||
host: '129.129.122.26'
|
host: '129.129.122.26'
|
||||||
@@ -180,7 +180,7 @@ samx:
|
|||||||
softwareTrigger: false
|
softwareTrigger: false
|
||||||
samy:
|
samy:
|
||||||
description: SGalil motor stage
|
description: SGalil motor stage
|
||||||
deviceClass: csaxs_bec.devices.galil.SGalilMotor
|
deviceClass: csaxs_bec.devices.omny.galil.SGalilMotor
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
axis_Id: "C"
|
axis_Id: "C"
|
||||||
host: '129.129.122.26'
|
host: '129.129.122.26'
|
||||||
@@ -198,7 +198,7 @@ samy:
|
|||||||
softwareTrigger: false
|
softwareTrigger: false
|
||||||
micfoc:
|
micfoc:
|
||||||
description: Focusing motor of Microscope stage
|
description: Focusing motor of Microscope stage
|
||||||
deviceClass: ophyd_devices.epics.devices.EpicsMotorEx
|
deviceClass: ophyd_devices.devices.EpicsMotorEx
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
prefix: X12SA-ES2-ES06
|
prefix: X12SA-ES2-ES06
|
||||||
motor_resolution: 0.00125
|
motor_resolution: 0.00125
|
||||||
@@ -216,7 +216,7 @@ micfoc:
|
|||||||
softwareTrigger: false
|
softwareTrigger: false
|
||||||
owis_samx:
|
owis_samx:
|
||||||
description: Owis motor stage samx
|
description: Owis motor stage samx
|
||||||
deviceClass: ophyd_devices.epics.devices.EpicsMotorEx
|
deviceClass: ophyd_devices.devices.EpicsMotorEx
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
prefix: X12SA-ES2-ES01
|
prefix: X12SA-ES2-ES01
|
||||||
motor_resolution: 0.00125
|
motor_resolution: 0.00125
|
||||||
@@ -234,7 +234,7 @@ owis_samx:
|
|||||||
softwareTrigger: false
|
softwareTrigger: false
|
||||||
owis_samy:
|
owis_samy:
|
||||||
description: Owis motor stage samx
|
description: Owis motor stage samx
|
||||||
deviceClass: ophyd_devices.epics.devices.EpicsMotorEx
|
deviceClass: ophyd_devices.devices.EpicsMotorEx
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
prefix: X12SA-ES2-ES02
|
prefix: X12SA-ES2-ES02
|
||||||
motor_resolution: 0.00125
|
motor_resolution: 0.00125
|
||||||
@@ -252,7 +252,7 @@ owis_samy:
|
|||||||
softwareTrigger: false
|
softwareTrigger: false
|
||||||
rotx:
|
rotx:
|
||||||
description: Rotation stage rotx
|
description: Rotation stage rotx
|
||||||
deviceClass: ophyd_devices.epics.devices.EpicsMotorEx
|
deviceClass: ophyd_devices.devices.EpicsMotorEx
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
prefix: X12SA-ES2-ES05
|
prefix: X12SA-ES2-ES05
|
||||||
motor_resolution: 0.0025
|
motor_resolution: 0.0025
|
||||||
@@ -273,7 +273,7 @@ rotx:
|
|||||||
softwareTrigger: false
|
softwareTrigger: false
|
||||||
roty:
|
roty:
|
||||||
description: Rotation stage rotx
|
description: Rotation stage rotx
|
||||||
deviceClass: ophyd_devices.epics.devices.EpicsMotorEx
|
deviceClass: ophyd_devices.devices.EpicsMotorEx
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
prefix: X12SA-ES2-ES04
|
prefix: X12SA-ES2-ES04
|
||||||
motor_resolution: 0.0025
|
motor_resolution: 0.0025
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
############################################################
|
############################################################
|
||||||
leyex:
|
leyex:
|
||||||
description: phase plate angle
|
description: phase plate angle
|
||||||
deviceClass: csaxs_bec.devices.galil.galil_ophyd.GalilMotor
|
deviceClass: csaxs_bec.devices.omny.galil.lgalil_ophyd.LamniGalilMotor
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
axis_Id: G
|
axis_Id: G
|
||||||
host: mpc2680.psi.ch
|
host: mpc2680.psi.ch
|
||||||
@@ -22,7 +22,7 @@ leyex:
|
|||||||
in: 14.117
|
in: 14.117
|
||||||
leyey:
|
leyey:
|
||||||
description: phase plate angle
|
description: phase plate angle
|
||||||
deviceClass: csaxs_bec.devices.galil.galil_ophyd.GalilMotor
|
deviceClass: csaxs_bec.devices.omny.galil.lgalil_ophyd.LamniGalilMotor
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
axis_Id: H
|
axis_Id: H
|
||||||
host: mpc2680.psi.ch
|
host: mpc2680.psi.ch
|
||||||
@@ -42,7 +42,7 @@ leyey:
|
|||||||
out: 0.5
|
out: 0.5
|
||||||
loptx:
|
loptx:
|
||||||
description: phase plate angle
|
description: phase plate angle
|
||||||
deviceClass: csaxs_bec.devices.galil.galil_ophyd.GalilMotor
|
deviceClass: csaxs_bec.devices.omny.galil.lgalil_ophyd.LamniGalilMotor
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
axis_Id: E
|
axis_Id: E
|
||||||
host: mpc2680.psi.ch
|
host: mpc2680.psi.ch
|
||||||
@@ -62,7 +62,7 @@ loptx:
|
|||||||
out: -0.699
|
out: -0.699
|
||||||
lopty:
|
lopty:
|
||||||
description: phase plate angle
|
description: phase plate angle
|
||||||
deviceClass: csaxs_bec.devices.galil.galil_ophyd.GalilMotor
|
deviceClass: csaxs_bec.devices.omny.galil.lgalil_ophyd.LamniGalilMotor
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
axis_Id: F
|
axis_Id: F
|
||||||
host: mpc2680.psi.ch
|
host: mpc2680.psi.ch
|
||||||
@@ -82,7 +82,7 @@ lopty:
|
|||||||
out: 3.53
|
out: 3.53
|
||||||
loptz:
|
loptz:
|
||||||
description: phase plate angle
|
description: phase plate angle
|
||||||
deviceClass: csaxs_bec.devices.galil.galil_ophyd.GalilMotor
|
deviceClass: csaxs_bec.devices.omny.galil.lgalil_ophyd.LamniGalilMotor
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
axis_Id: D
|
axis_Id: D
|
||||||
host: mpc2680.psi.ch
|
host: mpc2680.psi.ch
|
||||||
@@ -99,7 +99,7 @@ loptz:
|
|||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
lsamrot:
|
lsamrot:
|
||||||
description: phase plate angle
|
description: phase plate angle
|
||||||
deviceClass: csaxs_bec.devices.galil.galil_ophyd.GalilMotor
|
deviceClass: csaxs_bec.devices.omny.galil.lgalil_ophyd.LamniGalilMotor
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
axis_Id: C
|
axis_Id: C
|
||||||
host: mpc2680.psi.ch
|
host: mpc2680.psi.ch
|
||||||
@@ -116,7 +116,7 @@ lsamrot:
|
|||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
lsamx:
|
lsamx:
|
||||||
description: phase plate angle
|
description: phase plate angle
|
||||||
deviceClass: csaxs_bec.devices.galil.galil_ophyd.GalilMotor
|
deviceClass: csaxs_bec.devices.omny.galil.lgalil_ophyd.LamniGalilMotor
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
axis_Id: A
|
axis_Id: A
|
||||||
host: mpc2680.psi.ch
|
host: mpc2680.psi.ch
|
||||||
@@ -135,7 +135,7 @@ lsamx:
|
|||||||
center: 8.768
|
center: 8.768
|
||||||
lsamy:
|
lsamy:
|
||||||
description: phase plate angle
|
description: phase plate angle
|
||||||
deviceClass: csaxs_bec.devices.galil.galil_ophyd.GalilMotor
|
deviceClass: csaxs_bec.devices.omny.galil.lgalil_ophyd.LamniGalilMotor
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
axis_Id: B
|
axis_Id: B
|
||||||
host: mpc2680.psi.ch
|
host: mpc2680.psi.ch
|
||||||
@@ -162,7 +162,7 @@ lsamy:
|
|||||||
############################################################
|
############################################################
|
||||||
|
|
||||||
rtx:
|
rtx:
|
||||||
deviceClass: csaxs_bec.devices.rt_lamni.rt_lamni_ophyd.RtLamniMotor
|
deviceClass: csaxs_bec.devices.omny.rt.rt_lamni_ophyd.RtLamniMotor
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
axis_Id: A
|
axis_Id: A
|
||||||
device_access: true
|
device_access: true
|
||||||
@@ -179,7 +179,7 @@ rtx:
|
|||||||
enabled: true
|
enabled: true
|
||||||
readOnly: False
|
readOnly: False
|
||||||
rty:
|
rty:
|
||||||
deviceClass: csaxs_bec.devices.rt_lamni.rt_lamni_ophyd.RtLamniMotor
|
deviceClass: csaxs_bec.devices.omny.rt.rt_lamni_ophyd.RtLamniMotor
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
axis_Id: B
|
axis_Id: B
|
||||||
device_access: true
|
device_access: true
|
||||||
@@ -293,7 +293,7 @@ losaz:
|
|||||||
|
|
||||||
eiger1p5m:
|
eiger1p5m:
|
||||||
description: Eiger 1.5M in vacuum detector, in-house developed, PSI
|
description: Eiger 1.5M in vacuum detector, in-house developed, PSI
|
||||||
deviceClass: csaxs_bec.devices.eiger1p5m_csaxs.eiger1p5m.Eiger1p5MDetector
|
deviceClass: csaxs_bec.devices.omny.eiger1p5m.Eiger1p5MDetector
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
device_access: true
|
device_access: true
|
||||||
deviceTags:
|
deviceTags:
|
||||||
@@ -504,7 +504,7 @@ sls_filling_pattern:
|
|||||||
readOnly: True
|
readOnly: True
|
||||||
sls_info:
|
sls_info:
|
||||||
readoutPriority: on_request
|
readoutPriority: on_request
|
||||||
deviceClass: ophyd_devices.sls_devices.sls_devices.SLSInfo
|
deviceClass: ophyd_devices.devices.sls_devices.SLSInfo
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
deviceTags:
|
deviceTags:
|
||||||
- SLS status
|
- SLS status
|
||||||
@@ -537,7 +537,7 @@ sls_machine_status:
|
|||||||
readOnly: True
|
readOnly: True
|
||||||
sls_operator:
|
sls_operator:
|
||||||
readoutPriority: on_request
|
readoutPriority: on_request
|
||||||
deviceClass: ophyd_devices.sls_devices.sls_devices.SLSOperatorMessages
|
deviceClass: ophyd_devices.devices.sls_devices.SLSOperatorMessages
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
auto_monitor: true
|
auto_monitor: true
|
||||||
read_pv: ARIDI-BPM:OFB-MODE
|
read_pv: ARIDI-BPM:OFB-MODE
|
||||||
@@ -802,7 +802,7 @@ bm5try:
|
|||||||
softwareTrigger: false
|
softwareTrigger: false
|
||||||
bpm1:
|
bpm1:
|
||||||
description: 'XBPM 1: Somewhere around mono (VME)'
|
description: 'XBPM 1: Somewhere around mono (VME)'
|
||||||
deviceClass: csaxs_bec.devices.epics.devices.XbpmBase.XbpmCsaxsOp
|
deviceClass: csaxs_bec.devices.epics.XbpmBase.XbpmCsaxsOp
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
prefix: 'X12SA-OP-BPM2:'
|
prefix: 'X12SA-OP-BPM2:'
|
||||||
deviceTags:
|
deviceTags:
|
||||||
@@ -824,7 +824,7 @@ bpm1i:
|
|||||||
softwareTrigger: false
|
softwareTrigger: false
|
||||||
bpm2:
|
bpm2:
|
||||||
description: 'XBPM 2: Somewhere around mono (VME)'
|
description: 'XBPM 2: Somewhere around mono (VME)'
|
||||||
deviceClass: csaxs_bec.devices.epics.devices.XbpmBase.XbpmCsaxsOp
|
deviceClass: csaxs_bec.devices.epics.XbpmBase.XbpmCsaxsOp
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
prefix: 'X12SA-OP-BPM2:'
|
prefix: 'X12SA-OP-BPM2:'
|
||||||
deviceTags:
|
deviceTags:
|
||||||
@@ -1187,7 +1187,7 @@ dtpush:
|
|||||||
softwareTrigger: false
|
softwareTrigger: false
|
||||||
dtth:
|
dtth:
|
||||||
description: Detector tower tilt rotation
|
description: Detector tower tilt rotation
|
||||||
deviceClass: csaxs_bec.devices.epics.devices.specMotors.PmDetectorRotation
|
deviceClass: csaxs_bec.devices.epics.specMotors.PmDetectorRotation
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
prefix: X12SA-ES1-DETT:ROX1
|
prefix: X12SA-ES1-DETT:ROX1
|
||||||
deviceTags:
|
deviceTags:
|
||||||
@@ -1462,7 +1462,7 @@ fttrz:
|
|||||||
softwareTrigger: false
|
softwareTrigger: false
|
||||||
idgap:
|
idgap:
|
||||||
description: Undulator gap size [mm]
|
description: Undulator gap size [mm]
|
||||||
deviceClass: csaxs_bec.devices.epics.devices.InsertionDevice
|
deviceClass: csaxs_bec.devices.epics.InsertionDevice.InsertionDevice
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
prefix: X12SA-ID
|
prefix: X12SA-ID
|
||||||
deviceTags:
|
deviceTags:
|
||||||
@@ -1561,7 +1561,7 @@ mitry3:
|
|||||||
softwareTrigger: false
|
softwareTrigger: false
|
||||||
mobd:
|
mobd:
|
||||||
description: Monochromator bender virtual motor
|
description: Monochromator bender virtual motor
|
||||||
deviceClass: csaxs_bec.devices.epics.devices.specMotors.PmMonoBender
|
deviceClass: csaxs_bec.devices.epics.specMotors.PmMonoBender
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
prefix: 'X12SA-OP-MO:'
|
prefix: 'X12SA-OP-MO:'
|
||||||
deviceTags:
|
deviceTags:
|
||||||
@@ -1616,7 +1616,7 @@ mobddi:
|
|||||||
softwareTrigger: false
|
softwareTrigger: false
|
||||||
mokev:
|
mokev:
|
||||||
description: Monochromator energy in keV
|
description: Monochromator energy in keV
|
||||||
deviceClass: csaxs_bec.devices.epics.devices.specMotors.EnergyKev
|
deviceClass: csaxs_bec.devices.epics.specMotors.EnergyKev
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
read_pv: X12SA-OP-MO:ROX2
|
read_pv: X12SA-OP-MO:ROX2
|
||||||
deviceTags:
|
deviceTags:
|
||||||
@@ -1671,7 +1671,7 @@ moroll2:
|
|||||||
softwareTrigger: false
|
softwareTrigger: false
|
||||||
moth1:
|
moth1:
|
||||||
description: Monochromator Theta 1
|
description: Monochromator Theta 1
|
||||||
deviceClass: csaxs_bec.devices.epics.devices.specMotors.MonoTheta1
|
deviceClass: csaxs_bec.devices.epics.specMotors.MonoTheta1
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
read_pv: X12SA-OP-MO:ROX1
|
read_pv: X12SA-OP-MO:ROX1
|
||||||
deviceTags:
|
deviceTags:
|
||||||
@@ -1693,7 +1693,7 @@ moth1e:
|
|||||||
softwareTrigger: false
|
softwareTrigger: false
|
||||||
moth2:
|
moth2:
|
||||||
description: Monochromator Theta 2
|
description: Monochromator Theta 2
|
||||||
deviceClass: csaxs_bec.devices.epics.devices.specMotors.MonoTheta2
|
deviceClass: csaxs_bec.devices.epics.specMotors.MonoTheta2
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
read_pv: X12SA-OP-MO:ROX2
|
read_pv: X12SA-OP-MO:ROX2
|
||||||
deviceTags:
|
deviceTags:
|
||||||
@@ -1812,17 +1812,17 @@ sec:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
softwareTrigger: false
|
softwareTrigger: false
|
||||||
sl0h:
|
# sl0h:
|
||||||
description: FrontEnd slit virtual movement
|
# description: FrontEnd slit virtual movement
|
||||||
deviceClass: ophyd_devices.epics.devices.SlitH
|
# deviceClass: ophyd_devices.devices.SlitH
|
||||||
deviceConfig:
|
# deviceConfig:
|
||||||
prefix: 'X12SA-FE-SH1:'
|
# prefix: 'X12SA-FE-SH1:'
|
||||||
deviceTags:
|
# deviceTags:
|
||||||
- epicsDevice
|
# - epicsDevice
|
||||||
enabled: true
|
# enabled: true
|
||||||
onFailure: buffer
|
# onFailure: buffer
|
||||||
readoutPriority: baseline
|
# readoutPriority: baseline
|
||||||
softwareTrigger: false
|
# softwareTrigger: false
|
||||||
sl0trxi:
|
sl0trxi:
|
||||||
description: FrontEnd slit inner blade movement
|
description: FrontEnd slit inner blade movement
|
||||||
deviceClass: ophyd.EpicsMotor
|
deviceClass: ophyd.EpicsMotor
|
||||||
@@ -1845,17 +1845,17 @@ sl0trxo:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
softwareTrigger: false
|
softwareTrigger: false
|
||||||
sl1h:
|
# sl1h:
|
||||||
description: OpticsHutch slit virtual movement
|
# description: OpticsHutch slit virtual movement
|
||||||
deviceClass: ophyd_devices.epics.devices.SlitH
|
# deviceClass: ophyd_devices.devices.SlitH
|
||||||
deviceConfig:
|
# deviceConfig:
|
||||||
prefix: 'X12SA-OP-SH1:'
|
# prefix: 'X12SA-OP-SH1:'
|
||||||
deviceTags:
|
# deviceTags:
|
||||||
- epicsDevice
|
# - epicsDevice
|
||||||
enabled: true
|
# enabled: true
|
||||||
onFailure: buffer
|
# onFailure: buffer
|
||||||
readoutPriority: baseline
|
# readoutPriority: baseline
|
||||||
softwareTrigger: false
|
# softwareTrigger: false
|
||||||
sl1trxi:
|
sl1trxi:
|
||||||
description: OpticsHutch slit inner blade movement
|
description: OpticsHutch slit inner blade movement
|
||||||
deviceClass: ophyd.EpicsMotor
|
deviceClass: ophyd.EpicsMotor
|
||||||
@@ -1900,28 +1900,28 @@ sl1tryt:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
softwareTrigger: false
|
softwareTrigger: false
|
||||||
sl1v:
|
# sl1v:
|
||||||
description: OpticsHutch slit virtual movement
|
# description: OpticsHutch slit virtual movement
|
||||||
deviceClass: ophyd_devices.epics.devices.SlitV
|
# deviceClass: ophyd_devices.devices.SlitV
|
||||||
deviceConfig:
|
# deviceConfig:
|
||||||
prefix: 'X12SA-OP-SV1:'
|
# prefix: 'X12SA-OP-SV1:'
|
||||||
deviceTags:
|
# deviceTags:
|
||||||
- epicsDevice
|
# - epicsDevice
|
||||||
enabled: true
|
# enabled: true
|
||||||
onFailure: buffer
|
# onFailure: buffer
|
||||||
readoutPriority: baseline
|
# readoutPriority: baseline
|
||||||
softwareTrigger: false
|
# softwareTrigger: false
|
||||||
sl2h:
|
# sl2h:
|
||||||
description: OpticsHutch slit 2 virtual movement
|
# description: OpticsHutch slit 2 virtual movement
|
||||||
deviceClass: ophyd_devices.epics.devices.SlitH
|
# deviceClass: ophyd_devices.devices.SlitH
|
||||||
deviceConfig:
|
# deviceConfig:
|
||||||
prefix: 'X12SA-OP-SH2:'
|
# prefix: 'X12SA-OP-SH2:'
|
||||||
deviceTags:
|
# deviceTags:
|
||||||
- epicsDevice
|
# - epicsDevice
|
||||||
enabled: true
|
# enabled: true
|
||||||
onFailure: buffer
|
# onFailure: buffer
|
||||||
readoutPriority: baseline
|
# readoutPriority: baseline
|
||||||
softwareTrigger: false
|
# softwareTrigger: false
|
||||||
sl2trxi:
|
sl2trxi:
|
||||||
description: OpticsHutch slit 2 inner blade movement
|
description: OpticsHutch slit 2 inner blade movement
|
||||||
deviceClass: ophyd.EpicsMotor
|
deviceClass: ophyd.EpicsMotor
|
||||||
@@ -1966,72 +1966,72 @@ sl2tryt:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
softwareTrigger: false
|
softwareTrigger: false
|
||||||
sl2v:
|
# sl2v:
|
||||||
description: OpticsHutch slit 2 virtual movement
|
# description: OpticsHutch slit 2 virtual movement
|
||||||
deviceClass: ophyd_devices.epics.devices.SlitV
|
# deviceClass: ophyd_devices.devices.SlitV
|
||||||
deviceConfig:
|
# deviceConfig:
|
||||||
prefix: 'X12SA-OP-SV2:'
|
# prefix: 'X12SA-OP-SV2:'
|
||||||
deviceTags:
|
# deviceTags:
|
||||||
- epicsDevice
|
# - epicsDevice
|
||||||
enabled: true
|
# enabled: true
|
||||||
onFailure: buffer
|
# onFailure: buffer
|
||||||
readoutPriority: baseline
|
# readoutPriority: baseline
|
||||||
softwareTrigger: false
|
# softwareTrigger: false
|
||||||
strox:
|
# strox:
|
||||||
description: Girder virtual pitch
|
# description: Girder virtual pitch
|
||||||
deviceClass: ophyd_devices.epics.devices.GirderMotorPITCH
|
# deviceClass: ophyd_devices.devices.GirderMotorPITCH
|
||||||
deviceConfig:
|
# deviceConfig:
|
||||||
prefix: X12SA-HG
|
# prefix: X12SA-HG
|
||||||
deviceTags:
|
# deviceTags:
|
||||||
- beamlineMotor
|
# - beamlineMotor
|
||||||
enabled: true
|
# enabled: true
|
||||||
onFailure: buffer
|
# onFailure: buffer
|
||||||
readoutPriority: baseline
|
# readoutPriority: baseline
|
||||||
softwareTrigger: false
|
# softwareTrigger: false
|
||||||
stroy:
|
# stroy:
|
||||||
description: Girder virtual yaw
|
# description: Girder virtual yaw
|
||||||
deviceClass: ophyd_devices.epics.devices.GirderMotorYAW
|
# deviceClass: ophyd_devices.devices.GirderMotorYAW
|
||||||
deviceConfig:
|
# deviceConfig:
|
||||||
prefix: X12SA-HG
|
# prefix: X12SA-HG
|
||||||
deviceTags:
|
# deviceTags:
|
||||||
- beamlineMotor
|
# - beamlineMotor
|
||||||
enabled: true
|
# enabled: true
|
||||||
onFailure: buffer
|
# onFailure: buffer
|
||||||
readoutPriority: baseline
|
# readoutPriority: baseline
|
||||||
softwareTrigger: false
|
# softwareTrigger: false
|
||||||
stroz:
|
# stroz:
|
||||||
description: Girder virtual roll
|
# description: Girder virtual roll
|
||||||
deviceClass: ophyd_devices.epics.devices.GirderMotorROLL
|
# deviceClass: ophyd_devices.devices.GirderMotorROLL
|
||||||
deviceConfig:
|
# deviceConfig:
|
||||||
prefix: X12SA-HG
|
# prefix: X12SA-HG
|
||||||
deviceTags:
|
# deviceTags:
|
||||||
- beamlineMotor
|
# - beamlineMotor
|
||||||
enabled: true
|
# enabled: true
|
||||||
onFailure: buffer
|
# onFailure: buffer
|
||||||
readoutPriority: baseline
|
# readoutPriority: baseline
|
||||||
softwareTrigger: false
|
# softwareTrigger: false
|
||||||
sttrx:
|
# sttrx:
|
||||||
description: Girder X translation
|
# description: Girder X translation
|
||||||
deviceClass: ophyd_devices.epics.devices.GirderMotorX1
|
# deviceClass: ophyd_devices.devices.GirderMotorX1
|
||||||
deviceConfig:
|
# deviceConfig:
|
||||||
prefix: X12SA-HG
|
# prefix: X12SA-HG
|
||||||
deviceTags:
|
# deviceTags:
|
||||||
- beamlineMotor
|
# - beamlineMotor
|
||||||
enabled: true
|
# enabled: true
|
||||||
onFailure: buffer
|
# onFailure: buffer
|
||||||
readoutPriority: baseline
|
# readoutPriority: baseline
|
||||||
softwareTrigger: false
|
# softwareTrigger: false
|
||||||
sttry:
|
# sttry:
|
||||||
description: Girder Y translation
|
# description: Girder Y translation
|
||||||
deviceClass: ophyd_devices.epics.devices.GirderMotorY1
|
# deviceClass: ophyd_devices.devices.GirderMotorY1
|
||||||
deviceConfig:
|
# deviceConfig:
|
||||||
prefix: X12SA-HG
|
# prefix: X12SA-HG
|
||||||
deviceTags:
|
# deviceTags:
|
||||||
- beamlineMotor
|
# - beamlineMotor
|
||||||
enabled: true
|
# enabled: true
|
||||||
onFailure: buffer
|
# onFailure: buffer
|
||||||
readoutPriority: baseline
|
# readoutPriority: baseline
|
||||||
softwareTrigger: false
|
# softwareTrigger: false
|
||||||
transd:
|
transd:
|
||||||
description: Transmission diode
|
description: Transmission diode
|
||||||
deviceClass: ophyd.EpicsSignalRO
|
deviceClass: ophyd.EpicsSignalRO
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
|
############################################################
|
||||||
|
#################### flOMNI Galil motors ###################
|
||||||
|
############################################################
|
||||||
|
|
||||||
feyex:
|
feyex:
|
||||||
description: phase plate angle
|
description: Xray eye X
|
||||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
deviceClass: csaxs_bec.devices.omny.galil.fgalil_ophyd.FlomniGalilMotor
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
axis_Id: D
|
axis_Id: D
|
||||||
host: mpc2844.psi.ch
|
host: mpc2844.psi.ch
|
||||||
@@ -17,8 +21,8 @@ feyex:
|
|||||||
in: -16.267
|
in: -16.267
|
||||||
out: -1
|
out: -1
|
||||||
feyey:
|
feyey:
|
||||||
description: phase plate angle
|
description: Xray eye Y
|
||||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
deviceClass: csaxs_bec.devices.omny.galil.fgalil_ophyd.FlomniGalilMotor
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
axis_Id: E
|
axis_Id: E
|
||||||
host: mpc2844.psi.ch
|
host: mpc2844.psi.ch
|
||||||
@@ -34,8 +38,8 @@ feyey:
|
|||||||
userParameter:
|
userParameter:
|
||||||
in: -10.467
|
in: -10.467
|
||||||
fheater:
|
fheater:
|
||||||
description: phase plate angle
|
description: Heater Y
|
||||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
deviceClass: csaxs_bec.devices.omny.galil.fgalil_ophyd.FlomniGalilMotor
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
axis_Id: C
|
axis_Id: C
|
||||||
host: mpc2844.psi.ch
|
host: mpc2844.psi.ch
|
||||||
@@ -48,17 +52,9 @@ fheater:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
flomni_samples:
|
|
||||||
description: phase plate angle
|
|
||||||
deviceClass: csaxs_bec.devices.epics.devices.flomni_sample_storage.FlomniSampleStorage
|
|
||||||
deviceConfig: {}
|
|
||||||
enabled: true
|
|
||||||
onFailure: buffer
|
|
||||||
readOnly: false
|
|
||||||
readoutPriority: baseline
|
|
||||||
foptx:
|
foptx:
|
||||||
description: phase plate angle
|
description: Optics X
|
||||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
deviceClass: csaxs_bec.devices.omny.galil.fgalil_ophyd.FlomniGalilMotor
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
axis_Id: B
|
axis_Id: B
|
||||||
host: mpc2844.psi.ch
|
host: mpc2844.psi.ch
|
||||||
@@ -74,8 +70,8 @@ foptx:
|
|||||||
userParameter:
|
userParameter:
|
||||||
in: -13.761
|
in: -13.761
|
||||||
fopty:
|
fopty:
|
||||||
description: phase plate angle
|
description: Optics Y
|
||||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
deviceClass: csaxs_bec.devices.omny.galil.fgalil_ophyd.FlomniGalilMotor
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
axis_Id: F
|
axis_Id: F
|
||||||
host: mpc2844.psi.ch
|
host: mpc2844.psi.ch
|
||||||
@@ -92,8 +88,8 @@ fopty:
|
|||||||
in: 0.552
|
in: 0.552
|
||||||
out: 0.752
|
out: 0.752
|
||||||
foptz:
|
foptz:
|
||||||
description: phase plate angle
|
description: Optics Z
|
||||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
deviceClass: csaxs_bec.devices.omny.galil.fgalil_ophyd.FlomniGalilMotor
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
axis_Id: A
|
axis_Id: A
|
||||||
host: mpc2844.psi.ch
|
host: mpc2844.psi.ch
|
||||||
@@ -108,8 +104,166 @@ foptz:
|
|||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
userParameter:
|
userParameter:
|
||||||
in: 23
|
in: 23
|
||||||
|
fsamroy:
|
||||||
|
description: Sample rotation
|
||||||
|
deviceClass: csaxs_bec.devices.omny.galil.fupr_ophyd.FuprGalilMotor
|
||||||
|
deviceConfig:
|
||||||
|
axis_Id: A
|
||||||
|
host: mpc2844.psi.ch
|
||||||
|
limits:
|
||||||
|
- -5
|
||||||
|
- 365
|
||||||
|
port: 8084
|
||||||
|
sign: -1
|
||||||
|
enabled: true
|
||||||
|
onFailure: buffer
|
||||||
|
readOnly: false
|
||||||
|
readoutPriority: baseline
|
||||||
|
fsamx:
|
||||||
|
description: Sample coarse X
|
||||||
|
deviceClass: csaxs_bec.devices.omny.galil.fgalil_ophyd.FlomniGalilMotor
|
||||||
|
deviceConfig:
|
||||||
|
axis_Id: E
|
||||||
|
host: mpc2844.psi.ch
|
||||||
|
limits:
|
||||||
|
- -162
|
||||||
|
- 0
|
||||||
|
port: 8081
|
||||||
|
sign: 1
|
||||||
|
enabled: true
|
||||||
|
onFailure: buffer
|
||||||
|
readOnly: true
|
||||||
|
readoutPriority: baseline
|
||||||
|
userParameter:
|
||||||
|
in: -1.1
|
||||||
|
fsamy:
|
||||||
|
description: Sample coarse Y
|
||||||
|
deviceClass: csaxs_bec.devices.omny.galil.fgalil_ophyd.FlomniGalilMotor
|
||||||
|
deviceConfig:
|
||||||
|
axis_Id: F
|
||||||
|
host: mpc2844.psi.ch
|
||||||
|
limits:
|
||||||
|
- 2
|
||||||
|
- 3.1
|
||||||
|
port: 8081
|
||||||
|
sign: 1
|
||||||
|
enabled: true
|
||||||
|
onFailure: buffer
|
||||||
|
readOnly: true
|
||||||
|
readoutPriority: baseline
|
||||||
|
userParameter:
|
||||||
|
in: 2.75
|
||||||
|
ftracky:
|
||||||
|
description: Laser Tracker coarse Y
|
||||||
|
deviceClass: csaxs_bec.devices.omny.galil.fgalil_ophyd.FlomniGalilMotor
|
||||||
|
deviceConfig:
|
||||||
|
axis_Id: H
|
||||||
|
host: mpc2844.psi.ch
|
||||||
|
limits:
|
||||||
|
- 2.2
|
||||||
|
- 2.8
|
||||||
|
port: 8082
|
||||||
|
sign: 1
|
||||||
|
enabled: true
|
||||||
|
onFailure: buffer
|
||||||
|
readOnly: false
|
||||||
|
readoutPriority: baseline
|
||||||
|
ftrackz:
|
||||||
|
description: Laser Tracker coarse Z
|
||||||
|
deviceClass: csaxs_bec.devices.omny.galil.fgalil_ophyd.FlomniGalilMotor
|
||||||
|
deviceConfig:
|
||||||
|
axis_Id: G
|
||||||
|
host: mpc2844.psi.ch
|
||||||
|
limits:
|
||||||
|
- 4.5
|
||||||
|
- 5.5
|
||||||
|
port: 8082
|
||||||
|
sign: 1
|
||||||
|
enabled: true
|
||||||
|
onFailure: buffer
|
||||||
|
readOnly: false
|
||||||
|
readoutPriority: baseline
|
||||||
|
ftransx:
|
||||||
|
description: Sample transer X
|
||||||
|
deviceClass: csaxs_bec.devices.omny.galil.fgalil_ophyd.FlomniGalilMotor
|
||||||
|
deviceConfig:
|
||||||
|
axis_Id: C
|
||||||
|
host: mpc2844.psi.ch
|
||||||
|
limits:
|
||||||
|
- 0
|
||||||
|
- 50
|
||||||
|
port: 8081
|
||||||
|
sign: 1
|
||||||
|
enabled: true
|
||||||
|
onFailure: buffer
|
||||||
|
readOnly: false
|
||||||
|
readoutPriority: baseline
|
||||||
|
ftransy:
|
||||||
|
description: Sample transer Y
|
||||||
|
deviceClass: csaxs_bec.devices.omny.galil.fgalil_ophyd.FlomniGalilMotor
|
||||||
|
deviceConfig:
|
||||||
|
axis_Id: A
|
||||||
|
host: mpc2844.psi.ch
|
||||||
|
limits:
|
||||||
|
- -100
|
||||||
|
- 0
|
||||||
|
port: 8081
|
||||||
|
sign: 1
|
||||||
|
enabled: true
|
||||||
|
onFailure: buffer
|
||||||
|
readOnly: false
|
||||||
|
readoutPriority: baseline
|
||||||
|
ftransz:
|
||||||
|
description: Sample transer Z
|
||||||
|
deviceClass: csaxs_bec.devices.omny.galil.fgalil_ophyd.FlomniGalilMotor
|
||||||
|
deviceConfig:
|
||||||
|
axis_Id: B
|
||||||
|
host: mpc2844.psi.ch
|
||||||
|
limits:
|
||||||
|
- 0
|
||||||
|
- 145
|
||||||
|
port: 8081
|
||||||
|
sign: 1
|
||||||
|
enabled: true
|
||||||
|
onFailure: buffer
|
||||||
|
readOnly: false
|
||||||
|
readoutPriority: baseline
|
||||||
|
ftray:
|
||||||
|
description: Sample transfer tray
|
||||||
|
deviceClass: csaxs_bec.devices.omny.galil.fgalil_ophyd.FlomniGalilMotor
|
||||||
|
deviceConfig:
|
||||||
|
axis_Id: D
|
||||||
|
host: mpc2844.psi.ch
|
||||||
|
limits:
|
||||||
|
- -200
|
||||||
|
- 0
|
||||||
|
port: 8081
|
||||||
|
sign: -1
|
||||||
|
enabled: true
|
||||||
|
onFailure: buffer
|
||||||
|
readOnly: false
|
||||||
|
readoutPriority: baseline
|
||||||
|
|
||||||
|
|
||||||
|
############################################################
|
||||||
|
#################### flOMNI Sample Names ###################
|
||||||
|
############################################################
|
||||||
|
|
||||||
|
flomni_samples:
|
||||||
|
description: Sample names and storage
|
||||||
|
deviceClass: csaxs_bec.devices.omny.flomni_sample_storage.FlomniSampleStorage
|
||||||
|
deviceConfig: {}
|
||||||
|
enabled: true
|
||||||
|
onFailure: buffer
|
||||||
|
readOnly: false
|
||||||
|
readoutPriority: baseline
|
||||||
|
|
||||||
|
############################################################
|
||||||
|
#################### flOMNI Smaract motors #################
|
||||||
|
############################################################
|
||||||
|
|
||||||
fosax:
|
fosax:
|
||||||
description: phase plate angle
|
description: OSA X
|
||||||
deviceClass: csaxs_bec.devices.smaract.smaract_ophyd.SmaractMotor
|
deviceClass: csaxs_bec.devices.smaract.smaract_ophyd.SmaractMotor
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
axis_Id: A
|
axis_Id: A
|
||||||
@@ -127,7 +281,7 @@ fosax:
|
|||||||
in: 9.124
|
in: 9.124
|
||||||
out: 5.3
|
out: 5.3
|
||||||
fosay:
|
fosay:
|
||||||
description: phase plate angle
|
description: OSA Y
|
||||||
deviceClass: csaxs_bec.devices.smaract.smaract_ophyd.SmaractMotor
|
deviceClass: csaxs_bec.devices.smaract.smaract_ophyd.SmaractMotor
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
axis_Id: B
|
axis_Id: B
|
||||||
@@ -144,7 +298,7 @@ fosay:
|
|||||||
userParameter:
|
userParameter:
|
||||||
in: 0.367
|
in: 0.367
|
||||||
fosaz:
|
fosaz:
|
||||||
description: phase plate angle
|
description: OSA Z
|
||||||
deviceClass: csaxs_bec.devices.smaract.smaract_ophyd.SmaractMotor
|
deviceClass: csaxs_bec.devices.smaract.smaract_ophyd.SmaractMotor
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
axis_Id: C
|
axis_Id: C
|
||||||
@@ -161,148 +315,14 @@ fosaz:
|
|||||||
userParameter:
|
userParameter:
|
||||||
in: 8.5
|
in: 8.5
|
||||||
out: 6
|
out: 6
|
||||||
fsamroy:
|
|
||||||
description: phase plate angle
|
############################################################
|
||||||
deviceClass: csaxs_bec.devices.galil.fupr_ophyd.FuprGalilMotor
|
#################### flOMNI RT motors ######################
|
||||||
deviceConfig:
|
############################################################
|
||||||
axis_Id: A
|
|
||||||
host: mpc2844.psi.ch
|
|
||||||
limits:
|
|
||||||
- -5
|
|
||||||
- 365
|
|
||||||
port: 8084
|
|
||||||
sign: -1
|
|
||||||
enabled: true
|
|
||||||
onFailure: buffer
|
|
||||||
readOnly: false
|
|
||||||
readoutPriority: baseline
|
|
||||||
fsamx:
|
|
||||||
description: phase plate angle
|
|
||||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
|
||||||
deviceConfig:
|
|
||||||
axis_Id: E
|
|
||||||
host: mpc2844.psi.ch
|
|
||||||
limits:
|
|
||||||
- -162
|
|
||||||
- 0
|
|
||||||
port: 8081
|
|
||||||
sign: 1
|
|
||||||
enabled: true
|
|
||||||
onFailure: buffer
|
|
||||||
readOnly: true
|
|
||||||
readoutPriority: baseline
|
|
||||||
userParameter:
|
|
||||||
in: -1.1
|
|
||||||
fsamy:
|
|
||||||
description: phase plate angle
|
|
||||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
|
||||||
deviceConfig:
|
|
||||||
axis_Id: F
|
|
||||||
host: mpc2844.psi.ch
|
|
||||||
limits:
|
|
||||||
- 2
|
|
||||||
- 3.1
|
|
||||||
port: 8081
|
|
||||||
sign: 1
|
|
||||||
enabled: true
|
|
||||||
onFailure: buffer
|
|
||||||
readOnly: true
|
|
||||||
readoutPriority: baseline
|
|
||||||
userParameter:
|
|
||||||
in: 2.75
|
|
||||||
ftracky:
|
|
||||||
description: phase plate angle
|
|
||||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
|
||||||
deviceConfig:
|
|
||||||
axis_Id: H
|
|
||||||
host: mpc2844.psi.ch
|
|
||||||
limits:
|
|
||||||
- 2.2
|
|
||||||
- 2.8
|
|
||||||
port: 8082
|
|
||||||
sign: 1
|
|
||||||
enabled: true
|
|
||||||
onFailure: buffer
|
|
||||||
readOnly: false
|
|
||||||
readoutPriority: baseline
|
|
||||||
ftrackz:
|
|
||||||
description: phase plate angle
|
|
||||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
|
||||||
deviceConfig:
|
|
||||||
axis_Id: G
|
|
||||||
host: mpc2844.psi.ch
|
|
||||||
limits:
|
|
||||||
- 4.5
|
|
||||||
- 5.5
|
|
||||||
port: 8082
|
|
||||||
sign: 1
|
|
||||||
enabled: true
|
|
||||||
onFailure: buffer
|
|
||||||
readOnly: false
|
|
||||||
readoutPriority: baseline
|
|
||||||
ftransx:
|
|
||||||
description: phase plate angle
|
|
||||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
|
||||||
deviceConfig:
|
|
||||||
axis_Id: C
|
|
||||||
host: mpc2844.psi.ch
|
|
||||||
limits:
|
|
||||||
- 0
|
|
||||||
- 50
|
|
||||||
port: 8081
|
|
||||||
sign: 1
|
|
||||||
enabled: true
|
|
||||||
onFailure: buffer
|
|
||||||
readOnly: false
|
|
||||||
readoutPriority: baseline
|
|
||||||
ftransy:
|
|
||||||
description: phase plate angle
|
|
||||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
|
||||||
deviceConfig:
|
|
||||||
axis_Id: A
|
|
||||||
host: mpc2844.psi.ch
|
|
||||||
limits:
|
|
||||||
- -100
|
|
||||||
- 0
|
|
||||||
port: 8081
|
|
||||||
sign: 1
|
|
||||||
enabled: true
|
|
||||||
onFailure: buffer
|
|
||||||
readOnly: false
|
|
||||||
readoutPriority: baseline
|
|
||||||
ftransz:
|
|
||||||
description: phase plate angle
|
|
||||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
|
||||||
deviceConfig:
|
|
||||||
axis_Id: B
|
|
||||||
host: mpc2844.psi.ch
|
|
||||||
limits:
|
|
||||||
- 0
|
|
||||||
- 145
|
|
||||||
port: 8081
|
|
||||||
sign: 1
|
|
||||||
enabled: true
|
|
||||||
onFailure: buffer
|
|
||||||
readOnly: false
|
|
||||||
readoutPriority: baseline
|
|
||||||
ftray:
|
|
||||||
description: phase plate angle
|
|
||||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
|
||||||
deviceConfig:
|
|
||||||
axis_Id: D
|
|
||||||
host: mpc2844.psi.ch
|
|
||||||
limits:
|
|
||||||
- -200
|
|
||||||
- 0
|
|
||||||
port: 8081
|
|
||||||
sign: -1
|
|
||||||
enabled: true
|
|
||||||
onFailure: buffer
|
|
||||||
readOnly: false
|
|
||||||
readoutPriority: baseline
|
|
||||||
rtx:
|
rtx:
|
||||||
description: flomni rt
|
description: flomni rt
|
||||||
deviceClass: csaxs_bec.devices.rt_lamni.rt_flomni_ophyd.RtFlomniMotor
|
deviceClass: csaxs_bec.devices.omny.rt.rt_flomni_ophyd.RtFlomniMotor
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
axis_Id: A
|
axis_Id: A
|
||||||
host: mpc2844.psi.ch
|
host: mpc2844.psi.ch
|
||||||
@@ -318,7 +338,7 @@ rtx:
|
|||||||
rt_pid_voltage: -0.06219
|
rt_pid_voltage: -0.06219
|
||||||
rty:
|
rty:
|
||||||
description: flomni rt
|
description: flomni rt
|
||||||
deviceClass: csaxs_bec.devices.rt_lamni.rt_flomni_ophyd.RtFlomniMotor
|
deviceClass: csaxs_bec.devices.omny.rt.rt_flomni_ophyd.RtFlomniMotor
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
axis_Id: B
|
axis_Id: B
|
||||||
host: mpc2844.psi.ch
|
host: mpc2844.psi.ch
|
||||||
@@ -332,7 +352,7 @@ rty:
|
|||||||
tomo_additional_offsety: 0
|
tomo_additional_offsety: 0
|
||||||
rtz:
|
rtz:
|
||||||
description: flomni rt
|
description: flomni rt
|
||||||
deviceClass: csaxs_bec.devices.rt_lamni.rt_flomni_ophyd.RtFlomniMotor
|
deviceClass: csaxs_bec.devices.omny.rt.rt_flomni_ophyd.RtFlomniMotor
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
axis_Id: C
|
axis_Id: C
|
||||||
host: mpc2844.psi.ch
|
host: mpc2844.psi.ch
|
||||||
|
|||||||
@@ -1,340 +0,0 @@
|
|||||||
fheater:
|
|
||||||
readoutPriority: baseline
|
|
||||||
description: phase plate angle
|
|
||||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
|
||||||
deviceConfig:
|
|
||||||
axis_Id: C
|
|
||||||
host: mpc2844.psi.ch
|
|
||||||
limits:
|
|
||||||
- -15
|
|
||||||
- 0
|
|
||||||
port: 8082
|
|
||||||
sign: -1
|
|
||||||
onFailure: buffer
|
|
||||||
enabled: true
|
|
||||||
readOnly: false
|
|
||||||
feyex:
|
|
||||||
readoutPriority: baseline
|
|
||||||
description: phase plate angle
|
|
||||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
|
||||||
deviceConfig:
|
|
||||||
axis_Id: D
|
|
||||||
host: mpc2844.psi.ch
|
|
||||||
limits:
|
|
||||||
- -30
|
|
||||||
- -1
|
|
||||||
port: 8082
|
|
||||||
sign: 1
|
|
||||||
onFailure: buffer
|
|
||||||
userParameter:
|
|
||||||
in: -16.267
|
|
||||||
out: -1
|
|
||||||
enabled: true
|
|
||||||
readOnly: false
|
|
||||||
feyey:
|
|
||||||
readoutPriority: baseline
|
|
||||||
description: phase plate angle
|
|
||||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
|
||||||
deviceConfig:
|
|
||||||
axis_Id: E
|
|
||||||
host: mpc2844.psi.ch
|
|
||||||
limits:
|
|
||||||
- -1
|
|
||||||
- -10
|
|
||||||
port: 8082
|
|
||||||
sign: 1
|
|
||||||
onFailure: buffer
|
|
||||||
userParameter:
|
|
||||||
in: -10.467
|
|
||||||
enabled: true
|
|
||||||
readOnly: false
|
|
||||||
foptx:
|
|
||||||
readoutPriority: baseline
|
|
||||||
description: phase plate angle
|
|
||||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
|
||||||
deviceConfig:
|
|
||||||
axis_Id: B
|
|
||||||
host: mpc2844.psi.ch
|
|
||||||
limits:
|
|
||||||
- -17
|
|
||||||
- -12
|
|
||||||
port: 8082
|
|
||||||
sign: 1
|
|
||||||
onFailure: buffer
|
|
||||||
userParameter:
|
|
||||||
in: -13.761
|
|
||||||
enabled: true
|
|
||||||
readOnly: false
|
|
||||||
fopty:
|
|
||||||
readoutPriority: baseline
|
|
||||||
description: phase plate angle
|
|
||||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
|
||||||
deviceConfig:
|
|
||||||
axis_Id: F
|
|
||||||
host: mpc2844.psi.ch
|
|
||||||
limits:
|
|
||||||
- 0
|
|
||||||
- 4
|
|
||||||
port: 8082
|
|
||||||
sign: 1
|
|
||||||
onFailure: buffer
|
|
||||||
userParameter:
|
|
||||||
in: 0.552
|
|
||||||
out: 0.752
|
|
||||||
enabled: true
|
|
||||||
readOnly: false
|
|
||||||
foptz:
|
|
||||||
readoutPriority: baseline
|
|
||||||
description: phase plate angle
|
|
||||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
|
||||||
deviceConfig:
|
|
||||||
axis_Id: A
|
|
||||||
host: mpc2844.psi.ch
|
|
||||||
limits:
|
|
||||||
- 0
|
|
||||||
- 27
|
|
||||||
port: 8082
|
|
||||||
sign: 1
|
|
||||||
onFailure: buffer
|
|
||||||
userParameter:
|
|
||||||
in: 23
|
|
||||||
enabled: true
|
|
||||||
readOnly: false
|
|
||||||
fosax:
|
|
||||||
readoutPriority: baseline
|
|
||||||
description: phase plate angle
|
|
||||||
deviceClass: csaxs_bec.devices.smaract.smaract_ophyd.SmaractMotor
|
|
||||||
deviceConfig:
|
|
||||||
axis_Id: A
|
|
||||||
host: mpc2844.psi.ch
|
|
||||||
limits:
|
|
||||||
- 10.2
|
|
||||||
- 10.6
|
|
||||||
port: 3334
|
|
||||||
sign: -1
|
|
||||||
onFailure: buffer
|
|
||||||
userParameter:
|
|
||||||
in: 9.124
|
|
||||||
out: 5.3
|
|
||||||
enabled: true
|
|
||||||
readOnly: false
|
|
||||||
fosay:
|
|
||||||
readoutPriority: baseline
|
|
||||||
description: phase plate angle
|
|
||||||
deviceClass: csaxs_bec.devices.smaract.smaract_ophyd.SmaractMotor
|
|
||||||
deviceConfig:
|
|
||||||
axis_Id: B
|
|
||||||
host: mpc2844.psi.ch
|
|
||||||
limits:
|
|
||||||
- -3.1
|
|
||||||
- -2.9
|
|
||||||
port: 3334
|
|
||||||
sign: -1
|
|
||||||
onFailure: buffer
|
|
||||||
userParameter:
|
|
||||||
in: 0.367
|
|
||||||
enabled: true
|
|
||||||
readOnly: false
|
|
||||||
fosaz:
|
|
||||||
readoutPriority: baseline
|
|
||||||
description: phase plate angle
|
|
||||||
deviceClass: csaxs_bec.devices.smaract.smaract_ophyd.SmaractMotor
|
|
||||||
deviceConfig:
|
|
||||||
axis_Id: C
|
|
||||||
host: mpc2844.psi.ch
|
|
||||||
limits:
|
|
||||||
- -6
|
|
||||||
- -4
|
|
||||||
port: 3334
|
|
||||||
sign: 1
|
|
||||||
onFailure: buffer
|
|
||||||
userParameter:
|
|
||||||
in: 8.5
|
|
||||||
out: 6
|
|
||||||
enabled: true
|
|
||||||
readOnly: false
|
|
||||||
fsamroy:
|
|
||||||
readoutPriority: baseline
|
|
||||||
description: phase plate angle
|
|
||||||
deviceClass: csaxs_bec.devices.galil.fupr_ophyd.FuprGalilMotor
|
|
||||||
deviceConfig:
|
|
||||||
axis_Id: A
|
|
||||||
host: mpc2844.psi.ch
|
|
||||||
limits:
|
|
||||||
- -5
|
|
||||||
- 365
|
|
||||||
port: 8084
|
|
||||||
sign: -1
|
|
||||||
onFailure: buffer
|
|
||||||
enabled: true
|
|
||||||
readOnly: false
|
|
||||||
fsamx:
|
|
||||||
readoutPriority: baseline
|
|
||||||
description: phase plate angle
|
|
||||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
|
||||||
deviceConfig:
|
|
||||||
axis_Id: E
|
|
||||||
host: mpc2844.psi.ch
|
|
||||||
limits:
|
|
||||||
- -162
|
|
||||||
- 0
|
|
||||||
port: 8081
|
|
||||||
sign: 1
|
|
||||||
onFailure: buffer
|
|
||||||
enabled: true
|
|
||||||
readOnly: false
|
|
||||||
userParameter:
|
|
||||||
in: -1.1
|
|
||||||
fsamy:
|
|
||||||
readoutPriority: baseline
|
|
||||||
description: phase plate angle
|
|
||||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
|
||||||
deviceConfig:
|
|
||||||
axis_Id: F
|
|
||||||
host: mpc2844.psi.ch
|
|
||||||
limits:
|
|
||||||
- 2
|
|
||||||
- 3.1
|
|
||||||
port: 8081
|
|
||||||
sign: 1
|
|
||||||
onFailure: buffer
|
|
||||||
enabled: true
|
|
||||||
readOnly: false
|
|
||||||
userParameter:
|
|
||||||
in: 2.75
|
|
||||||
ftracky:
|
|
||||||
readoutPriority: baseline
|
|
||||||
description: phase plate angle
|
|
||||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
|
||||||
deviceConfig:
|
|
||||||
axis_Id: H
|
|
||||||
host: mpc2844.psi.ch
|
|
||||||
limits:
|
|
||||||
- 2.2
|
|
||||||
- 2.8
|
|
||||||
port: 8082
|
|
||||||
sign: 1
|
|
||||||
onFailure: buffer
|
|
||||||
enabled: true
|
|
||||||
readOnly: false
|
|
||||||
ftrackz:
|
|
||||||
readoutPriority: baseline
|
|
||||||
description: phase plate angle
|
|
||||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
|
||||||
deviceConfig:
|
|
||||||
axis_Id: G
|
|
||||||
host: mpc2844.psi.ch
|
|
||||||
limits:
|
|
||||||
- 4.5
|
|
||||||
- 5.5
|
|
||||||
port: 8082
|
|
||||||
sign: 1
|
|
||||||
onFailure: buffer
|
|
||||||
enabled: true
|
|
||||||
readOnly: false
|
|
||||||
ftransx:
|
|
||||||
readoutPriority: baseline
|
|
||||||
description: phase plate angle
|
|
||||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
|
||||||
deviceConfig:
|
|
||||||
axis_Id: C
|
|
||||||
host: mpc2844.psi.ch
|
|
||||||
limits:
|
|
||||||
- 0
|
|
||||||
- 50
|
|
||||||
port: 8081
|
|
||||||
sign: 1
|
|
||||||
onFailure: buffer
|
|
||||||
enabled: true
|
|
||||||
readOnly: false
|
|
||||||
ftransy:
|
|
||||||
readoutPriority: baseline
|
|
||||||
description: phase plate angle
|
|
||||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
|
||||||
deviceConfig:
|
|
||||||
axis_Id: A
|
|
||||||
host: mpc2844.psi.ch
|
|
||||||
limits:
|
|
||||||
- -100
|
|
||||||
- 0
|
|
||||||
port: 8081
|
|
||||||
sign: 1
|
|
||||||
onFailure: buffer
|
|
||||||
enabled: true
|
|
||||||
readOnly: false
|
|
||||||
ftransz:
|
|
||||||
readoutPriority: baseline
|
|
||||||
description: phase plate angle
|
|
||||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
|
||||||
deviceConfig:
|
|
||||||
axis_Id: B
|
|
||||||
host: mpc2844.psi.ch
|
|
||||||
limits:
|
|
||||||
- 0
|
|
||||||
- 145
|
|
||||||
port: 8081
|
|
||||||
sign: 1
|
|
||||||
onFailure: buffer
|
|
||||||
enabled: true
|
|
||||||
readOnly: false
|
|
||||||
ftray:
|
|
||||||
readoutPriority: baseline
|
|
||||||
description: phase plate angle
|
|
||||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
|
||||||
deviceConfig:
|
|
||||||
axis_Id: D
|
|
||||||
host: mpc2844.psi.ch
|
|
||||||
limits:
|
|
||||||
- -200
|
|
||||||
- 0
|
|
||||||
port: 8081
|
|
||||||
sign: -1
|
|
||||||
onFailure: buffer
|
|
||||||
enabled: true
|
|
||||||
readOnly: false
|
|
||||||
|
|
||||||
flomni_samples:
|
|
||||||
readoutPriority: baseline
|
|
||||||
description: phase plate angle
|
|
||||||
deviceClass: csaxs_bec.devices.epics.devices.FlomniSampleStorage
|
|
||||||
deviceConfig:
|
|
||||||
onFailure: buffer
|
|
||||||
enabled: true
|
|
||||||
readOnly: false
|
|
||||||
|
|
||||||
rtx:
|
|
||||||
readoutPriority: on_request
|
|
||||||
description: flomni rt
|
|
||||||
deviceClass: csaxs_bec.devices.rt_lamni.rt_flomni_ophyd.RtFlomniMotor
|
|
||||||
deviceConfig:
|
|
||||||
axis_Id: A
|
|
||||||
host: mpc2844.psi.ch
|
|
||||||
port: 2222
|
|
||||||
sign: 1
|
|
||||||
onFailure: buffer
|
|
||||||
enabled: true
|
|
||||||
readOnly: false
|
|
||||||
rty:
|
|
||||||
readoutPriority: on_request
|
|
||||||
description: flomni rt
|
|
||||||
deviceClass: csaxs_bec.devices.rt_lamni.rt_flomni_ophyd.RtFlomniMotor
|
|
||||||
deviceConfig:
|
|
||||||
axis_Id: B
|
|
||||||
host: mpc2844.psi.ch
|
|
||||||
port: 2222
|
|
||||||
sign: 1
|
|
||||||
onFailure: buffer
|
|
||||||
enabled: true
|
|
||||||
readOnly: false
|
|
||||||
rtz:
|
|
||||||
readoutPriority: on_request
|
|
||||||
description: flomni rt
|
|
||||||
deviceClass: csaxs_bec.devices.rt_lamni.rt_flomni_ophyd.RtFlomniMotor
|
|
||||||
deviceConfig:
|
|
||||||
axis_Id: C
|
|
||||||
host: mpc2844.psi.ch
|
|
||||||
port: 2222
|
|
||||||
sign: 1
|
|
||||||
onFailure: buffer
|
|
||||||
enabled: true
|
|
||||||
readOnly: false
|
|
||||||
261
csaxs_bec/device_configs/lamni_config.yaml
Normal file
261
csaxs_bec/device_configs/lamni_config.yaml
Normal file
@@ -0,0 +1,261 @@
|
|||||||
|
############################################################
|
||||||
|
#################### LamNI Galil motors ####################
|
||||||
|
############################################################
|
||||||
|
|
||||||
|
leyex:
|
||||||
|
description: Xray eye X
|
||||||
|
deviceClass: csaxs_bec.devices.omny.galil.lgalil_ophyd.LamniGalilMotor
|
||||||
|
deviceConfig:
|
||||||
|
axis_Id: G
|
||||||
|
host: mpc2680.psi.ch
|
||||||
|
limits:
|
||||||
|
- 0
|
||||||
|
- 0
|
||||||
|
port: 8081
|
||||||
|
sign: -1
|
||||||
|
deviceTags:
|
||||||
|
- lamni
|
||||||
|
enabled: true
|
||||||
|
onFailure: buffer
|
||||||
|
readOnly: false
|
||||||
|
readoutPriority: baseline
|
||||||
|
userParameter:
|
||||||
|
in: 14.117
|
||||||
|
leyey:
|
||||||
|
description: Xray eye Y
|
||||||
|
deviceClass: csaxs_bec.devices.omny.galil.lgalil_ophyd.LamniGalilMotor
|
||||||
|
deviceConfig:
|
||||||
|
axis_Id: H
|
||||||
|
host: mpc2680.psi.ch
|
||||||
|
limits:
|
||||||
|
- 0
|
||||||
|
- 0
|
||||||
|
port: 8081
|
||||||
|
sign: -1
|
||||||
|
deviceTags:
|
||||||
|
- lamni
|
||||||
|
enabled: true
|
||||||
|
onFailure: buffer
|
||||||
|
readOnly: false
|
||||||
|
readoutPriority: baseline
|
||||||
|
userParameter:
|
||||||
|
in: 48.069
|
||||||
|
out: 0.5
|
||||||
|
loptx:
|
||||||
|
description: Optics X
|
||||||
|
deviceClass: csaxs_bec.devices.omny.galil.lgalil_ophyd.LamniGalilMotor
|
||||||
|
deviceConfig:
|
||||||
|
axis_Id: E
|
||||||
|
host: mpc2680.psi.ch
|
||||||
|
limits:
|
||||||
|
- 0
|
||||||
|
- 0
|
||||||
|
port: 8081
|
||||||
|
sign: 1
|
||||||
|
deviceTags:
|
||||||
|
- lamni
|
||||||
|
enabled: true
|
||||||
|
onFailure: buffer
|
||||||
|
readOnly: false
|
||||||
|
readoutPriority: baseline
|
||||||
|
userParameter:
|
||||||
|
in: -0.244
|
||||||
|
out: -0.699
|
||||||
|
lopty:
|
||||||
|
description: Optics Y
|
||||||
|
deviceClass: csaxs_bec.devices.omny.galil.lgalil_ophyd.LamniGalilMotor
|
||||||
|
deviceConfig:
|
||||||
|
axis_Id: F
|
||||||
|
host: mpc2680.psi.ch
|
||||||
|
limits:
|
||||||
|
- 0
|
||||||
|
- 0
|
||||||
|
port: 8081
|
||||||
|
sign: 1
|
||||||
|
deviceTags:
|
||||||
|
- lamni
|
||||||
|
enabled: true
|
||||||
|
onFailure: buffer
|
||||||
|
readOnly: false
|
||||||
|
readoutPriority: baseline
|
||||||
|
userParameter:
|
||||||
|
in: 3.724
|
||||||
|
out: 3.53
|
||||||
|
loptz:
|
||||||
|
description: Optics Z
|
||||||
|
deviceClass: csaxs_bec.devices.omny.galil.lgalil_ophyd.LamniGalilMotor
|
||||||
|
deviceConfig:
|
||||||
|
axis_Id: D
|
||||||
|
host: mpc2680.psi.ch
|
||||||
|
limits:
|
||||||
|
- 0
|
||||||
|
- 0
|
||||||
|
port: 8081
|
||||||
|
sign: -1
|
||||||
|
deviceTags:
|
||||||
|
- lamni
|
||||||
|
enabled: true
|
||||||
|
onFailure: buffer
|
||||||
|
readOnly: false
|
||||||
|
readoutPriority: baseline
|
||||||
|
lsamrot:
|
||||||
|
description: Sample rotation
|
||||||
|
deviceClass: csaxs_bec.devices.omny.galil.lgalil_ophyd.LamniGalilMotor
|
||||||
|
deviceConfig:
|
||||||
|
axis_Id: C
|
||||||
|
host: mpc2680.psi.ch
|
||||||
|
limits:
|
||||||
|
- 0
|
||||||
|
- 0
|
||||||
|
port: 8081
|
||||||
|
sign: 1
|
||||||
|
deviceTags:
|
||||||
|
- lamni
|
||||||
|
enabled: true
|
||||||
|
onFailure: buffer
|
||||||
|
readOnly: false
|
||||||
|
readoutPriority: baseline
|
||||||
|
lsamx:
|
||||||
|
description: Sample coarse X
|
||||||
|
deviceClass: csaxs_bec.devices.omny.galil.lgalil_ophyd.LamniGalilMotor
|
||||||
|
deviceConfig:
|
||||||
|
axis_Id: A
|
||||||
|
host: mpc2680.psi.ch
|
||||||
|
limits:
|
||||||
|
- 0
|
||||||
|
- 0
|
||||||
|
port: 8081
|
||||||
|
sign: -1
|
||||||
|
deviceTags:
|
||||||
|
- lamni
|
||||||
|
enabled: true
|
||||||
|
onFailure: buffer
|
||||||
|
readOnly: false
|
||||||
|
readoutPriority: baseline
|
||||||
|
userParameter:
|
||||||
|
center: 8.768
|
||||||
|
lsamy:
|
||||||
|
description: Sample coarse Y
|
||||||
|
deviceClass: csaxs_bec.devices.omny.galil.lgalil_ophyd.LamniGalilMotor
|
||||||
|
deviceConfig:
|
||||||
|
axis_Id: B
|
||||||
|
host: mpc2680.psi.ch
|
||||||
|
limits:
|
||||||
|
- 0
|
||||||
|
- 0
|
||||||
|
port: 8081
|
||||||
|
sign: 1
|
||||||
|
deviceTags:
|
||||||
|
- lamni
|
||||||
|
enabled: true
|
||||||
|
onFailure: buffer
|
||||||
|
readOnly: false
|
||||||
|
readoutPriority: baseline
|
||||||
|
userParameter:
|
||||||
|
center: 10.041
|
||||||
|
|
||||||
|
|
||||||
|
############################################################
|
||||||
|
################ LamNI Smaract motors ######################
|
||||||
|
############################################################
|
||||||
|
|
||||||
|
losax:
|
||||||
|
description: OSA X
|
||||||
|
deviceClass: csaxs_bec.devices.smaract.smaract_ophyd.SmaractMotor
|
||||||
|
deviceConfig:
|
||||||
|
axis_Id: A
|
||||||
|
host: mpc2680.psi.ch
|
||||||
|
limits:
|
||||||
|
- 0
|
||||||
|
- 0
|
||||||
|
port: 8085
|
||||||
|
sign: -1
|
||||||
|
deviceTags:
|
||||||
|
- lamni
|
||||||
|
enabled: true
|
||||||
|
onFailure: buffer
|
||||||
|
readOnly: false
|
||||||
|
readoutPriority: baseline
|
||||||
|
userParameter:
|
||||||
|
in: -1.442
|
||||||
|
losay:
|
||||||
|
description: OSA Y
|
||||||
|
deviceClass: csaxs_bec.devices.smaract.smaract_ophyd.SmaractMotor
|
||||||
|
deviceConfig:
|
||||||
|
axis_Id: B
|
||||||
|
host: mpc2680.psi.ch
|
||||||
|
limits:
|
||||||
|
- 0
|
||||||
|
- 0
|
||||||
|
port: 8085
|
||||||
|
sign: -1
|
||||||
|
deviceTags:
|
||||||
|
- lamni
|
||||||
|
enabled: true
|
||||||
|
onFailure: buffer
|
||||||
|
readOnly: false
|
||||||
|
readoutPriority: baseline
|
||||||
|
userParameter:
|
||||||
|
in: -0.171
|
||||||
|
out: 3.8
|
||||||
|
losaz:
|
||||||
|
description: OSA Z
|
||||||
|
deviceClass: csaxs_bec.devices.smaract.smaract_ophyd.SmaractMotor
|
||||||
|
deviceConfig:
|
||||||
|
axis_Id: C
|
||||||
|
host: mpc2680.psi.ch
|
||||||
|
limits:
|
||||||
|
- 0
|
||||||
|
- 0
|
||||||
|
port: 8085
|
||||||
|
sign: 1
|
||||||
|
deviceTags:
|
||||||
|
- lamni
|
||||||
|
enabled: true
|
||||||
|
onFailure: buffer
|
||||||
|
readOnly: false
|
||||||
|
readoutPriority: baseline
|
||||||
|
userParameter:
|
||||||
|
in: -1
|
||||||
|
out: -3
|
||||||
|
|
||||||
|
############################################################
|
||||||
|
#################### flOMNI RT motors ######################
|
||||||
|
############################################################
|
||||||
|
|
||||||
|
rtx:
|
||||||
|
deviceClass: csaxs_bec.devices.omny.rt.rt_lamni_ophyd.RtLamniMotor
|
||||||
|
deviceConfig:
|
||||||
|
axis_Id: A
|
||||||
|
device_access: true
|
||||||
|
host: mpc2680.psi.ch
|
||||||
|
labels: rtx
|
||||||
|
limits:
|
||||||
|
- 0
|
||||||
|
- 0
|
||||||
|
port: 3333
|
||||||
|
sign: 1
|
||||||
|
deviceTags:
|
||||||
|
- lamni
|
||||||
|
readoutPriority: baseline
|
||||||
|
enabled: true
|
||||||
|
readOnly: False
|
||||||
|
rty:
|
||||||
|
deviceClass: csaxs_bec.devices.omny.rt.rt_lamni_ophyd.RtLamniMotor
|
||||||
|
deviceConfig:
|
||||||
|
axis_Id: B
|
||||||
|
device_access: true
|
||||||
|
host: mpc2680.psi.ch
|
||||||
|
labels: rty
|
||||||
|
limits:
|
||||||
|
- 0
|
||||||
|
- 0
|
||||||
|
port: 3333
|
||||||
|
sign: 1
|
||||||
|
deviceTags:
|
||||||
|
- lamni
|
||||||
|
readoutPriority: baseline
|
||||||
|
enabled: true
|
||||||
|
readOnly: False
|
||||||
|
|
||||||
|
|
||||||
8
csaxs_bec/device_configs/omny_config.yaml
Normal file
8
csaxs_bec/device_configs/omny_config.yaml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
omny_samples:
|
||||||
|
description: OMNYSampleStorage
|
||||||
|
deviceClass: csaxs_bec.devices.omny.omny_sample_storage.OMNYSampleStorage
|
||||||
|
deviceConfig: {}
|
||||||
|
enabled: true
|
||||||
|
onFailure: buffer
|
||||||
|
readOnly: false
|
||||||
|
readoutPriority: baseline
|
||||||
@@ -220,7 +220,7 @@ bm5try:
|
|||||||
softwareTrigger: false
|
softwareTrigger: false
|
||||||
bpm1:
|
bpm1:
|
||||||
description: 'XBPM 1: Somewhere around mono (VME)'
|
description: 'XBPM 1: Somewhere around mono (VME)'
|
||||||
deviceClass: csaxs_bec.devices.epics.devices.XbpmBase.XbpmCsaxsOp
|
deviceClass: csaxs_bec.devices.epics.XbpmBase.XbpmCsaxsOp
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
prefix: 'X12SA-OP-BPM2:'
|
prefix: 'X12SA-OP-BPM2:'
|
||||||
deviceTags:
|
deviceTags:
|
||||||
@@ -242,7 +242,7 @@ bpm1i:
|
|||||||
softwareTrigger: false
|
softwareTrigger: false
|
||||||
bpm2:
|
bpm2:
|
||||||
description: 'XBPM 2: Somewhere around mono (VME)'
|
description: 'XBPM 2: Somewhere around mono (VME)'
|
||||||
deviceClass: csaxs_bec.devices.epics.devices.XbpmBase.XbpmCsaxsOp
|
deviceClass: csaxs_bec.devices.epics.XbpmBase.XbpmCsaxsOp
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
prefix: 'X12SA-OP-BPM2:'
|
prefix: 'X12SA-OP-BPM2:'
|
||||||
deviceTags:
|
deviceTags:
|
||||||
@@ -605,7 +605,7 @@ dtpush:
|
|||||||
softwareTrigger: false
|
softwareTrigger: false
|
||||||
dtth:
|
dtth:
|
||||||
description: Detector tower tilt rotation
|
description: Detector tower tilt rotation
|
||||||
deviceClass: csaxs_bec.devices.epics.devices.specMotors.PmDetectorRotation
|
deviceClass: csaxs_bec.devices.epics.specMotors.PmDetectorRotation
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
prefix: X12SA-ES1-DETT:ROX1
|
prefix: X12SA-ES1-DETT:ROX1
|
||||||
deviceTags:
|
deviceTags:
|
||||||
@@ -880,7 +880,7 @@ fttrz:
|
|||||||
softwareTrigger: false
|
softwareTrigger: false
|
||||||
idgap:
|
idgap:
|
||||||
description: Undulator gap size [mm]
|
description: Undulator gap size [mm]
|
||||||
deviceClass: csaxs_bec.devices.epics.devices.InsertionDevice.InsertionDevice
|
deviceClass: csaxs_bec.devices.epics.InsertionDevice.InsertionDevice
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
prefix: X12SA-ID
|
prefix: X12SA-ID
|
||||||
deviceTags:
|
deviceTags:
|
||||||
@@ -979,7 +979,7 @@ mitry3:
|
|||||||
softwareTrigger: false
|
softwareTrigger: false
|
||||||
mobd:
|
mobd:
|
||||||
description: Monochromator bender virtual motor
|
description: Monochromator bender virtual motor
|
||||||
deviceClass: csaxs_bec.devices.epics.devices.specMotors.PmMonoBender
|
deviceClass: csaxs_bec.devices.epics.specMotors.PmMonoBender
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
prefix: 'X12SA-OP-MO:'
|
prefix: 'X12SA-OP-MO:'
|
||||||
deviceTags:
|
deviceTags:
|
||||||
@@ -1034,7 +1034,7 @@ mobddi:
|
|||||||
softwareTrigger: false
|
softwareTrigger: false
|
||||||
mokev:
|
mokev:
|
||||||
description: Monochromator energy in keV
|
description: Monochromator energy in keV
|
||||||
deviceClass: csaxs_bec.devices.epics.devices.specMotors.EnergyKev
|
deviceClass: csaxs_bec.devices.epics.specMotors.EnergyKev
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
read_pv: X12SA-OP-MO:ROX2
|
read_pv: X12SA-OP-MO:ROX2
|
||||||
deviceTags:
|
deviceTags:
|
||||||
@@ -1089,7 +1089,7 @@ moroll2:
|
|||||||
softwareTrigger: false
|
softwareTrigger: false
|
||||||
moth1:
|
moth1:
|
||||||
description: Monochromator Theta 1
|
description: Monochromator Theta 1
|
||||||
deviceClass: csaxs_bec.devices.epics.devices.specMotors.MonoTheta1
|
deviceClass: csaxs_bec.devices.epics.specMotors.MonoTheta1
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
read_pv: X12SA-OP-MO:ROX1
|
read_pv: X12SA-OP-MO:ROX1
|
||||||
deviceTags:
|
deviceTags:
|
||||||
@@ -1111,7 +1111,7 @@ moth1e:
|
|||||||
softwareTrigger: false
|
softwareTrigger: false
|
||||||
moth2:
|
moth2:
|
||||||
description: Monochromator Theta 2
|
description: Monochromator Theta 2
|
||||||
deviceClass: csaxs_bec.devices.epics.devices.specMotors.MonoTheta2
|
deviceClass: csaxs_bec.devices.epics.specMotors.MonoTheta2
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
read_pv: X12SA-OP-MO:ROX2
|
read_pv: X12SA-OP-MO:ROX2
|
||||||
deviceTags:
|
deviceTags:
|
||||||
@@ -1230,17 +1230,17 @@ sec:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
softwareTrigger: false
|
softwareTrigger: false
|
||||||
sl0h:
|
# sl0h:
|
||||||
description: FrontEnd slit virtual movement
|
# description: FrontEnd slit virtual movement
|
||||||
deviceClass: ophyd_devices.epics.devices.SlitH
|
# deviceClass: ophyd_devices.devices.SlitH
|
||||||
deviceConfig:
|
# deviceConfig:
|
||||||
prefix: 'X12SA-FE-SH1:'
|
# prefix: 'X12SA-FE-SH1:'
|
||||||
deviceTags:
|
# deviceTags:
|
||||||
- epicsDevice
|
# - epicsDevice
|
||||||
enabled: true
|
# enabled: true
|
||||||
onFailure: buffer
|
# onFailure: buffer
|
||||||
readoutPriority: baseline
|
# readoutPriority: baseline
|
||||||
softwareTrigger: false
|
# softwareTrigger: false
|
||||||
sl0trxi:
|
sl0trxi:
|
||||||
description: FrontEnd slit inner blade movement
|
description: FrontEnd slit inner blade movement
|
||||||
deviceClass: ophyd.EpicsMotor
|
deviceClass: ophyd.EpicsMotor
|
||||||
@@ -1263,17 +1263,17 @@ sl0trxo:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
softwareTrigger: false
|
softwareTrigger: false
|
||||||
sl1h:
|
# sl1h:
|
||||||
description: OpticsHutch slit virtual movement
|
# description: OpticsHutch slit virtual movement
|
||||||
deviceClass: ophyd_devices.epics.devices.SlitH
|
# deviceClass: ophyd_devices.devices.SlitH
|
||||||
deviceConfig:
|
# deviceConfig:
|
||||||
prefix: 'X12SA-OP-SH1:'
|
# prefix: 'X12SA-OP-SH1:'
|
||||||
deviceTags:
|
# deviceTags:
|
||||||
- epicsDevice
|
# - epicsDevice
|
||||||
enabled: true
|
# enabled: true
|
||||||
onFailure: buffer
|
# onFailure: buffer
|
||||||
readoutPriority: baseline
|
# readoutPriority: baseline
|
||||||
softwareTrigger: false
|
# softwareTrigger: false
|
||||||
sl1trxi:
|
sl1trxi:
|
||||||
description: OpticsHutch slit inner blade movement
|
description: OpticsHutch slit inner blade movement
|
||||||
deviceClass: ophyd.EpicsMotor
|
deviceClass: ophyd.EpicsMotor
|
||||||
@@ -1318,28 +1318,28 @@ sl1tryt:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
softwareTrigger: false
|
softwareTrigger: false
|
||||||
sl1v:
|
# sl1v:
|
||||||
description: OpticsHutch slit virtual movement
|
# description: OpticsHutch slit virtual movement
|
||||||
deviceClass: ophyd_devices.epics.devices.SlitV
|
# deviceClass: ophyd_devices.devices.SlitV
|
||||||
deviceConfig:
|
# deviceConfig:
|
||||||
prefix: 'X12SA-OP-SV1:'
|
# prefix: 'X12SA-OP-SV1:'
|
||||||
deviceTags:
|
# deviceTags:
|
||||||
- epicsDevice
|
# - epicsDevice
|
||||||
enabled: true
|
# enabled: true
|
||||||
onFailure: buffer
|
# onFailure: buffer
|
||||||
readoutPriority: baseline
|
# readoutPriority: baseline
|
||||||
softwareTrigger: false
|
# softwareTrigger: false
|
||||||
sl2h:
|
# sl2h:
|
||||||
description: OpticsHutch slit 2 virtual movement
|
# description: OpticsHutch slit 2 virtual movement
|
||||||
deviceClass: ophyd_devices.epics.devices.SlitH
|
# deviceClass: ophyd_devices.devices.SlitH
|
||||||
deviceConfig:
|
# deviceConfig:
|
||||||
prefix: 'X12SA-OP-SH2:'
|
# prefix: 'X12SA-OP-SH2:'
|
||||||
deviceTags:
|
# deviceTags:
|
||||||
- epicsDevice
|
# - epicsDevice
|
||||||
enabled: true
|
# enabled: true
|
||||||
onFailure: buffer
|
# onFailure: buffer
|
||||||
readoutPriority: baseline
|
# readoutPriority: baseline
|
||||||
softwareTrigger: false
|
# softwareTrigger: false
|
||||||
sl2trxi:
|
sl2trxi:
|
||||||
description: OpticsHutch slit 2 inner blade movement
|
description: OpticsHutch slit 2 inner blade movement
|
||||||
deviceClass: ophyd.EpicsMotor
|
deviceClass: ophyd.EpicsMotor
|
||||||
@@ -1384,72 +1384,72 @@ sl2tryt:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
softwareTrigger: false
|
softwareTrigger: false
|
||||||
sl2v:
|
# sl2v:
|
||||||
description: OpticsHutch slit 2 virtual movement
|
# description: OpticsHutch slit 2 virtual movement
|
||||||
deviceClass: ophyd_devices.epics.devices.SlitV
|
# deviceClass: ophyd_devices.devices.SlitV
|
||||||
deviceConfig:
|
# deviceConfig:
|
||||||
prefix: 'X12SA-OP-SV2:'
|
# prefix: 'X12SA-OP-SV2:'
|
||||||
deviceTags:
|
# deviceTags:
|
||||||
- epicsDevice
|
# - epicsDevice
|
||||||
enabled: true
|
# enabled: true
|
||||||
onFailure: buffer
|
# onFailure: buffer
|
||||||
readoutPriority: baseline
|
# readoutPriority: baseline
|
||||||
softwareTrigger: false
|
# softwareTrigger: false
|
||||||
strox:
|
# strox:
|
||||||
description: Girder virtual pitch
|
# description: Girder virtual pitch
|
||||||
deviceClass: ophyd_devices.epics.devices.GirderMotorPITCH
|
# deviceClass: ophyd_devices.devices.GirderMotorPITCH
|
||||||
deviceConfig:
|
# deviceConfig:
|
||||||
prefix: X12SA-HG
|
# prefix: X12SA-HG
|
||||||
deviceTags:
|
# deviceTags:
|
||||||
- beamlineMotor
|
# - beamlineMotor
|
||||||
enabled: true
|
# enabled: true
|
||||||
onFailure: buffer
|
# onFailure: buffer
|
||||||
readoutPriority: baseline
|
# readoutPriority: baseline
|
||||||
softwareTrigger: false
|
# softwareTrigger: false
|
||||||
stroy:
|
# stroy:
|
||||||
description: Girder virtual yaw
|
# description: Girder virtual yaw
|
||||||
deviceClass: ophyd_devices.epics.devices.GirderMotorYAW
|
# deviceClass: ophyd_devices.devices.GirderMotorYAW
|
||||||
deviceConfig:
|
# deviceConfig:
|
||||||
prefix: X12SA-HG
|
# prefix: X12SA-HG
|
||||||
deviceTags:
|
# deviceTags:
|
||||||
- beamlineMotor
|
# - beamlineMotor
|
||||||
enabled: true
|
# enabled: true
|
||||||
onFailure: buffer
|
# onFailure: buffer
|
||||||
readoutPriority: baseline
|
# readoutPriority: baseline
|
||||||
softwareTrigger: false
|
# softwareTrigger: false
|
||||||
stroz:
|
# stroz:
|
||||||
description: Girder virtual roll
|
# description: Girder virtual roll
|
||||||
deviceClass: ophyd_devices.epics.devices.GirderMotorROLL
|
# deviceClass: ophyd_devices.devices.GirderMotorROLL
|
||||||
deviceConfig:
|
# deviceConfig:
|
||||||
prefix: X12SA-HG
|
# prefix: X12SA-HG
|
||||||
deviceTags:
|
# deviceTags:
|
||||||
- beamlineMotor
|
# - beamlineMotor
|
||||||
enabled: true
|
# enabled: true
|
||||||
onFailure: buffer
|
# onFailure: buffer
|
||||||
readoutPriority: baseline
|
# readoutPriority: baseline
|
||||||
softwareTrigger: false
|
# softwareTrigger: false
|
||||||
sttrx:
|
# sttrx:
|
||||||
description: Girder X translation
|
# description: Girder X translation
|
||||||
deviceClass: ophyd_devices.epics.devices.GirderMotorX1
|
# deviceClass: ophyd_devices.devices.GirderMotorX1
|
||||||
deviceConfig:
|
# deviceConfig:
|
||||||
prefix: X12SA-HG
|
# prefix: X12SA-HG
|
||||||
deviceTags:
|
# deviceTags:
|
||||||
- beamlineMotor
|
# - beamlineMotor
|
||||||
enabled: true
|
# enabled: true
|
||||||
onFailure: buffer
|
# onFailure: buffer
|
||||||
readoutPriority: baseline
|
# readoutPriority: baseline
|
||||||
softwareTrigger: false
|
# softwareTrigger: false
|
||||||
sttry:
|
# sttry:
|
||||||
description: Girder Y translation
|
# description: Girder Y translation
|
||||||
deviceClass: ophyd_devices.epics.devices.GirderMotorY1
|
# deviceClass: ophyd_devices.devices.GirderMotorY1
|
||||||
deviceConfig:
|
# deviceConfig:
|
||||||
prefix: X12SA-HG
|
# prefix: X12SA-HG
|
||||||
deviceTags:
|
# deviceTags:
|
||||||
- beamlineMotor
|
# - beamlineMotor
|
||||||
enabled: true
|
# enabled: true
|
||||||
onFailure: buffer
|
# onFailure: buffer
|
||||||
readoutPriority: baseline
|
# readoutPriority: baseline
|
||||||
softwareTrigger: false
|
# softwareTrigger: false
|
||||||
transd:
|
transd:
|
||||||
description: Transmission diode
|
description: Transmission diode
|
||||||
deviceClass: ophyd.EpicsSignalRO
|
deviceClass: ophyd.EpicsSignalRO
|
||||||
|
|||||||
37
csaxs_bec/devices/device_list.md
Normal file
37
csaxs_bec/devices/device_list.md
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
// This file was autogenerated. Do not edit it manually.
|
||||||
|
## Device List
|
||||||
|
### csaxs_bec
|
||||||
|
| Device | Documentation | Module |
|
||||||
|
| :----- | :------------- | :------ |
|
||||||
|
| InsertionDevice | Python wrapper for the CSAXS insertion device control<br><br> This wrapper provides a positioner interface for the ID control.<br> is completely custom XBPM with templates directly in the<br> VME repo. Thus it needs a custom ophyd template as well...<br><br> WARN: The x and y are not updated by the IOC<br> | [csaxs_bec.devices.epics.InsertionDevice](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/epics/InsertionDevice.py) |
|
||||||
|
| XbpmBase | Python wrapper for X-ray Beam Position Monitors<br><br> XBPM's consist of a metal-coated diamond window that ejects<br> photoelectrons from the incoming X-ray beam. These electons<br> are collected and their current is measured. Effectively<br> they act as four quadrant photodiodes and are used as BPMs<br> at the undulator beamlines of SLS.<br><br> Note: EPICS provided signals are read only, but the user can<br> change the beam position offset.<br> | [csaxs_bec.devices.epics.XbpmBase](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/epics/XbpmBase.py) |
|
||||||
|
| XbpmCsaxsOp | Python wrapper for custom XBPMs in the cSAXS optics hutch<br><br> This is completely custom XBPM with templates directly in the<br> VME repo. Thus it needs a custom ophyd template as well...<br><br> WARN: The x and y are not updated by the IOC<br> | [csaxs_bec.devices.epics.XbpmBase](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/epics/XbpmBase.py) |
|
||||||
|
| XbpmSim | Python wrapper for simulated X-ray Beam Position Monitors<br><br> XBPM's consist of a metal-coated diamond window that ejects<br> photoelectrons from the incoming X-ray beam. These electons<br> are collected and their current is measured. Effectively<br> they act as four quadrant photodiodes and are used as BPMs<br> at the undulator beamlines of SLS.<br><br> Note: EPICS provided signals are read only, but the user can<br> change the beam position offset.<br><br> This simulation device extends the basic proxy with a script that<br> fills signals with quasi-randomized values.<br> | [csaxs_bec.devices.epics.XbpmBase](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/epics/XbpmBase.py) |
|
||||||
|
| DelayGeneratorcSAXS | <br> DG645 delay generator at cSAXS (multiple can be in use depending on the setup)<br><br> Default values for setting up DDG.<br> Note: checks of set calues are not (only partially) included, check manual for details on possible settings.<br> https://www.thinksrs.com/downloads/pdfs/manuals/DG645m.pdf<br><br> - delay_burst : (float >=0) Delay between trigger and first pulse in burst mode<br> - delta_width : (float >= 0) Add width to fast shutter signal to make sure its open during acquisition<br> - additional_triggers : (int) add additional triggers to burst mode (mcs card needs +1 triggers per line)<br> - polarity : (list of 0/1) polarity for different channels<br> - amplitude : (float) amplitude voltage of TTLs<br> - offset : (float) offset for ampltitude<br> - thres_trig_level : (float) threshold of trigger amplitude<br><br> Custom signals for logic in different DDGs during scans (for custom_prepare.prepare_ddg):<br><br> - set_high_on_exposure : (bool): if True, then TTL signal should go high during the full acquisition time of a scan.<br> # TODO trigger_width and fixed_ttl could be combined into single list.<br> - fixed_ttl_width : (list of either 1 or 0), one for each channel.<br> - trigger_width : (float) if fixed_ttl_width is True, then the width of the TTL pulse is set to this value.<br> - set_trigger_source : (TriggerSource) specifies the default trigger source for the DDG.<br> - premove_trigger : (bool) if True, then a trigger should be executed before the scan starts (to be implemented in on_pre_scan).<br> - set_high_on_stage : (bool) if True, then TTL signal should go high already on stage.<br> | [csaxs_bec.devices.epics.delay_generator_csaxs](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/epics/delay_generator_csaxs.py) |
|
||||||
|
| Eiger9McSAXS | <br> Eiger9M detector for CSAXS<br><br> Parent class: PSIDetectorBase<br><br> class attributes:<br> custom_prepare_cls (FalconSetup) : Custom detector setup class for cSAXS,<br> inherits from CustomDetectorMixin<br> PSIDetectorBase.set_min_readout (float) : Minimum readout time for the detector<br> Various EpicsPVs for controlling the detector<br> | [csaxs_bec.devices.epics.eiger9m_csaxs](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/epics/eiger9m_csaxs.py) |
|
||||||
|
| SLSDetectorCam | SLS Detector Camera - Pilatus<br><br> Base class to map EPICS PVs to ophyd signals.<br> | [csaxs_bec.devices.epics.pilatus_csaxs](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/epics/pilatus_csaxs.py) |
|
||||||
|
| EpicsDXPFalcon | <br> DXP parameters for Falcon detector<br><br> Base class to map EPICS PVs from DXP parameters to ophyd signals.<br> | [csaxs_bec.devices.epics.falcon_csaxs](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/epics/falcon_csaxs.py) |
|
||||||
|
| FalconHDF5Plugins | <br> HDF5 parameters for Falcon detector<br><br> Base class to map EPICS PVs from HDF5 Plugin to ophyd signals.<br> | [csaxs_bec.devices.epics.falcon_csaxs](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/epics/falcon_csaxs.py) |
|
||||||
|
| FalconcSAXS | <br> Falcon Sitoro detector for CSAXS<br><br> Parent class: PSIDetectorBase<br><br> class attributes:<br> custom_prepare_cls (FalconSetup) : Custom detector setup class for cSAXS,<br> inherits from CustomDetectorMixin<br> PSIDetectorBase.set_min_readout (float) : Minimum readout time for the detector<br> dxp (EpicsDXPFalcon) : DXP parameters for Falcon detector<br> mca (EpicsMCARecord) : MCA parameters for Falcon detector<br> hdf5 (FalconHDF5Plugins) : HDF5 parameters for Falcon detector<br> MIN_READOUT (float) : Minimum readout time for the detector<br> | [csaxs_bec.devices.epics.falcon_csaxs](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/epics/falcon_csaxs.py) |
|
||||||
|
| MCScSAXS | MCS card for cSAXS for implementation at cSAXS beamline | [csaxs_bec.devices.epics.mcs_csaxs](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/epics/mcs_csaxs.py) |
|
||||||
|
| SIS38XX | SIS38XX card for access to EPICs PVs at cSAXS beamline | [csaxs_bec.devices.epics.mcs_csaxs](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/epics/mcs_csaxs.py) |
|
||||||
|
| PilatuscSAXS | Pilatus_2 300k detector for CSAXS<br><br> Parent class: PSIDetectorBase<br><br> class attributes:<br> custom_prepare_cls (Eiger9MSetup) : Custom detector setup class for cSAXS,<br> inherits from CustomDetectorMixin<br> cam (SLSDetectorCam) : Detector camera<br> MIN_READOUT (float) : Minimum readout time for the detector<br><br> | [csaxs_bec.devices.epics.pilatus_csaxs](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/epics/pilatus_csaxs.py) |
|
||||||
|
| Bpm4i | | [csaxs_bec.devices.epics.specMotors](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/epics/specMotors.py) |
|
||||||
|
| GirderMotorPITCH | Girder YAW pseudo motor | [csaxs_bec.devices.epics.specMotors](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/epics/specMotors.py) |
|
||||||
|
| GirderMotorROLL | Girder ROLL pseudo motor | [csaxs_bec.devices.epics.specMotors](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/epics/specMotors.py) |
|
||||||
|
| GirderMotorX1 | Girder X translation pseudo motor | [csaxs_bec.devices.epics.specMotors](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/epics/specMotors.py) |
|
||||||
|
| GirderMotorY1 | Girder Y translation pseudo motor | [csaxs_bec.devices.epics.specMotors](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/epics/specMotors.py) |
|
||||||
|
| GirderMotorYAW | Girder YAW pseudo motor | [csaxs_bec.devices.epics.specMotors](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/epics/specMotors.py) |
|
||||||
|
| PmDetectorRotation | Detector rotation pseudo motor<br><br> Small wrapper to convert detector pusher position to rotation angle.<br> | [csaxs_bec.devices.epics.specMotors](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/epics/specMotors.py) |
|
||||||
|
| PmMonoBender | Monochromator bender<br><br> Small wrapper to combine the four monochromator bender motors.<br> | [csaxs_bec.devices.epics.specMotors](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/epics/specMotors.py) |
|
||||||
|
| Xeye | | [csaxs_bec.devices.sls_devices.cSAXS.xeye](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/sls_devices/cSAXS/xeye.py) |
|
||||||
|
| SmaractMotor | | [csaxs_bec.devices.smaract.smaract_ophyd](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/smaract/smaract_ophyd.py) |
|
||||||
|
| Eiger1p5MDetector | | [csaxs_bec.devices.omny.eiger1p5m](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/omny/eiger1p5m.py) |
|
||||||
|
| FlomniSampleStorage | | [csaxs_bec.devices.omny.flomni_sample_storage](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/omny/flomni_sample_storage.py) |
|
||||||
|
| OMNYSampleStorage | | [csaxs_bec.devices.omny.omny_sample_storage](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/omny/omny_sample_storage.py) |
|
||||||
|
| FlomniGalilMotor | | [csaxs_bec.devices.omny.galil.fgalil_ophyd](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/omny/galil/fgalil_ophyd.py) |
|
||||||
|
| FuprGalilMotor | | [csaxs_bec.devices.omny.galil.fupr_ophyd](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/omny/galil/fupr_ophyd.py) |
|
||||||
|
| LamniGalilMotor | | [csaxs_bec.devices.omny.galil.lgalil_ophyd](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/omny/galil/lgalil_ophyd.py) |
|
||||||
|
| SGalilMotor | "SGalil Motors at cSAXS have a<br> DC motor (y axis - vertical) - implemented as C<br> and a step motor (x-axis horizontal) - implemented as E<br> that require different communication for control<br> | [csaxs_bec.devices.omny.galil.sgalil_ophyd](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/omny/galil/sgalil_ophyd.py) |
|
||||||
|
| RtFlomniMotor | | [csaxs_bec.devices.omny.rt.rt_flomni_ophyd](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/omny/rt/rt_flomni_ophyd.py) |
|
||||||
|
| RtLamniMotor | | [csaxs_bec.devices.omny.rt.rt_lamni_ophyd](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/omny/rt/rt_lamni_ophyd.py) |
|
||||||
@@ -1,8 +1 @@
|
|||||||
# Standard ophyd classes
|
|
||||||
from ophyd import EpicsMotor, EpicsSignal, EpicsSignalRO
|
|
||||||
from ophyd.quadem import QuadEM
|
|
||||||
from ophyd.sim import SynAxis, SynPeriodicSignal, SynSignal
|
|
||||||
|
|
||||||
from .devices.delay_generator_csaxs import DelayGeneratorcSAXS
|
|
||||||
from .devices.flomni_sample_storage import FlomniSampleStorage
|
|
||||||
from .devices.InsertionDevice import InsertionDevice
|
|
||||||
|
|||||||
32
csaxs_bec/devices/epics/cSaxsVirtualMotors.py
Normal file
32
csaxs_bec/devices/epics/cSaxsVirtualMotors.py
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
""" TODO This class seems to be missing various imports and appears to have not been tested in motion yet."""
|
||||||
|
|
||||||
|
# TABLES_DT_PUSH_DIST_MM = 890
|
||||||
|
|
||||||
|
|
||||||
|
# class DetectorTableTheta(PseudoPositioner):
|
||||||
|
# """Detector table tilt motor
|
||||||
|
|
||||||
|
# Small wrapper to adjust the detector table tilt as angle.
|
||||||
|
# The table is pushed from one side by a single vertical motor.
|
||||||
|
|
||||||
|
# Note: Rarely used!
|
||||||
|
# """
|
||||||
|
|
||||||
|
# # Real axis (in degrees)
|
||||||
|
# pusher = Component(EpicsMotor, "", name="pusher")
|
||||||
|
# # Virtual axis
|
||||||
|
# theta = Component(PseudoSingle, name="theta")
|
||||||
|
|
||||||
|
# _real = ["pusher"]
|
||||||
|
|
||||||
|
# @pseudo_position_argument
|
||||||
|
# def forward(self, pseudo_pos):
|
||||||
|
# return self.RealPosition(
|
||||||
|
# pusher=tan(pseudo_pos.theta * 3.141592 / 180.0) * TABLES_DT_PUSH_DIST_MM
|
||||||
|
# )
|
||||||
|
|
||||||
|
# @real_position_argument
|
||||||
|
# def inverse(self, real_pos):
|
||||||
|
# return self.PseudoPosition(
|
||||||
|
# theta=-180 * atan(real_pos.pusher / TABLES_DT_PUSH_DIST_MM) / 3.141592
|
||||||
|
# )
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
from bec_lib import bec_logger
|
from bec_lib import bec_logger
|
||||||
from ophyd import Component
|
from ophyd import Component
|
||||||
from ophyd_devices.epics.devices.psi_delay_generator_base import (
|
from ophyd_devices.interfaces.base_classes.psi_delay_generator_base import (
|
||||||
DDGCustomMixin,
|
DDGCustomMixin,
|
||||||
PSIDelayGeneratorBase,
|
PSIDelayGeneratorBase,
|
||||||
TriggerSource,
|
TriggerSource,
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
# Standard ophyd classes
|
|
||||||
from ophyd import EpicsMotor, EpicsSignal, EpicsSignalRO
|
|
||||||
from ophyd.quadem import QuadEM
|
|
||||||
from ophyd.sim import SynAxis, SynPeriodicSignal, SynSignal
|
|
||||||
|
|
||||||
from .delay_generator_csaxs import DelayGeneratorcSAXS
|
|
||||||
from .eiger9m_csaxs import Eiger9McSAXS
|
|
||||||
|
|
||||||
# cSAXS
|
|
||||||
from .falcon_csaxs import FalconcSAXS
|
|
||||||
from .flomni_sample_storage import FlomniSampleStorage
|
|
||||||
from .InsertionDevice import InsertionDevice
|
|
||||||
from .mcs_csaxs import MCScSAXS
|
|
||||||
from .pilatus_csaxs import PilatuscSAXS
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
""" TODO This class seems to be missing various imports and appears to have not been tested in motion yet."""
|
|
||||||
|
|
||||||
TABLES_DT_PUSH_DIST_MM = 890
|
|
||||||
|
|
||||||
|
|
||||||
class DetectorTableTheta(PseudoPositioner):
|
|
||||||
"""Detector table tilt motor
|
|
||||||
|
|
||||||
Small wrapper to adjust the detector table tilt as angle.
|
|
||||||
The table is pushed from one side by a single vertical motor.
|
|
||||||
|
|
||||||
Note: Rarely used!
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Real axis (in degrees)
|
|
||||||
pusher = Component(EpicsMotor, "", name="pusher")
|
|
||||||
# Virtual axis
|
|
||||||
theta = Component(PseudoSingle, name="theta")
|
|
||||||
|
|
||||||
_real = ["pusher"]
|
|
||||||
|
|
||||||
@pseudo_position_argument
|
|
||||||
def forward(self, pseudo_pos):
|
|
||||||
return self.RealPosition(
|
|
||||||
pusher=tan(pseudo_pos.theta * 3.141592 / 180.0) * TABLES_DT_PUSH_DIST_MM
|
|
||||||
)
|
|
||||||
|
|
||||||
@real_position_argument
|
|
||||||
def inverse(self, real_pos):
|
|
||||||
return self.PseudoPosition(
|
|
||||||
theta=-180 * atan(real_pos.pusher / TABLES_DT_PUSH_DIST_MM) / 3.141592
|
|
||||||
)
|
|
||||||
@@ -5,12 +5,15 @@ import time
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from bec_lib import messages, threadlocked
|
from bec_lib import messages
|
||||||
from bec_lib.endpoints import MessageEndpoints
|
from bec_lib.endpoints import MessageEndpoints
|
||||||
from bec_lib.logger import bec_logger
|
from bec_lib.logger import bec_logger
|
||||||
from ophyd import ADComponent as ADCpt
|
from ophyd import ADComponent as ADCpt
|
||||||
from ophyd import Device, EpicsSignal, EpicsSignalRO, EpicsSignalWithRBV
|
from ophyd import Device, EpicsSignal, EpicsSignalRO, EpicsSignalWithRBV
|
||||||
from ophyd_devices.epics.devices.psi_detector_base import CustomDetectorMixin, PSIDetectorBase
|
from ophyd_devices.interfaces.base_classes.psi_detector_base import (
|
||||||
|
CustomDetectorMixin,
|
||||||
|
PSIDetectorBase,
|
||||||
|
)
|
||||||
from std_daq_client import StdDaqClient
|
from std_daq_client import StdDaqClient
|
||||||
|
|
||||||
logger = bec_logger.logger
|
logger = bec_logger.logger
|
||||||
@@ -305,33 +308,35 @@ class Eiger9MSetup(CustomDetectorMixin):
|
|||||||
)
|
)
|
||||||
pipe.execute()
|
pipe.execute()
|
||||||
|
|
||||||
@threadlocked
|
|
||||||
def finished(self):
|
def finished(self):
|
||||||
"""Check if acquisition is finished."""
|
"""Check if acquisition is finished."""
|
||||||
signal_conditions = [
|
with self._lock:
|
||||||
(
|
signal_conditions = [
|
||||||
lambda: self.parent.cam.acquire.read()[self.parent.cam.acquire.name]["value"],
|
(
|
||||||
DetectorState.IDLE,
|
lambda: self.parent.cam.acquire.read()[self.parent.cam.acquire.name]["value"],
|
||||||
),
|
DetectorState.IDLE,
|
||||||
(lambda: self.std_client.get_status()["acquisition"]["state"], "FINISHED"),
|
),
|
||||||
(
|
(lambda: self.std_client.get_status()["acquisition"]["state"], "FINISHED"),
|
||||||
lambda: self.std_client.get_status()["acquisition"]["stats"]["n_write_completed"],
|
(
|
||||||
int(self.parent.scaninfo.num_points * self.parent.scaninfo.frames_per_trigger),
|
lambda: self.std_client.get_status()["acquisition"]["stats"][
|
||||||
),
|
"n_write_completed"
|
||||||
]
|
],
|
||||||
if not self.wait_for_signals(
|
int(self.parent.scaninfo.num_points * self.parent.scaninfo.frames_per_trigger),
|
||||||
signal_conditions=signal_conditions,
|
),
|
||||||
timeout=self.parent.timeout,
|
]
|
||||||
check_stopped=True,
|
if not self.wait_for_signals(
|
||||||
all_signals=True,
|
signal_conditions=signal_conditions,
|
||||||
):
|
timeout=self.parent.timeout,
|
||||||
raise EigerTimeoutError(
|
check_stopped=True,
|
||||||
f"Reached timeout with detector state {signal_conditions[0][0]}, std_daq state"
|
all_signals=True,
|
||||||
f" {signal_conditions[1][0]} and received frames of {signal_conditions[2][0]} for"
|
):
|
||||||
" the file writer"
|
raise EigerTimeoutError(
|
||||||
)
|
f"Reached timeout with detector state {signal_conditions[0][0]}, std_daq state"
|
||||||
self.stop_detector()
|
f" {signal_conditions[1][0]} and received frames of {signal_conditions[2][0]} for"
|
||||||
self.stop_detector_backend()
|
" the file writer"
|
||||||
|
)
|
||||||
|
self.stop_detector()
|
||||||
|
self.stop_detector_backend()
|
||||||
|
|
||||||
|
|
||||||
class SLSDetectorCam(Device):
|
class SLSDetectorCam(Device):
|
||||||
@@ -7,7 +7,10 @@ from bec_lib.logger import bec_logger
|
|||||||
from ophyd import Component as Cpt
|
from ophyd import Component as Cpt
|
||||||
from ophyd import Device, EpicsSignal, EpicsSignalRO, EpicsSignalWithRBV
|
from ophyd import Device, EpicsSignal, EpicsSignalRO, EpicsSignalWithRBV
|
||||||
from ophyd.mca import EpicsMCARecord
|
from ophyd.mca import EpicsMCARecord
|
||||||
from ophyd_devices.epics.devices.psi_detector_base import CustomDetectorMixin, PSIDetectorBase
|
from ophyd_devices.interfaces.base_classes.psi_detector_base import (
|
||||||
|
CustomDetectorMixin,
|
||||||
|
PSIDetectorBase,
|
||||||
|
)
|
||||||
|
|
||||||
logger = bec_logger.logger
|
logger = bec_logger.logger
|
||||||
|
|
||||||
@@ -3,10 +3,14 @@ import threading
|
|||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from bec_lib import MessageEndpoints, bec_logger, messages, threadlocked
|
from bec_lib import bec_logger, messages
|
||||||
|
from bec_lib.endpoints import MessageEndpoints
|
||||||
from ophyd import Component as Cpt
|
from ophyd import Component as Cpt
|
||||||
from ophyd import Device, EpicsSignal, EpicsSignalRO
|
from ophyd import Device, EpicsSignal, EpicsSignalRO
|
||||||
from ophyd_devices.epics.devices.psi_detector_base import CustomDetectorMixin, PSIDetectorBase
|
from ophyd_devices.interfaces.base_classes.psi_detector_base import (
|
||||||
|
CustomDetectorMixin,
|
||||||
|
PSIDetectorBase,
|
||||||
|
)
|
||||||
from ophyd_devices.utils import bec_utils
|
from ophyd_devices.utils import bec_utils
|
||||||
|
|
||||||
logger = bec_logger.logger
|
logger = bec_logger.logger
|
||||||
@@ -109,17 +113,17 @@ class MCSSetup(CustomDetectorMixin):
|
|||||||
done=bool(max_value == value), # == self.counter),
|
done=bool(max_value == value), # == self.counter),
|
||||||
)
|
)
|
||||||
|
|
||||||
@threadlocked
|
|
||||||
def _on_mca_data(self, *args, obj=None, value=None, **kwargs) -> None:
|
def _on_mca_data(self, *args, obj=None, value=None, **kwargs) -> None:
|
||||||
"""Callback function for scan progress"""
|
"""Callback function for scan progress"""
|
||||||
if not isinstance(value, (list, np.ndarray)):
|
with self._lock:
|
||||||
return
|
if not isinstance(value, (list, np.ndarray)):
|
||||||
self.mca_data[obj.attr_name] = value
|
return
|
||||||
if len(self.mca_names) != len(self.mca_data):
|
self.mca_data[obj.attr_name] = value
|
||||||
return
|
if len(self.mca_names) != len(self.mca_data):
|
||||||
self.acquisition_done = True
|
return
|
||||||
self._send_data_to_bec()
|
self.acquisition_done = True
|
||||||
self.mca_data = defaultdict(lambda: [])
|
self._send_data_to_bec()
|
||||||
|
self.mca_data = defaultdict(lambda: [])
|
||||||
|
|
||||||
def _send_data_to_bec(self) -> None:
|
def _send_data_to_bec(self) -> None:
|
||||||
"""Sends bundled data to BEC"""
|
"""Sends bundled data to BEC"""
|
||||||
@@ -5,10 +5,14 @@ import time
|
|||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import requests
|
import requests
|
||||||
from bec_lib import MessageEndpoints, bec_logger, messages
|
from bec_lib import bec_logger, messages
|
||||||
|
from bec_lib.endpoints import MessageEndpoints
|
||||||
from ophyd import ADComponent as ADCpt
|
from ophyd import ADComponent as ADCpt
|
||||||
from ophyd import Device, EpicsSignal, EpicsSignalRO, EpicsSignalWithRBV, Staged
|
from ophyd import Device, EpicsSignal, EpicsSignalRO, EpicsSignalWithRBV, Staged
|
||||||
from ophyd_devices.epics.devices.psi_detector_base import CustomDetectorMixin, PSIDetectorBase
|
from ophyd_devices.interfaces.base_classes.psi_detector_base import (
|
||||||
|
CustomDetectorMixin,
|
||||||
|
PSIDetectorBase,
|
||||||
|
)
|
||||||
|
|
||||||
logger = bec_logger.logger
|
logger = bec_logger.logger
|
||||||
|
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from bec_lib import MessageEndpoints, bec_logger, messages
|
from bec_lib import bec_logger, messages
|
||||||
|
from bec_lib.endpoints import MessageEndpoints
|
||||||
from ophyd import Component as Cpt
|
from ophyd import Component as Cpt
|
||||||
from ophyd import Device, DeviceStatus, EpicsSignal, EpicsSignalRO, Signal
|
from ophyd import Device, EpicsSignal, EpicsSignalRO, Signal
|
||||||
|
|
||||||
logger = bec_logger.logger
|
logger = bec_logger.logger
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
from .fgalil_ophyd import FlomniGalilController, FlomniGalilMotor
|
from .fgalil_ophyd import FlomniGalilController, FlomniGalilMotor
|
||||||
from .fupr_ophyd import FuprGalilController, FuprGalilMotor
|
from .fupr_ophyd import FuprGalilController, FuprGalilMotor
|
||||||
from .galil_ophyd import GalilController, GalilMotor
|
from .lgalil_ophyd import LamniGalilController, LamniGalilMotor
|
||||||
from .sgalil_ophyd import SGalilMotor
|
from .sgalil_ophyd import SGalilMotor
|
||||||
|
Before Width: | Height: | Size: 157 KiB After Width: | Height: | Size: 157 KiB |
@@ -10,7 +10,7 @@ from ophyd.utils import LimitError
|
|||||||
from ophyd_devices.utils.controller import threadlocked
|
from ophyd_devices.utils.controller import threadlocked
|
||||||
from ophyd_devices.utils.socket import SocketIO, raise_if_disconnected
|
from ophyd_devices.utils.socket import SocketIO, raise_if_disconnected
|
||||||
|
|
||||||
from csaxs_bec.devices.galil.galil_ophyd import (
|
from csaxs_bec.devices.omny.galil.galil_ophyd import (
|
||||||
BECConfigError,
|
BECConfigError,
|
||||||
GalilAxesReferenced,
|
GalilAxesReferenced,
|
||||||
GalilController,
|
GalilController,
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
import functools
|
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
|
|
||||||
@@ -7,15 +6,13 @@ from bec_lib import bec_logger
|
|||||||
from ophyd import Component as Cpt
|
from ophyd import Component as Cpt
|
||||||
from ophyd import Device, PositionerBase, Signal
|
from ophyd import Device, PositionerBase, Signal
|
||||||
from ophyd.status import wait as status_wait
|
from ophyd.status import wait as status_wait
|
||||||
from ophyd.utils import LimitError, ReadOnlyError
|
from ophyd.utils import LimitError
|
||||||
from ophyd_devices.utils.controller import Controller, threadlocked
|
from ophyd_devices.utils.controller import threadlocked
|
||||||
from ophyd_devices.utils.socket import SocketIO, SocketSignal, raise_if_disconnected
|
from ophyd_devices.utils.socket import SocketIO, raise_if_disconnected
|
||||||
from prettytable import PrettyTable
|
|
||||||
|
|
||||||
from csaxs_bec.devices.galil.galil_ophyd import (
|
from csaxs_bec.devices.omny.galil.galil_ophyd import (
|
||||||
BECConfigError,
|
BECConfigError,
|
||||||
GalilAxesReferenced,
|
GalilAxesReferenced,
|
||||||
GalilCommunicationError,
|
|
||||||
GalilController,
|
GalilController,
|
||||||
GalilError,
|
GalilError,
|
||||||
GalilMotorIsMoving,
|
GalilMotorIsMoving,
|
||||||
@@ -1,15 +1,14 @@
|
|||||||
|
"""
|
||||||
|
This module contains the base class for Galil controllers as well as the signals used for Galil devices.
|
||||||
|
"""
|
||||||
|
|
||||||
import functools
|
import functools
|
||||||
import threading
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
import numpy as np
|
|
||||||
from bec_lib import bec_logger
|
from bec_lib import bec_logger
|
||||||
from ophyd import Component as Cpt
|
from ophyd.utils import ReadOnlyError
|
||||||
from ophyd import Device, PositionerBase, Signal
|
|
||||||
from ophyd.status import wait as status_wait
|
|
||||||
from ophyd.utils import LimitError, ReadOnlyError
|
|
||||||
from ophyd_devices.utils.controller import Controller, threadlocked
|
from ophyd_devices.utils.controller import Controller, threadlocked
|
||||||
from ophyd_devices.utils.socket import SocketIO, SocketSignal, raise_if_disconnected
|
from ophyd_devices.utils.socket import SocketSignal
|
||||||
from prettytable import PrettyTable
|
from prettytable import PrettyTable
|
||||||
|
|
||||||
logger = bec_logger.logger
|
logger = bec_logger.logger
|
||||||
@@ -42,6 +41,10 @@ def retry_once(fcn):
|
|||||||
|
|
||||||
|
|
||||||
class GalilController(Controller):
|
class GalilController(Controller):
|
||||||
|
"""
|
||||||
|
Base class for Galil controllers. This class provides the basic functionality for Galil controllers and should be subclassed for specific devices.
|
||||||
|
"""
|
||||||
|
|
||||||
_axes_per_controller = 8
|
_axes_per_controller = 8
|
||||||
USER_ACCESS = [
|
USER_ACCESS = [
|
||||||
"describe",
|
"describe",
|
||||||
@@ -49,7 +52,6 @@ class GalilController(Controller):
|
|||||||
"galil_show_all",
|
"galil_show_all",
|
||||||
"socket_put_and_receive",
|
"socket_put_and_receive",
|
||||||
"socket_put_confirmed",
|
"socket_put_confirmed",
|
||||||
"lgalil_is_air_off_and_orchestra_enabled",
|
|
||||||
"drive_axis_to_limit",
|
"drive_axis_to_limit",
|
||||||
"find_reference",
|
"find_reference",
|
||||||
"get_motor_limit_switch",
|
"get_motor_limit_switch",
|
||||||
@@ -61,18 +63,6 @@ class GalilController(Controller):
|
|||||||
def socket_put(self, val: str) -> None:
|
def socket_put(self, val: str) -> None:
|
||||||
self.sock.put(f"{val}\r".encode())
|
self.sock.put(f"{val}\r".encode())
|
||||||
|
|
||||||
@threadlocked
|
|
||||||
def socket_get(self) -> str:
|
|
||||||
return self.sock.receive().decode()
|
|
||||||
|
|
||||||
@retry_once
|
|
||||||
@threadlocked
|
|
||||||
def socket_put_and_receive(self, val: str, remove_trailing_chars=True) -> str:
|
|
||||||
self.socket_put(val)
|
|
||||||
if remove_trailing_chars:
|
|
||||||
return self._remove_trailing_characters(self.sock.receive().decode())
|
|
||||||
return self.socket_get()
|
|
||||||
|
|
||||||
@retry_once
|
@retry_once
|
||||||
def socket_put_confirmed(self, val: str) -> None:
|
def socket_put_confirmed(self, val: str) -> None:
|
||||||
"""Send message to controller and ensure that it is received by checking that the socket receives a colon.
|
"""Send message to controller and ensure that it is received by checking that the socket receives a colon.
|
||||||
@@ -94,7 +84,9 @@ class GalilController(Controller):
|
|||||||
if axis_Id is None and axis_Id_numeric is not None:
|
if axis_Id is None and axis_Id_numeric is not None:
|
||||||
axis_Id = self.axis_Id_numeric_to_alpha(axis_Id_numeric)
|
axis_Id = self.axis_Id_numeric_to_alpha(axis_Id_numeric)
|
||||||
is_moving = bool(float(self.socket_put_and_receive(f"MG_BG{axis_Id}")) != 0)
|
is_moving = bool(float(self.socket_put_and_receive(f"MG_BG{axis_Id}")) != 0)
|
||||||
backlash_is_active = bool(float(self.socket_put_and_receive(f"MGbcklact[axis]")) != 0)
|
backlash_is_active = bool(
|
||||||
|
float(self.socket_put_and_receive(f"MGbcklact[{axis_Id_numeric}]")) != 0
|
||||||
|
)
|
||||||
return bool(
|
return bool(
|
||||||
is_moving or backlash_is_active or self.is_thread_active(0) or self.is_thread_active(2)
|
is_moving or backlash_is_active or self.is_thread_active(0) or self.is_thread_active(2)
|
||||||
)
|
)
|
||||||
@@ -105,19 +97,11 @@ class GalilController(Controller):
|
|||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _remove_trailing_characters(self, var) -> str:
|
|
||||||
if len(var) > 1:
|
|
||||||
return var.split("\r\n")[0]
|
|
||||||
return var
|
|
||||||
|
|
||||||
def stop_all_axes(self) -> str:
|
def stop_all_axes(self) -> str:
|
||||||
return self.socket_put_and_receive(f"XQ#STOP,1")
|
return self.socket_put_and_receive("XQ#STOP,1")
|
||||||
|
|
||||||
def lgalil_is_air_off_and_orchestra_enabled(self) -> bool:
|
def get_digital_input(self, channel):
|
||||||
# TODO: move this to the LamNI-specific controller
|
return bool(float(self.socket_put_and_receive(f"MG @IN[{channel}]").strip()))
|
||||||
rt_not_blocked_by_galil = bool(self.socket_put_and_receive(f"MG@OUT[9]"))
|
|
||||||
air_off = bool(self.socket_put_and_receive(f"MG@OUT[13]"))
|
|
||||||
return rt_not_blocked_by_galil and air_off
|
|
||||||
|
|
||||||
def axis_is_referenced(self, axis_Id_numeric) -> bool:
|
def axis_is_referenced(self, axis_Id_numeric) -> bool:
|
||||||
return bool(float(self.socket_put_and_receive(f"MG axisref[{axis_Id_numeric}]").strip()))
|
return bool(float(self.socket_put_and_receive(f"MG axisref[{axis_Id_numeric}]").strip()))
|
||||||
@@ -146,9 +130,9 @@ class GalilController(Controller):
|
|||||||
self.socket_put_confirmed(f"naxis={axis_Id_numeric}")
|
self.socket_put_confirmed(f"naxis={axis_Id_numeric}")
|
||||||
self.socket_put_confirmed(f"ndir={direction_flag}")
|
self.socket_put_confirmed(f"ndir={direction_flag}")
|
||||||
self.socket_put_confirmed("XQ#NEWPAR")
|
self.socket_put_confirmed("XQ#NEWPAR")
|
||||||
time.sleep(0.005)
|
time.sleep(0.1)
|
||||||
self.socket_put_confirmed("XQ#FES")
|
self.socket_put_confirmed("XQ#FES")
|
||||||
time.sleep(0.01)
|
time.sleep(0.1)
|
||||||
while self.is_axis_moving(None, axis_Id_numeric):
|
while self.is_axis_moving(None, axis_Id_numeric):
|
||||||
time.sleep(0.01)
|
time.sleep(0.01)
|
||||||
|
|
||||||
@@ -169,8 +153,10 @@ class GalilController(Controller):
|
|||||||
Args:
|
Args:
|
||||||
axis_Id_numeric (int): Axis number
|
axis_Id_numeric (int): Axis number
|
||||||
"""
|
"""
|
||||||
|
time.sleep(0.1)
|
||||||
self.socket_put_confirmed(f"naxis={axis_Id_numeric}")
|
self.socket_put_confirmed(f"naxis={axis_Id_numeric}")
|
||||||
self.socket_put_and_receive("XQ#NEWPAR")
|
self.socket_put_and_receive("XQ#NEWPAR")
|
||||||
|
time.sleep(0.1)
|
||||||
self.socket_put_confirmed("XQ#FRM")
|
self.socket_put_confirmed("XQ#FRM")
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
while self.is_axis_moving(None, axis_Id_numeric):
|
while self.is_axis_moving(None, axis_Id_numeric):
|
||||||
@@ -241,6 +227,13 @@ class GalilController(Controller):
|
|||||||
print(t)
|
print(t)
|
||||||
|
|
||||||
self.show_running_threads()
|
self.show_running_threads()
|
||||||
|
self.show_status_other()
|
||||||
|
|
||||||
|
def show_status_other(self) -> None:
|
||||||
|
"""
|
||||||
|
Show additional device-specific status information.
|
||||||
|
Override in subclasses.
|
||||||
|
"""
|
||||||
|
|
||||||
def galil_show_all(self) -> None:
|
def galil_show_all(self) -> None:
|
||||||
for controller in self._controller_instances.values():
|
for controller in self._controller_instances.values():
|
||||||
@@ -334,12 +327,18 @@ class GalilSetpointSignal(GalilSignalBase):
|
|||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
|
|
||||||
if self.parent.axis_Id_numeric == 2:
|
if self.parent.axis_Id_numeric == 2:
|
||||||
angle_status = self.parent.device_manager.devices[
|
try:
|
||||||
self.parent.rt
|
rt = self.parent.device_manager.devices[self.parent.rt]
|
||||||
].obj.controller.feedback_status_angle_lamni()
|
if rt.enabled:
|
||||||
|
angle_status = self.parent.device_manager.devices[
|
||||||
if angle_status:
|
self.parent.rt
|
||||||
self.controller.socket_put_confirmed("angintf=1")
|
].obj.controller.feedback_status_angle_lamni()
|
||||||
|
if angle_status:
|
||||||
|
self.controller.socket_put_confirmed("angintf=1")
|
||||||
|
except KeyError:
|
||||||
|
logger.warning(
|
||||||
|
"RT is disabled. Failed to update RT angle interferometer status to galil."
|
||||||
|
)
|
||||||
|
|
||||||
self.controller.socket_put_confirmed(f"naxis={self.parent.axis_Id_numeric}")
|
self.controller.socket_put_confirmed(f"naxis={self.parent.axis_Id_numeric}")
|
||||||
self.controller.socket_put_confirmed(f"ntarget={target_val:.3f}")
|
self.controller.socket_put_confirmed(f"ntarget={target_val:.3f}")
|
||||||
@@ -376,229 +375,3 @@ class GalilAxesReferenced(GalilSignalRO):
|
|||||||
@threadlocked
|
@threadlocked
|
||||||
def _socket_get(self):
|
def _socket_get(self):
|
||||||
return self.controller.all_axes_referenced()
|
return self.controller.all_axes_referenced()
|
||||||
|
|
||||||
|
|
||||||
class GalilMotor(Device, PositionerBase):
|
|
||||||
USER_ACCESS = ["controller"]
|
|
||||||
readback = Cpt(GalilReadbackSignal, signal_name="readback", kind="hinted")
|
|
||||||
user_setpoint = Cpt(GalilSetpointSignal, signal_name="setpoint")
|
|
||||||
motor_resolution = Cpt(GalilMotorResolution, signal_name="resolution", kind="config")
|
|
||||||
motor_is_moving = Cpt(GalilMotorIsMoving, signal_name="motor_is_moving", kind="normal")
|
|
||||||
all_axes_referenced = Cpt(GalilAxesReferenced, signal_name="all_axes_referenced", kind="config")
|
|
||||||
high_limit_travel = Cpt(Signal, value=0, kind="omitted")
|
|
||||||
low_limit_travel = Cpt(Signal, value=0, kind="omitted")
|
|
||||||
|
|
||||||
SUB_READBACK = "readback"
|
|
||||||
SUB_CONNECTION_CHANGE = "connection_change"
|
|
||||||
_default_sub = SUB_READBACK
|
|
||||||
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
axis_Id,
|
|
||||||
prefix="",
|
|
||||||
*,
|
|
||||||
name,
|
|
||||||
kind=None,
|
|
||||||
read_attrs=None,
|
|
||||||
configuration_attrs=None,
|
|
||||||
parent=None,
|
|
||||||
host="mpc2680.psi.ch",
|
|
||||||
port=8081,
|
|
||||||
limits=None,
|
|
||||||
sign=1,
|
|
||||||
socket_cls=SocketIO,
|
|
||||||
device_manager=None,
|
|
||||||
**kwargs,
|
|
||||||
):
|
|
||||||
self.controller = GalilController(socket_cls=socket_cls, socket_host=host, socket_port=port)
|
|
||||||
self.axis_Id = axis_Id
|
|
||||||
self.controller.set_axis(axis=self, axis_nr=self.axis_Id_numeric)
|
|
||||||
self.sign = sign
|
|
||||||
self.tolerance = kwargs.pop("tolerance", 0.5)
|
|
||||||
self.device_mapping = kwargs.pop("device_mapping", {})
|
|
||||||
self.device_manager = device_manager
|
|
||||||
|
|
||||||
if len(self.device_mapping) > 0 and self.device_manager is None:
|
|
||||||
raise BECConfigError(
|
|
||||||
"device_mapping has been specified but the device_manager cannot be accessed."
|
|
||||||
)
|
|
||||||
self.rt = self.device_mapping.get("rt")
|
|
||||||
|
|
||||||
super().__init__(
|
|
||||||
prefix,
|
|
||||||
name=name,
|
|
||||||
kind=kind,
|
|
||||||
read_attrs=read_attrs,
|
|
||||||
configuration_attrs=configuration_attrs,
|
|
||||||
parent=parent,
|
|
||||||
**kwargs,
|
|
||||||
)
|
|
||||||
self.readback.name = self.name
|
|
||||||
self.controller.subscribe(
|
|
||||||
self._update_connection_state, event_type=self.SUB_CONNECTION_CHANGE
|
|
||||||
)
|
|
||||||
self._update_connection_state()
|
|
||||||
# self.readback.subscribe(self._forward_readback, event_type=self.readback.SUB_VALUE)
|
|
||||||
|
|
||||||
if limits is not None:
|
|
||||||
assert len(limits) == 2
|
|
||||||
self.low_limit_travel.put(limits[0])
|
|
||||||
self.high_limit_travel.put(limits[1])
|
|
||||||
|
|
||||||
@property
|
|
||||||
def limits(self):
|
|
||||||
return (self.low_limit_travel.get(), self.high_limit_travel.get())
|
|
||||||
|
|
||||||
@property
|
|
||||||
def low_limit(self):
|
|
||||||
return self.limits[0]
|
|
||||||
|
|
||||||
@property
|
|
||||||
def high_limit(self):
|
|
||||||
return self.limits[1]
|
|
||||||
|
|
||||||
def check_value(self, pos):
|
|
||||||
"""Check that the position is within the soft limits"""
|
|
||||||
low_limit, high_limit = self.limits
|
|
||||||
|
|
||||||
if low_limit < high_limit and not (low_limit <= pos <= high_limit):
|
|
||||||
raise LimitError(f"position={pos} not within limits {self.limits}")
|
|
||||||
|
|
||||||
def _update_connection_state(self, **kwargs):
|
|
||||||
for walk in self.walk_signals():
|
|
||||||
walk.item._metadata["connected"] = self.controller.connected
|
|
||||||
|
|
||||||
def _forward_readback(self, **kwargs):
|
|
||||||
kwargs.pop("sub_type")
|
|
||||||
self._run_subs(sub_type="readback", **kwargs)
|
|
||||||
|
|
||||||
@raise_if_disconnected
|
|
||||||
def move(self, position, wait=True, **kwargs):
|
|
||||||
"""Move to a specified position, optionally waiting for motion to
|
|
||||||
complete.
|
|
||||||
|
|
||||||
Parameters
|
|
||||||
----------
|
|
||||||
position
|
|
||||||
Position to move to
|
|
||||||
moved_cb : callable
|
|
||||||
Call this callback when movement has finished. This callback must
|
|
||||||
accept one keyword argument: 'obj' which will be set to this
|
|
||||||
positioner instance.
|
|
||||||
timeout : float, optional
|
|
||||||
Maximum time to wait for the motion. If None, the default timeout
|
|
||||||
for this positioner is used.
|
|
||||||
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
status : MoveStatus
|
|
||||||
|
|
||||||
Raises
|
|
||||||
------
|
|
||||||
TimeoutError
|
|
||||||
When motion takes longer than `timeout`
|
|
||||||
ValueError
|
|
||||||
On invalid positions
|
|
||||||
RuntimeError
|
|
||||||
If motion fails other than timing out
|
|
||||||
"""
|
|
||||||
self._started_moving = False
|
|
||||||
timeout = kwargs.pop("timeout", 100)
|
|
||||||
status = super().move(position, timeout=timeout, **kwargs)
|
|
||||||
self.user_setpoint.put(position, wait=False)
|
|
||||||
|
|
||||||
def move_and_finish():
|
|
||||||
while self.motor_is_moving.get():
|
|
||||||
logger.info("motor is moving")
|
|
||||||
val = self.readback.read()
|
|
||||||
self._run_subs(sub_type=self.SUB_READBACK, value=val, timestamp=time.time())
|
|
||||||
time.sleep(0.1)
|
|
||||||
val = self.readback.read()
|
|
||||||
success = np.isclose(val[self.name]["value"], position, atol=self.tolerance)
|
|
||||||
|
|
||||||
if not success:
|
|
||||||
print(" stop")
|
|
||||||
self._done_moving(success=success)
|
|
||||||
logger.info("Move finished")
|
|
||||||
|
|
||||||
threading.Thread(target=move_and_finish, daemon=True).start()
|
|
||||||
try:
|
|
||||||
if wait:
|
|
||||||
status_wait(status)
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
self.stop()
|
|
||||||
raise
|
|
||||||
|
|
||||||
return status
|
|
||||||
|
|
||||||
@property
|
|
||||||
def axis_Id(self):
|
|
||||||
return self._axis_Id_alpha
|
|
||||||
|
|
||||||
@axis_Id.setter
|
|
||||||
def axis_Id(self, val):
|
|
||||||
if isinstance(val, str):
|
|
||||||
if len(val) != 1:
|
|
||||||
raise ValueError(f"Only single-character axis_Ids are supported.")
|
|
||||||
self._axis_Id_alpha = val
|
|
||||||
self._axis_Id_numeric = self.controller.axis_Id_to_numeric(val)
|
|
||||||
else:
|
|
||||||
raise TypeError(f"Expected value of type str but received {type(val)}")
|
|
||||||
|
|
||||||
@property
|
|
||||||
def axis_Id_numeric(self):
|
|
||||||
return self._axis_Id_numeric
|
|
||||||
|
|
||||||
@axis_Id_numeric.setter
|
|
||||||
def axis_Id_numeric(self, val):
|
|
||||||
if isinstance(val, int):
|
|
||||||
if val > 26:
|
|
||||||
raise ValueError(f"Numeric value exceeds supported range.")
|
|
||||||
self._axis_Id_alpha = self.controller.axis_Id_numeric_to_alpha(val)
|
|
||||||
self._axis_Id_numeric = val
|
|
||||||
else:
|
|
||||||
raise TypeError(f"Expected value of type int but received {type(val)}")
|
|
||||||
|
|
||||||
@property
|
|
||||||
def egu(self):
|
|
||||||
"""The engineering units (EGU) for positions"""
|
|
||||||
return "mm"
|
|
||||||
|
|
||||||
def stage(self) -> list[object]:
|
|
||||||
return super().stage()
|
|
||||||
|
|
||||||
def unstage(self) -> list[object]:
|
|
||||||
return super().unstage()
|
|
||||||
|
|
||||||
def stop(self, *, success=False):
|
|
||||||
self.controller.stop_all_axes()
|
|
||||||
return super().stop(success=success)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
# pytest: skip-file
|
|
||||||
mock = False
|
|
||||||
if not mock:
|
|
||||||
leyey = GalilMotor("H", name="leyey", host="mpc2680.psi.ch", port=8081, sign=-1)
|
|
||||||
leyey.stage()
|
|
||||||
status = leyey.move(0, wait=True)
|
|
||||||
status = leyey.move(10, wait=True)
|
|
||||||
leyey.read()
|
|
||||||
|
|
||||||
leyey.get()
|
|
||||||
leyey.describe()
|
|
||||||
|
|
||||||
leyey.unstage()
|
|
||||||
else:
|
|
||||||
from ophyd_devices.utils.socket import SocketMock
|
|
||||||
|
|
||||||
leyex = GalilMotor(
|
|
||||||
"G", name="leyex", host="mpc2680.psi.ch", port=8081, socket_cls=SocketMock
|
|
||||||
)
|
|
||||||
leyey = GalilMotor(
|
|
||||||
"H", name="leyey", host="mpc2680.psi.ch", port=8081, socket_cls=SocketMock
|
|
||||||
)
|
|
||||||
leyex.stage()
|
|
||||||
# leyey.stage()
|
|
||||||
|
|
||||||
leyex.controller.galil_show_all()
|
|
||||||
265
csaxs_bec/devices/omny/galil/lgalil_ophyd.py
Normal file
265
csaxs_bec/devices/omny/galil/lgalil_ophyd.py
Normal file
@@ -0,0 +1,265 @@
|
|||||||
|
import threading
|
||||||
|
import time
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
from bec_lib.logger import bec_logger
|
||||||
|
from ophyd import Component as Cpt
|
||||||
|
from ophyd import Device, PositionerBase, Signal
|
||||||
|
from ophyd.status import wait as status_wait
|
||||||
|
from ophyd.utils import LimitError
|
||||||
|
from ophyd_devices.utils.socket import SocketIO, raise_if_disconnected
|
||||||
|
|
||||||
|
from csaxs_bec.devices.omny.galil.galil_ophyd import (
|
||||||
|
BECConfigError,
|
||||||
|
GalilAxesReferenced,
|
||||||
|
GalilController,
|
||||||
|
GalilMotorIsMoving,
|
||||||
|
GalilMotorResolution,
|
||||||
|
GalilReadbackSignal,
|
||||||
|
GalilSetpointSignal,
|
||||||
|
)
|
||||||
|
|
||||||
|
logger = bec_logger.logger
|
||||||
|
|
||||||
|
|
||||||
|
class LamniGalilController(GalilController):
|
||||||
|
USER_ACCESS = [
|
||||||
|
"describe",
|
||||||
|
"show_running_threads",
|
||||||
|
"galil_show_all",
|
||||||
|
"socket_put_and_receive",
|
||||||
|
"socket_put_confirmed",
|
||||||
|
"lgalil_is_air_off_and_orchestra_enabled",
|
||||||
|
"drive_axis_to_limit",
|
||||||
|
"find_reference",
|
||||||
|
"get_motor_limit_switch",
|
||||||
|
"is_motor_on",
|
||||||
|
"all_axes_referenced",
|
||||||
|
]
|
||||||
|
|
||||||
|
def show_status_other(self):
|
||||||
|
if self.get_digital_input(5):
|
||||||
|
print("Emergency stop is not pushed.")
|
||||||
|
else:
|
||||||
|
print("Emergency stop is pushed.")
|
||||||
|
if self.get_digital_input(6):
|
||||||
|
print("Driver axis 2 error.")
|
||||||
|
if self.get_digital_input(13):
|
||||||
|
print("No air pressure at inner rotation.")
|
||||||
|
else:
|
||||||
|
print("There is air pressure at the inner rotation.")
|
||||||
|
if self.get_digital_input(14):
|
||||||
|
print("No air pressure at outer rotation axial.")
|
||||||
|
else:
|
||||||
|
print("There is air pressure at the outer rotation axial.")
|
||||||
|
if self.get_digital_input(15):
|
||||||
|
print("No air pressure at outer rotation radial.")
|
||||||
|
else:
|
||||||
|
print("There is air pressure at the outer rotation radial.")
|
||||||
|
swver = float(self.socket_put_and_receive("MGswver"))
|
||||||
|
print(f"Lgalil LAMNI firmware version {swver:2.0f}.")
|
||||||
|
|
||||||
|
def lamni_lights_off(self):
|
||||||
|
self.socket_put_confirmed("SB1")
|
||||||
|
|
||||||
|
def lamni_lights_on(self):
|
||||||
|
self.socket_put_confirmed("CB1")
|
||||||
|
|
||||||
|
def lgalil_is_air_off_and_orchestra_enabled(self) -> bool:
|
||||||
|
# TODO: move this to the LamNI-specific controller
|
||||||
|
rt_not_blocked_by_galil = bool(self.socket_put_and_receive("MG@OUT[9]"))
|
||||||
|
air_off = bool(self.socket_put_and_receive("MG@OUT[13]"))
|
||||||
|
return rt_not_blocked_by_galil and air_off
|
||||||
|
|
||||||
|
|
||||||
|
class LamniGalilMotor(Device, PositionerBase):
|
||||||
|
USER_ACCESS = ["controller"]
|
||||||
|
readback = Cpt(GalilReadbackSignal, signal_name="readback", kind="hinted")
|
||||||
|
user_setpoint = Cpt(GalilSetpointSignal, signal_name="setpoint")
|
||||||
|
motor_resolution = Cpt(GalilMotorResolution, signal_name="resolution", kind="config")
|
||||||
|
motor_is_moving = Cpt(GalilMotorIsMoving, signal_name="motor_is_moving", kind="normal")
|
||||||
|
all_axes_referenced = Cpt(GalilAxesReferenced, signal_name="all_axes_referenced", kind="config")
|
||||||
|
high_limit_travel = Cpt(Signal, value=0, kind="omitted")
|
||||||
|
low_limit_travel = Cpt(Signal, value=0, kind="omitted")
|
||||||
|
|
||||||
|
SUB_READBACK = "readback"
|
||||||
|
SUB_CONNECTION_CHANGE = "connection_change"
|
||||||
|
_default_sub = SUB_READBACK
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
axis_Id,
|
||||||
|
prefix="",
|
||||||
|
*,
|
||||||
|
name,
|
||||||
|
kind=None,
|
||||||
|
read_attrs=None,
|
||||||
|
configuration_attrs=None,
|
||||||
|
parent=None,
|
||||||
|
host="mpc2680.psi.ch",
|
||||||
|
port=8081,
|
||||||
|
limits=None,
|
||||||
|
sign=1,
|
||||||
|
socket_cls=SocketIO,
|
||||||
|
device_manager=None,
|
||||||
|
**kwargs,
|
||||||
|
):
|
||||||
|
self.controller = LamniGalilController(
|
||||||
|
socket_cls=socket_cls, socket_host=host, socket_port=port
|
||||||
|
)
|
||||||
|
self.axis_Id = axis_Id
|
||||||
|
self.controller.set_axis(axis=self, axis_nr=self.axis_Id_numeric)
|
||||||
|
self.sign = sign
|
||||||
|
self.tolerance = kwargs.pop("tolerance", 0.5)
|
||||||
|
self.device_mapping = kwargs.pop("device_mapping", {})
|
||||||
|
self.device_manager = device_manager
|
||||||
|
|
||||||
|
if len(self.device_mapping) > 0 and self.device_manager is None:
|
||||||
|
raise BECConfigError(
|
||||||
|
"device_mapping has been specified but the device_manager cannot be accessed."
|
||||||
|
)
|
||||||
|
self.rt = self.device_mapping.get("rt")
|
||||||
|
|
||||||
|
super().__init__(
|
||||||
|
prefix,
|
||||||
|
name=name,
|
||||||
|
kind=kind,
|
||||||
|
read_attrs=read_attrs,
|
||||||
|
configuration_attrs=configuration_attrs,
|
||||||
|
parent=parent,
|
||||||
|
**kwargs,
|
||||||
|
)
|
||||||
|
self.readback.name = self.name
|
||||||
|
self.controller.subscribe(
|
||||||
|
self._update_connection_state, event_type=self.SUB_CONNECTION_CHANGE
|
||||||
|
)
|
||||||
|
self._update_connection_state()
|
||||||
|
# self.readback.subscribe(self._forward_readback, event_type=self.readback.SUB_VALUE)
|
||||||
|
|
||||||
|
if limits is not None:
|
||||||
|
assert len(limits) == 2
|
||||||
|
self.low_limit_travel.put(limits[0])
|
||||||
|
self.high_limit_travel.put(limits[1])
|
||||||
|
|
||||||
|
@property
|
||||||
|
def limits(self):
|
||||||
|
return (self.low_limit_travel.get(), self.high_limit_travel.get())
|
||||||
|
|
||||||
|
@property
|
||||||
|
def low_limit(self):
|
||||||
|
return self.limits[0]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def high_limit(self):
|
||||||
|
return self.limits[1]
|
||||||
|
|
||||||
|
def check_value(self, pos):
|
||||||
|
"""Check that the position is within the soft limits"""
|
||||||
|
low_limit, high_limit = self.limits
|
||||||
|
|
||||||
|
if low_limit < high_limit and not (low_limit <= pos <= high_limit):
|
||||||
|
raise LimitError(f"position={pos} not within limits {self.limits}")
|
||||||
|
|
||||||
|
def _update_connection_state(self, **kwargs):
|
||||||
|
for walk in self.walk_signals():
|
||||||
|
walk.item._metadata["connected"] = self.controller.connected
|
||||||
|
|
||||||
|
def _forward_readback(self, **kwargs):
|
||||||
|
kwargs.pop("sub_type")
|
||||||
|
self._run_subs(sub_type="readback", **kwargs)
|
||||||
|
|
||||||
|
@raise_if_disconnected
|
||||||
|
def move(self, position, wait=True, **kwargs):
|
||||||
|
"""Move to a specified position, optionally waiting for motion to
|
||||||
|
complete.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
position
|
||||||
|
Position to move to
|
||||||
|
moved_cb : callable
|
||||||
|
Call this callback when movement has finished. This callback must
|
||||||
|
accept one keyword argument: 'obj' which will be set to this
|
||||||
|
positioner instance.
|
||||||
|
timeout : float, optional
|
||||||
|
Maximum time to wait for the motion. If None, the default timeout
|
||||||
|
for this positioner is used.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
status : MoveStatus
|
||||||
|
|
||||||
|
Raises
|
||||||
|
------
|
||||||
|
TimeoutError
|
||||||
|
When motion takes longer than `timeout`
|
||||||
|
ValueError
|
||||||
|
On invalid positions
|
||||||
|
RuntimeError
|
||||||
|
If motion fails other than timing out
|
||||||
|
"""
|
||||||
|
self._started_moving = False
|
||||||
|
timeout = kwargs.pop("timeout", 100)
|
||||||
|
status = super().move(position, timeout=timeout, **kwargs)
|
||||||
|
self.user_setpoint.put(position, wait=False)
|
||||||
|
|
||||||
|
def move_and_finish():
|
||||||
|
while self.motor_is_moving.get():
|
||||||
|
logger.info("motor is moving")
|
||||||
|
val = self.readback.read()
|
||||||
|
self._run_subs(sub_type=self.SUB_READBACK, value=val, timestamp=time.time())
|
||||||
|
time.sleep(0.1)
|
||||||
|
val = self.readback.read()
|
||||||
|
success = np.isclose(val[self.name]["value"], position, atol=self.tolerance)
|
||||||
|
|
||||||
|
if not success:
|
||||||
|
print(" stop")
|
||||||
|
self._done_moving(success=success)
|
||||||
|
logger.info("Move finished")
|
||||||
|
|
||||||
|
threading.Thread(target=move_and_finish, daemon=True).start()
|
||||||
|
try:
|
||||||
|
if wait:
|
||||||
|
status_wait(status)
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
self.stop()
|
||||||
|
raise
|
||||||
|
|
||||||
|
return status
|
||||||
|
|
||||||
|
@property
|
||||||
|
def axis_Id(self):
|
||||||
|
return self._axis_Id_alpha
|
||||||
|
|
||||||
|
@axis_Id.setter
|
||||||
|
def axis_Id(self, val):
|
||||||
|
if isinstance(val, str):
|
||||||
|
if len(val) != 1:
|
||||||
|
raise ValueError("Only single-character axis_Ids are supported.")
|
||||||
|
self._axis_Id_alpha = val
|
||||||
|
self._axis_Id_numeric = self.controller.axis_Id_to_numeric(val)
|
||||||
|
else:
|
||||||
|
raise TypeError(f"Expected value of type str but received {type(val)}")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def axis_Id_numeric(self):
|
||||||
|
return self._axis_Id_numeric
|
||||||
|
|
||||||
|
@axis_Id_numeric.setter
|
||||||
|
def axis_Id_numeric(self, val):
|
||||||
|
if isinstance(val, int):
|
||||||
|
if val > 26:
|
||||||
|
raise ValueError("Numeric value exceeds supported range.")
|
||||||
|
self._axis_Id_alpha = self.controller.axis_Id_numeric_to_alpha(val)
|
||||||
|
self._axis_Id_numeric = val
|
||||||
|
else:
|
||||||
|
raise TypeError(f"Expected value of type int but received {type(val)}")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def egu(self):
|
||||||
|
"""The engineering units (EGU) for positions"""
|
||||||
|
return "mm"
|
||||||
|
|
||||||
|
def stop(self, *, success=False):
|
||||||
|
self.controller.stop_all_axes()
|
||||||
|
return super().stop(success=success)
|
||||||
@@ -4,7 +4,7 @@ Ophyd wrapper for the SGalil controller and stages.
|
|||||||
## Integration of the device in IPython kernel
|
## Integration of the device in IPython kernel
|
||||||
BEC needs to be able to reach the host TCP to initiate a connection to the device.
|
BEC needs to be able to reach the host TCP to initiate a connection to the device.
|
||||||
```Python
|
```Python
|
||||||
from csaxs_bec.devices.galil.sgalil_ophyd import SGalilMotor
|
from csaxs_bec.devices.omny.galil.sgalil_ophyd import SGalilMotor
|
||||||
samx = SGalilMotor("E", name="samx", host="129.129.122.26", port=23, sign=-1)
|
samx = SGalilMotor("E", name="samx", host="129.129.122.26", port=23, sign=-1)
|
||||||
samy = SGalilMotor("C", name="samy", host="129.129.122.26", port=23, sign=-1)
|
samy = SGalilMotor("C", name="samy", host="129.129.122.26", port=23, sign=-1)
|
||||||
# connect to the controller
|
# connect to the controller
|
||||||
@@ -28,6 +28,7 @@ class OMNYSampleStorage(Device):
|
|||||||
"unset_shuttle_slot",
|
"unset_shuttle_slot",
|
||||||
"get_shuttle_name_slot",
|
"get_shuttle_name_slot",
|
||||||
"is_shuttle_slot_used",
|
"is_shuttle_slot_used",
|
||||||
|
"search_shuttle_in_slot",
|
||||||
"show_all",
|
"show_all",
|
||||||
]
|
]
|
||||||
SUB_VALUE = "value"
|
SUB_VALUE = "value"
|
||||||
@@ -59,7 +60,7 @@ class OMNYSampleStorage(Device):
|
|||||||
parking_placed = Dcpt(parking_placed)
|
parking_placed = Dcpt(parking_placed)
|
||||||
|
|
||||||
sample_placed = {
|
sample_placed = {
|
||||||
f"parking{i}": (EpicsSignal, f"XOMNY-SAMPLE_DB_omny:{i}", {})
|
f"sample{i}": (EpicsSignal, f"XOMNY-SAMPLE_DB_omny:{i}", {})
|
||||||
for i in [10, 11, 12, 13, 14, 32, 33, 34, 100, 101]
|
for i in [10, 11, 12, 13, 14, 32, 33, 34, 100, 101]
|
||||||
}
|
}
|
||||||
sample_placed = Dcpt(sample_placed)
|
sample_placed = Dcpt(sample_placed)
|
||||||
@@ -227,11 +228,25 @@ class OMNYSampleStorage(Device):
|
|||||||
val = self.sample_in_samplestage_name.get()
|
val = self.sample_in_samplestage_name.get()
|
||||||
return str(val)
|
return str(val)
|
||||||
|
|
||||||
|
def search_shuttle_in_slot(self, shuttle: str) -> int:
|
||||||
|
returnvalue = 0
|
||||||
|
for i in range(1, 7):
|
||||||
|
if self.get_shuttle_name_slot(i) == shuttle:
|
||||||
|
returnvalue = i
|
||||||
|
return returnvalue
|
||||||
|
|
||||||
def show_all(self):
|
def show_all(self):
|
||||||
t = PrettyTable()
|
t = PrettyTable()
|
||||||
|
red = "\x1b[91m"
|
||||||
|
green = "\x1b[92m"
|
||||||
|
white = "\x1b[0m"
|
||||||
for ch in ["A", "B", "C"]:
|
for ch in ["A", "B", "C"]:
|
||||||
t.clear()
|
t.clear()
|
||||||
t.title = "Shuttle " + ch
|
shuttle_in_slot = self.search_shuttle_in_slot(ch)
|
||||||
|
if shuttle_in_slot > 0:
|
||||||
|
t.title = green + "Shuttle " + ch + " in OMNY slot " + str(shuttle_in_slot) + white
|
||||||
|
else:
|
||||||
|
t.title = red + "Shuttle " + ch + white
|
||||||
field_names = [""]
|
field_names = [""]
|
||||||
for ax in [1, 3, 5]:
|
for ax in [1, 3, 5]:
|
||||||
row = []
|
row = []
|
||||||
@@ -3,29 +3,31 @@ import time
|
|||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from bec_lib import MessageEndpoints, bec_logger, messages
|
from bec_lib import bec_logger, messages
|
||||||
|
from bec_lib.endpoints import MessageEndpoints
|
||||||
from ophyd import Component as Cpt
|
from ophyd import Component as Cpt
|
||||||
from ophyd import Device, PositionerBase, Signal
|
from ophyd import Device, PositionerBase, Signal
|
||||||
from ophyd.status import wait as status_wait
|
from ophyd.status import wait as status_wait
|
||||||
from ophyd.utils import LimitError
|
from ophyd.utils import LimitError
|
||||||
from csaxs_bec.devices.rt_lamni.rt_ophyd import (
|
from ophyd_devices.utils.controller import Controller, threadlocked
|
||||||
|
from ophyd_devices.utils.socket import SocketIO, raise_if_disconnected
|
||||||
|
from prettytable import PrettyTable
|
||||||
|
|
||||||
|
from csaxs_bec.devices.omny.rt.rt_ophyd import (
|
||||||
BECConfigError,
|
BECConfigError,
|
||||||
RtCommunicationError,
|
RtCommunicationError,
|
||||||
RtController,
|
|
||||||
RtError,
|
RtError,
|
||||||
RtReadbackSignal,
|
RtReadbackSignal,
|
||||||
RtSetpointSignal,
|
RtSetpointSignal,
|
||||||
RtSignalRO,
|
RtSignalRO,
|
||||||
retry_once,
|
retry_once,
|
||||||
)
|
)
|
||||||
from ophyd_devices.utils.controller import threadlocked
|
|
||||||
from ophyd_devices.utils.socket import SocketIO, raise_if_disconnected
|
|
||||||
from prettytable import PrettyTable
|
|
||||||
|
|
||||||
logger = bec_logger.logger
|
logger = bec_logger.logger
|
||||||
|
|
||||||
|
|
||||||
class RtFlomniController(RtController):
|
class RtFlomniController(Controller):
|
||||||
|
_axes_per_controller = 3
|
||||||
USER_ACCESS = [
|
USER_ACCESS = [
|
||||||
"socket_put_and_receive",
|
"socket_put_and_receive",
|
||||||
"set_rotation_angle",
|
"set_rotation_angle",
|
||||||
@@ -50,7 +52,7 @@ class RtFlomniController(RtController):
|
|||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
*,
|
*,
|
||||||
name=None,
|
name="RtFlomniController",
|
||||||
socket_cls=None,
|
socket_cls=None,
|
||||||
socket_host=None,
|
socket_host=None,
|
||||||
socket_port=None,
|
socket_port=None,
|
||||||
@@ -73,6 +75,15 @@ class RtFlomniController(RtController):
|
|||||||
self._min_scan_buffer_reached = False
|
self._min_scan_buffer_reached = False
|
||||||
self.rt_pid_voltage = None
|
self.rt_pid_voltage = None
|
||||||
|
|
||||||
|
def is_axis_moving(self, axis_Id) -> bool:
|
||||||
|
# this checks that axis is on target
|
||||||
|
axis_is_on_target = bool(float(self.socket_put_and_receive("o")))
|
||||||
|
return not axis_is_on_target
|
||||||
|
|
||||||
|
@threadlocked
|
||||||
|
def stop_all_axes(self):
|
||||||
|
self.socket_put("sc")
|
||||||
|
|
||||||
def add_pos_to_scan(self, positions) -> None:
|
def add_pos_to_scan(self, positions) -> None:
|
||||||
def send_positions(parent, positions):
|
def send_positions(parent, positions):
|
||||||
parent._min_scan_buffer_reached = False
|
parent._min_scan_buffer_reached = False
|
||||||
@@ -487,7 +498,7 @@ class RtFlomniController(RtController):
|
|||||||
MessageEndpoints.device_status("rt_scan"),
|
MessageEndpoints.device_status("rt_scan"),
|
||||||
messages.DeviceStatusMessage(
|
messages.DeviceStatusMessage(
|
||||||
device="rt_scan", status=1, metadata=self.readout_metadata
|
device="rt_scan", status=1, metadata=self.readout_metadata
|
||||||
).dumps(),
|
),
|
||||||
)
|
)
|
||||||
# while scan is running
|
# while scan is running
|
||||||
while mode > 0:
|
while mode > 0:
|
||||||
@@ -522,7 +533,7 @@ class RtFlomniController(RtController):
|
|||||||
MessageEndpoints.device_status("rt_scan"),
|
MessageEndpoints.device_status("rt_scan"),
|
||||||
messages.DeviceStatusMessage(
|
messages.DeviceStatusMessage(
|
||||||
device="rt_scan", status=0, metadata=self.readout_metadata
|
device="rt_scan", status=0, metadata=self.readout_metadata
|
||||||
).dumps(),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
@@ -536,7 +547,7 @@ class RtFlomniController(RtController):
|
|||||||
MessageEndpoints.device_read("rt_flomni"),
|
MessageEndpoints.device_read("rt_flomni"),
|
||||||
messages.DeviceMessage(
|
messages.DeviceMessage(
|
||||||
signals=signals, metadata={"point_id": point_id, **self.readout_metadata}
|
signals=signals, metadata={"point_id": point_id, **self.readout_metadata}
|
||||||
).dumps(),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
def start_readout(self):
|
def start_readout(self):
|
||||||
@@ -683,15 +694,16 @@ class RtFlomniMotor(Device, PositionerBase):
|
|||||||
def high_limit(self):
|
def high_limit(self):
|
||||||
return self.limits[1]
|
return self.limits[1]
|
||||||
|
|
||||||
def check_value(self, pos):
|
def check_value(self, value, **kwargs):
|
||||||
"""Check that the position is within the soft limits"""
|
"""Check that the position is within the soft limits"""
|
||||||
low_limit, high_limit = self.limits
|
low_limit, high_limit = self.limits
|
||||||
|
|
||||||
if low_limit < high_limit and not (low_limit <= pos <= high_limit):
|
if low_limit < high_limit and not (low_limit <= value <= high_limit):
|
||||||
raise LimitError(f"position={pos} not within limits {self.limits}")
|
raise LimitError(f"position={value} not within limits {self.limits}")
|
||||||
|
|
||||||
def _update_connection_state(self, **kwargs):
|
def _update_connection_state(self, **kwargs):
|
||||||
for walk in self.walk_signals():
|
for walk in self.walk_signals():
|
||||||
|
# pylint: disable=protected-access
|
||||||
walk.item._metadata["connected"] = self.controller.connected
|
walk.item._metadata["connected"] = self.controller.connected
|
||||||
|
|
||||||
def _forward_readback(self, **kwargs):
|
def _forward_readback(self, **kwargs):
|
||||||
@@ -761,7 +773,7 @@ class RtFlomniMotor(Device, PositionerBase):
|
|||||||
def axis_Id(self, val):
|
def axis_Id(self, val):
|
||||||
if isinstance(val, str):
|
if isinstance(val, str):
|
||||||
if len(val) != 1:
|
if len(val) != 1:
|
||||||
raise ValueError(f"Only single-character axis_Ids are supported.")
|
raise ValueError("Only single-character axis_Ids are supported.")
|
||||||
self._axis_Id_alpha = val
|
self._axis_Id_alpha = val
|
||||||
self._axis_Id_numeric = ord(val.lower()) - 97
|
self._axis_Id_numeric = ord(val.lower()) - 97
|
||||||
else:
|
else:
|
||||||
@@ -775,7 +787,7 @@ class RtFlomniMotor(Device, PositionerBase):
|
|||||||
def axis_Id_numeric(self, val):
|
def axis_Id_numeric(self, val):
|
||||||
if isinstance(val, int):
|
if isinstance(val, int):
|
||||||
if val > 26:
|
if val > 26:
|
||||||
raise ValueError(f"Numeric value exceeds supported range.")
|
raise ValueError("Numeric value exceeds supported range.")
|
||||||
self._axis_Id_alpha = val
|
self._axis_Id_alpha = val
|
||||||
self._axis_Id_numeric = (chr(val + 97)).capitalize()
|
self._axis_Id_numeric = (chr(val + 97)).capitalize()
|
||||||
else:
|
else:
|
||||||
@@ -789,14 +801,6 @@ class RtFlomniMotor(Device, PositionerBase):
|
|||||||
"""The engineering units (EGU) for positions"""
|
"""The engineering units (EGU) for positions"""
|
||||||
return "um"
|
return "um"
|
||||||
|
|
||||||
# how is this used later?
|
|
||||||
|
|
||||||
def stage(self) -> List[object]:
|
|
||||||
return super().stage()
|
|
||||||
|
|
||||||
def unstage(self) -> List[object]:
|
|
||||||
return super().unstage()
|
|
||||||
|
|
||||||
def stop(self, *, success=False):
|
def stop(self, *, success=False):
|
||||||
self.controller.stop_all_axes()
|
self.controller.stop_all_axes()
|
||||||
self._stopped = True
|
self._stopped = True
|
||||||
@@ -3,7 +3,8 @@ import threading
|
|||||||
import time
|
import time
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from bec_lib import MessageEndpoints, bec_logger, messages
|
from bec_lib import bec_logger, messages
|
||||||
|
from bec_lib.endpoints import MessageEndpoints
|
||||||
from ophyd import Component as Cpt
|
from ophyd import Component as Cpt
|
||||||
from ophyd import Device, PositionerBase, Signal
|
from ophyd import Device, PositionerBase, Signal
|
||||||
from ophyd.status import wait as status_wait
|
from ophyd.status import wait as status_wait
|
||||||
@@ -11,6 +12,8 @@ from ophyd.utils import LimitError, ReadOnlyError
|
|||||||
from ophyd_devices.utils.controller import Controller, threadlocked
|
from ophyd_devices.utils.controller import Controller, threadlocked
|
||||||
from ophyd_devices.utils.socket import SocketIO, SocketSignal, raise_if_disconnected
|
from ophyd_devices.utils.socket import SocketIO, SocketSignal, raise_if_disconnected
|
||||||
|
|
||||||
|
from csaxs_bec.devices.omny.rt.rt_ophyd import RtCommunicationError, RtError
|
||||||
|
|
||||||
logger = bec_logger.logger
|
logger = bec_logger.logger
|
||||||
|
|
||||||
|
|
||||||
@@ -41,6 +44,11 @@ def retry_once(fcn):
|
|||||||
|
|
||||||
|
|
||||||
class RtLamniController(Controller):
|
class RtLamniController(Controller):
|
||||||
|
"""
|
||||||
|
RT-Lamni controller class for all rt devices.
|
||||||
|
"""
|
||||||
|
|
||||||
|
_axes_per_controller = 3
|
||||||
USER_ACCESS = [
|
USER_ACCESS = [
|
||||||
"socket_put_and_receive",
|
"socket_put_and_receive",
|
||||||
"set_rotation_angle",
|
"set_rotation_angle",
|
||||||
@@ -60,110 +68,25 @@ class RtLamniController(Controller):
|
|||||||
self,
|
self,
|
||||||
*,
|
*,
|
||||||
name="RtLamniController",
|
name="RtLamniController",
|
||||||
kind=None,
|
socket_cls=None,
|
||||||
parent=None,
|
socket_host=None,
|
||||||
socket=None,
|
socket_port=None,
|
||||||
attr_name="",
|
attr_name="",
|
||||||
|
parent=None,
|
||||||
labels=None,
|
labels=None,
|
||||||
|
kind=None,
|
||||||
):
|
):
|
||||||
if not hasattr(self, "_initialized") or not self._initialized:
|
super().__init__(
|
||||||
self._rtlamni_axis_per_controller = 3
|
name=name,
|
||||||
self._axis = [None for axis_num in range(self._rtlamni_axis_per_controller)]
|
socket_cls=socket_cls,
|
||||||
self._min_scan_buffer_reached = False
|
socket_host=socket_host,
|
||||||
super().__init__(
|
socket_port=socket_port,
|
||||||
name=name,
|
attr_name=attr_name,
|
||||||
socket=socket,
|
parent=parent,
|
||||||
attr_name=attr_name,
|
labels=labels,
|
||||||
parent=parent,
|
kind=kind,
|
||||||
labels=labels,
|
)
|
||||||
kind=kind,
|
self._min_scan_buffer_reached = False
|
||||||
)
|
|
||||||
self.readout_metadata = {}
|
|
||||||
|
|
||||||
def on(self, controller_num=0) -> None:
|
|
||||||
"""Open a new socket connection to the controller"""
|
|
||||||
if not self.connected:
|
|
||||||
try:
|
|
||||||
self.sock.open()
|
|
||||||
# discuss - after disconnect takes a while for the server to be ready again
|
|
||||||
max_retries = 10
|
|
||||||
tries = 0
|
|
||||||
while not self.connected:
|
|
||||||
try:
|
|
||||||
welcome_message = self.sock.receive()
|
|
||||||
self.connected = True
|
|
||||||
except ConnectionResetError as conn_reset:
|
|
||||||
if tries > max_retries:
|
|
||||||
raise conn_reset
|
|
||||||
tries += 1
|
|
||||||
time.sleep(2)
|
|
||||||
except ConnectionRefusedError as conn_error:
|
|
||||||
logger.error("Failed to open a connection to RTLamNI.")
|
|
||||||
raise RtLamniCommunicationError from conn_error
|
|
||||||
|
|
||||||
else:
|
|
||||||
logger.info("The connection has already been established.")
|
|
||||||
# warnings.warn(f"The connection has already been established.", stacklevel=2)
|
|
||||||
|
|
||||||
self._update_flyer_device_info()
|
|
||||||
|
|
||||||
def off(self) -> None:
|
|
||||||
"""Close the socket connection to the controller"""
|
|
||||||
if self.connected:
|
|
||||||
self.sock.close()
|
|
||||||
self.connected = False
|
|
||||||
else:
|
|
||||||
logger.info("The connection is already closed.")
|
|
||||||
|
|
||||||
def set_axis(self, axis: Device, axis_nr: int) -> None:
|
|
||||||
"""Assign an axis to a device instance.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
axis (Device): Device instance (e.g. GalilMotor)
|
|
||||||
axis_nr (int): Controller axis number
|
|
||||||
|
|
||||||
"""
|
|
||||||
self._axis[axis_nr] = axis
|
|
||||||
|
|
||||||
@threadlocked
|
|
||||||
def socket_put(self, val: str) -> None:
|
|
||||||
self.sock.put(f"{val}\n".encode())
|
|
||||||
|
|
||||||
@threadlocked
|
|
||||||
def socket_get(self) -> str:
|
|
||||||
return self.sock.receive().decode()
|
|
||||||
|
|
||||||
@retry_once
|
|
||||||
@threadlocked
|
|
||||||
def socket_put_and_receive(self, val: str, remove_trailing_chars=True) -> str:
|
|
||||||
self.socket_put(val)
|
|
||||||
if remove_trailing_chars:
|
|
||||||
return self._remove_trailing_characters(self.sock.receive().decode())
|
|
||||||
return self.socket_get()
|
|
||||||
|
|
||||||
def is_axis_moving(self, axis_Id) -> bool:
|
|
||||||
# this checks that axis is on target
|
|
||||||
axis_is_on_target = bool(float(self.socket_put_and_receive(f"o")))
|
|
||||||
return not axis_is_on_target
|
|
||||||
|
|
||||||
# def is_thread_active(self, thread_id: int) -> bool:
|
|
||||||
# val = float(self.socket_put_and_receive(f"MG_XQ{thread_id}"))
|
|
||||||
# if val == -1:
|
|
||||||
# return False
|
|
||||||
# return True
|
|
||||||
|
|
||||||
def _remove_trailing_characters(self, var) -> str:
|
|
||||||
if len(var) > 1:
|
|
||||||
return var.split("\r\n")[0]
|
|
||||||
return var
|
|
||||||
|
|
||||||
@threadlocked
|
|
||||||
def set_rotation_angle(self, val: float):
|
|
||||||
self.socket_put(f"a{(val-300+30.538)/180*np.pi}")
|
|
||||||
|
|
||||||
@threadlocked
|
|
||||||
def stop_all_axes(self):
|
|
||||||
self.socket_put("sc")
|
|
||||||
|
|
||||||
@threadlocked
|
@threadlocked
|
||||||
def feedback_disable(self):
|
def feedback_disable(self):
|
||||||
@@ -175,6 +98,19 @@ class RtLamniController(Controller):
|
|||||||
self.set_device_enabled("lopty", True)
|
self.set_device_enabled("lopty", True)
|
||||||
self.set_device_enabled("loptz", True)
|
self.set_device_enabled("loptz", True)
|
||||||
|
|
||||||
|
def is_axis_moving(self, axis_Id) -> bool:
|
||||||
|
# this checks that axis is on target
|
||||||
|
axis_is_on_target = bool(float(self.socket_put_and_receive("o")))
|
||||||
|
return not axis_is_on_target
|
||||||
|
|
||||||
|
@threadlocked
|
||||||
|
def stop_all_axes(self):
|
||||||
|
self.socket_put("sc")
|
||||||
|
|
||||||
|
@threadlocked
|
||||||
|
def set_rotation_angle(self, val: float):
|
||||||
|
self.socket_put(f"a{(val-300+30.538)/180*np.pi}")
|
||||||
|
|
||||||
@threadlocked
|
@threadlocked
|
||||||
def _set_axis_velocity(self, um_per_s):
|
def _set_axis_velocity(self, um_per_s):
|
||||||
self.socket_put(f"V{um_per_s}")
|
self.socket_put(f"V{um_per_s}")
|
||||||
@@ -234,19 +170,6 @@ class RtLamniController(Controller):
|
|||||||
self.set_device_enabled("lopty", True)
|
self.set_device_enabled("lopty", True)
|
||||||
self.set_device_enabled("loptz", True)
|
self.set_device_enabled("loptz", True)
|
||||||
|
|
||||||
def get_device_manager(self):
|
|
||||||
for axis in self._axis:
|
|
||||||
if hasattr(axis, "device_manager") and axis.device_manager:
|
|
||||||
return axis.device_manager
|
|
||||||
raise BECConfigError("Could not access the device_manager")
|
|
||||||
|
|
||||||
def get_axis_by_name(self, name):
|
|
||||||
for axis in self._axis:
|
|
||||||
if axis:
|
|
||||||
if axis.name == name:
|
|
||||||
return axis
|
|
||||||
raise RuntimeError(f"Could not find an axis with name {name}")
|
|
||||||
|
|
||||||
@threadlocked
|
@threadlocked
|
||||||
def clear_trajectory_generator(self):
|
def clear_trajectory_generator(self):
|
||||||
self.socket_put("sc")
|
self.socket_put("sc")
|
||||||
@@ -256,7 +179,7 @@ class RtLamniController(Controller):
|
|||||||
def send_positions(parent, positions):
|
def send_positions(parent, positions):
|
||||||
parent._min_scan_buffer_reached = False
|
parent._min_scan_buffer_reached = False
|
||||||
for pos_index, pos in enumerate(positions):
|
for pos_index, pos in enumerate(positions):
|
||||||
parent.socket_put_and_receive(f"s{pos[0]:.05f},{pos[1]:05f},0")
|
parent.socket_put_and_receive(f"s{pos[0]:.05f},{pos[1]:.05f},0")
|
||||||
if pos_index > 100:
|
if pos_index > 100:
|
||||||
parent._min_scan_buffer_reached = True
|
parent._min_scan_buffer_reached = True
|
||||||
parent._min_scan_buffer_reached = True
|
parent._min_scan_buffer_reached = True
|
||||||
@@ -268,7 +191,7 @@ class RtLamniController(Controller):
|
|||||||
def get_scan_status(self):
|
def get_scan_status(self):
|
||||||
return_table = (self.socket_put_and_receive(f"sr")).split(",")
|
return_table = (self.socket_put_and_receive(f"sr")).split(",")
|
||||||
if len(return_table) != 3:
|
if len(return_table) != 3:
|
||||||
raise RtLamniCommunicationError(
|
raise RtCommunicationError(
|
||||||
f"Expected to receive 3 return values. Instead received {return_table}"
|
f"Expected to receive 3 return values. Instead received {return_table}"
|
||||||
)
|
)
|
||||||
mode = int(return_table[0])
|
mode = int(return_table[0])
|
||||||
@@ -288,7 +211,7 @@ class RtLamniController(Controller):
|
|||||||
logger.error(
|
logger.error(
|
||||||
"Cannot start scan because feedback loop is not running or there is an interferometer error."
|
"Cannot start scan because feedback loop is not running or there is an interferometer error."
|
||||||
)
|
)
|
||||||
raise RtLamniError(
|
raise RtError(
|
||||||
"Cannot start scan because feedback loop is not running or there is an interferometer error."
|
"Cannot start scan because feedback loop is not running or there is an interferometer error."
|
||||||
)
|
)
|
||||||
# here exception
|
# here exception
|
||||||
@@ -296,7 +219,7 @@ class RtLamniController(Controller):
|
|||||||
|
|
||||||
if number_of_positions_planned == 0:
|
if number_of_positions_planned == 0:
|
||||||
logger.error("Cannot start scan because no target positions are planned.")
|
logger.error("Cannot start scan because no target positions are planned.")
|
||||||
raise RtLamniError("Cannot start scan because no target positions are planned.")
|
raise RtError("Cannot start scan because no target positions are planned.")
|
||||||
# hier exception
|
# hier exception
|
||||||
# start a point-by-point scan (for cont scan in flomni it would be "sa")
|
# start a point-by-point scan (for cont scan in flomni it would be "sa")
|
||||||
self.socket_put_and_receive("sd")
|
self.socket_put_and_receive("sd")
|
||||||
@@ -305,29 +228,6 @@ class RtLamniController(Controller):
|
|||||||
readout = threading.Thread(target=self.read_positions_from_sampler)
|
readout = threading.Thread(target=self.read_positions_from_sampler)
|
||||||
readout.start()
|
readout.start()
|
||||||
|
|
||||||
def _update_flyer_device_info(self):
|
|
||||||
flyer_info = self._get_flyer_device_info()
|
|
||||||
self.get_device_manager().connector.set(
|
|
||||||
MessageEndpoints.device_info("rt_scan"),
|
|
||||||
messages.DeviceInfoMessage(device="rt_scan", info=flyer_info),
|
|
||||||
)
|
|
||||||
|
|
||||||
def _get_flyer_device_info(self) -> dict:
|
|
||||||
return {
|
|
||||||
"device_name": self.name,
|
|
||||||
"device_attr_name": getattr(self, "attr_name", ""),
|
|
||||||
"device_dotted_name": getattr(self, "dotted_name", ""),
|
|
||||||
"device_info": {
|
|
||||||
"device_base_class": "ophydobject",
|
|
||||||
"signals": [],
|
|
||||||
"hints": {"fields": ["average_x_st_fzp", "average_y_st_fzp"]},
|
|
||||||
"describe": {},
|
|
||||||
"describe_configuration": {},
|
|
||||||
"sub_devices": [],
|
|
||||||
"custom_user_access": [],
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
def kickoff(self, metadata):
|
def kickoff(self, metadata):
|
||||||
self.readout_metadata = metadata
|
self.readout_metadata = metadata
|
||||||
while not self._min_scan_buffer_reached:
|
while not self._min_scan_buffer_reached:
|
||||||
@@ -439,7 +339,7 @@ class RtLamniController(Controller):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def feedback_status_angle_lamni(self) -> bool:
|
def feedback_status_angle_lamni(self) -> bool:
|
||||||
return_table = (self.socket_put_and_receive(f"J7")).split(",")
|
return_table = (self.socket_put_and_receive("J7")).split(",")
|
||||||
logger.debug(
|
logger.debug(
|
||||||
f"LamNI angle interferomter status {bool(return_table[0])}, position {float(return_table[1])}, signal {float(return_table[2])}"
|
f"LamNI angle interferomter status {bool(return_table[0])}, position {float(return_table[1])}, signal {float(return_table[2])}"
|
||||||
)
|
)
|
||||||
@@ -448,21 +348,21 @@ class RtLamniController(Controller):
|
|||||||
def feedback_enable_with_reset(self):
|
def feedback_enable_with_reset(self):
|
||||||
if not self.feedback_status_angle_lamni():
|
if not self.feedback_status_angle_lamni():
|
||||||
self.feedback_disable_and_even_reset_lamni_angle_interferometer()
|
self.feedback_disable_and_even_reset_lamni_angle_interferometer()
|
||||||
logger.info(f"LamNI resetting interferometer inclusive angular interferomter.")
|
logger.info("LamNI resetting interferometer inclusive angular interferomter.")
|
||||||
else:
|
else:
|
||||||
self.feedback_disable()
|
self.feedback_disable()
|
||||||
logger.info(
|
logger.info(
|
||||||
f"LamNI resetting interferomter except angular interferometer which is already running."
|
"LamNI resetting interferomter except angular interferometer which is already running."
|
||||||
)
|
)
|
||||||
|
|
||||||
# set these as closed loop target position
|
# set these as closed loop target position
|
||||||
|
|
||||||
self.socket_put(f"pa0,0")
|
self.socket_put("pa0,0")
|
||||||
self.get_axis_by_name("rtx").user_setpoint.setpoint = 0
|
self.get_axis_by_name("rtx").user_setpoint.setpoint = 0
|
||||||
self.socket_put(f"pa1,0")
|
self.socket_put("pa1,0")
|
||||||
self.get_axis_by_name("rty").user_setpoint.setpoint = 0
|
self.get_axis_by_name("rty").user_setpoint.setpoint = 0
|
||||||
self.socket_put(
|
self.socket_put(
|
||||||
f"pa2,0"
|
"pa2,0"
|
||||||
) # we set all three outputs of the traj. gen. although in LamNI case only 0,1 are used
|
) # we set all three outputs of the traj. gen. although in LamNI case only 0,1 are used
|
||||||
self.clear_trajectory_generator()
|
self.clear_trajectory_generator()
|
||||||
|
|
||||||
@@ -476,7 +376,7 @@ class RtLamniController(Controller):
|
|||||||
logger.error(
|
logger.error(
|
||||||
"Cannot enable feedback. The small rotation air is on and/or orchestra disabled by the motor controller."
|
"Cannot enable feedback. The small rotation air is on and/or orchestra disabled by the motor controller."
|
||||||
)
|
)
|
||||||
raise RtLamniError(
|
raise RtError(
|
||||||
"Cannot enable feedback. The small rotation air is on and/or orchestra disabled by the motor controller."
|
"Cannot enable feedback. The small rotation air is on and/or orchestra disabled by the motor controller."
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -515,7 +415,7 @@ class RtLamniController(Controller):
|
|||||||
logger.error(
|
logger.error(
|
||||||
"Cannot start scan because feedback loop is not running or there is an interferometer error."
|
"Cannot start scan because feedback loop is not running or there is an interferometer error."
|
||||||
)
|
)
|
||||||
raise RtLamniError(
|
raise RtError(
|
||||||
"Cannot start scan because feedback loop is not running or there is an interferometer error."
|
"Cannot start scan because feedback loop is not running or there is an interferometer error."
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -523,15 +423,6 @@ class RtLamniController(Controller):
|
|||||||
|
|
||||||
# ptychography_alignment_done = 0
|
# ptychography_alignment_done = 0
|
||||||
|
|
||||||
def set_device_enabled(self, device_name: str, enabled: bool) -> None:
|
|
||||||
"""enable / disable a device"""
|
|
||||||
if device_name not in self.get_device_manager().devices:
|
|
||||||
logger.warning(
|
|
||||||
f"Device {device_name} is not configured and cannot be enabled/disabled."
|
|
||||||
)
|
|
||||||
return
|
|
||||||
self.get_device_manager().devices[device_name].read_only = not enabled
|
|
||||||
|
|
||||||
|
|
||||||
class RtLamniSignalBase(SocketSignal):
|
class RtLamniSignalBase(SocketSignal):
|
||||||
def __init__(self, signal_name, **kwargs):
|
def __init__(self, signal_name, **kwargs):
|
||||||
@@ -567,7 +458,7 @@ class RtLamniReadbackSignal(RtLamniSignalRO):
|
|||||||
readback_index = 1
|
readback_index = 1
|
||||||
else:
|
else:
|
||||||
raise RtLamniError("Currently, only two axes are supported.")
|
raise RtLamniError("Currently, only two axes are supported.")
|
||||||
|
print(return_table)
|
||||||
current_pos = float(return_table[readback_index])
|
current_pos = float(return_table[readback_index])
|
||||||
|
|
||||||
current_pos *= self.parent.sign
|
current_pos *= self.parent.sign
|
||||||
@@ -667,7 +558,9 @@ class RtLamniMotor(Device, PositionerBase):
|
|||||||
):
|
):
|
||||||
self.axis_Id = axis_Id
|
self.axis_Id = axis_Id
|
||||||
self.sign = sign
|
self.sign = sign
|
||||||
self.controller = RtLamniController(socket=socket_cls(host=host, port=port))
|
self.controller = RtLamniController(
|
||||||
|
socket_cls=socket_cls, socket_host=host, socket_port=port
|
||||||
|
)
|
||||||
self.controller.set_axis(axis=self, axis_nr=self.axis_Id_numeric)
|
self.controller.set_axis(axis=self, axis_nr=self.axis_Id_numeric)
|
||||||
self.device_manager = device_manager
|
self.device_manager = device_manager
|
||||||
self.tolerance = kwargs.pop("tolerance", 0.5)
|
self.tolerance = kwargs.pop("tolerance", 0.5)
|
||||||
@@ -705,15 +598,16 @@ class RtLamniMotor(Device, PositionerBase):
|
|||||||
def high_limit(self):
|
def high_limit(self):
|
||||||
return self.limits[1]
|
return self.limits[1]
|
||||||
|
|
||||||
def check_value(self, pos):
|
def check_value(self, value, **kwargs):
|
||||||
"""Check that the position is within the soft limits"""
|
"""Check that the position is within the soft limits"""
|
||||||
low_limit, high_limit = self.limits
|
low_limit, high_limit = self.limits
|
||||||
|
|
||||||
if low_limit < high_limit and not (low_limit <= pos <= high_limit):
|
if low_limit < high_limit and not (low_limit <= value <= high_limit):
|
||||||
raise LimitError(f"position={pos} not within limits {self.limits}")
|
raise LimitError(f"position={value} not within limits {self.limits}")
|
||||||
|
|
||||||
def _update_connection_state(self, **kwargs):
|
def _update_connection_state(self, **kwargs):
|
||||||
for walk in self.walk_signals():
|
for walk in self.walk_signals():
|
||||||
|
# pylint: disable=protected-access
|
||||||
walk.item._metadata["connected"] = self.controller.connected
|
walk.item._metadata["connected"] = self.controller.connected
|
||||||
|
|
||||||
def _forward_readback(self, **kwargs):
|
def _forward_readback(self, **kwargs):
|
||||||
@@ -782,7 +676,7 @@ class RtLamniMotor(Device, PositionerBase):
|
|||||||
def axis_Id(self, val):
|
def axis_Id(self, val):
|
||||||
if isinstance(val, str):
|
if isinstance(val, str):
|
||||||
if len(val) != 1:
|
if len(val) != 1:
|
||||||
raise ValueError(f"Only single-character axis_Ids are supported.")
|
raise ValueError("Only single-character axis_Ids are supported.")
|
||||||
self._axis_Id_alpha = val
|
self._axis_Id_alpha = val
|
||||||
self._axis_Id_numeric = ord(val.lower()) - 97
|
self._axis_Id_numeric = ord(val.lower()) - 97
|
||||||
else:
|
else:
|
||||||
@@ -796,7 +690,7 @@ class RtLamniMotor(Device, PositionerBase):
|
|||||||
def axis_Id_numeric(self, val):
|
def axis_Id_numeric(self, val):
|
||||||
if isinstance(val, int):
|
if isinstance(val, int):
|
||||||
if val > 26:
|
if val > 26:
|
||||||
raise ValueError(f"Numeric value exceeds supported range.")
|
raise ValueError("Numeric value exceeds supported range.")
|
||||||
self._axis_Id_alpha = val
|
self._axis_Id_alpha = val
|
||||||
self._axis_Id_numeric = (chr(val + 97)).capitalize()
|
self._axis_Id_numeric = (chr(val + 97)).capitalize()
|
||||||
else:
|
else:
|
||||||
@@ -823,9 +717,7 @@ class RtLamniMotor(Device, PositionerBase):
|
|||||||
return super().stop(success=success)
|
return super().stop(success=success)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__": # pragma: no cover
|
||||||
logging.basicConfig(level=logging.DEBUG)
|
|
||||||
|
|
||||||
mock = False
|
mock = False
|
||||||
if not mock:
|
if not mock:
|
||||||
rty = RtLamniMotor("B", name="rty", host="mpc2680.psi.ch", port=3333, sign=1)
|
rty = RtLamniMotor("B", name="rty", host="mpc2680.psi.ch", port=3333, sign=1)
|
||||||
140
csaxs_bec/devices/omny/rt/rt_ophyd.py
Normal file
140
csaxs_bec/devices/omny/rt/rt_ophyd.py
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
"""
|
||||||
|
This module contains base signals for RT devices. Controller and motors are implemented in the
|
||||||
|
bespoke modules such as `rt_flomni_ophyd.py` or `rt_lamni_ophyd.py`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import functools
|
||||||
|
import time
|
||||||
|
|
||||||
|
from bec_lib import bec_logger
|
||||||
|
from ophyd.utils import ReadOnlyError
|
||||||
|
from ophyd_devices.utils.controller import ControllerCommunicationError, threadlocked
|
||||||
|
from ophyd_devices.utils.socket import SocketSignal
|
||||||
|
|
||||||
|
logger = bec_logger.logger
|
||||||
|
|
||||||
|
|
||||||
|
class RtCommunicationError(ControllerCommunicationError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class RtError(ControllerCommunicationError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class BECConfigError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def retry_once(fcn):
|
||||||
|
"""Decorator to rerun a function in case a CommunicationError was raised. This may happen if the buffer was not empty."""
|
||||||
|
|
||||||
|
@functools.wraps(fcn)
|
||||||
|
def wrapper(self, *args, **kwargs):
|
||||||
|
try:
|
||||||
|
val = fcn(self, *args, **kwargs)
|
||||||
|
except (RtCommunicationError, RtError):
|
||||||
|
val = fcn(self, *args, **kwargs)
|
||||||
|
return val
|
||||||
|
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
|
class RtSignalBase(SocketSignal):
|
||||||
|
def __init__(self, signal_name, **kwargs):
|
||||||
|
self.signal_name = signal_name
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
self.controller = self.parent.controller
|
||||||
|
self.sock = self.parent.controller.sock
|
||||||
|
|
||||||
|
|
||||||
|
class RtSignalRO(RtSignalBase):
|
||||||
|
def __init__(self, signal_name, **kwargs):
|
||||||
|
super().__init__(signal_name, **kwargs)
|
||||||
|
self._metadata["write_access"] = False
|
||||||
|
|
||||||
|
def _socket_set(self, val):
|
||||||
|
raise ReadOnlyError("Read-only signals cannot be set")
|
||||||
|
|
||||||
|
|
||||||
|
class RtReadbackSignal(RtSignalRO):
|
||||||
|
@retry_once
|
||||||
|
@threadlocked
|
||||||
|
def _socket_get(self) -> float:
|
||||||
|
"""Get command for the readback signal
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
float: Readback value after adjusting for sign and motor resolution.
|
||||||
|
"""
|
||||||
|
return_table = (self.controller.socket_put_and_receive("J4")).split(",")
|
||||||
|
if self.parent.axis_Id_numeric == 0:
|
||||||
|
readback_index = 2
|
||||||
|
elif self.parent.axis_Id_numeric == 1:
|
||||||
|
readback_index = 1
|
||||||
|
else:
|
||||||
|
raise RtError("Currently, only two axes are supported.")
|
||||||
|
|
||||||
|
current_pos = float(return_table[readback_index])
|
||||||
|
|
||||||
|
current_pos *= self.parent.sign
|
||||||
|
return current_pos
|
||||||
|
|
||||||
|
|
||||||
|
class RtSetpointSignal(RtSignalBase):
|
||||||
|
setpoint = 0
|
||||||
|
|
||||||
|
def _socket_get(self) -> float:
|
||||||
|
"""Get command for receiving the setpoint / target value.
|
||||||
|
The value is not pulled from the controller but instead just the last setpoint used.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
float: setpoint / target value
|
||||||
|
"""
|
||||||
|
return self.setpoint
|
||||||
|
|
||||||
|
@retry_once
|
||||||
|
@threadlocked
|
||||||
|
def _socket_set(self, val: float) -> None:
|
||||||
|
"""Set a new target value / setpoint value. Before submission, the target value is adjusted for the axis' sign.
|
||||||
|
Furthermore, it is ensured that all axes are referenced before a new setpoint is submitted.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
val (float): Target value / setpoint value
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
RtError: Raised if interferometer feedback is disabled.
|
||||||
|
|
||||||
|
"""
|
||||||
|
interferometer_feedback_not_running = int(
|
||||||
|
(self.controller.socket_put_and_receive("J2")).split(",")[0]
|
||||||
|
)
|
||||||
|
if interferometer_feedback_not_running != 0:
|
||||||
|
raise RtError(
|
||||||
|
"The interferometer feedback is not running. Either it is turned off or and interferometer error occured."
|
||||||
|
)
|
||||||
|
self.set_with_feedback_disabled(val)
|
||||||
|
|
||||||
|
def set_with_feedback_disabled(self, val):
|
||||||
|
target_val = val * self.parent.sign
|
||||||
|
self.setpoint = target_val
|
||||||
|
self.controller.socket_put(f"pa{self.parent.axis_Id_numeric},{target_val:.4f}")
|
||||||
|
|
||||||
|
|
||||||
|
class RtMotorIsMoving(RtSignalRO):
|
||||||
|
def _socket_get(self):
|
||||||
|
return self.controller.is_axis_moving(self.parent.axis_Id_numeric)
|
||||||
|
|
||||||
|
def get(self):
|
||||||
|
val = super().get()
|
||||||
|
if val is not None:
|
||||||
|
self._run_subs(sub_type=self.SUB_VALUE, value=val, timestamp=time.time())
|
||||||
|
return val
|
||||||
|
|
||||||
|
|
||||||
|
class RtFeedbackRunning(RtSignalRO):
|
||||||
|
@threadlocked
|
||||||
|
def _socket_get(self):
|
||||||
|
if int((self.controller.socket_put_and_receive("J2")).split(",")[0]) == 0:
|
||||||
|
return 1
|
||||||
|
else:
|
||||||
|
return 0
|
||||||
@@ -1,817 +0,0 @@
|
|||||||
import functools
|
|
||||||
import threading
|
|
||||||
import time
|
|
||||||
from typing import List
|
|
||||||
|
|
||||||
import numpy as np
|
|
||||||
from bec_lib import MessageEndpoints, bec_logger, messages
|
|
||||||
from ophyd import Component as Cpt
|
|
||||||
from ophyd import Device, PositionerBase, Signal
|
|
||||||
from ophyd.status import wait as status_wait
|
|
||||||
from ophyd.utils import LimitError, ReadOnlyError
|
|
||||||
from ophyd_devices.utils.controller import Controller, threadlocked
|
|
||||||
from ophyd_devices.utils.socket import SocketIO, SocketSignal, raise_if_disconnected
|
|
||||||
|
|
||||||
logger = bec_logger.logger
|
|
||||||
|
|
||||||
|
|
||||||
class RtCommunicationError(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class RtError(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class BECConfigError(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def retry_once(fcn):
|
|
||||||
"""Decorator to rerun a function in case a CommunicationError was raised. This may happen if the buffer was not empty."""
|
|
||||||
|
|
||||||
@functools.wraps(fcn)
|
|
||||||
def wrapper(self, *args, **kwargs):
|
|
||||||
try:
|
|
||||||
val = fcn(self, *args, **kwargs)
|
|
||||||
except (RtCommunicationError, RtError):
|
|
||||||
val = fcn(self, *args, **kwargs)
|
|
||||||
return val
|
|
||||||
|
|
||||||
return wrapper
|
|
||||||
|
|
||||||
|
|
||||||
class RtController(Controller):
|
|
||||||
_axes_per_controller = 3
|
|
||||||
USER_ACCESS = [
|
|
||||||
"socket_put_and_receive",
|
|
||||||
"set_rotation_angle",
|
|
||||||
"feedback_disable",
|
|
||||||
"feedback_enable_without_reset",
|
|
||||||
"feedback_disable_and_even_reset_lamni_angle_interferometer",
|
|
||||||
"feedback_enable_with_reset",
|
|
||||||
"add_pos_to_scan",
|
|
||||||
"clear_trajectory_generator",
|
|
||||||
"_set_axis_velocity",
|
|
||||||
"_set_axis_velocity_maximum_speed",
|
|
||||||
"_position_sampling_single_read",
|
|
||||||
"_position_sampling_single_reset_and_start_sampling",
|
|
||||||
]
|
|
||||||
|
|
||||||
def on(self, controller_num=0) -> None:
|
|
||||||
"""Open a new socket connection to the controller"""
|
|
||||||
# if not self.connected:
|
|
||||||
# try:
|
|
||||||
# self.sock.open()
|
|
||||||
# # discuss - after disconnect takes a while for the server to be ready again
|
|
||||||
# max_retries = 10
|
|
||||||
# tries = 0
|
|
||||||
# while not self.connected:
|
|
||||||
# try:
|
|
||||||
# welcome_message = self.sock.receive()
|
|
||||||
# self.connected = True
|
|
||||||
# except ConnectionResetError as conn_reset:
|
|
||||||
# if tries > max_retries:
|
|
||||||
# raise conn_reset
|
|
||||||
# tries += 1
|
|
||||||
# time.sleep(2)
|
|
||||||
# except ConnectionRefusedError as conn_error:
|
|
||||||
# logger.error("Failed to open a connection to RTLamNI.")
|
|
||||||
# raise RtCommunicationError from conn_error
|
|
||||||
|
|
||||||
# else:
|
|
||||||
# logger.info("The connection has already been established.")
|
|
||||||
# # warnings.warn(f"The connection has already been established.", stacklevel=2)
|
|
||||||
super().on()
|
|
||||||
# self._update_flyer_device_info()
|
|
||||||
|
|
||||||
def set_axis(self, axis: Device, axis_nr: int) -> None:
|
|
||||||
"""Assign an axis to a device instance.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
axis (Device): Device instance (e.g. GalilMotor)
|
|
||||||
axis_nr (int): Controller axis number
|
|
||||||
|
|
||||||
"""
|
|
||||||
self._axis[axis_nr] = axis
|
|
||||||
|
|
||||||
@threadlocked
|
|
||||||
def socket_put(self, val: str) -> None:
|
|
||||||
self.sock.put(f"{val}\n".encode())
|
|
||||||
|
|
||||||
@threadlocked
|
|
||||||
def socket_get(self) -> str:
|
|
||||||
return self.sock.receive().decode()
|
|
||||||
|
|
||||||
@retry_once
|
|
||||||
@threadlocked
|
|
||||||
def socket_put_and_receive(self, val: str, remove_trailing_chars=True) -> str:
|
|
||||||
self.socket_put(val)
|
|
||||||
if remove_trailing_chars:
|
|
||||||
return self._remove_trailing_characters(self.sock.receive().decode())
|
|
||||||
return self.socket_get()
|
|
||||||
|
|
||||||
def is_axis_moving(self, axis_Id) -> bool:
|
|
||||||
# this checks that axis is on target
|
|
||||||
axis_is_on_target = bool(float(self.socket_put_and_receive(f"o")))
|
|
||||||
return not axis_is_on_target
|
|
||||||
|
|
||||||
# def is_thread_active(self, thread_id: int) -> bool:
|
|
||||||
# val = float(self.socket_put_and_receive(f"MG_XQ{thread_id}"))
|
|
||||||
# if val == -1:
|
|
||||||
# return False
|
|
||||||
# return True
|
|
||||||
|
|
||||||
def _remove_trailing_characters(self, var) -> str:
|
|
||||||
if len(var) > 1:
|
|
||||||
return var.split("\r\n")[0]
|
|
||||||
return var
|
|
||||||
|
|
||||||
@threadlocked
|
|
||||||
def set_rotation_angle(self, val: float):
|
|
||||||
self.socket_put(f"a{(val-300+30.538)/180*np.pi}")
|
|
||||||
|
|
||||||
@threadlocked
|
|
||||||
def stop_all_axes(self):
|
|
||||||
self.socket_put("sc")
|
|
||||||
|
|
||||||
@threadlocked
|
|
||||||
def feedback_disable(self):
|
|
||||||
self.socket_put("J0")
|
|
||||||
logger.info("LamNI Feedback disabled.")
|
|
||||||
self.set_device_enabled("lsamx", True)
|
|
||||||
self.set_device_enabled("lsamy", True)
|
|
||||||
self.set_device_enabled("loptx", True)
|
|
||||||
self.set_device_enabled("lopty", True)
|
|
||||||
self.set_device_enabled("loptz", True)
|
|
||||||
|
|
||||||
@threadlocked
|
|
||||||
def _set_axis_velocity(self, um_per_s):
|
|
||||||
self.socket_put(f"V{um_per_s}")
|
|
||||||
|
|
||||||
@threadlocked
|
|
||||||
def _set_axis_velocity_maximum_speed(self):
|
|
||||||
self.socket_put(f"V0")
|
|
||||||
|
|
||||||
# for developement of soft continuous scanning
|
|
||||||
@threadlocked
|
|
||||||
def _position_sampling_single_reset_and_start_sampling(self):
|
|
||||||
self.socket_put(f"Ss")
|
|
||||||
|
|
||||||
@threadlocked
|
|
||||||
def _position_sampling_single_read(self):
|
|
||||||
(number_of_samples, sum0, sum0_2, sum1, sum1_2, sum2, sum2_2) = self.socket_put_and_receive(
|
|
||||||
f"Sr"
|
|
||||||
).split(",")
|
|
||||||
avg_x = float(sum1) / int(number_of_samples)
|
|
||||||
avg_y = float(sum0) / int(number_of_samples)
|
|
||||||
stdev_x = np.sqrt(
|
|
||||||
float(sum1_2) / int(number_of_samples)
|
|
||||||
- np.power(float(sum1) / int(number_of_samples), 2)
|
|
||||||
)
|
|
||||||
stdev_y = np.sqrt(
|
|
||||||
float(sum0_2) / int(number_of_samples)
|
|
||||||
- np.power(float(sum0) / int(number_of_samples), 2)
|
|
||||||
)
|
|
||||||
return (avg_x, avg_y, stdev_x, stdev_y)
|
|
||||||
|
|
||||||
@threadlocked
|
|
||||||
def feedback_enable_without_reset(self):
|
|
||||||
# read current interferometer position
|
|
||||||
return_table = (self.socket_put_and_receive(f"J4")).split(",")
|
|
||||||
x_curr = float(return_table[2])
|
|
||||||
y_curr = float(return_table[1])
|
|
||||||
# set these as closed loop target position
|
|
||||||
self.socket_put(f"pa0,{x_curr:.4f}")
|
|
||||||
self.socket_put(f"pa1,{y_curr:.4f}")
|
|
||||||
self.get_device_manager().devices.rtx.obj.user_setpoint.set_with_feedback_disabled(x_curr)
|
|
||||||
self.get_device_manager().devices.rty.obj.user_setpoint.set_with_feedback_disabled(y_curr)
|
|
||||||
self.socket_put("J5")
|
|
||||||
logger.info("LamNI Feedback enabled (without reset).")
|
|
||||||
self.set_device_enabled("lsamx", False)
|
|
||||||
self.set_device_enabled("lsamy", False)
|
|
||||||
self.set_device_enabled("loptx", False)
|
|
||||||
self.set_device_enabled("lopty", False)
|
|
||||||
self.set_device_enabled("loptz", False)
|
|
||||||
|
|
||||||
@threadlocked
|
|
||||||
def feedback_disable_and_even_reset_lamni_angle_interferometer(self):
|
|
||||||
self.socket_put("J6")
|
|
||||||
logger.info("LamNI Feedback disabled including the angular interferometer.")
|
|
||||||
self.set_device_enabled("lsamx", True)
|
|
||||||
self.set_device_enabled("lsamy", True)
|
|
||||||
self.set_device_enabled("loptx", True)
|
|
||||||
self.set_device_enabled("lopty", True)
|
|
||||||
self.set_device_enabled("loptz", True)
|
|
||||||
|
|
||||||
def get_device_manager(self):
|
|
||||||
for axis in self._axis:
|
|
||||||
if hasattr(axis, "device_manager") and axis.device_manager:
|
|
||||||
return axis.device_manager
|
|
||||||
raise BECConfigError("Could not access the device_manager")
|
|
||||||
|
|
||||||
def get_axis_by_name(self, name):
|
|
||||||
for axis in self._axis:
|
|
||||||
if axis:
|
|
||||||
if axis.name == name:
|
|
||||||
return axis
|
|
||||||
raise RuntimeError(f"Could not find an axis with name {name}")
|
|
||||||
|
|
||||||
@threadlocked
|
|
||||||
def clear_trajectory_generator(self):
|
|
||||||
self.socket_put("sc")
|
|
||||||
logger.info("LamNI scan stopped and deleted, moving to start position")
|
|
||||||
|
|
||||||
def add_pos_to_scan(self, positions) -> None:
|
|
||||||
def send_positions(parent, positions):
|
|
||||||
parent._min_scan_buffer_reached = False
|
|
||||||
for pos_index, pos in enumerate(positions):
|
|
||||||
parent.socket_put_and_receive(f"s{pos[0]},{pos[1]},0")
|
|
||||||
if pos_index > 100:
|
|
||||||
parent._min_scan_buffer_reached = True
|
|
||||||
parent._min_scan_buffer_reached = True
|
|
||||||
|
|
||||||
threading.Thread(target=send_positions, args=(self, positions), daemon=True).start()
|
|
||||||
|
|
||||||
@retry_once
|
|
||||||
@threadlocked
|
|
||||||
def get_scan_status(self):
|
|
||||||
return_table = (self.socket_put_and_receive(f"sr")).split(",")
|
|
||||||
if len(return_table) != 3:
|
|
||||||
raise RtCommunicationError(
|
|
||||||
f"Expected to receive 3 return values. Instead received {return_table}"
|
|
||||||
)
|
|
||||||
mode = int(return_table[0])
|
|
||||||
# mode 0: direct positioning
|
|
||||||
# mode 1: running internal timer (not tested/used anymore)
|
|
||||||
# mode 2: rt point scan running
|
|
||||||
# mode 3: rt point scan starting
|
|
||||||
# mode 5/6: rt continuous scanning (not available in LamNI)
|
|
||||||
number_of_positions_planned = int(return_table[1])
|
|
||||||
current_position_in_scan = int(return_table[2])
|
|
||||||
return (mode, number_of_positions_planned, current_position_in_scan)
|
|
||||||
|
|
||||||
@threadlocked
|
|
||||||
def start_scan(self):
|
|
||||||
interferometer_feedback_not_running = int((self.socket_put_and_receive("J2")).split(",")[0])
|
|
||||||
if interferometer_feedback_not_running == 1:
|
|
||||||
logger.error(
|
|
||||||
"Cannot start scan because feedback loop is not running or there is an interferometer error."
|
|
||||||
)
|
|
||||||
raise RtError(
|
|
||||||
"Cannot start scan because feedback loop is not running or there is an interferometer error."
|
|
||||||
)
|
|
||||||
# here exception
|
|
||||||
(mode, number_of_positions_planned, current_position_in_scan) = self.get_scan_status()
|
|
||||||
|
|
||||||
if number_of_positions_planned == 0:
|
|
||||||
logger.error("Cannot start scan because no target positions are planned.")
|
|
||||||
raise RtError("Cannot start scan because no target positions are planned.")
|
|
||||||
# hier exception
|
|
||||||
# start a point-by-point scan (for cont scan in flomni it would be "sa")
|
|
||||||
self.socket_put_and_receive("sd")
|
|
||||||
|
|
||||||
def start_readout(self):
|
|
||||||
readout = threading.Thread(target=self.read_positions_from_sampler)
|
|
||||||
readout.start()
|
|
||||||
|
|
||||||
def _update_flyer_device_info(self):
|
|
||||||
flyer_info = self._get_flyer_device_info()
|
|
||||||
self.get_device_manager().connector.set(
|
|
||||||
MessageEndpoints.device_info("rt_scan"),
|
|
||||||
messages.DeviceInfoMessage(device="rt_scan", info=flyer_info).dumps(),
|
|
||||||
)
|
|
||||||
|
|
||||||
def _get_flyer_device_info(self) -> dict:
|
|
||||||
return {
|
|
||||||
"device_name": self.name,
|
|
||||||
"device_attr_name": getattr(self, "attr_name", ""),
|
|
||||||
"device_dotted_name": getattr(self, "dotted_name", ""),
|
|
||||||
"device_info": {
|
|
||||||
"device_base_class": "ophydobject",
|
|
||||||
"signals": [],
|
|
||||||
"hints": {"fields": ["average_x_st_fzp", "average_y_st_fzp"]},
|
|
||||||
"describe": {},
|
|
||||||
"describe_configuration": {},
|
|
||||||
"sub_devices": [],
|
|
||||||
"custom_user_access": [],
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
def kickoff(self, metadata):
|
|
||||||
self.readout_metadata = metadata
|
|
||||||
while not self._min_scan_buffer_reached:
|
|
||||||
time.sleep(0.001)
|
|
||||||
self.start_scan()
|
|
||||||
time.sleep(0.1)
|
|
||||||
self.start_readout()
|
|
||||||
|
|
||||||
def _get_signals_from_table(self, return_table) -> dict:
|
|
||||||
self.average_stdeviations_x_st_fzp += float(return_table[5])
|
|
||||||
self.average_stdeviations_y_st_fzp += float(return_table[8])
|
|
||||||
self.average_lamni_angle += float(return_table[19])
|
|
||||||
signals = {
|
|
||||||
"target_x": {"value": float(return_table[3])},
|
|
||||||
"average_x_st_fzp": {"value": float(return_table[4])},
|
|
||||||
"stdev_x_st_fzp": {"value": float(return_table[5])},
|
|
||||||
"target_y": {"value": float(return_table[6])},
|
|
||||||
"average_y_st_fzp": {"value": float(return_table[7])},
|
|
||||||
"stdev_y_st_fzp": {"value": float(return_table[8])},
|
|
||||||
"average_cap1": {"value": float(return_table[9])},
|
|
||||||
"stdev_cap1": {"value": float(return_table[10])},
|
|
||||||
"average_cap2": {"value": float(return_table[11])},
|
|
||||||
"stdev_cap2": {"value": float(return_table[12])},
|
|
||||||
"average_cap3": {"value": float(return_table[13])},
|
|
||||||
"stdev_cap3": {"value": float(return_table[14])},
|
|
||||||
"average_cap4": {"value": float(return_table[15])},
|
|
||||||
"stdev_cap4": {"value": float(return_table[16])},
|
|
||||||
"average_cap5": {"value": float(return_table[17])},
|
|
||||||
"stdev_cap5": {"value": float(return_table[18])},
|
|
||||||
"average_angle_interf_ST": {"value": float(return_table[19])},
|
|
||||||
"stdev_angle_interf_ST": {"value": float(return_table[20])},
|
|
||||||
"average_stdeviations_x_st_fzp": {
|
|
||||||
"value": self.average_stdeviations_x_st_fzp / (int(return_table[0]) + 1)
|
|
||||||
},
|
|
||||||
"average_stdeviations_y_st_fzp": {
|
|
||||||
"value": self.average_stdeviations_y_st_fzp / (int(return_table[0]) + 1)
|
|
||||||
},
|
|
||||||
"average_lamni_angle": {"value": self.average_lamni_angle / (int(return_table[0]) + 1)},
|
|
||||||
}
|
|
||||||
return signals
|
|
||||||
|
|
||||||
def read_positions_from_sampler(self):
|
|
||||||
# this was for reading after the scan completed
|
|
||||||
number_of_samples_to_read = 1 # self.get_scan_status()[1] #number of valid samples, will be updated upon first data read
|
|
||||||
|
|
||||||
read_counter = 0
|
|
||||||
previous_point_in_scan = 0
|
|
||||||
|
|
||||||
self.average_stdeviations_x_st_fzp = 0
|
|
||||||
self.average_stdeviations_y_st_fzp = 0
|
|
||||||
self.average_lamni_angle = 0
|
|
||||||
|
|
||||||
mode, number_of_positions_planned, current_position_in_scan = self.get_scan_status()
|
|
||||||
|
|
||||||
# if not (mode==2 or mode==3):
|
|
||||||
# error
|
|
||||||
self.get_device_manager().connector.set(
|
|
||||||
MessageEndpoints.device_status("rt_scan"),
|
|
||||||
messages.DeviceStatusMessage(
|
|
||||||
device="rt_scan", status=1, metadata=self.readout_metadata
|
|
||||||
).dumps(),
|
|
||||||
)
|
|
||||||
# while scan is running
|
|
||||||
while mode > 0:
|
|
||||||
# logger.info(f"Current scan position {current_position_in_scan} out of {number_of_positions_planned}")
|
|
||||||
mode, number_of_positions_planned, current_position_in_scan = self.get_scan_status()
|
|
||||||
time.sleep(0.01)
|
|
||||||
if current_position_in_scan > 5:
|
|
||||||
while current_position_in_scan > read_counter + 1:
|
|
||||||
return_table = (self.socket_put_and_receive(f"r{read_counter}")).split(",")
|
|
||||||
# logger.info(f"{return_table}")
|
|
||||||
logger.info(f"Read {read_counter} out of {number_of_positions_planned}")
|
|
||||||
|
|
||||||
read_counter = read_counter + 1
|
|
||||||
|
|
||||||
signals = self._get_signals_from_table(return_table)
|
|
||||||
|
|
||||||
self.publish_device_data(signals=signals, point_id=int(return_table[0]))
|
|
||||||
|
|
||||||
time.sleep(0.05)
|
|
||||||
|
|
||||||
# read the last samples even though scan is finished already
|
|
||||||
while number_of_positions_planned > read_counter:
|
|
||||||
return_table = (self.socket_put_and_receive(f"r{read_counter}")).split(",")
|
|
||||||
logger.info(f"Read {read_counter} out of {number_of_positions_planned}")
|
|
||||||
# logger.info(f"{return_table}")
|
|
||||||
read_counter = read_counter + 1
|
|
||||||
|
|
||||||
signals = self._get_signals_from_table(return_table)
|
|
||||||
self.publish_device_data(signals=signals, point_id=int(return_table[0]))
|
|
||||||
|
|
||||||
self.get_device_manager().connector.set(
|
|
||||||
MessageEndpoints.device_status("rt_scan"),
|
|
||||||
messages.DeviceStatusMessage(
|
|
||||||
device="rt_scan", status=0, metadata=self.readout_metadata
|
|
||||||
).dumps(),
|
|
||||||
)
|
|
||||||
|
|
||||||
logger.info(
|
|
||||||
f"LamNI statistics: Average of all standard deviations: x {self.average_stdeviations_x_st_fzp/number_of_samples_to_read}, y {self.average_stdeviations_y_st_fzp/number_of_samples_to_read}, angle {self.average_lamni_angle/number_of_samples_to_read}."
|
|
||||||
)
|
|
||||||
|
|
||||||
def publish_device_data(self, signals, point_id):
|
|
||||||
self.get_device_manager().connector.set_and_publish(
|
|
||||||
MessageEndpoints.device_read("rt_lamni"),
|
|
||||||
messages.DeviceMessage(
|
|
||||||
signals=signals, metadata={"point_id": point_id, **self.readout_metadata}
|
|
||||||
).dumps(),
|
|
||||||
)
|
|
||||||
|
|
||||||
def feedback_status_angle_lamni(self) -> bool:
|
|
||||||
return_table = (self.socket_put_and_receive(f"J7")).split(",")
|
|
||||||
logger.debug(
|
|
||||||
f"LamNI angle interferomter status {bool(return_table[0])}, position {float(return_table[1])}, signal {float(return_table[2])}"
|
|
||||||
)
|
|
||||||
return bool(return_table[0])
|
|
||||||
|
|
||||||
def feedback_enable_with_reset(self):
|
|
||||||
if not self.feedback_status_angle_lamni():
|
|
||||||
self.feedback_disable_and_even_reset_lamni_angle_interferometer()
|
|
||||||
logger.info(f"LamNI resetting interferometer inclusive angular interferomter.")
|
|
||||||
else:
|
|
||||||
self.feedback_disable()
|
|
||||||
logger.info(
|
|
||||||
f"LamNI resetting interferomter except angular interferometer which is already running."
|
|
||||||
)
|
|
||||||
|
|
||||||
# set these as closed loop target position
|
|
||||||
|
|
||||||
self.socket_put(f"pa0,0")
|
|
||||||
self.get_axis_by_name("rtx").user_setpoint.setpoint = 0
|
|
||||||
self.socket_put(f"pa1,0")
|
|
||||||
self.get_axis_by_name("rty").user_setpoint.setpoint = 0
|
|
||||||
self.socket_put(
|
|
||||||
f"pa2,0"
|
|
||||||
) # we set all three outputs of the traj. gen. although in LamNI case only 0,1 are used
|
|
||||||
self.clear_trajectory_generator()
|
|
||||||
|
|
||||||
self.get_device_manager().devices.lsamrot.obj.move(0, wait=True)
|
|
||||||
|
|
||||||
galil_controller_rt_status = (
|
|
||||||
self.get_device_manager().devices.lsamx.obj.controller.lgalil_is_air_off_and_orchestra_enabled()
|
|
||||||
)
|
|
||||||
|
|
||||||
if galil_controller_rt_status == 0:
|
|
||||||
logger.error(
|
|
||||||
"Cannot enable feedback. The small rotation air is on and/or orchestra disabled by the motor controller."
|
|
||||||
)
|
|
||||||
raise RtError(
|
|
||||||
"Cannot enable feedback. The small rotation air is on and/or orchestra disabled by the motor controller."
|
|
||||||
)
|
|
||||||
|
|
||||||
time.sleep(0.03)
|
|
||||||
|
|
||||||
lsamx_user_params = self.get_device_manager().devices.lsamx.user_parameter
|
|
||||||
if lsamx_user_params is None or lsamx_user_params.get("center") is None:
|
|
||||||
raise RuntimeError("lsamx center is not defined")
|
|
||||||
lsamy_user_params = self.get_device_manager().devices.lsamy.user_parameter
|
|
||||||
if lsamy_user_params is None or lsamy_user_params.get("center") is None:
|
|
||||||
raise RuntimeError("lsamy center is not defined")
|
|
||||||
lsamx_center = lsamx_user_params.get("center")
|
|
||||||
lsamy_center = lsamy_user_params.get("center")
|
|
||||||
self.get_device_manager().devices.lsamx.obj.move(lsamx_center, wait=True)
|
|
||||||
self.get_device_manager().devices.lsamy.obj.move(lsamy_center, wait=True)
|
|
||||||
self.socket_put("J1")
|
|
||||||
|
|
||||||
_waitforfeedbackctr = 0
|
|
||||||
|
|
||||||
interferometer_feedback_not_running = int((self.socket_put_and_receive("J2")).split(",")[0])
|
|
||||||
|
|
||||||
while interferometer_feedback_not_running == 1 and _waitforfeedbackctr < 100:
|
|
||||||
time.sleep(0.01)
|
|
||||||
_waitforfeedbackctr = _waitforfeedbackctr + 1
|
|
||||||
interferometer_feedback_not_running = int(
|
|
||||||
(self.socket_put_and_receive("J2")).split(",")[0]
|
|
||||||
)
|
|
||||||
|
|
||||||
self.set_device_enabled("lsamx", False)
|
|
||||||
self.set_device_enabled("lsamy", False)
|
|
||||||
self.set_device_enabled("loptx", False)
|
|
||||||
self.set_device_enabled("lopty", False)
|
|
||||||
self.set_device_enabled("loptz", False)
|
|
||||||
|
|
||||||
if interferometer_feedback_not_running == 1:
|
|
||||||
logger.error(
|
|
||||||
"Cannot start scan because feedback loop is not running or there is an interferometer error."
|
|
||||||
)
|
|
||||||
raise RtError(
|
|
||||||
"Cannot start scan because feedback loop is not running or there is an interferometer error."
|
|
||||||
)
|
|
||||||
|
|
||||||
time.sleep(0.01)
|
|
||||||
|
|
||||||
# ptychography_alignment_done = 0
|
|
||||||
|
|
||||||
def set_device_enabled(self, device_name: str, enabled: bool) -> None:
|
|
||||||
"""enable / disable a device"""
|
|
||||||
if device_name not in self.get_device_manager().devices:
|
|
||||||
logger.warning(
|
|
||||||
f"Device {device_name} is not configured and cannot be enabled/disabled."
|
|
||||||
)
|
|
||||||
return
|
|
||||||
self.get_device_manager().devices[device_name].read_only = not enabled
|
|
||||||
|
|
||||||
|
|
||||||
class RtSignalBase(SocketSignal):
|
|
||||||
def __init__(self, signal_name, **kwargs):
|
|
||||||
self.signal_name = signal_name
|
|
||||||
super().__init__(**kwargs)
|
|
||||||
self.controller = self.parent.controller
|
|
||||||
self.sock = self.parent.controller.sock
|
|
||||||
|
|
||||||
|
|
||||||
class RtSignalRO(RtSignalBase):
|
|
||||||
def __init__(self, signal_name, **kwargs):
|
|
||||||
super().__init__(signal_name, **kwargs)
|
|
||||||
self._metadata["write_access"] = False
|
|
||||||
|
|
||||||
def _socket_set(self, val):
|
|
||||||
raise ReadOnlyError("Read-only signals cannot be set")
|
|
||||||
|
|
||||||
|
|
||||||
class RtReadbackSignal(RtSignalRO):
|
|
||||||
@retry_once
|
|
||||||
@threadlocked
|
|
||||||
def _socket_get(self) -> float:
|
|
||||||
"""Get command for the readback signal
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
float: Readback value after adjusting for sign and motor resolution.
|
|
||||||
"""
|
|
||||||
return_table = (self.controller.socket_put_and_receive(f"J4")).split(",")
|
|
||||||
print(return_table)
|
|
||||||
if self.parent.axis_Id_numeric == 0:
|
|
||||||
readback_index = 2
|
|
||||||
elif self.parent.axis_Id_numeric == 1:
|
|
||||||
readback_index = 1
|
|
||||||
else:
|
|
||||||
raise RtError("Currently, only two axes are supported.")
|
|
||||||
|
|
||||||
current_pos = float(return_table[readback_index])
|
|
||||||
|
|
||||||
current_pos *= self.parent.sign
|
|
||||||
return current_pos
|
|
||||||
|
|
||||||
|
|
||||||
class RtSetpointSignal(RtSignalBase):
|
|
||||||
setpoint = 0
|
|
||||||
|
|
||||||
def _socket_get(self) -> float:
|
|
||||||
"""Get command for receiving the setpoint / target value.
|
|
||||||
The value is not pulled from the controller but instead just the last setpoint used.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
float: setpoint / target value
|
|
||||||
"""
|
|
||||||
return self.setpoint
|
|
||||||
|
|
||||||
@retry_once
|
|
||||||
@threadlocked
|
|
||||||
def _socket_set(self, val: float) -> None:
|
|
||||||
"""Set a new target value / setpoint value. Before submission, the target value is adjusted for the axis' sign.
|
|
||||||
Furthermore, it is ensured that all axes are referenced before a new setpoint is submitted.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
val (float): Target value / setpoint value
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
RtError: Raised if interferometer feedback is disabled.
|
|
||||||
|
|
||||||
"""
|
|
||||||
interferometer_feedback_not_running = int(
|
|
||||||
(self.controller.socket_put_and_receive("J2")).split(",")[0]
|
|
||||||
)
|
|
||||||
if interferometer_feedback_not_running != 0:
|
|
||||||
raise RtError(
|
|
||||||
"The interferometer feedback is not running. Either it is turned off or and interferometer error occured."
|
|
||||||
)
|
|
||||||
self.set_with_feedback_disabled(val)
|
|
||||||
|
|
||||||
def set_with_feedback_disabled(self, val):
|
|
||||||
target_val = val * self.parent.sign
|
|
||||||
self.setpoint = target_val
|
|
||||||
self.controller.socket_put(f"pa{self.parent.axis_Id_numeric},{target_val:.4f}")
|
|
||||||
|
|
||||||
|
|
||||||
class RtMotorIsMoving(RtSignalRO):
|
|
||||||
def _socket_get(self):
|
|
||||||
return self.controller.is_axis_moving(self.parent.axis_Id_numeric)
|
|
||||||
|
|
||||||
def get(self):
|
|
||||||
val = super().get()
|
|
||||||
if val is not None:
|
|
||||||
self._run_subs(sub_type=self.SUB_VALUE, value=val, timestamp=time.time())
|
|
||||||
return val
|
|
||||||
|
|
||||||
|
|
||||||
class RtFeedbackRunning(RtSignalRO):
|
|
||||||
@threadlocked
|
|
||||||
def _socket_get(self):
|
|
||||||
if int((self.controller.socket_put_and_receive("J2")).split(",")[0]) == 0:
|
|
||||||
return 1
|
|
||||||
else:
|
|
||||||
return 0
|
|
||||||
|
|
||||||
|
|
||||||
class RtMotor(Device, PositionerBase):
|
|
||||||
USER_ACCESS = ["controller"]
|
|
||||||
readback = Cpt(RtReadbackSignal, signal_name="readback", kind="hinted")
|
|
||||||
user_setpoint = Cpt(RtSetpointSignal, signal_name="setpoint")
|
|
||||||
|
|
||||||
motor_is_moving = Cpt(RtMotorIsMoving, signal_name="motor_is_moving", kind="normal")
|
|
||||||
high_limit_travel = Cpt(Signal, value=0, kind="omitted")
|
|
||||||
low_limit_travel = Cpt(Signal, value=0, kind="omitted")
|
|
||||||
|
|
||||||
SUB_READBACK = "readback"
|
|
||||||
SUB_CONNECTION_CHANGE = "connection_change"
|
|
||||||
_default_sub = SUB_READBACK
|
|
||||||
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
axis_Id,
|
|
||||||
prefix="",
|
|
||||||
*,
|
|
||||||
name,
|
|
||||||
kind=None,
|
|
||||||
read_attrs=None,
|
|
||||||
configuration_attrs=None,
|
|
||||||
parent=None,
|
|
||||||
host="mpc2680.psi.ch",
|
|
||||||
port=3333,
|
|
||||||
sign=1,
|
|
||||||
socket_cls=SocketIO,
|
|
||||||
device_manager=None,
|
|
||||||
limits=None,
|
|
||||||
**kwargs,
|
|
||||||
):
|
|
||||||
self.axis_Id = axis_Id
|
|
||||||
self.sign = sign
|
|
||||||
self.controller = RtController(socket=socket_cls(host=host, port=port))
|
|
||||||
self.controller.set_axis(axis=self, axis_nr=self.axis_Id_numeric)
|
|
||||||
self.device_manager = device_manager
|
|
||||||
self.tolerance = kwargs.pop("tolerance", 0.5)
|
|
||||||
|
|
||||||
super().__init__(
|
|
||||||
prefix,
|
|
||||||
name=name,
|
|
||||||
kind=kind,
|
|
||||||
read_attrs=read_attrs,
|
|
||||||
configuration_attrs=configuration_attrs,
|
|
||||||
parent=parent,
|
|
||||||
**kwargs,
|
|
||||||
)
|
|
||||||
self.readback.name = self.name
|
|
||||||
self.controller.subscribe(
|
|
||||||
self._update_connection_state, event_type=self.SUB_CONNECTION_CHANGE
|
|
||||||
)
|
|
||||||
self._update_connection_state()
|
|
||||||
|
|
||||||
# self.readback.subscribe(self._forward_readback, event_type=self.readback.SUB_VALUE)
|
|
||||||
if limits is not None:
|
|
||||||
assert len(limits) == 2
|
|
||||||
self.low_limit_travel.put(limits[0])
|
|
||||||
self.high_limit_travel.put(limits[1])
|
|
||||||
|
|
||||||
@property
|
|
||||||
def limits(self):
|
|
||||||
return (self.low_limit_travel.get(), self.high_limit_travel.get())
|
|
||||||
|
|
||||||
@property
|
|
||||||
def low_limit(self):
|
|
||||||
return self.limits[0]
|
|
||||||
|
|
||||||
@property
|
|
||||||
def high_limit(self):
|
|
||||||
return self.limits[1]
|
|
||||||
|
|
||||||
def check_value(self, pos):
|
|
||||||
"""Check that the position is within the soft limits"""
|
|
||||||
low_limit, high_limit = self.limits
|
|
||||||
|
|
||||||
if low_limit < high_limit and not (low_limit <= pos <= high_limit):
|
|
||||||
raise LimitError(f"position={pos} not within limits {self.limits}")
|
|
||||||
|
|
||||||
def _update_connection_state(self, **kwargs):
|
|
||||||
for walk in self.walk_signals():
|
|
||||||
walk.item._metadata["connected"] = self.controller.connected
|
|
||||||
|
|
||||||
def _forward_readback(self, **kwargs):
|
|
||||||
kwargs.pop("sub_type")
|
|
||||||
self._run_subs(sub_type="readback", **kwargs)
|
|
||||||
|
|
||||||
@raise_if_disconnected
|
|
||||||
def move(self, position, wait=True, **kwargs):
|
|
||||||
"""Move to a specified position, optionally waiting for motion to
|
|
||||||
complete.
|
|
||||||
|
|
||||||
Parameters
|
|
||||||
----------
|
|
||||||
position
|
|
||||||
Position to move to
|
|
||||||
moved_cb : callable
|
|
||||||
Call this callback when movement has finished. This callback must
|
|
||||||
accept one keyword argument: 'obj' which will be set to this
|
|
||||||
positioner instance.
|
|
||||||
timeout : float, optional
|
|
||||||
Maximum time to wait for the motion. If None, the default timeout
|
|
||||||
for this positioner is used.
|
|
||||||
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
status : MoveStatus
|
|
||||||
|
|
||||||
Raises
|
|
||||||
------
|
|
||||||
TimeoutError
|
|
||||||
When motion takes longer than `timeout`
|
|
||||||
ValueError
|
|
||||||
On invalid positions
|
|
||||||
RuntimeError
|
|
||||||
If motion fails other than timing out
|
|
||||||
"""
|
|
||||||
self._started_moving = False
|
|
||||||
timeout = kwargs.pop("timeout", 100)
|
|
||||||
status = super().move(position, timeout=timeout, **kwargs)
|
|
||||||
self.user_setpoint.put(position, wait=False)
|
|
||||||
|
|
||||||
def move_and_finish():
|
|
||||||
while self.motor_is_moving.get():
|
|
||||||
print("motor is moving")
|
|
||||||
val = self.readback.read()
|
|
||||||
self._run_subs(sub_type=self.SUB_READBACK, value=val, timestamp=time.time())
|
|
||||||
time.sleep(0.01)
|
|
||||||
print("Move finished")
|
|
||||||
self._done_moving()
|
|
||||||
|
|
||||||
threading.Thread(target=move_and_finish, daemon=True).start()
|
|
||||||
try:
|
|
||||||
if wait:
|
|
||||||
status_wait(status)
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
self.stop()
|
|
||||||
raise
|
|
||||||
|
|
||||||
return status
|
|
||||||
|
|
||||||
@property
|
|
||||||
def axis_Id(self):
|
|
||||||
return self._axis_Id_alpha
|
|
||||||
|
|
||||||
@axis_Id.setter
|
|
||||||
def axis_Id(self, val):
|
|
||||||
if isinstance(val, str):
|
|
||||||
if len(val) != 1:
|
|
||||||
raise ValueError(f"Only single-character axis_Ids are supported.")
|
|
||||||
self._axis_Id_alpha = val
|
|
||||||
self._axis_Id_numeric = ord(val.lower()) - 97
|
|
||||||
else:
|
|
||||||
raise TypeError(f"Expected value of type str but received {type(val)}")
|
|
||||||
|
|
||||||
@property
|
|
||||||
def axis_Id_numeric(self):
|
|
||||||
return self._axis_Id_numeric
|
|
||||||
|
|
||||||
@axis_Id_numeric.setter
|
|
||||||
def axis_Id_numeric(self, val):
|
|
||||||
if isinstance(val, int):
|
|
||||||
if val > 26:
|
|
||||||
raise ValueError(f"Numeric value exceeds supported range.")
|
|
||||||
self._axis_Id_alpha = val
|
|
||||||
self._axis_Id_numeric = (chr(val + 97)).capitalize()
|
|
||||||
else:
|
|
||||||
raise TypeError(f"Expected value of type int but received {type(val)}")
|
|
||||||
|
|
||||||
def kickoff(self, metadata, **kwargs) -> None:
|
|
||||||
self.controller.kickoff(metadata)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def egu(self):
|
|
||||||
"""The engineering units (EGU) for positions"""
|
|
||||||
return "um"
|
|
||||||
|
|
||||||
# how is this used later?
|
|
||||||
|
|
||||||
def stage(self) -> List[object]:
|
|
||||||
return super().stage()
|
|
||||||
|
|
||||||
def unstage(self) -> List[object]:
|
|
||||||
return super().unstage()
|
|
||||||
|
|
||||||
def stop(self, *, success=False):
|
|
||||||
self.controller.stop_all_axes()
|
|
||||||
return super().stop(success=success)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
logging.basicConfig(level=logging.DEBUG)
|
|
||||||
|
|
||||||
mock = False
|
|
||||||
if not mock:
|
|
||||||
rty = RtLamniMotor("B", name="rty", host="mpc2680.psi.ch", port=3333, sign=1)
|
|
||||||
rty.stage()
|
|
||||||
status = rty.move(0, wait=True)
|
|
||||||
status = rty.move(10, wait=True)
|
|
||||||
rty.read()
|
|
||||||
|
|
||||||
rty.get()
|
|
||||||
rty.describe()
|
|
||||||
|
|
||||||
rty.unstage()
|
|
||||||
else:
|
|
||||||
from ophyd_devices.utils.socket import SocketMock
|
|
||||||
|
|
||||||
rtx = RtLamniMotor("A", name="rtx", host="mpc2680.psi.ch", port=3333, socket_cls=SocketMock)
|
|
||||||
rty = RtLamniMotor("B", name="rty", host="mpc2680.psi.ch", port=3333, socket_cls=SocketMock)
|
|
||||||
rtx.stage()
|
|
||||||
# rty.stage()
|
|
||||||
@@ -111,10 +111,6 @@ class SmaractController(Controller):
|
|||||||
def socket_put(self, val: str):
|
def socket_put(self, val: str):
|
||||||
self.sock.put(f":{val}\n".encode())
|
self.sock.put(f":{val}\n".encode())
|
||||||
|
|
||||||
@threadlocked
|
|
||||||
def socket_get(self):
|
|
||||||
return self.sock.receive().decode()
|
|
||||||
|
|
||||||
@threadlocked
|
@threadlocked
|
||||||
def socket_put_and_receive(
|
def socket_put_and_receive(
|
||||||
self, val: str, remove_trailing_chars=True, check_for_errors=True, raise_if_not_status=False
|
self, val: str, remove_trailing_chars=True, check_for_errors=True, raise_if_not_status=False
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from bec_lib import DeviceManagerBase
|
from bec_lib.devicemanager import DeviceManagerBase
|
||||||
from bec_server.file_writer.file_writer import HDF5Storage
|
from bec_server.file_writer.file_writer import HDF5Storage
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,8 @@ but they are executed in a specific order:
|
|||||||
import time
|
import time
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from bec_lib import MessageEndpoints, bec_logger
|
from bec_lib import bec_logger
|
||||||
|
from bec_lib.endpoints import MessageEndpoints
|
||||||
from bec_server.scan_server.errors import ScanAbortion
|
from bec_server.scan_server.errors import ScanAbortion
|
||||||
from bec_server.scan_server.scans import RequestBase, ScanArgType, ScanBase
|
from bec_server.scan_server.scans import RequestBase, ScanArgType, ScanBase
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,8 @@ but they are executed in a specific order:
|
|||||||
import time
|
import time
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from bec_lib import MessageEndpoints, bec_logger, messages
|
from bec_lib import bec_logger, messages
|
||||||
|
from bec_lib.endpoints import MessageEndpoints
|
||||||
from bec_server.scan_server.errors import ScanAbortion
|
from bec_server.scan_server.errors import ScanAbortion
|
||||||
from bec_server.scan_server.scans import SyncFlyScanBase
|
from bec_server.scan_server.scans import SyncFlyScanBase
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,8 @@ but they are executed in a specific order:
|
|||||||
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from bec_lib import MessageEndpoints, bec_logger
|
from bec_lib import bec_logger
|
||||||
|
from bec_lib.endpoints import MessageEndpoints
|
||||||
from bec_server.scan_server.scans import AsyncFlyScanBase, ScanAbortion
|
from bec_server.scan_server.scans import AsyncFlyScanBase, ScanAbortion
|
||||||
|
|
||||||
logger = bec_logger.logger
|
logger = bec_logger.logger
|
||||||
@@ -32,7 +33,7 @@ class OwisGrid(AsyncFlyScanBase):
|
|||||||
"""Owis-based grid scan."""
|
"""Owis-based grid scan."""
|
||||||
|
|
||||||
scan_name = "owis_grid"
|
scan_name = "owis_grid"
|
||||||
scan_report_hint = "scan_progress"
|
scan_report_hint = "device_progress"
|
||||||
required_kwargs = []
|
required_kwargs = []
|
||||||
arg_input = {}
|
arg_input = {}
|
||||||
arg_bundle_size = {"bundle": len(arg_input), "min": None, "max": None}
|
arg_bundle_size = {"bundle": len(arg_input), "min": None, "max": None}
|
||||||
@@ -153,11 +154,11 @@ class OwisGrid(AsyncFlyScanBase):
|
|||||||
if not self.scan_report_hint:
|
if not self.scan_report_hint:
|
||||||
yield None
|
yield None
|
||||||
return
|
return
|
||||||
yield from self.stubs.scan_report_instruction({"scan_progress": ["mcs"]})
|
yield from self.stubs.scan_report_instruction({"device_progress": ["mcs"]})
|
||||||
|
|
||||||
def pre_scan(self):
|
def pre_scan(self):
|
||||||
"""Pre scan instructions, move to start position"""
|
"""Pre scan instructions, move to start position"""
|
||||||
yield from self._move_and_wait([self.start_x, self.start_y])
|
yield from self._move_scan_motors_and_wait([self.start_x, self.start_y])
|
||||||
yield from self.stubs.pre_scan()
|
yield from self.stubs.pre_scan()
|
||||||
|
|
||||||
def scan_progress(self) -> int:
|
def scan_progress(self) -> int:
|
||||||
@@ -307,3 +308,11 @@ class OwisGrid(AsyncFlyScanBase):
|
|||||||
yield from self.stubs.send_rpc_and_wait("samy", "velocity.put", self.high_velocity)
|
yield from self.stubs.send_rpc_and_wait("samy", "velocity.put", self.high_velocity)
|
||||||
yield from self.stubs.send_rpc_and_wait("samy", "acceleration.put", self.high_acc_time)
|
yield from self.stubs.send_rpc_and_wait("samy", "acceleration.put", self.high_acc_time)
|
||||||
super().finalize()
|
super().finalize()
|
||||||
|
|
||||||
|
def _move_scan_motors_and_wait(self, pos):
|
||||||
|
# TODO: remove this method once BEC MR 637 is merged
|
||||||
|
# pylint: disable=no-member
|
||||||
|
if hasattr(super(), "_move_scan_motors_and_wait"):
|
||||||
|
yield from super()._move_scan_motors_and_wait(pos)
|
||||||
|
else:
|
||||||
|
yield from self._move_and_wait(pos)
|
||||||
|
|||||||
@@ -25,7 +25,8 @@ but they are executed in a specific order:
|
|||||||
|
|
||||||
# import numpy as np
|
# import numpy as np
|
||||||
|
|
||||||
# from bec_lib import MessageEndpoints, bec_logger, messages
|
# from bec_lib import bec_logger, messages
|
||||||
|
# from bec_lib.endpoints import MessageEndpoints
|
||||||
# from bec_server.scan_server.errors import ScanAbortion
|
# from bec_server.scan_server.errors import ScanAbortion
|
||||||
# from bec_server.scan_server.scans import FlyScanBase, RequestBase, ScanArgType, ScanBase
|
# from bec_server.scan_server.scans import FlyScanBase, RequestBase, ScanArgType, ScanBase
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,8 @@ but they are executed in a specific order:
|
|||||||
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from bec_lib import MessageEndpoints, bec_logger
|
from bec_lib import bec_logger
|
||||||
|
from bec_lib.endpoints import MessageEndpoints
|
||||||
from bec_server.scan_server.scans import AsyncFlyScanBase
|
from bec_server.scan_server.scans import AsyncFlyScanBase
|
||||||
|
|
||||||
logger = bec_logger.logger
|
logger = bec_logger.logger
|
||||||
@@ -30,7 +31,7 @@ logger = bec_logger.logger
|
|||||||
|
|
||||||
class SgalilGrid(AsyncFlyScanBase):
|
class SgalilGrid(AsyncFlyScanBase):
|
||||||
scan_name = "sgalil_grid"
|
scan_name = "sgalil_grid"
|
||||||
scan_report_hint = "scan_progress"
|
scan_report_hint = "device_progress"
|
||||||
required_kwargs = []
|
required_kwargs = []
|
||||||
arg_input = {}
|
arg_input = {}
|
||||||
arg_bundle_size = {"bundle": len(arg_input), "min": None, "max": None}
|
arg_bundle_size = {"bundle": len(arg_input), "min": None, "max": None}
|
||||||
@@ -96,10 +97,10 @@ class SgalilGrid(AsyncFlyScanBase):
|
|||||||
if not self.scan_report_hint:
|
if not self.scan_report_hint:
|
||||||
yield None
|
yield None
|
||||||
return
|
return
|
||||||
yield from self.stubs.scan_report_instruction({"scan_progress": ["mcs"]})
|
yield from self.stubs.scan_report_instruction({"device_progress": ["mcs"]})
|
||||||
|
|
||||||
def pre_scan(self):
|
def pre_scan(self):
|
||||||
yield from self._move_and_wait([self.start_x, self.start_y])
|
yield from self._move_scan_motors_and_wait([self.start_x, self.start_y])
|
||||||
yield from self.stubs.pre_scan()
|
yield from self.stubs.pre_scan()
|
||||||
# TODO move to start position
|
# TODO move to start position
|
||||||
|
|
||||||
@@ -214,3 +215,11 @@ class SgalilGrid(AsyncFlyScanBase):
|
|||||||
# logger.info('Testing Scan abortion, would have raised here!')
|
# logger.info('Testing Scan abortion, would have raised here!')
|
||||||
# except Exception as exc:
|
# except Exception as exc:
|
||||||
# logger.info(f'{exc}')
|
# logger.info(f'{exc}')
|
||||||
|
|
||||||
|
def _move_scan_motors_and_wait(self, pos):
|
||||||
|
# TODO: remove this method once BEC MR 637 is merged
|
||||||
|
# pylint: disable=no-member
|
||||||
|
if hasattr(super(), "_move_scan_motors_and_wait"):
|
||||||
|
yield from super()._move_scan_motors_and_wait(pos)
|
||||||
|
else:
|
||||||
|
yield from self._move_and_wait(pos)
|
||||||
|
|||||||
20
docs/Makefile
Normal file
20
docs/Makefile
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
# Minimal makefile for Sphinx documentation
|
||||||
|
#
|
||||||
|
|
||||||
|
# You can set these variables from the command line, and also
|
||||||
|
# from the environment for the first two.
|
||||||
|
SPHINXOPTS ?=
|
||||||
|
SPHINXBUILD ?= sphinx-build
|
||||||
|
SOURCEDIR = .
|
||||||
|
BUILDDIR = _build
|
||||||
|
|
||||||
|
# Put it first so that "make" without argument is like "make help".
|
||||||
|
help:
|
||||||
|
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||||
|
|
||||||
|
.PHONY: help Makefile
|
||||||
|
|
||||||
|
# Catch-all target: route all unknown targets to Sphinx using the new
|
||||||
|
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
||||||
|
%: Makefile
|
||||||
|
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||||
34
docs/_templates/custom-class-template.rst
vendored
Normal file
34
docs/_templates/custom-class-template.rst
vendored
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
{{ fullname | escape | underline}}
|
||||||
|
|
||||||
|
.. currentmodule:: {{ module }}
|
||||||
|
|
||||||
|
.. autoclass:: {{ objname }}
|
||||||
|
:members:
|
||||||
|
:show-inheritance:
|
||||||
|
:inherited-members:
|
||||||
|
:special-members: __call__, __add__, __mul__
|
||||||
|
|
||||||
|
{% block methods %}
|
||||||
|
{% if methods %}
|
||||||
|
.. rubric:: {{ _('Methods') }}
|
||||||
|
|
||||||
|
.. autosummary::
|
||||||
|
:nosignatures:
|
||||||
|
{% for item in methods %}
|
||||||
|
{%- if not item.startswith('_') %}
|
||||||
|
~{{ name }}.{{ item }}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- endfor %}
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block attributes %}
|
||||||
|
{% if attributes %}
|
||||||
|
.. rubric:: {{ _('Attributes') }}
|
||||||
|
|
||||||
|
.. autosummary::
|
||||||
|
{% for item in attributes %}
|
||||||
|
~{{ name }}.{{ item }}
|
||||||
|
{%- endfor %}
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
66
docs/_templates/custom-module-template.rst
vendored
Normal file
66
docs/_templates/custom-module-template.rst
vendored
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
{{ fullname | escape | underline}}
|
||||||
|
|
||||||
|
.. automodule:: {{ fullname }}
|
||||||
|
|
||||||
|
{% block attributes %}
|
||||||
|
{% if attributes %}
|
||||||
|
.. rubric:: Module attributes
|
||||||
|
|
||||||
|
.. autosummary::
|
||||||
|
:toctree:
|
||||||
|
{% for item in attributes %}
|
||||||
|
{{ item }}
|
||||||
|
{%- endfor %}
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block functions %}
|
||||||
|
{% if functions %}
|
||||||
|
.. rubric:: {{ _('Functions') }}
|
||||||
|
|
||||||
|
.. autosummary::
|
||||||
|
:toctree:
|
||||||
|
:nosignatures:
|
||||||
|
{% for item in functions %}
|
||||||
|
{{ item }}
|
||||||
|
{%- endfor %}
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block classes %}
|
||||||
|
{% if classes %}
|
||||||
|
.. rubric:: {{ _('Classes') }}
|
||||||
|
|
||||||
|
.. autosummary::
|
||||||
|
:toctree:
|
||||||
|
:template: custom-class-template.rst
|
||||||
|
:nosignatures:
|
||||||
|
{% for item in classes %}
|
||||||
|
{{ item }}
|
||||||
|
{%- endfor %}
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block exceptions %}
|
||||||
|
{% if exceptions %}
|
||||||
|
.. rubric:: {{ _('Exceptions') }}
|
||||||
|
|
||||||
|
.. autosummary::
|
||||||
|
:toctree:
|
||||||
|
{% for item in exceptions %}
|
||||||
|
{{ item }}
|
||||||
|
{%- endfor %}
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block modules %}
|
||||||
|
{% if modules %}
|
||||||
|
.. autosummary::
|
||||||
|
:toctree:
|
||||||
|
:template: custom-module-template.rst
|
||||||
|
:recursive:
|
||||||
|
{% for item in modules %}
|
||||||
|
{{ item }}
|
||||||
|
{%- endfor %}
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
81
docs/conf.py
Normal file
81
docs/conf.py
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
# Configuration file for the Sphinx documentation builder.
|
||||||
|
#
|
||||||
|
# For the full list of built-in configuration values, see the documentation:
|
||||||
|
# https://www.sphinx-doc.org/en/master/usage/configuration.html
|
||||||
|
|
||||||
|
# -- Project information -----------------------------------------------------
|
||||||
|
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
|
||||||
|
|
||||||
|
import os
|
||||||
|
import pathlib
|
||||||
|
|
||||||
|
import tomli
|
||||||
|
|
||||||
|
project = "cSAXS"
|
||||||
|
copyright = "2023, Paul Scherrer Institute"
|
||||||
|
author = "Paul Scherrer Institute"
|
||||||
|
|
||||||
|
# -- General configuration ---------------------------------------------------
|
||||||
|
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
|
||||||
|
|
||||||
|
current_path = pathlib.Path(__file__).parent.parent.resolve()
|
||||||
|
version_path = f"{current_path}/pyproject.toml"
|
||||||
|
|
||||||
|
|
||||||
|
def get_version():
|
||||||
|
"""load the version from the version file"""
|
||||||
|
with open(version_path, "r", encoding="utf-8") as file:
|
||||||
|
res = tomli.loads(file.read())
|
||||||
|
return res["project"]["version"]
|
||||||
|
|
||||||
|
|
||||||
|
release = get_version()
|
||||||
|
|
||||||
|
extensions = [
|
||||||
|
"sphinx.ext.autodoc",
|
||||||
|
"sphinx.ext.autosummary",
|
||||||
|
# "sphinx.ext.coverage",
|
||||||
|
"sphinx.ext.viewcode",
|
||||||
|
"sphinx.ext.napoleon",
|
||||||
|
"sphinx_toolbox.collapse",
|
||||||
|
"sphinx_copybutton",
|
||||||
|
"myst_parser",
|
||||||
|
"sphinx_design",
|
||||||
|
]
|
||||||
|
|
||||||
|
myst_enable_extensions = [
|
||||||
|
"amsmath",
|
||||||
|
"attrs_inline",
|
||||||
|
"colon_fence",
|
||||||
|
"deflist",
|
||||||
|
"dollarmath",
|
||||||
|
"fieldlist",
|
||||||
|
"html_admonition",
|
||||||
|
"html_image",
|
||||||
|
"replacements",
|
||||||
|
"smartquotes",
|
||||||
|
"strikethrough",
|
||||||
|
"substitution",
|
||||||
|
"tasklist",
|
||||||
|
]
|
||||||
|
|
||||||
|
autosummary_generate = True # Turn on sphinx.ext.autosummary
|
||||||
|
add_module_names = False # Remove namespaces from class/method signatures
|
||||||
|
autodoc_inherit_docstrings = True # If no docstring, inherit from base class
|
||||||
|
set_type_checking_flag = True # Enable 'expensive' imports for sphinx_autodoc_typehints
|
||||||
|
autoclass_content = "both" # Include both class docstring and __init__
|
||||||
|
|
||||||
|
# Add any paths that contain templates here, relative to this directory.
|
||||||
|
templates_path = ["_templates"]
|
||||||
|
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
|
||||||
|
|
||||||
|
language = "Python"
|
||||||
|
|
||||||
|
# -- Options for HTML output -------------------------------------------------
|
||||||
|
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
|
||||||
|
|
||||||
|
html_theme = "pydata_sphinx_theme"
|
||||||
|
html_static_path = ["_static"]
|
||||||
|
html_css_files = ["css/custom.css"]
|
||||||
|
html_logo = "_static/bec.png"
|
||||||
|
html_theme_options = {"show_nav_level": 1, "navbar_align": "content"}
|
||||||
11
docs/developer/developer.md
Normal file
11
docs/developer/developer.md
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
(developer)=
|
||||||
|
# Development
|
||||||
|
|
||||||
|
```{toctree}
|
||||||
|
---
|
||||||
|
maxdepth: 1
|
||||||
|
hidden: true
|
||||||
|
---
|
||||||
|
reference/
|
||||||
|
```
|
||||||
|
|
||||||
10
docs/developer/reference.md
Normal file
10
docs/developer/reference.md
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
## API Reference
|
||||||
|
|
||||||
|
```{eval-rst}
|
||||||
|
.. autosummary::
|
||||||
|
:toctree: _autosummary
|
||||||
|
:template: custom-module-template.rst
|
||||||
|
:recursive:
|
||||||
|
|
||||||
|
csaxs_bec
|
||||||
|
```
|
||||||
39
docs/index.md
Normal file
39
docs/index.md
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
# cSAXS documentation
|
||||||
|
|
||||||
|
<br><br>
|
||||||
|
|
||||||
|
````{grid} 3
|
||||||
|
:gutter: 5
|
||||||
|
|
||||||
|
```{grid-item-card} Introduction
|
||||||
|
:link: introduction
|
||||||
|
:link-type: ref
|
||||||
|
|
||||||
|
General information.
|
||||||
|
```
|
||||||
|
|
||||||
|
```{grid-item-card} User
|
||||||
|
:link: user
|
||||||
|
:link-type: ref
|
||||||
|
|
||||||
|
Information for users.
|
||||||
|
```
|
||||||
|
|
||||||
|
```{grid-item-card} Developer
|
||||||
|
:link: developer
|
||||||
|
:link-type: ref
|
||||||
|
|
||||||
|
Information for developers.
|
||||||
|
```
|
||||||
|
````
|
||||||
|
|
||||||
|
|
||||||
|
```{toctree}
|
||||||
|
---
|
||||||
|
numbered: true
|
||||||
|
maxdepth: 1
|
||||||
|
---
|
||||||
|
|
||||||
|
introduction/introduction
|
||||||
|
user/user
|
||||||
|
developer/developer
|
||||||
2
docs/introduction/introduction.md
Normal file
2
docs/introduction/introduction.md
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
(introduction)=
|
||||||
|
# Introduction
|
||||||
35
docs/make.bat
Normal file
35
docs/make.bat
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
@ECHO OFF
|
||||||
|
|
||||||
|
pushd %~dp0
|
||||||
|
|
||||||
|
REM Command file for Sphinx documentation
|
||||||
|
|
||||||
|
if "%SPHINXBUILD%" == "" (
|
||||||
|
set SPHINXBUILD=sphinx-build
|
||||||
|
)
|
||||||
|
set SOURCEDIR=.
|
||||||
|
set BUILDDIR=_build
|
||||||
|
|
||||||
|
%SPHINXBUILD% >NUL 2>NUL
|
||||||
|
if errorlevel 9009 (
|
||||||
|
echo.
|
||||||
|
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
|
||||||
|
echo.installed, then set the SPHINXBUILD environment variable to point
|
||||||
|
echo.to the full path of the 'sphinx-build' executable. Alternatively you
|
||||||
|
echo.may add the Sphinx directory to PATH.
|
||||||
|
echo.
|
||||||
|
echo.If you don't have Sphinx installed, grab it from
|
||||||
|
echo.https://www.sphinx-doc.org/
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "" goto help
|
||||||
|
|
||||||
|
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
||||||
|
goto end
|
||||||
|
|
||||||
|
:help
|
||||||
|
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
||||||
|
|
||||||
|
:end
|
||||||
|
popd
|
||||||
9
docs/requirements.txt
Normal file
9
docs/requirements.txt
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
sphinx
|
||||||
|
sphinx_copybutton
|
||||||
|
recommonmark
|
||||||
|
sphinx-toolbox
|
||||||
|
pydata-sphinx-theme
|
||||||
|
sphinx-copybutton
|
||||||
|
myst-parser
|
||||||
|
sphinx-design
|
||||||
|
tomli
|
||||||
2
docs/user/user.md
Normal file
2
docs/user/user.md
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
(user)=
|
||||||
|
# User
|
||||||
@@ -2,9 +2,9 @@
|
|||||||
from unittest import mock
|
from unittest import mock
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from ophyd_devices.epics.devices.psi_delay_generator_base import TriggerSource
|
from ophyd_devices.interfaces.base_classes.psi_delay_generator_base import TriggerSource
|
||||||
|
|
||||||
from csaxs_bec.devices.epics.devices.delay_generator_csaxs import DDGSetup
|
from csaxs_bec.devices.epics.delay_generator_csaxs import DDGSetup
|
||||||
|
|
||||||
|
|
||||||
def patch_dual_pvs(device):
|
def patch_dual_pvs(device):
|
||||||
|
|||||||
@@ -4,11 +4,12 @@ from unittest import mock
|
|||||||
|
|
||||||
import ophyd
|
import ophyd
|
||||||
import pytest
|
import pytest
|
||||||
from bec_lib import MessageEndpoints, messages
|
from bec_lib import messages
|
||||||
|
from bec_lib.endpoints import MessageEndpoints
|
||||||
from bec_server.device_server.tests.utils import DMMock
|
from bec_server.device_server.tests.utils import DMMock
|
||||||
from ophyd_devices.tests.utils import MockPV
|
from ophyd_devices.tests.utils import MockPV
|
||||||
|
|
||||||
from csaxs_bec.devices.epics.devices.eiger9m_csaxs import Eiger9McSAXS
|
from csaxs_bec.devices.epics.eiger9m_csaxs import Eiger9McSAXS
|
||||||
|
|
||||||
|
|
||||||
def patch_dual_pvs(device):
|
def patch_dual_pvs(device):
|
||||||
@@ -29,9 +30,9 @@ def mock_det():
|
|||||||
dm = DMMock()
|
dm = DMMock()
|
||||||
with mock.patch.object(dm, "connector"):
|
with mock.patch.object(dm, "connector"):
|
||||||
with (
|
with (
|
||||||
mock.patch("ophyd_devices.epics.devices.psi_detector_base.FileWriter"),
|
mock.patch("ophyd_devices.interfaces.base_classes.psi_detector_base.FileWriter"),
|
||||||
mock.patch(
|
mock.patch(
|
||||||
"ophyd_devices.epics.devices.psi_detector_base.PSIDetectorBase._update_service_config"
|
"ophyd_devices.interfaces.base_classes.psi_detector_base.PSIDetectorBase._update_service_config"
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
with mock.patch.object(ophyd, "cl") as mock_cl:
|
with mock.patch.object(ophyd, "cl") as mock_cl:
|
||||||
@@ -53,22 +54,22 @@ def test_init():
|
|||||||
dm = DMMock()
|
dm = DMMock()
|
||||||
with mock.patch.object(dm, "connector"):
|
with mock.patch.object(dm, "connector"):
|
||||||
with (
|
with (
|
||||||
mock.patch("ophyd_devices.epics.devices.psi_detector_base.FileWriter"),
|
mock.patch("ophyd_devices.interfaces.base_classes.psi_detector_base.FileWriter"),
|
||||||
mock.patch(
|
mock.patch(
|
||||||
"ophyd_devices.epics.devices.psi_detector_base.PSIDetectorBase._update_service_config"
|
"ophyd_devices.interfaces.base_classes.psi_detector_base.PSIDetectorBase._update_service_config"
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
with mock.patch.object(ophyd, "cl") as mock_cl:
|
with mock.patch.object(ophyd, "cl") as mock_cl:
|
||||||
mock_cl.get_pv = MockPV
|
mock_cl.get_pv = MockPV
|
||||||
with (
|
with (
|
||||||
mock.patch(
|
mock.patch(
|
||||||
"csaxs_bec.devices.epics.devices.eiger9m_csaxs.Eiger9MSetup.initialize_default_parameter"
|
"csaxs_bec.devices.epics.eiger9m_csaxs.Eiger9MSetup.initialize_default_parameter"
|
||||||
) as mock_default,
|
) as mock_default,
|
||||||
mock.patch(
|
mock.patch(
|
||||||
"csaxs_bec.devices.epics.devices.eiger9m_csaxs.Eiger9MSetup.initialize_detector"
|
"csaxs_bec.devices.epics.eiger9m_csaxs.Eiger9MSetup.initialize_detector"
|
||||||
) as mock_init_det,
|
) as mock_init_det,
|
||||||
mock.patch(
|
mock.patch(
|
||||||
"csaxs_bec.devices.epics.devices.eiger9m_csaxs.Eiger9MSetup.initialize_detector_backend"
|
"csaxs_bec.devices.epics.eiger9m_csaxs.Eiger9MSetup.initialize_detector_backend"
|
||||||
) as mock_init_backend,
|
) as mock_init_backend,
|
||||||
):
|
):
|
||||||
Eiger9McSAXS(name=name, prefix=prefix, device_manager=dm, sim_mode=sim_mode)
|
Eiger9McSAXS(name=name, prefix=prefix, device_manager=dm, sim_mode=sim_mode)
|
||||||
@@ -146,7 +147,7 @@ def test_initialize_detector_backend(
|
|||||||
|
|
||||||
Validation upon checking set values in mocked std_daq instance
|
Validation upon checking set values in mocked std_daq instance
|
||||||
"""
|
"""
|
||||||
with mock.patch("csaxs_bec.devices.epics.devices.eiger9m_csaxs.StdDaqClient") as mock_std_daq:
|
with mock.patch("csaxs_bec.devices.epics.eiger9m_csaxs.StdDaqClient") as mock_std_daq:
|
||||||
instance = mock_std_daq.return_value
|
instance = mock_std_daq.return_value
|
||||||
instance.stop_writer.return_value = None
|
instance.stop_writer.return_value = None
|
||||||
instance.get_status.return_value = daq_status
|
instance.get_status.return_value = daq_status
|
||||||
|
|||||||
@@ -5,11 +5,12 @@ from unittest import mock
|
|||||||
|
|
||||||
import ophyd
|
import ophyd
|
||||||
import pytest
|
import pytest
|
||||||
from bec_lib import MessageEndpoints, messages
|
from bec_lib import messages
|
||||||
|
from bec_lib.endpoints import MessageEndpoints
|
||||||
from bec_server.device_server.tests.utils import DMMock
|
from bec_server.device_server.tests.utils import DMMock
|
||||||
from ophyd_devices.tests.utils import MockPV
|
from ophyd_devices.tests.utils import MockPV
|
||||||
|
|
||||||
from csaxs_bec.devices.epics.devices.falcon_csaxs import FalconcSAXS, FalconTimeoutError
|
from csaxs_bec.devices.epics.falcon_csaxs import FalconcSAXS, FalconTimeoutError
|
||||||
|
|
||||||
|
|
||||||
def patch_dual_pvs(device):
|
def patch_dual_pvs(device):
|
||||||
@@ -30,9 +31,11 @@ def mock_det():
|
|||||||
dm = DMMock()
|
dm = DMMock()
|
||||||
with mock.patch.object(dm, "connector"):
|
with mock.patch.object(dm, "connector"):
|
||||||
with (
|
with (
|
||||||
mock.patch("ophyd_devices.epics.devices.psi_detector_base.FileWriter") as filemixin,
|
|
||||||
mock.patch(
|
mock.patch(
|
||||||
"ophyd_devices.epics.devices.psi_detector_base.PSIDetectorBase._update_service_config"
|
"ophyd_devices.interfaces.base_classes.psi_detector_base.FileWriter"
|
||||||
|
) as filemixin,
|
||||||
|
mock.patch(
|
||||||
|
"ophyd_devices.interfaces.base_classes.psi_detector_base.PSIDetectorBase._update_service_config"
|
||||||
) as mock_service_config,
|
) as mock_service_config,
|
||||||
):
|
):
|
||||||
with mock.patch.object(ophyd, "cl") as mock_cl:
|
with mock.patch.object(ophyd, "cl") as mock_cl:
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ from unittest import mock
|
|||||||
import pytest
|
import pytest
|
||||||
from ophyd_devices.tests.utils import SocketMock
|
from ophyd_devices.tests.utils import SocketMock
|
||||||
|
|
||||||
from csaxs_bec.devices.galil.fupr_ophyd import FuprGalilController, FuprGalilMotor
|
from csaxs_bec.devices.omny.galil.fupr_ophyd import FuprGalilController, FuprGalilMotor
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
|
import copy
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from ophyd_devices.tests.utils import SocketMock
|
from ophyd_devices.tests.utils import SocketMock
|
||||||
|
|
||||||
from csaxs_bec.devices.galil.galil_ophyd import GalilController, GalilMotor
|
from csaxs_bec.devices.omny.galil.lgalil_ophyd import LamniGalilController, LamniGalilMotor
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="function")
|
@pytest.fixture(scope="function")
|
||||||
def leyey():
|
def leyey():
|
||||||
GalilController._reset_controller()
|
LamniGalilController._reset_controller()
|
||||||
leyey_motor = GalilMotor(
|
leyey_motor = LamniGalilMotor(
|
||||||
"H", name="leyey", host="mpc2680.psi.ch", port=8081, socket_cls=SocketMock
|
"H", name="leyey", host="mpc2680.psi.ch", port=8081, socket_cls=SocketMock
|
||||||
)
|
)
|
||||||
leyey_motor.controller.on()
|
leyey_motor.controller.on()
|
||||||
@@ -20,8 +21,8 @@ def leyey():
|
|||||||
|
|
||||||
@pytest.fixture(scope="function")
|
@pytest.fixture(scope="function")
|
||||||
def leyex():
|
def leyex():
|
||||||
GalilController._reset_controller()
|
LamniGalilController._reset_controller()
|
||||||
leyex_motor = GalilMotor(
|
leyex_motor = LamniGalilMotor(
|
||||||
"A", name="leyey", host="mpc2680.psi.ch", port=8081, socket_cls=SocketMock
|
"A", name="leyey", host="mpc2680.psi.ch", port=8081, socket_cls=SocketMock
|
||||||
)
|
)
|
||||||
leyex_motor.controller.on()
|
leyex_motor.controller.on()
|
||||||
@@ -60,7 +61,7 @@ def test_axis_get(leyey, pos, msg, sign):
|
|||||||
)
|
)
|
||||||
def test_axis_put(leyey, target_pos, socket_put_messages, socket_get_messages):
|
def test_axis_put(leyey, target_pos, socket_put_messages, socket_get_messages):
|
||||||
leyey.controller.sock.flush_buffer()
|
leyey.controller.sock.flush_buffer()
|
||||||
leyey.controller.sock.buffer_recv = socket_get_messages
|
leyey.controller.sock.buffer_recv = copy.deepcopy(socket_get_messages)
|
||||||
leyey.user_setpoint.put(target_pos)
|
leyey.user_setpoint.put(target_pos)
|
||||||
assert leyey.controller.sock.buffer_put == socket_put_messages
|
assert leyey.controller.sock.buffer_put == socket_put_messages
|
||||||
|
|
||||||
@@ -77,7 +78,7 @@ def test_axis_put(leyey, target_pos, socket_put_messages, socket_get_messages):
|
|||||||
b"XQ#NEWPAR\r",
|
b"XQ#NEWPAR\r",
|
||||||
b"XQ#FES\r",
|
b"XQ#FES\r",
|
||||||
b"MG_BGA\r",
|
b"MG_BGA\r",
|
||||||
b"MGbcklact[axis]\r",
|
b"MGbcklact[0]\r",
|
||||||
b"MG_XQ0\r",
|
b"MG_XQ0\r",
|
||||||
b"MG_XQ2\r",
|
b"MG_XQ2\r",
|
||||||
b"MG _LRA, _LFA\r",
|
b"MG _LRA, _LFA\r",
|
||||||
@@ -93,7 +94,7 @@ def test_axis_put(leyey, target_pos, socket_put_messages, socket_get_messages):
|
|||||||
b"XQ#NEWPAR\r",
|
b"XQ#NEWPAR\r",
|
||||||
b"XQ#FES\r",
|
b"XQ#FES\r",
|
||||||
b"MG_BGB\r",
|
b"MG_BGB\r",
|
||||||
b"MGbcklact[axis]\r",
|
b"MGbcklact[1]\r",
|
||||||
b"MG_XQ0\r",
|
b"MG_XQ0\r",
|
||||||
b"MG_XQ2\r",
|
b"MG_XQ2\r",
|
||||||
b"MG _LRB, _LFB\r",
|
b"MG _LRB, _LFB\r",
|
||||||
@@ -104,7 +105,7 @@ def test_axis_put(leyey, target_pos, socket_put_messages, socket_get_messages):
|
|||||||
)
|
)
|
||||||
def test_drive_axis_to_limit(leyex, axis_nr, direction, socket_put_messages, socket_get_messages):
|
def test_drive_axis_to_limit(leyex, axis_nr, direction, socket_put_messages, socket_get_messages):
|
||||||
leyex.controller.sock.flush_buffer()
|
leyex.controller.sock.flush_buffer()
|
||||||
leyex.controller.sock.buffer_recv = socket_get_messages
|
leyex.controller.sock.buffer_recv = copy.deepcopy(socket_get_messages)
|
||||||
leyex.controller.drive_axis_to_limit(axis_nr, direction)
|
leyex.controller.drive_axis_to_limit(axis_nr, direction)
|
||||||
assert leyex.controller.sock.buffer_put == socket_put_messages
|
assert leyex.controller.sock.buffer_put == socket_put_messages
|
||||||
|
|
||||||
@@ -119,7 +120,7 @@ def test_drive_axis_to_limit(leyex, axis_nr, direction, socket_put_messages, soc
|
|||||||
b"XQ#NEWPAR\r",
|
b"XQ#NEWPAR\r",
|
||||||
b"XQ#FRM\r",
|
b"XQ#FRM\r",
|
||||||
b"MG_BGA\r",
|
b"MG_BGA\r",
|
||||||
b"MGbcklact[axis]\r",
|
b"MGbcklact[0]\r",
|
||||||
b"MG_XQ0\r",
|
b"MG_XQ0\r",
|
||||||
b"MG_XQ2\r",
|
b"MG_XQ2\r",
|
||||||
b"MG axisref[0]\r",
|
b"MG axisref[0]\r",
|
||||||
@@ -133,7 +134,7 @@ def test_drive_axis_to_limit(leyex, axis_nr, direction, socket_put_messages, soc
|
|||||||
b"XQ#NEWPAR\r",
|
b"XQ#NEWPAR\r",
|
||||||
b"XQ#FRM\r",
|
b"XQ#FRM\r",
|
||||||
b"MG_BGB\r",
|
b"MG_BGB\r",
|
||||||
b"MGbcklact[axis]\r",
|
b"MGbcklact[1]\r",
|
||||||
b"MG_XQ0\r",
|
b"MG_XQ0\r",
|
||||||
b"MG_XQ2\r",
|
b"MG_XQ2\r",
|
||||||
b"MG axisref[1]\r",
|
b"MG axisref[1]\r",
|
||||||
@@ -144,6 +145,9 @@ def test_drive_axis_to_limit(leyex, axis_nr, direction, socket_put_messages, soc
|
|||||||
)
|
)
|
||||||
def test_find_reference(leyex, axis_nr, socket_put_messages, socket_get_messages):
|
def test_find_reference(leyex, axis_nr, socket_put_messages, socket_get_messages):
|
||||||
leyex.controller.sock.flush_buffer()
|
leyex.controller.sock.flush_buffer()
|
||||||
leyex.controller.sock.buffer_recv = socket_get_messages
|
leyex.controller.sock.buffer_recv = copy.deepcopy(socket_get_messages)
|
||||||
leyex.controller.find_reference(axis_nr)
|
try:
|
||||||
|
leyex.controller.find_reference(axis_nr)
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
assert leyex.controller.sock.buffer_put == socket_put_messages
|
assert leyex.controller.sock.buffer_put == socket_put_messages
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
from unittest import mock
|
import copy
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from ophyd_devices.tests.utils import SocketMock
|
from ophyd_devices.tests.utils import SocketMock
|
||||||
|
|
||||||
from csaxs_bec.devices.galil.fgalil_ophyd import FlomniGalilController, FlomniGalilMotor
|
from csaxs_bec.devices.omny.galil.fgalil_ophyd import FlomniGalilController, FlomniGalilMotor
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="function")
|
@pytest.fixture(scope="function")
|
||||||
@@ -60,7 +60,7 @@ def test_axis_get(leyey, pos, msg, sign):
|
|||||||
)
|
)
|
||||||
def test_axis_put(leyey, target_pos, socket_put_messages, socket_get_messages):
|
def test_axis_put(leyey, target_pos, socket_put_messages, socket_get_messages):
|
||||||
leyey.controller.sock.flush_buffer()
|
leyey.controller.sock.flush_buffer()
|
||||||
leyey.controller.sock.buffer_recv = socket_get_messages
|
leyey.controller.sock.buffer_recv = copy.deepcopy(socket_get_messages)
|
||||||
leyey.user_setpoint.put(target_pos)
|
leyey.user_setpoint.put(target_pos)
|
||||||
assert leyey.controller.sock.buffer_put == socket_put_messages
|
assert leyey.controller.sock.buffer_put == socket_put_messages
|
||||||
|
|
||||||
@@ -104,7 +104,7 @@ def test_axis_put(leyey, target_pos, socket_put_messages, socket_get_messages):
|
|||||||
)
|
)
|
||||||
def test_drive_axis_to_limit(leyex, axis_nr, direction, socket_put_messages, socket_get_messages):
|
def test_drive_axis_to_limit(leyex, axis_nr, direction, socket_put_messages, socket_get_messages):
|
||||||
leyex.controller.sock.flush_buffer()
|
leyex.controller.sock.flush_buffer()
|
||||||
leyex.controller.sock.buffer_recv = socket_get_messages
|
leyex.controller.sock.buffer_recv = copy.deepcopy(socket_get_messages)
|
||||||
leyex.controller.drive_axis_to_limit(axis_nr, direction)
|
leyex.controller.drive_axis_to_limit(axis_nr, direction)
|
||||||
assert leyex.controller.sock.buffer_put == socket_put_messages
|
assert leyex.controller.sock.buffer_put == socket_put_messages
|
||||||
|
|
||||||
@@ -144,7 +144,7 @@ def test_drive_axis_to_limit(leyex, axis_nr, direction, socket_put_messages, soc
|
|||||||
)
|
)
|
||||||
def test_find_reference(leyex, axis_nr, socket_put_messages, socket_get_messages):
|
def test_find_reference(leyex, axis_nr, socket_put_messages, socket_get_messages):
|
||||||
leyex.controller.sock.flush_buffer()
|
leyex.controller.sock.flush_buffer()
|
||||||
leyex.controller.sock.buffer_recv = socket_get_messages
|
leyex.controller.sock.buffer_recv = copy.deepcopy(socket_get_messages)
|
||||||
leyex.controller.find_reference(axis_nr)
|
leyex.controller.find_reference(axis_nr)
|
||||||
assert leyex.controller.sock.buffer_put == socket_put_messages
|
assert leyex.controller.sock.buffer_put == socket_put_messages
|
||||||
|
|
||||||
@@ -165,7 +165,7 @@ def test_fosaz_light_curtain_is_triggered(
|
|||||||
)
|
)
|
||||||
fosaz.controller.on()
|
fosaz.controller.on()
|
||||||
fosaz.controller.sock.flush_buffer()
|
fosaz.controller.sock.flush_buffer()
|
||||||
fosaz.controller.sock.buffer_recv = socket_get_messages
|
fosaz.controller.sock.buffer_recv = copy.deepcopy(socket_get_messages)
|
||||||
assert fosaz.controller.fosaz_light_curtain_is_triggered() == triggered
|
assert fosaz.controller.fosaz_light_curtain_is_triggered() == triggered
|
||||||
assert fosaz.controller.sock.buffer_put == socket_put_messages
|
assert fosaz.controller.sock.buffer_put == socket_put_messages
|
||||||
fosaz.controller.off()
|
fosaz.controller.off()
|
||||||
|
|||||||
@@ -4,11 +4,12 @@ from unittest import mock
|
|||||||
|
|
||||||
import ophyd
|
import ophyd
|
||||||
import pytest
|
import pytest
|
||||||
from bec_lib import MessageEndpoints, messages
|
from bec_lib import messages
|
||||||
|
from bec_lib.endpoints import MessageEndpoints
|
||||||
from bec_server.device_server.tests.utils import DMMock
|
from bec_server.device_server.tests.utils import DMMock
|
||||||
from ophyd_devices.tests.utils import MockPV
|
from ophyd_devices.tests.utils import MockPV
|
||||||
|
|
||||||
from csaxs_bec.devices.epics.devices.mcs_csaxs import (
|
from csaxs_bec.devices.epics.mcs_csaxs import (
|
||||||
MCScSAXS,
|
MCScSAXS,
|
||||||
MCSError,
|
MCSError,
|
||||||
MCSTimeoutError,
|
MCSTimeoutError,
|
||||||
@@ -35,9 +36,11 @@ def mock_det():
|
|||||||
dm = DMMock()
|
dm = DMMock()
|
||||||
with mock.patch.object(dm, "connector"):
|
with mock.patch.object(dm, "connector"):
|
||||||
with (
|
with (
|
||||||
mock.patch("ophyd_devices.epics.devices.psi_detector_base.FileWriter") as filemixin,
|
|
||||||
mock.patch(
|
mock.patch(
|
||||||
"ophyd_devices.epics.devices.psi_detector_base.PSIDetectorBase._update_service_config"
|
"ophyd_devices.interfaces.base_classes.psi_detector_base.FileWriter"
|
||||||
|
) as filemixin,
|
||||||
|
mock.patch(
|
||||||
|
"ophyd_devices.interfaces.base_classes.psi_detector_base.PSIDetectorBase._update_service_config"
|
||||||
) as mock_service_config,
|
) as mock_service_config,
|
||||||
):
|
):
|
||||||
with mock.patch.object(ophyd, "cl") as mock_cl:
|
with mock.patch.object(ophyd, "cl") as mock_cl:
|
||||||
@@ -57,22 +60,22 @@ def test_init():
|
|||||||
dm = DMMock()
|
dm = DMMock()
|
||||||
with mock.patch.object(dm, "connector"):
|
with mock.patch.object(dm, "connector"):
|
||||||
with (
|
with (
|
||||||
mock.patch("ophyd_devices.epics.devices.psi_detector_base.FileWriter"),
|
mock.patch("ophyd_devices.interfaces.base_classes.psi_detector_base.FileWriter"),
|
||||||
mock.patch(
|
mock.patch(
|
||||||
"ophyd_devices.epics.devices.psi_detector_base.PSIDetectorBase._update_service_config"
|
"ophyd_devices.interfaces.base_classes.psi_detector_base.PSIDetectorBase._update_service_config"
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
with mock.patch.object(ophyd, "cl") as mock_cl:
|
with mock.patch.object(ophyd, "cl") as mock_cl:
|
||||||
mock_cl.get_pv = MockPV
|
mock_cl.get_pv = MockPV
|
||||||
with (
|
with (
|
||||||
mock.patch(
|
mock.patch(
|
||||||
"csaxs_bec.devices.epics.devices.mcs_csaxs.MCSSetup.initialize_default_parameter"
|
"csaxs_bec.devices.epics.mcs_csaxs.MCSSetup.initialize_default_parameter"
|
||||||
) as mock_default,
|
) as mock_default,
|
||||||
mock.patch(
|
mock.patch(
|
||||||
"csaxs_bec.devices.epics.devices.mcs_csaxs.MCSSetup.initialize_detector"
|
"csaxs_bec.devices.epics.mcs_csaxs.MCSSetup.initialize_detector"
|
||||||
) as mock_init_det,
|
) as mock_init_det,
|
||||||
mock.patch(
|
mock.patch(
|
||||||
"csaxs_bec.devices.epics.devices.mcs_csaxs.MCSSetup.initialize_detector_backend"
|
"csaxs_bec.devices.epics.mcs_csaxs.MCSSetup.initialize_detector_backend"
|
||||||
) as mock_init_backend,
|
) as mock_init_backend,
|
||||||
):
|
):
|
||||||
MCScSAXS(name=name, prefix=prefix, device_manager=dm, sim_mode=sim_mode)
|
MCScSAXS(name=name, prefix=prefix, device_manager=dm, sim_mode=sim_mode)
|
||||||
@@ -172,7 +175,11 @@ def test_on_mca_data(mock_det, values, expected_nothing):
|
|||||||
[
|
[
|
||||||
(
|
(
|
||||||
{"scan_id": 123},
|
{"scan_id": 123},
|
||||||
{"mca1": [100, 120, 140], "mca3": [200, 220, 240], "mca4": [300, 320, 340]},
|
{
|
||||||
|
"mca1": {"value": [100, 120, 140]},
|
||||||
|
"mca3": {"value": [200, 220, 240]},
|
||||||
|
"mca4": {"value": [300, 320, 340]},
|
||||||
|
},
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import copy
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from csaxs_bec.devices.npoint import NPointAxis, NPointController
|
from csaxs_bec.devices.npoint import NPointAxis, NPointController
|
||||||
@@ -121,7 +123,12 @@ def test_set_axis_out_of_range():
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_hex_list_to_int(in_buffer, byteorder, signed, val):
|
def test_hex_list_to_int(in_buffer, byteorder, signed, val):
|
||||||
assert NPointController._hex_list_to_int(in_buffer, byteorder=byteorder, signed=signed) == val
|
assert (
|
||||||
|
NPointController._hex_list_to_int(
|
||||||
|
copy.deepcopy(in_buffer), byteorder=byteorder, signed=signed
|
||||||
|
)
|
||||||
|
== val
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
|
|||||||
@@ -5,11 +5,12 @@ from unittest import mock
|
|||||||
|
|
||||||
import ophyd
|
import ophyd
|
||||||
import pytest
|
import pytest
|
||||||
from bec_lib import MessageEndpoints, messages
|
from bec_lib import messages
|
||||||
|
from bec_lib.endpoints import MessageEndpoints
|
||||||
from bec_server.device_server.tests.utils import DMMock
|
from bec_server.device_server.tests.utils import DMMock
|
||||||
from ophyd_devices.tests.utils import MockPV
|
from ophyd_devices.tests.utils import MockPV
|
||||||
|
|
||||||
from csaxs_bec.devices.epics.devices.pilatus_csaxs import PilatuscSAXS
|
from csaxs_bec.devices.epics.pilatus_csaxs import PilatuscSAXS
|
||||||
|
|
||||||
|
|
||||||
def patch_dual_pvs(device):
|
def patch_dual_pvs(device):
|
||||||
@@ -30,9 +31,9 @@ def mock_det():
|
|||||||
dm = DMMock()
|
dm = DMMock()
|
||||||
with mock.patch.object(dm, "connector"):
|
with mock.patch.object(dm, "connector"):
|
||||||
with (
|
with (
|
||||||
mock.patch("ophyd_devices.epics.devices.psi_detector_base.FileWriter"),
|
mock.patch("ophyd_devices.interfaces.base_classes.psi_detector_base.FileWriter"),
|
||||||
mock.patch(
|
mock.patch(
|
||||||
"ophyd_devices.epics.devices.psi_detector_base.PSIDetectorBase._update_service_config"
|
"ophyd_devices.interfaces.base_classes.psi_detector_base.PSIDetectorBase._update_service_config"
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
with mock.patch.object(ophyd, "cl") as mock_cl:
|
with mock.patch.object(ophyd, "cl") as mock_cl:
|
||||||
|
|||||||
@@ -3,12 +3,13 @@ from unittest import mock
|
|||||||
import pytest
|
import pytest
|
||||||
from ophyd_devices.tests.utils import SocketMock
|
from ophyd_devices.tests.utils import SocketMock
|
||||||
|
|
||||||
from csaxs_bec.devices.rt_lamni import RtFlomniController, RtFlomniMotor
|
from csaxs_bec.devices.omny.rt import RtFlomniController, RtFlomniMotor
|
||||||
from csaxs_bec.devices.rt_lamni.rt_ophyd import RtError
|
from csaxs_bec.devices.omny.rt.rt_ophyd import RtError
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
def rt_flomni():
|
def rt_flomni():
|
||||||
|
RtFlomniController._reset_controller()
|
||||||
rt_flomni = RtFlomniController(
|
rt_flomni = RtFlomniController(
|
||||||
name="rt_flomni", socket_cls=SocketMock, socket_host="localhost", socket_port=8081
|
name="rt_flomni", socket_cls=SocketMock, socket_host="localhost", socket_port=8081
|
||||||
)
|
)
|
||||||
@@ -16,14 +17,21 @@ def rt_flomni():
|
|||||||
with mock.patch.object(rt_flomni, "sock"):
|
with mock.patch.object(rt_flomni, "sock"):
|
||||||
rtx = mock.MagicMock(spec=RtFlomniMotor)
|
rtx = mock.MagicMock(spec=RtFlomniMotor)
|
||||||
rtx.name = "rtx"
|
rtx.name = "rtx"
|
||||||
|
rtx.axis_Id = "A"
|
||||||
|
rtx.axis_Id_numeric = 0
|
||||||
rty = mock.MagicMock(spec=RtFlomniMotor)
|
rty = mock.MagicMock(spec=RtFlomniMotor)
|
||||||
rty.name = "rty"
|
rty.name = "rty"
|
||||||
|
rty.axis_Id = "B"
|
||||||
|
rty.axis_Id_numeric = 1
|
||||||
rtz = mock.MagicMock(spec=RtFlomniMotor)
|
rtz = mock.MagicMock(spec=RtFlomniMotor)
|
||||||
rtz.name = "rtz"
|
rtz.name = "rtz"
|
||||||
rt_flomni.set_axis(rtx, 0)
|
rtz.axis_Id = "C"
|
||||||
rt_flomni.set_axis(rty, 1)
|
rtz.axis_Id_numeric = 2
|
||||||
rt_flomni.set_axis(rtz, 2)
|
rt_flomni.set_axis(axis=rtx, axis_nr=0)
|
||||||
|
rt_flomni.set_axis(axis=rty, axis_nr=1)
|
||||||
|
rt_flomni.set_axis(axis=rtz, axis_nr=2)
|
||||||
yield rt_flomni
|
yield rt_flomni
|
||||||
|
RtFlomniController._reset_controller()
|
||||||
|
|
||||||
|
|
||||||
def test_rt_flomni_move_to_zero(rt_flomni):
|
def test_rt_flomni_move_to_zero(rt_flomni):
|
||||||
|
|||||||
Reference in New Issue
Block a user