diff --git a/mxcubecore/HardwareObjects/EMBLFlexHarvester.py b/mxcubecore/HardwareObjects/EMBLFlexHarvester.py
index 80d27ed1c8..142f126d25 100644
--- a/mxcubecore/HardwareObjects/EMBLFlexHarvester.py
+++ b/mxcubecore/HardwareObjects/EMBLFlexHarvester.py
@@ -30,12 +30,9 @@
import logging
import time
-from typing import (
- Any,
- List,
-)
+from typing import Any, List
-import gevent
+from gevent import Timeout, sleep, spawn
from mxcubecore import HardwareRepository as HWR
from mxcubecore.HardwareObjects.EMBLFlexHCD import EMBLFlexHCD
@@ -48,11 +45,9 @@
class EMBLFlexHarvester(EMBLFlexHCD):
- """EMBLFlexHarvester is the Hardware Object interface for the EMBL Flex Sample Changer
- It inherits from EMBLFlexHCD and implements the Harvester interface.
- """
+ """Implement the MBL Harvester interface as Flex sample changer" """
- __TYPE__ = "Flex Sample Changer"
+ __TYPE__ = "EMBL Harvester Sample Changer"
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
@@ -66,7 +61,7 @@ def init(self):
self._loaded_sample = (-1, -1, -1)
self._harvester_hwo = self.get_object_by_role("harvester")
- EMBLFlexHCD.init(self)
+ super().init()
def get_room_temperature_mode(self) -> bool:
"""Get the Harvester Room Temperature Mode"""
@@ -96,9 +91,9 @@ def get_sample_list(self) -> List[Any]:
ha_sample_lists = self._harvester_hwo.get_crystal_uuids()
ha_sample_names = self._harvester_hwo.get_sample_names()
ha_sample_states = self._harvester_hwo.get_samples_state()
- except Exception as e:
+ except Exception as err:
self.user_log.error(
- "Failed retrieving sample metadata from Harvester: %s", e
+ f"Failed retrieving sample metadata from Harvester: {err}"
)
return present_sample_list
@@ -173,7 +168,7 @@ def load_a_pin_for_calibration(self):
self.prepare_load()
self.enable_power()
- load_task = gevent.spawn(
+ load_task = spawn(
self._execute_cmd_exporter,
"loadSampleFromHarvester",
self.pin_cleaning,
@@ -182,12 +177,12 @@ def load_a_pin_for_calibration(self):
self._wait_busy(30)
err_msg = "Timeout while waiting to sample to be loaded"
- with gevent.Timeout(600, RuntimeError(err_msg)):
+ with Timeout(600, RuntimeError(err_msg)):
while not load_task.ready():
logging.getLogger("user_level_log").info("wait loading task")
- gevent.sleep(2)
+ sleep(2)
- with gevent.Timeout(600, RuntimeError(err_msg)):
+ with Timeout(600, RuntimeError(err_msg)):
while True:
logging.getLogger("user_level_log").info("Wait Robot Safe position")
is_safe = self._execute_cmd_exporter(
@@ -195,27 +190,20 @@ def load_a_pin_for_calibration(self):
)
if is_safe:
break
- gevent.sleep(2)
+ sleep(2)
return True
except RuntimeError:
return False
def start_harvester_centring(self):
+ logging.getLogger("user_level_log").info("Start Auto Harvesting Centring")
try:
- dm = HWR.beamline.diffractometer
-
- logging.getLogger("user_level_log").info("Start Auto Harvesting Centring")
-
- computed_offset = HWR.beamline.harvester.get_offsets_for_sample_centring()
- dm.start_harvester_centring(computed_offset)
+ HWR.beamline.sample_view.start_harvester_centring()
except Exception as exc:
- logging.getLogger("user_level_log").exception(
- "Could not center sample, skipping"
- )
- raise QueueExecutionException(
- "Could not center sample, skipping", self
- ) from exc
+ msg = "Could not center sample, skipping"
+ logging.getLogger("user_level_log").exception(msg)
+ raise QueueExecutionException(msg, self) from exc
def _set_loaded_sample_and_prepare(self, loaded_sample_tup, previous_sample_tup):
res = False
@@ -232,7 +220,8 @@ def _set_loaded_sample_and_prepare(self, loaded_sample_tup, previous_sample_tup)
self.queue_harvest_next_sample(loaded_sample.get_address())
# we expect CENTRING_METHOD to be None
- # NB: move this call to base_queue_entry mount_sample and add Harvester Centring METHOD
+ # NB: move this call to base_queue_entry mount_sample and
+ # add Harvester Centring METHOD
HWR.beamline.queue_manager.centring_method = CENTRING_METHOD.NONE
self.start_harvester_centring()
@@ -263,7 +252,8 @@ def _do_load(self, sample=None) -> bool:
sample.get_basket_no(),
sample.get_vial_no(),
)
- # Flex/Exporter Does not know the loaded sample location we keep track of it ourselfs
+ # Flex/Exporter does not know the loaded sample location,
+ # keep track locally.
self._loaded_sample = loaded_sample
return self._set_loaded_sample_and_prepare(loaded_sample, previous_sample)
@@ -272,7 +262,7 @@ def _perform_loading_sequence(self, sample_uuid) -> bool:
logging.getLogger("user_level_log").info(
"Start loading from harvester SAMPLE_UUID %s", sample_uuid
)
- load_task = gevent.spawn(
+ load_task = spawn(
self._execute_cmd_exporter,
"loadSampleFromHarvester",
sample_uuid,
@@ -296,13 +286,13 @@ def _perform_loading_sequence(self, sample_uuid) -> bool:
# Wait for sample to be loaded
err_msg = "Timeout while waiting to sample to be loaded"
try:
- with gevent.Timeout(600, RuntimeError(err_msg)):
+ with Timeout(600, RuntimeError(err_msg)):
while not load_task.ready():
logging.getLogger("user_level_log").info("Wait loading task")
loaded_sample = self._hw_get_mounted_crystal_id()
if loaded_sample == sample_uuid:
break
- gevent.sleep(2)
+ sleep(2)
except RuntimeError:
logging.getLogger("user_level_log").error(err_msg)
return False
@@ -314,14 +304,14 @@ def _finalize_loading_sequence(self) -> bool:
# Wait for robot to be in safe state
err_msg = "Timeout while waiting for robot to be in safe state"
try:
- with gevent.Timeout(600, RuntimeError(err_msg)):
+ with Timeout(600, RuntimeError(err_msg)):
while True:
is_safe = self._execute_cmd_exporter(
"getRobotIsSafe", attribute=True
)
if is_safe:
break
- gevent.sleep(2)
+ sleep(2)
except RuntimeError:
logging.getLogger("user_level_log").error(err_msg)
return False
diff --git a/mxcubecore/HardwareObjects/Harvester.py b/mxcubecore/HardwareObjects/Harvester.py
index 2b1462117f..59944215bc 100644
--- a/mxcubecore/HardwareObjects/Harvester.py
+++ b/mxcubecore/HardwareObjects/Harvester.py
@@ -38,7 +38,6 @@
harvester
wid30harvest:9001
------------------------------------------------------------------
"""
from __future__ import annotations
@@ -46,7 +45,7 @@
import logging
from typing import List, Optional, Union
-import gevent
+from gevent import Timeout, sleep
from mxcubecore.BaseHardwareObjects import HardwareObject
@@ -98,7 +97,6 @@ def __init__(self, name):
super().__init__(name)
self.timeout = 600 # default timeout
- # Internal variables -----------
self.calibration_state = False
def init(self):
@@ -111,49 +109,48 @@ def set_calibration_state(self, state: bool):
"""Set Calibration state
Args:
- state (bool) : Whether a calibration procedure is on going
+ state: True if a calibration procedure is on going.
"""
self.calibration_state = state
def _wait_ready(self, timeout: Union[float, None] = None):
- """Wait Harvester to be ready
+ """Wait timeout seconds until status is ready.
Args:
- (timeout) : Whether to wait for a amount of time
- timeout is None wait forever, timeout <=0 use default timeout
+ timeout: optional - timeout [s],
+ if timeout = 0: return at once and do not wait,
+ if timeout is None: wait forever (default).
"""
- if timeout is not None and timeout <= 0:
- timeout = self.timeout
+ if timeout == 0:
+ return
err_msg = "Timeout waiting for Harvester to be ready"
- with gevent.Timeout(timeout, RuntimeError(err_msg)):
+ with Timeout(timeout, RuntimeError(err_msg)):
while not self._ready():
logging.getLogger("user_level_log").info(
"Waiting Harvester to be Ready"
)
- gevent.sleep(3)
+ sleep(3)
def _wait_sample_transfer_ready(self, timeout: Union[float, None] = None):
- """Wait Harvester to be ready to transfer a sample
+ """Wait timeout seconds until ready to transfer a sample.
Args:
- timeout (second) : Whether to wait for a amount of time
- timeout is None wait forever, timeout <=0 use default timeout
+ timeout: optional - timeout [s],
+ if timeout = 0: return at once and do not wait,
+ if timeout is None: wait forever (default).
"""
- if timeout is not None and timeout <= 0:
- timeout = self.timeout
+ if timeout == 0:
+ return
err_msg = "Timeout waiting for Harvester to be ready to transfer"
try:
- with gevent.Timeout(timeout, RuntimeError(err_msg)):
- while not self._ready_to_transfer():
- logging.getLogger("user_level_log").info(
- "Waiting Harvester to be ready to transfer for 10 minutes"
- )
- gevent.sleep(3)
+ with Timeout(timeout, RuntimeError(err_msg)):
+ while not self._ready_to_transfer:
+ sleep(3)
except RuntimeError as exc:
# In case of timeout we as abort, park and trash
self.abort()
@@ -220,6 +217,7 @@ def get_status(self) -> str:
"""
return self._execute_cmd_exporter("getStatus", attribute=True)
+ @property
def _ready(self) -> str:
"""check whether the Harvester is READY
@@ -227,17 +225,12 @@ def _ready(self) -> str:
"""
return self._execute_cmd_exporter("getState", attribute=True) == "Ready"
- def _busy(self) -> bool:
- """check whether the Harvester is BUSY
-
- Return (bool): True if Harvester is not Ready otherwise False
- """
- return self._execute_cmd_exporter("getState", attribute=True) != "Ready"
-
+ @property
def _ready_to_transfer(self) -> bool:
- """check whether the Harvester is Waiting Sample Transfer
+ """check if the Harvester is Waiting Sample Transfer
- Return (bool): True if Harvester is Waiting Sample Transfer otherwise False
+ Returns:
+ True if Harvester is Waiting Sample Transfer otherwise False
"""
return (
self._execute_cmd_exporter("getStatus", attribute=True)
@@ -247,31 +240,31 @@ def _ready_to_transfer(self) -> bool:
def get_samples_state(self) -> List[str]:
"""Get the Harvester Samples State
- Return (List): list of crystal state "waiting_for_transfer, Running etc.."
+ Return:
+ List of states "Waiting Sample Transfer", "Running"...
"""
return self._execute_cmd_exporter("getSampleStates", attribute=True)
def get_current_crystal(self) -> str:
- """Get the Harvester current harvested crystal
+ """Get the current harvested crystal
Return (str): the crystal uuid
"""
return self._execute_cmd_exporter("getCurrentSampleID", attribute=True)
- def is_crystal_harvested(self, crystal_uuid: str) -> str:
+ def is_crystal_harvested(self, crystal_uuid: str) -> bool:
"""Check Whether if the current crystal is harvested
- args: the crystal uuid
-
- Return (bool): True if the crystal is the current harvested crystal
+ Args:
+ crystal_uuid: the crystal uuid
+ Returns:
+ True if the crystal is the current harvested crystal.
"""
- res = False
- in_list = crystal_uuid in self.get_crystal_uuids()
- if in_list:
- Current_SampleID = self.get_current_crystal()
- if crystal_uuid == Current_SampleID:
- res = True
- return res
+ if crystal_uuid in self.get_crystal_uuids():
+ current_sample_id = self.get_current_crystal()
+ if crystal_uuid == current_sample_id:
+ return True
+ return False
def current_crystal_state(self, crystal_uuid: str) -> str:
"""get current crystal state
@@ -352,8 +345,6 @@ def get_sample_acronyms(self) -> List[str]:
)
return harvester_sample_acronyms
- # ------------------------------------------------------------------------------------
-
def abort(self) -> str:
"""Send Abort command
Abort any current Harvester Actions
@@ -388,8 +379,6 @@ def trash_sample(self):
"""Trash the current Harvested Crystal"""
return self._execute_cmd_exporter("trashSample", command=True)
- # -----------------------------------------------------------------------------
-
def load_plate(self, plate_id: str) -> str:
"""Change Harvester current plate
@@ -445,7 +434,7 @@ def set_room_temperature_mode(self, value: bool) -> bool:
print("setting HA Room temperature to: %s" % value)
return self.get_room_temperature_mode()
- # -------------------- Calibrate Drift Shape offset ----------------------------
+ # -------------------- Calibrate Drift Shape offset ----------------
def get_last_sample_drift_offset_x(self) -> float:
"""Sample Offset X position when drifted
@@ -474,7 +463,7 @@ def get_last_sample_drift_offset_z(self) -> float:
)
return pin_last_drift_offset_z
- # ---------------------- Calibrate Cut Shape offset----------------------------
+ # ---------------------- Calibrate Cut Shape offset---------------
def get_last_pin_cut_shape_offset_x(self) -> float:
"""Pin shape Offset x position
@@ -542,7 +531,7 @@ def queue_harvest_sample(
wait_before_load = not self.get_room_temperature_mode()
if self.get_number_of_available_pin() > 0:
- gevent.sleep(2)
+ sleep(2)
if current_queue_index == 0:
logging.getLogger("user_level_log").info("Harvesting First Sample")
@@ -551,9 +540,10 @@ def queue_harvest_sample(
sample_uuid, wait_before_load
)
if harvest_res is False:
- # if sample could not be Harvest, but no exception is raised, let's skip the sample
+ # if sample could not be harvested, but no exception is
+ # raised, the sample is skipped
logging.getLogger("user_level_log").error(
- "Harvester could not Harvest sample, Stopping queue"
+ "Harvester could not harvest sample, Stopping queue"
)
else:
logging.getLogger("user_level_log").info("checking last Harvesting")
@@ -561,23 +551,21 @@ def queue_harvest_sample(
sample_uuid, wait_before_load
)
if harvest_res is False:
- # if sample could not be Harvest, but no exception is raised, let's skip the sample
+ # if sample could not be harvested, but no exception is
+ # raised, the sample is skipped
logging.getLogger("user_level_log").error(
"There is no more Pins in the Harvester, Stopping queue"
)
- elif self.get_number_of_available_pin() == 0 and self._ready_to_transfer():
+ elif self.get_number_of_available_pin() == 0 and self._ready_to_transfer:
logging.getLogger("user_level_log").warning(
- "Warning: Harvester pins is approaching to ZERO"
- )
- logging.getLogger("user_level_log").warning(
- "Warning: Mounting last Sample, Queue will stop on next one"
+ "Mounting the last Sample, Queue will stop on next one"
)
# in this case we just load the sample that is ready in the Harester
harvest_res = True
else:
# raise Not enough pins available in the pin provider
logging.getLogger("user_level_log").error(
- "There is no more Pins in the Harvester, Stopping queue"
+ "No more Pins left in the Harvester, Stopping queue"
)
return harvest_res
@@ -601,11 +589,11 @@ def queue_harvest_next_sample(self, next_sample_loc_str: str, sample_uuid: str):
def harvest_sample_before_mount(
self, sample_uuid: str, wait_before_load: bool = False
) -> bool:
- """send harvest sample command
- Check and set the current state of the Harvester and the sample before Harvest
-
- Return (bool): whether the sample has been harvest then mount (True)
- or had and exception (False)
+ """Check and set the current state of the Harvester and the sample
+ before harvesting.
+ Return:
+ True if the sample has been harvested and mounted.
+ False if exception has been received.
"""
res = None
@@ -638,7 +626,6 @@ def harvest_sample_before_mount(
self._wait_sample_transfer_ready(self.timeout)
res = True
else:
- # logging.getLogger("user_level_log").info("ERROR: Sample Could not be Harvested (Harvester Ready, ) ")
msg = self.get_status()
logging.getLogger("user_level_log").exception(
"ERROR: Sample Could not be Harvested"
@@ -651,7 +638,7 @@ def harvest_sample_before_mount(
except RuntimeError:
return False
- elif self._ready_to_transfer():
+ elif self._ready_to_transfer:
try:
if (
self.current_crystal_state(sample_uuid)
@@ -718,7 +705,7 @@ def harvest_sample_before_mount(
# Try an abort and move to next sample
return False
- def get_offsets_for_sample_centring(self) -> tuple[float]:
+ def get_offsets_for_sample_centering(self) -> tuple[float]:
"""Calculate sample centring offsets
based on Harvested pin shape pre-calculated offsets
diff --git a/mxcubecore/HardwareObjects/HarvesterMaintenance.py b/mxcubecore/HardwareObjects/HarvesterMaintenance.py
index 3b6300a24a..ceedeaf861 100644
--- a/mxcubecore/HardwareObjects/HarvesterMaintenance.py
+++ b/mxcubecore/HardwareObjects/HarvesterMaintenance.py
@@ -24,7 +24,7 @@
import logging
-import gevent
+from gevent import sleep
from mxcubecore import HardwareRepository as HWR
from mxcubecore.BaseHardwareObjects import HardwareObject
@@ -40,6 +40,7 @@ class HarvesterMaintenance(HardwareObject):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
+ self.saved_motor_positions = {}
def init(self):
self._harvester = self.get_object_by_role("harvester")
@@ -150,7 +151,7 @@ def get_cmd_info(self):
return cmd_list
def send_command(self, cmd_name, args=None):
- if cmd_name in ["park"]:
+ if "park" in cmd_name:
self._do_park()
if cmd_name == "trash":
self._do_trash()
@@ -176,17 +177,19 @@ def calibrate_pin(self) -> bool:
self._harvester.load_calibrated_pin()
self._harvester._wait_sample_transfer_ready(None)
- print("waiting 40 seconds before mount")
- # For some reason the Harvester return READY too soon
+
+ # For some reason the Harvester returns READY too soon
# approximately 40 Second sooner
- gevent.sleep(40)
+ print("waiting 40 seconds before mount")
+ sleep(40)
+
sample_mount_device = HWR.beamline.sample_changer
mount_current_sample = sample_mount_device.load_a_pin_for_calibration()
if mount_current_sample:
try:
- md = HWR.beamline.diffractometer
- md._wait_ready()
+ diffr = HWR.beamline.diffractometer
+ diffr.wait_status_ready()
sample_drift_x = float(self._harvester.get_last_sample_drift_offset_x())
sample_drift_y = float(self._harvester.get_last_sample_drift_offset_y())
@@ -194,25 +197,16 @@ def calibrate_pin(self) -> bool:
-self._harvester.get_last_sample_drift_offset_z()
)
- motor_pos_dict = {
- "kappa": float(
- md["HacentringReferencePosition"].get_property("kappa_ref")
- ),
- "kappa_phi": float(
- md["HacentringReferencePosition"].get_property("phi_ref")
- ),
- "phi": float(
- md["HacentringReferencePosition"].get_property("omega_ref")
- ),
- "phiy": md.phiyMotor.get_value() + sample_drift_x,
- }
-
- md.move_motors(motor_pos_dict)
- md._wait_ready()
- md.centringFocus.set_value_relative(sample_drift_z, None)
- md.centringVertical.set_value_relative(sample_drift_y, None)
-
- md.save_current_motor_position()
+ motor_pos_dict = HWR.beamline.sample_view.harvester_reference.copy()
+ motor_pos_dict["phiy"] = diffr.phiy.get_value() + sample_drift_x
+
+ diffr.set_value_motors(motor_pos_dict)
+ diffr.wait_status_ready()
+ diffr.sample_focus.set_value_relative(sample_drift_z, None)
+ diffr.sample_vertical.set_value_relative(sample_drift_y, None)
+
+ self.saved_motor_positions = diffr.get_value_motors()
+
self._harvester.set_calibration_state(True)
logging.getLogger("user_level_log").info(
@@ -240,40 +234,25 @@ def validate_calibration(self) -> bool:
goes to end (True) or had and exception (False)
"""
try:
- md = HWR.beamline.diffractometer
-
- motor_pos_dict = {
- "focus": md.focusMotor.get_value(),
- "phiy": md.phiyMotor.get_value(),
- "phiz": md.phizMotor.get_value(),
- "centring_focus": md.centringFocus.get_value(),
- "centring_vertical": md.centringVertical.get_value(),
- }
+ diffr = HWR.beamline.diffractometer
+
+ motor_pos_dict = diffr.get_value_motors()
+ new_motor_offset = {}
+ saved_position = self.saved_motor_positions
- saved_position = md.saved_motor_position
# find offset position based on old and new motor position
- new_motor_offset = {
- "focus": motor_pos_dict["focus"] - saved_position["focus"],
- "phiy": motor_pos_dict["phiy"] - saved_position["phiy"],
- "phiz": motor_pos_dict["phiz"] - saved_position["phiz"],
- "centring_focus": (
- motor_pos_dict["centring_focus"] - saved_position["centring_focus"]
- ),
- "centring_vertical": (
- motor_pos_dict["centring_vertical"]
- - saved_position["centring_vertical"]
- ),
- }
+ for nam in ("focus", "phiy", "phiz", "sample_focus", "sample_vertical"):
+ new_motor_offset[nam] = motor_pos_dict[nam] - saved_position[nam]
calibrated_motor_offset = {
- "focus": new_motor_offset["focus"] + new_motor_offset["centring_focus"],
+ "focus": new_motor_offset["focus"] + new_motor_offset["sample_focus"],
"phiy": new_motor_offset["phiy"],
"phiz": (
- new_motor_offset["phiz"] + new_motor_offset["centring_vertical"]
+ new_motor_offset["phiz"] + new_motor_offset["sample_vertical"]
),
}
- # we store the motor offset in the Harvester, to be used for sample centring
+ # store the offset in the Harvester, to be used for sample centring
self._harvester.store_calibrated_pin(
calibrated_motor_offset["focus"],
calibrated_motor_offset["phiy"],
diff --git a/mxcubecore/HardwareObjects/SampleView.py b/mxcubecore/HardwareObjects/SampleView.py
index 68f6132fdb..3d1891e218 100644
--- a/mxcubecore/HardwareObjects/SampleView.py
+++ b/mxcubecore/HardwareObjects/SampleView.py
@@ -77,6 +77,7 @@ def __init__(self, name):
self.centring_status = {}
self.rotation_reference = {}
self.chi_angle = None
+ self.harvester_reference = {}
def init(self):
super().init()
@@ -110,6 +111,9 @@ def init(self):
self.centring_motors[role].motor.connect(
"stateChanged", self._update_shape_positions
)
+
+ diffr.zoom.connect("valueChanged", self._update_shape_positions)
+
self._camera = self.get_object_by_role("camera")
self._last_oav_image = None
@@ -121,11 +125,17 @@ def init(self):
self.rotation_reference.update(
{"motor": self.centring_motors.get(self.rotation_reference.get("name"))}
)
+ harvester_reference = self.get_property("harvester_reference_position", {})
+ if isinstance(harvester_reference, str):
+ self.harvester_reference = literal_eval(harvester_reference)
def _update_shape_positions(self, *args, **kwargs):
- for shape in self.get_shapes():
+ _shapes = self._shapes.copy()
+
+ for _key, shape in _shapes.items():
shape.update_position(self.motor_positions_to_screen)
+ self._shapes = _shapes
self.emit("shapesChanged")
def get_positions(self) -> dict[str, float]:
@@ -186,7 +196,7 @@ def get_centred_point_from_coord(self, x, y, return_by_names=None):
phiz = motors_dict.get("phiz") + dy
return {
- "omega": motors_dict.get("omega"),
+ "omega": -motors_dict.get("omega"),
"phiy": float(-phiy),
"phiz": phiz,
"sampx": float(-sampx),
@@ -212,10 +222,15 @@ def motor_positions_to_screen(
diffr.wait_status_ready(50)
motors_dict = self.get_positions()
for key, val in positions_dict.items():
+ if val is None:
+ continue
new_pos_dict[key] = self.centring_motors[key].direction * (
val - motors_dict.get(key)
)
- omega_angle = math.radians(motors_dict.get("omega", 0))
+ omega_angle = (
+ math.radians(motors_dict.get("omega", 0))
+ * self.centring_motors["omega"].direction
+ )
rot_matrix = np.matrix(
[
[math.cos(omega_angle), -math.sin(omega_angle)],
@@ -304,6 +319,7 @@ def auto_centring_done(self, auto_centring_procedure):
logging.exception("Could not complete automatic centring")
logging.getLogger("user_level_log").info("Automatic loop centring failed")
self.centring_failed()
+ self.reject_centring()
else:
if res is None:
logging.error("Could not complete automatic centring")
@@ -311,6 +327,7 @@ def auto_centring_done(self, auto_centring_procedure):
"Automatic loop centring failed"
)
self.centring_failed()
+ self.reject_centring()
else:
self.centring_done()
self.accept_centring()
@@ -373,7 +390,7 @@ def run_custom_auto_centring(self):
self.current_centring_method = "Automatic"
self.emit("centringStarted", ("Automatic"))
diffr = HWR.beamline.diffractometer
- self.wait_status_ready(60)
+ diffr.wait_status_ready(60)
diffr.run_custom_script("sample_centering")
diffr.wait_status_ready()
@@ -424,6 +441,36 @@ def start_auto_centring(self):
self.emit("centringStarted", ("Automatic"))
self.current_centring_procedure.link(self.auto_centring_done)
+ def start_harvester_centring(self):
+ """Start harvester automatic centring procedure"""
+
+ if self.current_centring_procedure is not None:
+ logging.getLogger("HWR").exception("Already centring")
+
+ self.log.info("Harvester sample centring")
+ self.current_centring_method = "Automatic"
+ self.emit("centringStarted", ("Automatic"))
+ diffr = HWR.beamline.diffractometer
+ diffr.wait_status_ready(60)
+ # diffr.set_phase(diffr.get_phase_enum.CENTRE)
+
+ motors_dict = self.get_positions()
+ for key, val in self.harvester_reference.items():
+ motors_dict.update({key: val})
+ _offsets = HWR.beamline.harvester.get_offsets_for_sample_centering()
+ motors_dict["phiy"] += _offsets[0]
+ diffr.set_value_motors(motors_dict)
+
+ # next two motors are not part of the centring motors
+ # we move them separately
+ diffr.motors_hwobj_dict["sample_focus"].set_value_relative(_offsets[1])
+ diffr.motors_hwobj_dict["sample_vertical"].set_value_relative(_offsets[2])
+
+ diffr.wait_status_ready(10)
+
+ self.centring_done()
+ self.accept_centring()
+
def move_to_beam(self, x: float, y: float):
"""Move the sample to the x,y coordinates.
Args:
diff --git a/ruff.toml b/ruff.toml
index dbb3093686..d8bffcf5d0 100644
--- a/ruff.toml
+++ b/ruff.toml
@@ -380,11 +380,6 @@ convention = "google"
"B006",
"S301",
]
-"mxcubecore/HardwareObjects/EMBLFlexHarvester.py" = [
- "B904",
- "E501",
- "E712",
-]
"mxcubecore/HardwareObjects/ESRF/BlissHutchTrigger.py" = [
"B904",
]
@@ -512,12 +507,6 @@ convention = "google"
"B905",
"F841",
]
-"mxcubecore/HardwareObjects/Harvester.py" = [
- "E501",
-]
-"mxcubecore/HardwareObjects/HarvesterMaintenance.py" = [
- "E501",
-]
"mxcubecore/HardwareObjects/ICATLIMS.py" = [
"E501",
]