WIP
This commit is contained in:
+11
-10
@@ -12,11 +12,11 @@ Standard bluesky interface:
|
|||||||
AerotechAbrStage.kickoff()
|
AerotechAbrStage.kickoff()
|
||||||
AerotechAbrStage.stop()
|
AerotechAbrStage.stop()
|
||||||
Additional bluesky functionality:
|
Additional bluesky functionality:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Aerotech.is_homed()
|
Aerotech.is_homed()
|
||||||
Aerotech.do_homing(wait=True)
|
Aerotech.do_homing(wait=True)
|
||||||
Aerotech.get_ready(ostart=None, orange=None, etime=None, wait=True)
|
Aerotech.get_ready(ostart=None, orange=None, etime=None, wait=True)
|
||||||
@@ -66,7 +66,6 @@ from bec_lib import bec_logger
|
|||||||
logger = bec_logger.logger
|
logger = bec_logger.logger
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# pylint: disable=logging-fstring-interpolation
|
# pylint: disable=logging-fstring-interpolation
|
||||||
class AerotechAbrMixin(CustomPrepare):
|
class AerotechAbrMixin(CustomPrepare):
|
||||||
"""Configuration class for the Aerotech A3200 controller for the ABR stage"""
|
"""Configuration class for the Aerotech A3200 controller for the ABR stage"""
|
||||||
@@ -84,7 +83,13 @@ class AerotechAbrMixin(CustomPrepare):
|
|||||||
scanargs = self.parent.scaninfo.scan_msg.info["kwargs"]
|
scanargs = self.parent.scaninfo.scan_msg.info["kwargs"]
|
||||||
scanname = self.parent.scaninfo.scan_msg.info["scan_name"]
|
scanname = self.parent.scaninfo.scan_msg.info["scan_name"]
|
||||||
|
|
||||||
if scanname in ("standardscan", "helicalscan", "helicalscan1", "helicalscan2", "helicalscan3"):
|
if scanname in (
|
||||||
|
"standardscan",
|
||||||
|
"helicalscan",
|
||||||
|
"helicalscan1",
|
||||||
|
"helicalscan2",
|
||||||
|
"helicalscan3",
|
||||||
|
):
|
||||||
d["scan_command"] = AbrCmd.MEASURE_STANDARD
|
d["scan_command"] = AbrCmd.MEASURE_STANDARD
|
||||||
d["var_1"] = scanargs["start"]
|
d["var_1"] = scanargs["start"]
|
||||||
d["var_2"] = scanargs["range"]
|
d["var_2"] = scanargs["range"]
|
||||||
@@ -295,9 +300,7 @@ class AerotechAbrStage(BECDeviceBase):
|
|||||||
return bool(value == 0)
|
return bool(value == 0)
|
||||||
|
|
||||||
# Subscribe and wait for update
|
# Subscribe and wait for update
|
||||||
status = SubscriptionStatus(
|
status = SubscriptionStatus(self.scan_done, is_busy, timeout=timeout, settle_time=0.1)
|
||||||
self.scan_done, is_busy, timeout=timeout, settle_time=0.1
|
|
||||||
)
|
|
||||||
status.wait()
|
status.wait()
|
||||||
# return status
|
# return status
|
||||||
|
|
||||||
@@ -321,9 +324,7 @@ class AerotechAbrStage(BECDeviceBase):
|
|||||||
|
|
||||||
# Subscribe and wait for update
|
# Subscribe and wait for update
|
||||||
# status = SubscriptionStatus(self.task1, is_idle, timeout=timeout, settle_time=0.5)
|
# status = SubscriptionStatus(self.task1, is_idle, timeout=timeout, settle_time=0.5)
|
||||||
status = SubscriptionStatus(
|
status = SubscriptionStatus(self.scan_done, is_idle, timeout=timeout, settle_time=0.5)
|
||||||
self.scan_done, is_idle, timeout=timeout, settle_time=0.5
|
|
||||||
)
|
|
||||||
return status
|
return status
|
||||||
|
|
||||||
def reset(self, settle_time=0.1, wait_after_reload=1) -> None:
|
def reset(self, settle_time=0.1, wait_after_reload=1) -> None:
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ class A3200Axis(PVPositioner):
|
|||||||
vmax = Component(Signal, kind=Kind.config)
|
vmax = Component(Signal, kind=Kind.config)
|
||||||
offset = Component(EpicsSignal, "-OFF", put_complete=True, kind=Kind.config)
|
offset = Component(EpicsSignal, "-OFF", put_complete=True, kind=Kind.config)
|
||||||
|
|
||||||
#pylint: disable=too-many-arguments
|
# pylint: disable=too-many-arguments
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
prefix="",
|
prefix="",
|
||||||
@@ -255,5 +255,5 @@ class A3200Axis(PVPositioner):
|
|||||||
|
|
||||||
# Automatically start an axis if directly invoked
|
# Automatically start an axis if directly invoked
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
omega = A3200Axis(prefix="X06DA-ES-DF1:OMEGA", base_pv='X06DA-ES', name="omega")
|
omega = A3200Axis(prefix="X06DA-ES-DF1:OMEGA", base_pv="X06DA-ES", name="omega")
|
||||||
omega.wait_for_connection()
|
omega.wait_for_connection()
|
||||||
|
|||||||
@@ -170,10 +170,10 @@ class SmarGonAxis(PVPositioner):
|
|||||||
self.__class__.__dict__["setpoint"].kwargs["high_limit"] = high_limit
|
self.__class__.__dict__["setpoint"].kwargs["high_limit"] = high_limit
|
||||||
self.__class__.__dict__["sg_url"].kwargs["value"] = sg_url
|
self.__class__.__dict__["sg_url"].kwargs["value"] = sg_url
|
||||||
# Fine-tune HTTP connection behavior
|
# Fine-tune HTTP connection behavior
|
||||||
# NOTE: SmarGon has a few failed requests every one in a while
|
# NOTE: SmarGon has a few failed requests every one in a while
|
||||||
self._s = requests.Session()
|
self._s = requests.Session()
|
||||||
retries = Retry(total=5, backoff_factor=0.05, status_forcelist=[ 500, 502, 503, 504 ])
|
retries = Retry(total=5, backoff_factor=0.05, status_forcelist=[500, 502, 503, 504])
|
||||||
self._s.mount('http://', HTTPAdapter(max_retries=retries))
|
self._s.mount("http://", HTTPAdapter(max_retries=retries))
|
||||||
|
|
||||||
super().__init__(
|
super().__init__(
|
||||||
prefix=prefix,
|
prefix=prefix,
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ class LimitedSmarGonSignal(Signal):
|
|||||||
if value > hil:
|
if value > hil:
|
||||||
raise ValueError(f"Target {value} outside of limits {self.limits}")
|
raise ValueError(f"Target {value} outside of limits {self.limits}")
|
||||||
|
|
||||||
def put(self, value, *, timestamp=None, force=False, metadata=None, **kwargs,):
|
def put(self, value, *, timestamp=None, force=False, metadata=None, **kwargs):
|
||||||
"""Overriden put to add communication with smargopolo"""
|
"""Overriden put to add communication with smargopolo"""
|
||||||
# Validate new value and get timestamp
|
# Validate new value and get timestamp
|
||||||
if not force:
|
if not force:
|
||||||
@@ -88,6 +88,7 @@ class SmarGonAxis(PVPositioner):
|
|||||||
This class controls the SmarGon goniometer via the REST interface. All
|
This class controls the SmarGon goniometer via the REST interface. All
|
||||||
SmarGon axes share a common mutex to manage actual HW access.
|
SmarGon axes share a common mutex to manage actual HW access.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
USER_ACCESS = ["omove", "oldmove"]
|
USER_ACCESS = ["omove", "oldmove"]
|
||||||
|
|
||||||
# Status attributes
|
# Status attributes
|
||||||
@@ -119,10 +120,10 @@ class SmarGonAxis(PVPositioner):
|
|||||||
self.__class__.__dict__["setpoint"].kwargs["high_limit"] = high_limit
|
self.__class__.__dict__["setpoint"].kwargs["high_limit"] = high_limit
|
||||||
self.__class__.__dict__["sg_url"].kwargs["value"] = sg_url
|
self.__class__.__dict__["sg_url"].kwargs["value"] = sg_url
|
||||||
# Fine-tune HTTP connection behavior
|
# Fine-tune HTTP connection behavior
|
||||||
# NOTE: SmarGon has a few failed requests every one in a while
|
# NOTE: SmarGon has a few failed requests every one in a while
|
||||||
self._s = requests.Session()
|
self._s = requests.Session()
|
||||||
retries = Retry(total=5, backoff_factor=0.05, status_forcelist=[ 500, 502, 503, 504 ])
|
retries = Retry(total=5, backoff_factor=0.05, status_forcelist=[500, 502, 503, 504])
|
||||||
self._s.mount('http://', HTTPAdapter(max_retries=retries))
|
self._s.mount("http://", HTTPAdapter(max_retries=retries))
|
||||||
|
|
||||||
super().__init__(
|
super().__init__(
|
||||||
prefix=prefix,
|
prefix=prefix,
|
||||||
@@ -149,7 +150,7 @@ class SmarGonAxis(PVPositioner):
|
|||||||
# print(f"Readback: {rb}\tSetpoint: {sp}")
|
# print(f"Readback: {rb}\tSetpoint: {sp}")
|
||||||
# Check if they're within tolerance
|
# Check if they're within tolerance
|
||||||
distance = abs(rb - sp)
|
distance = abs(rb - sp)
|
||||||
done = 1 if distance<self._tol else 0
|
done = 1 if distance < self._tol else 0
|
||||||
self.done.put(done, force=True)
|
self.done.put(done, force=True)
|
||||||
time.sleep(0.2)
|
time.sleep(0.2)
|
||||||
|
|
||||||
@@ -181,7 +182,6 @@ class SmarGonAxis(PVPositioner):
|
|||||||
d[str(self.name)] = d[f"{self.name}_readback"]
|
d[str(self.name)] = d[f"{self.name}_readback"]
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
|
||||||
def read(self) -> OrderedDict[str, dict]:
|
def read(self) -> OrderedDict[str, dict]:
|
||||||
"""Workaround to schema expected by the BEC"""
|
"""Workaround to schema expected by the BEC"""
|
||||||
d = super().read()
|
d = super().read()
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ class StdDaqPreviewMixin(CustomDetectorMixin):
|
|||||||
self._mon.join(timeout=1)
|
self._mon.join(timeout=1)
|
||||||
# So also disconnect the socket
|
# So also disconnect the socket
|
||||||
try:
|
try:
|
||||||
#pylint: disable=protected-access
|
# pylint: disable=protected-access
|
||||||
self.parent._socket.disconnect(self.parent.url.get())
|
self.parent._socket.disconnect(self.parent.url.get())
|
||||||
except zmq.error.ZMQError:
|
except zmq.error.ZMQError:
|
||||||
# Might be already closed
|
# Might be already closed
|
||||||
@@ -73,7 +73,7 @@ class StdDaqPreviewMixin(CustomDetectorMixin):
|
|||||||
break
|
break
|
||||||
|
|
||||||
# pylint: disable=no-member
|
# pylint: disable=no-member
|
||||||
#pylint: disable=protected-access
|
# pylint: disable=protected-access
|
||||||
r = self.parent._socket.recv_multipart(flags=zmq.NOBLOCK)
|
r = self.parent._socket.recv_multipart(flags=zmq.NOBLOCK)
|
||||||
|
|
||||||
# Length and throtling checks
|
# Length and throtling checks
|
||||||
@@ -105,7 +105,7 @@ class StdDaqPreviewMixin(CustomDetectorMixin):
|
|||||||
# self.parent.array_data.put(data, force=True)
|
# self.parent.array_data.put(data, force=True)
|
||||||
self.parent.shaped_image.put(image, force=True)
|
self.parent.shaped_image.put(image, force=True)
|
||||||
|
|
||||||
#pylint: disable=protected-access
|
# pylint: disable=protected-access
|
||||||
self.parent._last_image = image
|
self.parent._last_image = image
|
||||||
self.parent._run_subs(sub_type=self.parent.SUB_MONITOR, value=image)
|
self.parent._run_subs(sub_type=self.parent.SUB_MONITOR, value=image)
|
||||||
t_last = t_curr
|
t_last = t_curr
|
||||||
@@ -133,7 +133,7 @@ class StdDaqPreviewDetector(PSIDetectorBase):
|
|||||||
This was meant to provide live image stream directly from the StdDAQ but
|
This was meant to provide live image stream directly from the StdDAQ but
|
||||||
also works with other ARRAY v1 streamers, like the AreaDetector ZMQ plugin.
|
also works with other ARRAY v1 streamers, like the AreaDetector ZMQ plugin.
|
||||||
Note that the preview stream must be already throtled in order to cope with
|
Note that the preview stream must be already throtled in order to cope with
|
||||||
the incoming data and the python class might throttle it further.
|
the incoming data and the python class might throttle it further.
|
||||||
|
|
||||||
NOTE: As an explicit request, it does not record the image data.
|
NOTE: As an explicit request, it does not record the image data.
|
||||||
|
|
||||||
@@ -185,8 +185,8 @@ class StdDaqPreviewDetector(PSIDetectorBase):
|
|||||||
self._socket.connect(self.url.get())
|
self._socket.connect(self.url.get())
|
||||||
|
|
||||||
def savemode(self, save=False):
|
def savemode(self, save=False):
|
||||||
""" Toggle save mode for the shaped image"""
|
"""Toggle save mode for the shaped image"""
|
||||||
#pylint: disable=protected-access
|
# pylint: disable=protected-access
|
||||||
if save:
|
if save:
|
||||||
self.shaped_image._kind = Kind.normal
|
self.shaped_image._kind = Kind.normal
|
||||||
else:
|
else:
|
||||||
|
|||||||
Reference in New Issue
Block a user