#
# Project name: MXCuBE
# https://github.com/mxcube
#
# This file is part of MXCuBE software.
#
# MXCuBE is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# MXCuBE is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with MXCuBE. If not, see <http://www.gnu.org/licenses/>.
"""EMBLBSD (Beam shaping device) represents a diffractometer without a gonio"""
import logging
import time
import gevent
from mxcubecore.HardwareObjects.GenericDiffractometer import GenericDiffractometer
__credits__ = ["EMBL Hamburg"]
__license__ = "LGPLv3+"
__category__ = "General"
[docs]class EMBLBSD(GenericDiffractometer):
"""EMBLBSD represents a diffractometer without a gonio"""
def __init__(self, *args):
"""Based on the GenericDiffractometer without centring motors"""
GenericDiffractometer.__init__(self, *args)
# Hardware objects ----------------------------------------------------
self.zoom_motor_hwobj = None
self.omega_reference_motor = None
# Channels and commands -----------------------------------------------
self.chan_beamstop_position = None
self.chan_calib_x = None
self.chan_calib_y = None
self.chan_current_phase = None
self.chan_fast_shutter_is_open = None
self.chan_state = None
self.chan_sync_move_motors = None
self.chan_scintillator_position = None
self.chan_capillary_position = None
self.chan_status = None
self.cmd_start_set_phase = None
self.cmd_start_auto_focus = None
self.cmd_save_centring_positions = None
# Internal values -----------------------------------------------------
self.use_sc = False
self.omega_reference_par = None
self.omega_reference_pos = [0, 0]
self.current_state = None
self.fast_shutter_is_open = None
[docs] def init(self):
"""Initiates variables"""
GenericDiffractometer.init(self)
self.chan_state = self.get_channel_object("State")
self.current_state = self.chan_state.get_value()
self.chan_state.connect_signal("update", self.state_changed)
self.chan_status = self.get_channel_object("Status")
self.chan_status.connect_signal("update", self.status_changed)
self.chan_calib_x = self.get_channel_object("CoaxCamScaleX")
self.chan_calib_y = self.get_channel_object("CoaxCamScaleY")
self.update_pixels_per_mm()
self.chan_current_phase = self.get_channel_object("CurrentPhase")
self.connect(self.chan_current_phase, "update", self.current_phase_changed)
self.chan_fast_shutter_is_open = self.get_channel_object("FastShutterIsOpen")
self.chan_fast_shutter_is_open.connect_signal(
"update", self.fast_shutter_state_changed
)
self.chan_scintillator_position = self.get_channel_object(
"ScintillatorPosition"
)
self.chan_capillary_position = self.get_channel_object("CapillaryPosition")
self.cmd_start_set_phase = self.get_command_object("startSetPhase")
self.cmd_start_auto_focus = self.get_command_object("startAutoFocus")
self.zoom_motor_hwobj = self.get_object_by_role("zoom")
self.connect(self.zoom_motor_hwobj, "valueChanged", self.zoom_position_changed)
self.connect(
self.zoom_motor_hwobj,
"predefinedPositionChanged",
self.zoom_motor_predefined_position_changed,
)
self.chan_beamstop_position = self.get_channel_object("BeamstopPosition")
[docs] def use_sample_changer(self):
"""Returns true if sample changer is used
:return: bool
"""
return False
[docs] def manual_centring(self):
"""No need to implement"""
return
[docs] def automatic_centring(self):
"""No need to implement"""
return
[docs] def get_centred_point_from_coord(self, x, y, return_by_names=None):
"""No need to implement"""
return
[docs] def state_changed(self, state):
"""Emits state change signal"""
self.current_state = state
self.emit("minidiffStateChanged", (self.current_state))
self.emit("minidiffStatusChanged", (self.current_state))
[docs] def status_changed(self, state):
"""Emits status message"""
self.emit("statusMessage", ("diffractometer", state, "busy"))
[docs] def zoom_position_changed(self, value):
"""After the zoom change updates pixels per mm"""
self.update_pixels_per_mm()
self.current_motor_positions["zoom"] = value
[docs] def zoom_motor_predefined_position_changed(self, position_name, offset):
"""Updates pixels per mm when the zoom has been changed"""
self.update_pixels_per_mm()
self.emit("zoomMotorPredefinedPositionChanged", (position_name, offset))
[docs] def fast_shutter_state_changed(self, is_open):
"""Stores fast shutter state"""
self.fast_shutter_is_open = is_open
if is_open:
msg = "Opened"
else:
msg = "Closed"
self.emit("minidiffShutterStateChanged", (self.fast_shutter_is_open, msg))
[docs] def update_pixels_per_mm(self, *args):
"""Updates pixels per mm"""
if self.chan_calib_x:
self.pixels_per_mm_x = 1.0 / self.chan_calib_x.get_value()
self.pixels_per_mm_y = 1.0 / self.chan_calib_y.get_value()
self.emit(
"pixelsPerMmChanged", ((self.pixels_per_mm_x, self.pixels_per_mm_y),)
)
[docs] def set_phase(self, phase, timeout=80):
"""Sets diffractometer to the selected phase.
In the plate mode before going to or away from
Transfer or Beam location phase if needed then detector
is moved to the safe distance to avoid collision.
"""
# self.wait_device_ready(2)
logging.getLogger("GUI").warning(
"Diffractometer: Setting %s phase. Please wait..." % phase
)
if timeout is not None:
_start = time.time()
self.cmd_start_set_phase(phase)
gevent.sleep(5)
with gevent.Timeout(
timeout, Exception("Timeout waiting for phase %s" % phase)
):
while phase != self.chan_current_phase.get_value():
gevent.sleep(0.1)
self.wait_device_ready(30)
self.wait_device_ready(30)
_howlong = time.time() - _start
if _howlong > 11.0:
logging.getLogger("GUI").error(
"Changing phase to %s took %.1f seconds" % (phase, _howlong)
)
else:
self.cmd_start_set_phase(phase)
[docs] def start_auto_focus(self, timeout=None):
"""Autofocus method"""
if timeout:
self.ready_event.clear()
gevent.spawn(self.execute_server_task, self.cmd_start_auto_focus(), timeout)
self.ready_event.wait()
self.ready_event.clear()
else:
self.cmd_start_auto_focus()
[docs] def emit_diffractometer_moved(self, *args):
"""Emits diffractometerMoved signal"""
self.emit("diffractometerMoved", ())
[docs] def re_emit_values(self):
"""Reemits all signals"""
self.emit("minidiffPhaseChanged", (self.current_phase,))
self.emit("minidiffShutterStateChanged", (self.fast_shutter_is_open,))
self.emit("pixelsPerMmChanged", ((self.pixels_per_mm_x, self.pixels_per_mm_y),))
[docs] def move_omega(self, angle):
"""No need to implement"""
return
[docs] def set_zoom(self, position):
"""Sets zoom"""
self.zoom_motor_hwobj.move_to_position(position)
[docs] def get_osc_limits(self):
"""Return oscillation limits"""
return (-1e6, 1e6)
[docs] def get_scintillator_position(self):
"""Returns scintillator position"""
return self.chan_scintillator_position.get_value()
[docs] def set_scintillator_position(self, position):
"""Sets scintillator position"""
self.chan_scintillator_position.set_value(position)
with gevent.Timeout(5, Exception("Timeout waiting for scintillator position")):
while position != self.get_scintillator_position():
gevent.sleep(0.01)
[docs] def get_capillary_position(self):
"""Returns capillary position"""
return self.chan_capillary_position.get_value()
[docs] def set_capillary_position(self, position):
"""Moves capillary to requested position"""
self.chan_capillary_position.set_value(position)
with gevent.Timeout(5, Exception("Timeout waiting for capillary position")):
while position != self.get_capillary_position():
gevent.sleep(0.01)
[docs] def zoom_in(self):
"""Steps zoom one step in"""
self.zoom_motor_hwobj.zoom_in()
[docs] def zoom_out(self):
"""Steps zoom one step out"""
self.zoom_motor_hwobj.zoom_out()
[docs] def set_beamstop_park(self):
"""Sets beamstop to the parking position"""
self.chan_beamstop_position.set_value("PARK")
[docs] def set_beamstop_beam(self):
"""Sets beamstop in the beam position"""
self.chan_beamstop_position.set_value("BEAM")