diff --git a/mxcubecore/Command/Sardana.py b/mxcubecore/Command/Sardana.py
index 9c70617293..99940f17af 100644
--- a/mxcubecore/Command/Sardana.py
+++ b/mxcubecore/Command/Sardana.py
@@ -50,9 +50,10 @@
# from mxcubecore.TaskUtils import task
try:
- from sardana.taurus.core.tango.sardana import registerExtensions
from taurus import Device, Attribute
import taurus
+ from taurus.core.tango.enums import DevState
+ from taurus.core.tango.tangoattribute import TangoAttrValue
except Exception:
logging.getLogger("HWR").warning("Sardana is not available in this computer.")
@@ -191,10 +192,16 @@ def __call__(self, *args, **kwargs):
import time
self.t0 = time.time()
- if self.doorstate in ["ON", "ALARM"]:
+ if self.doorstate in [DevState.ON, DevState.ALARM]:
self.door.runMacro(fullcmd.split())
self.macrostate = SardanaMacro.STARTED
self.emit("commandBeginWaitReply", (str(self.name()),))
+
+ if wait:
+ logging.getLogger("HWR").debug("... start waiting...")
+ t = gevent.spawn(end_of_macro, self)
+ t.get()
+ logging.getLogger("HWR").debug("... end waiting...")
else:
logging.getLogger("HWR").error(
"%s. Cannot execute. Door is not READY", str(self.name())
@@ -226,29 +233,24 @@ def __call__(self, *args, **kwargs):
)
self.emit("commandFailed", (-1, self.name()))
- if wait:
- logging.getLogger("HWR").debug("... start waiting...")
- t = gevent.spawn(end_of_macro, self)
- t.get()
- logging.getLogger("HWR").debug("... end waiting...")
-
return
def update(self, event):
data = event.event[2]
try:
- if not isinstance(data, PyTango.DeviceAttribute):
+ if not isinstance(data, PyTango.DeviceAttribute) and \
+ not isinstance(data, TangoAttrValue):
# Events different than a value changed on attribute. Taurus sends an event with attribute info
# logging.getLogger('HWR').debug("==========. Got an event, but it is not an attribute . it is %s" % type(data))
# logging.getLogger('HWR').debug("doorstate event. type is %s" % str(type(data)))
return
# Handling macro state changed event
- doorstate = str(data.value)
- logging.getLogger("HWR").debug(
- "doorstate changed. it is %s" % str(doorstate)
- )
+ doorstate = data.rvalue
+ #logging.getLogger("HWR").debug(
+ #"doorstate changed. it is %s" % str(doorstate)
+ #)
if doorstate != self.doorstate:
self.doorstate = doorstate
@@ -256,24 +258,25 @@ def update(self, event):
# logging.getLogger('HWR').debug("self.doorstate is %s" % self.canExecute())
self.emit("commandCanExecute", (self.can_execute(),))
- if doorstate in ["ON", "ALARM"]:
+ if doorstate in [DevState.ON, DevState.ALARM]:
# logging.getLogger('HWR').debug("Macroserver ready for commands")
self.emit("commandReady", ())
else:
# logging.getLogger('HWR').debug("Macroserver busy ")
self.emit("commandNotReady", ())
- if self.macrostate == SardanaMacro.STARTED and doorstate == "RUNNING":
+ if self.macrostate == SardanaMacro.STARTED and \
+ doorstate == DevState.RUNNING:
# logging.getLogger('HWR').debug("Macro server is running")
self.macrostate = SardanaMacro.RUNNING
- elif self.macrostate == SardanaMacro.RUNNING and (
- doorstate in ["ON", "ALARM"]
+ elif self.macrostate == SardanaMacro.RUNNING and (\
+ doorstate in [DevState.ON, DevState.ALARM]
):
logging.getLogger("HWR").debug("Macro execution finished")
self.macrostate = SardanaMacro.DONE
self.result = self.door.result
self.emit("commandReplyArrived", (self.result, str(self.name())))
- if doorstate == "ALARM":
+ if doorstate == DevState.ALARM:
self.emit("commandAborted", (str(self.name()),))
self._reply_arrived_event.set()
elif (
@@ -412,22 +415,23 @@ def init_device(self):
return
# read information
- try:
- if taurus.Release.version_info[0] == 3:
- ranges = self.attribute.getConfig().getRanges()
- if ranges is not None and ranges[0] != "Not specified":
- self.info.minval = float(ranges[0])
- if ranges is not None and ranges[-1] != "Not specified":
- self.info.maxval = float(ranges[-1])
- elif taurus.Release.version_info[0] > 3: # taurus 4 and beyond
- minval, maxval = self.attribute.ranges()
- self.info.minval = minval.magnitude
- self.info.maxval = maxval.magnitude
- except Exception:
- import traceback
-
- logging.getLogger("HWR").info("info initialized. Cannot get limits")
- logging.getLogger("HWR").info("%s" % traceback.format_exc())
+ if "Position" in str(self.attribute): # RB: quick hack, find a better way to check if this channel is a position channel
+ try:
+ if taurus.Release.version_info[0] == 3:
+ ranges = self.attribute.getConfig().getRanges()
+ if ranges is not None and ranges[0] != "Not specified":
+ self.info.minval = float(ranges[0])
+ if ranges is not None and ranges[-1] != "Not specified":
+ self.info.maxval = float(ranges[-1])
+ elif taurus.Release.version_info[0] > 3: # taurus 4 and beyond
+ minval, maxval = self.attribute.getRanges()
+ self.info.minval = minval.magnitude
+ self.info.maxval = maxval.magnitude
+ except Exception:
+ import traceback
+
+ logging.getLogger("HWR").info("info initialized for Sardana channel %s. Cannot get limits" % self.model)
+ logging.getLogger("HWR").info("%s" % traceback.format_exc())
# prepare polling
# if the polling value is a number set it as the taurus polling period
@@ -441,26 +445,58 @@ def init_device(self):
def get_value(self):
return self._read_value()
+ def force_get_value(self):
+ return self._force_read_value()
+
def set_value(self, new_value):
self._write_value(new_value)
def _write_value(self, new_value):
self.attribute.write(new_value)
+ #TODO improve this: the magnitude is probably only available for certain channels, and the rvalue for others
+ # Instead of an exception, an if statement should decide which read method is to be applied,
+ # and a proper exception should be issued when necessary
def _read_value(self):
- value = self.attribute.read().value
+ value = None
+ if taurus.Release.version_info[0] == 3:
+ value = self.attribute.read().value
+ elif taurus.Release.version_info[0] > 3: # taurus 4 and beyond
+ try:
+ magnitude = getattr(self.attribute.rvalue, 'magnitude')
+ value = magnitude
+ except Exception:
+ value = self.attribute.rvalue
+ return value
+
+ def _force_read_value(self):
+ value = None
+ if taurus.Release.version_info[0] == 3: # not sure if this works in versions of taurus 3 and below
+ value = self.attribute.read(cache=False).value
+ elif taurus.Release.version_info[0] > 3: # taurus 4 and beyond
+ try:
+ value = getattr(self.attribute.read(cache=False).rvalue, 'magnitude')
+ except Exception:
+ value = self.attribute.rvalue
+
return value
def get_info(self):
try:
- b = dir(self.attribute)
- (
- self.info.minval,
- self.info.maxval,
- ) = self.attribute._TangoAttribute__attr_config.get_limits()
+ if taurus.Release.version_info[0] == 3:
+ ranges = self.attribute.getConfig().getRanges()
+ if ranges is not None and ranges[0] != "Not specified":
+ self.info.min_val = float(ranges[0])
+ if ranges is not None and ranges[-1] != "Not specified":
+ self.info.max_val = float(ranges[-1])
+ elif taurus.Release.version_info[0] > 3: # taurus 4 and beyond
+ range = getattr(self.attribute, 'range')
+ self.info.min_val = range[0].magnitude
+ self.info.max_val = range[1].magnitude
except Exception:
import traceback
+ logging.getLogger("HWR").info("info initialized. Cannot get limits")
logging.getLogger("HWR").info("%s" % traceback.format_exc())
return self.info
@@ -469,7 +505,14 @@ def update(self, event):
data = event.event[2]
try:
- new_value = data.value
+ new_value = None
+ if taurus.Release.version_info[0] == 3:
+ new_value = data.value
+ elif taurus.Release.version_info[0] > 3: # taurus 4 and beyond
+ try:
+ new_value = data.rvalue.magnitude
+ except Exception:
+ new_value = data.rvalue
if new_value is None:
new_value = self.get_value()
diff --git a/mxcubecore/Command/Tango.py b/mxcubecore/Command/Tango.py
index f7325697c7..816271e384 100644
--- a/mxcubecore/Command/Tango.py
+++ b/mxcubecore/Command/Tango.py
@@ -143,10 +143,7 @@ class TangoChannel(ChannelObject):
_tangoEventsQueue = queue.Queue()
_eventReceivers = {}
- if gevent_version < [1, 3, 0]:
- _tangoEventsProcessingTimer = getattr(gevent.get_hub().loop, "async")()
- else:
- _tangoEventsProcessingTimer = gevent.get_hub().loop.async_()
+ _tangoEventsProcessingTimer = gevent.get_hub().loop.async()
# start Tango events processing timer
_tangoEventsProcessingTimer.start(process_tango_events)
diff --git a/mxcubecore/CommandContainer.py b/mxcubecore/CommandContainer.py
index 5a9028eb6f..5a69525cf9 100644
--- a/mxcubecore/CommandContainer.py
+++ b/mxcubecore/CommandContainer.py
@@ -123,6 +123,10 @@ def connect_signal(self, signalName, callableFunc):
except Exception:
pass
dispatcher.connect(callableFunc, signalName, self)
+ # RB: do not commit
+ # The cats_simple_brick doesnt receive the powered signal,
+ # the following line fixes that, but a better solution needs to be found.
+ self.emit(signalName, self.get_value())
def disconnect_signal(self, signalName, callableFunc):
try:
diff --git a/mxcubecore/HardwareObjects/ALBA/ALBAAutoProcessing.py b/mxcubecore/HardwareObjects/ALBA/ALBAAutoProcessing.py
deleted file mode 100644
index 8990d358d9..0000000000
--- a/mxcubecore/HardwareObjects/ALBA/ALBAAutoProcessing.py
+++ /dev/null
@@ -1,216 +0,0 @@
-from xaloc import XalocJob
-from XSDataCommon import XSDataFile, XSDataString, XSDataInteger
-from XSDataAutoprocv1_0 import XSDataAutoprocInput
-from mxcubecore.BaseHardwareObjects import HardwareObject
-from PyTango import DeviceProxy
-import os
-import logging
-import math
-from datetime import datetime
-
-from ALBAClusterJob import ALBAEdnaProcJob
-
-import sys
-
-sys.path.append("/beamlines/bl13/controls/devel/pycharm/ALBAClusterClient")
-
-
-root = os.environ["POST_PROCESSING_SCRIPTS_ROOT"]
-sls_script = os.path.join(root, "gphl/autoproc/autoproc.process.sl")
-
-
-class ALBAAutoProcessing(HardwareObject):
- def init(self):
- HardwareObject.init(self)
-
- self.template_dir = self.get_property("template_dir")
- var_dsname = self.get_property("variables_ds")
- logging.getLogger("HWR").debug(
- "ALBAAutoProcessing INIT: var_ds=%s, template_dir=%s"
- % (var_dsname, self.template_dir)
- )
- self.var_ds = DeviceProxy(var_dsname)
-
- # input files for standard collection auto processing
- def create_input_files(self, xds_dir, mosflm_dir, dc_pars):
-
- fileinfo = dc_pars["fileinfo"]
- osc_seq = dc_pars["oscillation_sequence"][0]
-
- prefix = fileinfo["prefix"]
- runno = fileinfo["run_number"]
-
- exp_time = osc_seq["exposure_time"]
-
- start_angle = osc_seq["start"]
- nb_images = osc_seq["number_of_images"]
- start_img_num = osc_seq["start_image_number"]
- angle_increment = osc_seq["range"]
-
- wavelength = osc_seq.get("wavelength", 0)
-
- xds_template_name = "XDS_TEMPLATE.INP"
- mosflm_template_name = "mosflm_template.dat"
-
- xds_template_path = os.path.join(self.template_dir, xds_template_name)
- mosflm_template_path = os.path.join(self.template_dir, mosflm_template_name)
-
- xds_file = os.path.join(xds_dir, "XDS.INP")
- mosflm_file = os.path.join(mosflm_dir, "mosflm.dat")
-
- t = datetime.now()
-
- # PREPARE VARIABLES
- detsamdis = self.var_ds.detsamdis
- beamx, beamy = self.var_ds.beamx, self.var_ds.beamy
-
- mbeamx, mbeamy = beamy * 0.172, beamx * 0.172
-
- datarangestartnum = start_img_num
- datarangefinishnum = start_img_num + nb_images - 1
- backgroundrangestartnum = start_img_num
- spotrangestartnum = start_img_num
- if angle_increment != 0:
- minimumrange = int(round(20 / angle_increment))
- elif angle_increment == 0:
- minimumrange = 1
- if nb_images >= minimumrange:
- backgroundrangefinishnum = start_img_num + minimumrange - 1
- if nb_images >= minimumrange:
- spotrangefinishnum = start_img_num + minimumrange - 1
- if nb_images < minimumrange:
- backgroundrangefinishnum = start_img_num + nb_images - 1
- if nb_images < minimumrange:
- spotrangefinishnum = start_img_num + nb_images - 1
-
- testlowres = 8.0
- largestvector = (
- 0.172
- * ((max(beamx, 2463 - beamx)) ** 2 + (max(beamy, 2527 - beamy)) ** 2) ** 0.5
- )
- testhighres = round(
- wavelength / (2 * math.sin(0.5 * math.atan(largestvector / detsamdis))), 2
- )
- lowres = 50.0
- highres = testhighres
- datafilename = prefix + "_" + str(runno) + "_????"
- mdatafilename = prefix + "_" + str(runno) + "_####.cbf"
- seconds = 5 * exp_time
-
- if angle_increment < 1 and not angle_increment == 0:
- seconds = 5 * exp_time / angle_increment
-
- # DEFINE SG/UNIT CELL
- spacegroupnumber = ""
- unitcellconstants = ""
-
- datapath_dir = os.path.abspath(xds_file).replace("PROCESS_DATA", "RAW_DATA")
- datapath_dir = os.path.dirname(os.path.dirname(datapath_dir)) + os.path.sep
-
- # CREATE XDS.INP FILE
- xds_templ = open(xds_template_path, "r").read()
-
- xds_templ = xds_templ.replace("###BEAMX###", str(round(beamx, 2)))
- xds_templ = xds_templ.replace("###BEAMY###", str(round(beamy, 2)))
- xds_templ = xds_templ.replace("###DETSAMDIS###", str(round(detsamdis, 2)))
- xds_templ = xds_templ.replace("###ANGLEINCREMENT###", str(angle_increment))
- xds_templ = xds_templ.replace("###WAVELENGTH###", str(wavelength))
- xds_templ = xds_templ.replace("###DATARANGESTARTNUM###", str(datarangestartnum))
- xds_templ = xds_templ.replace(
- "###DATARANGEFINISHNUM###", str(datarangefinishnum)
- )
- xds_templ = xds_templ.replace(
- "###BACKGROUNDRANGESTART###", str(backgroundrangestartnum)
- )
- xds_templ = xds_templ.replace(
- "###BACKGROUNDRANGEFINISHNUM###", str(backgroundrangefinishnum)
- )
- xds_templ = xds_templ.replace("###SPOTRANGESTARTNUM###", str(spotrangestartnum))
- xds_templ = xds_templ.replace(
- "###SPOTRANGEFINISHNUM###", str(spotrangefinishnum)
- )
- xds_templ = xds_templ.replace("###TESTLOWRES###", str(testlowres))
- xds_templ = xds_templ.replace("###TESTHIGHRES###", str(testhighres))
- xds_templ = xds_templ.replace("###LOWRES###", str(lowres))
- xds_templ = xds_templ.replace("###HIGHRES###", str(highres))
- xds_templ = xds_templ.replace("###DIRECTORY###", str(datapath_dir))
- xds_templ = xds_templ.replace("###FILENAME###", str(datafilename))
- xds_templ = xds_templ.replace("###SECONDS###", str(int(seconds)))
- xds_templ = xds_templ.replace(
- "###LYSOZYME_SPACE_GROUP_NUMBER###", str(spacegroupnumber)
- )
- xds_templ = xds_templ.replace(
- "###LYSOZYME_UNIT_CELL_CONSTANTS###", str(unitcellconstants)
- )
-
- open(xds_file, "w").write(xds_templ)
-
- # CREATE MOSFLM.DAT FILE
-
- mosflm_templ = open(mosflm_template_path, "r").read()
-
- mosflm_templ = mosflm_templ.replace("###DETSAMDIS###", str(round(detsamdis, 2)))
- mosflm_templ = mosflm_templ.replace("###BEAMX###", str(round(mbeamx, 2)))
- mosflm_templ = mosflm_templ.replace("###BEAMY###", str(round(mbeamy, 2)))
- mosflm_templ = mosflm_templ.replace("###DIRECTORY###", str(datapath_dir))
- mosflm_templ = mosflm_templ.replace("###FILENAME###", str(mdatafilename))
- mosflm_templ = mosflm_templ.replace("###WAVELENGTH###", str(wavelength))
- mosflm_templ = mosflm_templ.replace(
- "###DATARANGESTARTNUM###", str(datarangestartnum)
- )
-
- open(mosflm_file, "w").write(mosflm_templ)
-
- # CREATE EDNAPROC XML FILE
- collection_id = dc_pars["collection_id"]
- output_dir = dc_pars["ednaproc_dir"]
-
- ednaproc_input_file = os.path.join(
- output_dir, "EDNAprocInput_%d.xml" % collection_id
- )
-
- ednaproc_input = XSDataAutoprocInput()
-
- input_file = XSDataFile()
- path = XSDataString()
- path.set_value(xds_file)
- input_file.setPath(path)
-
- ednaproc_input.setInput_file(input_file)
- ednaproc_input.setData_collection_id(XSDataInteger(collection_id))
-
- # output_dir = XSDataFile()
- # outpath = XSDataString()
- # outpath.set_value(output_dir)
- # output_dir.setPath(path)
-
- # ednaproc_input.setOutput_directory( output_dir )
-
- ednaproc_input.exportToFile(ednaproc_input_file)
-
- self.input_file = ednaproc_input_file
-
- # trigger auto processing for standard collection
- def trigger_auto_processing(self, dc_pars):
- logging.getLogger("HWR").debug(
- " ALBAAutoProcessing. triggering auto processing."
- )
-
- dc_id = dc_pars["collection_id"]
- output_dir = dc_pars["ednaproc_dir"]
-
- logging.getLogger("HWR").debug(" - collection_id = %s " % dc_id)
- logging.getLogger("HWR").debug(" - output_dir = %s " % output_dir)
-
- job = ALBAEdnaProcJob()
- input_file = self.input_file # TODO
-
- job.run(dc_id, input_file, output_dir)
-
-
-def test_hwo(hwo):
- ofile = "/tmp/edna/edna_result"
- odir = "/tmp/edna"
- test_input_file = "/beamlines/bl13/projects/cycle2018-I/2018012551-bcalisto/mx2018012551/DATA/20180131/PROCESS_DATA/characterisation_ref-Thrombin-TB-TTI1_A_run1_1/EDNAInput_2004391.xml"
- result = hwo.run_edna(test_input_file, ofile, odir)
- print(result)
diff --git a/mxcubecore/HardwareObjects/ALBA/ALBABeamInfo.py b/mxcubecore/HardwareObjects/ALBA/ALBABeamInfo.py
deleted file mode 100644
index bcc29ef5c8..0000000000
--- a/mxcubecore/HardwareObjects/ALBA/ALBABeamInfo.py
+++ /dev/null
@@ -1,198 +0,0 @@
-"""
-[Name] BeamInfo
-
-[Description]
-BeamInfo hardware object is used to define final beam size and shape.
-It can include aperture, slits and/or other beam definer (lenses or other eq.)
-
-[Emited signals]
-beamInfoChanged
-beamPosChanged
-
-[Included Hardware Objects]
------------------------------------------------------------------------
-| name | signals | functions
------------------------------------------------------------------------
- aperture_hwobj apertureChanged
- slits_hwobj
- beam_definer_hwobj
------------------------------------------------------------------------
-"""
-
-import logging
-from mxcubecore.BaseHardwareObjects import Equipment
-
-
-class ALBABeamInfo(Equipment):
- """
- Description:
- """
-
- def __init__(self, *args):
- """
- Descrip. :
- """
- Equipment.__init__(self, *args)
-
- self.aperture_hwobj = None
- self.slits_hwobj = None
-
- self.beam_size_slits = None
- self.beam_size_aperture = None
- self.beam_size_definer = None
- self.beam_position = None
- self.beam_info_dict = None
- self.default_beam_divergence = None
-
- def init(self):
- """
- Descript. :
- """
- self.beam_size_slits = [9999, 9999]
- self.beam_size_aperture = [9999, 9999]
- self.beam_size_definer = [9999, 9999]
-
- self.beam_position = [0, 0]
- self.beam_info_dict = {}
-
- self.beam_width_chan = self.get_channel_object("BeamWidth")
- self.beam_height_chan = self.get_channel_object("BeamHeight")
- self.beam_posx_chan = self.get_channel_object("BeamPositionHorizontal")
- self.beam_posy_chan = self.get_channel_object("BeamPositionVertical")
-
- self.beam_height_chan.connect_signal("update", self.beam_height_changed)
- self.beam_width_chan.connect_signal("update", self.beam_width_changed)
- self.beam_posx_chan.connect_signal("update", self.beam_posx_changed)
- self.beam_posy_chan.connect_signal("update", self.beam_posy_changed)
-
- # divergence can be added as fixed properties in xml
- default_beam_divergence_vertical = None
- default_beam_divergence_horizontal = None
-
- try:
- default_beam_divergence_vertical = int(
- self.get_property("beam_divergence_vertical")
- )
- default_beam_divergence_horizontal = int(
- self.get_property("beam_divergence_horizontal")
- )
- except Exception:
- pass
-
- self.default_beam_divergence = [
- default_beam_divergence_horizontal,
- default_beam_divergence_vertical,
- ]
-
- def connect_notify(self, *args):
- self.evaluate_beam_info()
- self.re_emit_values()
-
- def get_beam_divergence_hor(self):
- """
- Descript. :
- """
- return self.default_beam_divergence[0]
-
- def get_beam_divergence_ver(self):
- """
- Descript. :
- """
- return self.default_beam_divergence[1]
-
- def get_beam_position(self):
- """
- Descript. :
- Arguments :
- Return :
- """
- self.beam_position = (
- self.beam_posx_chan.get_value(),
- self.beam_posy_chan.get_value(),
- )
- return self.beam_position
-
- def get_slits_gap(self):
- return None, None
-
- def set_beam_position(self, beam_x, beam_y):
- """
- Descript. :
- Arguments :
- Return :
- """
- self.beam_position = (beam_x, beam_y)
-
- def get_beam_info(self):
- """
- Descript. :
- Arguments :
- Return :
- """
- return self.evaluate_beam_info()
-
- def get_beam_size(self):
- """
- Descript. : returns beam size in millimeters
- Return : list with two integers
- """
- self.evaluate_beam_info()
- return self.beam_info_dict["size_x"], self.beam_info_dict["size_y"]
-
- def get_beam_shape(self):
- """
- Descript. :
- Arguments :
- Return :
- """
- return self.beam_info_dict["shape"]
-
- def beam_width_changed(self, value):
- self.beam_info_dict["size_x"] = value
- self.re_emit_values()
-
- def beam_height_changed(self, value):
- self.beam_info_dict["size_y"] = value
- self.re_emit_values()
-
- def beam_posx_changed(self, value):
- self.beam_position["x"] = value
- self.re_emit_values()
-
- def beam_posy_changed(self, value):
- self.beam_position["y"] = value
- self.re_emit_values()
-
- def evaluate_beam_info(self):
- """
- Descript. : called if aperture, slits or focusing has been changed
- Return : dictionary,{size_x:0.1, size_y:0.1, shape:"rectangular"}
- """
-
- self.beam_info_dict["size_x"] = self.beam_width_chan.get_value() / 1000.0
- self.beam_info_dict["size_y"] = self.beam_height_chan.get_value() / 1000.0
- self.beam_info_dict["shape"] = "rectangular"
-
- return self.beam_info_dict
-
- def re_emit_values(self):
- """
- Descript. :
- Arguments :
- Return :
- """
- logging.getLogger("HWR").debug(" emitting beam info")
- if (
- self.beam_info_dict["size_x"] != 9999
- and self.beam_info_dict["size_y"] != 9999
- ):
- self.emit(
- "beamSizeChanged",
- ((self.beam_info_dict["size_x"], self.beam_info_dict["size_y"]),),
- )
- self.emit("beamInfoChanged", (self.beam_info_dict,))
-
-
-def test_hwo(hwo):
- print(hwo.get_beam_info())
- print(hwo.get_beam_position())
diff --git a/mxcubecore/HardwareObjects/ALBA/ALBACalibration.py b/mxcubecore/HardwareObjects/ALBA/ALBACalibration.py
deleted file mode 100644
index fe987fa070..0000000000
--- a/mxcubecore/HardwareObjects/ALBA/ALBACalibration.py
+++ /dev/null
@@ -1,84 +0,0 @@
-#
-# Project: 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 .
-
-"""
-[Name]
-ALBACalibration
-
-[Description]
-HwObj used to grab the zoom/pixel size calibration from
-PySignal simulator (TangoDS).
-
-
-Example Hardware Object XML file :
-==================================
-
- Calibration
- bl13/ct/variables
- OAV_PIXELSIZE_X
- OAV_PIXELSIZE_Y
- 200
- 0.001
-
-"""
-
-from mxcubecore import HardwareRepository as HWR
-from mxcubecore import BaseHardwareObjects
-import logging
-
-__author__ = "Jordi Andreu"
-__credits__ = ["MXCuBE collaboration"]
-
-__version__ = "2.2."
-__maintainer__ = "Jordi Andreu"
-__email__ = "jandreu[at]cells.es"
-__status__ = "Draft"
-
-
-class ALBACalibration(BaseHardwareObjects.Device):
- def __init__(self, name):
- BaseHardwareObjects.Device.__init__(self, name)
-
- def init(self):
-
- self.calibx = self.get_channel_object("calibx")
- self.caliby = self.get_channel_object("caliby")
-
- if self.calibx is not None and self.caliby is not None:
- logging.getLogger().info("Connected to pixel size calibration channels")
-
- def getCalibration(self):
- calibx = self.calibx.get_value()
- caliby = self.caliby.get_value()
- logging.getLogger().debug(
- "Returning calibration: x=%s, y=%s" % (calibx, caliby)
- )
- return [calibx, caliby]
-
-
-def test():
- hwr = HWR.get_hardware_repository()
- hwr.connect()
-
- calib = hwr.get_hardware_object("/calibration")
- print("Calibration is: ", calib.getCalibration())
-
-
-if __name__ == "__main__":
- test()
diff --git a/mxcubecore/HardwareObjects/ALBA/ALBACats.py b/mxcubecore/HardwareObjects/ALBA/ALBACats.py
deleted file mode 100644
index b292f2deff..0000000000
--- a/mxcubecore/HardwareObjects/ALBA/ALBACats.py
+++ /dev/null
@@ -1,674 +0,0 @@
-from __future__ import print_function
-
-from mxcubecore.HardwareObjects.Cats90 import (
- Cats90,
- SampleChangerState,
- TOOL_SPINE,
-)
-
-import logging
-import time
-import gevent
-
-TIMEOUT = 3
-
-
-class ALBACats(Cats90):
- """
- Main class used @ ALBA to integrate the CATS-IRELEC sample changer.
- """
-
- def __init__(self, *args):
- Cats90.__init__(self, *args)
-
- def init(self):
- Cats90.init(self)
-
- self.shifts_channel = self.get_channel_object("shifts")
- self.phase_channel = self.get_channel_object("phase")
-
- self.go_transfer_cmd = self.get_command_object("go_transfer")
- self.go_sampleview_cmd = self.get_command_object("go_sampleview")
- self.super_abort_cmd = self.get_command_object("super_abort")
- self.super_state_channel = self.get_channel_object("super_state")
-
- self.auto_prepare_diff = self.get_property("auto_prepare_diff")
- self.detdist_position_channel = self.get_channel_object("detdist_position")
- self.detdist_saved = None
-
- self._cmdLoadHT = self.get_command_object("_cmdLoadHT")
- self._cmdChainedLoadHT = self.get_command_object("_cmdChainedLoadHT")
- self._cmdUnloadHT = self.get_command_object("_cmdUnloadHT")
-
- self._chnPathSafe = self.get_channel_object("_chnPathSafe")
-
- if self._chnPathRunning is not None:
- self._chnPathRunning.connect_signal("update", self._update_running_state)
-
- if self._chnPowered is not None:
- self._chnPowered.connect_signal("update", self._update_powered_state)
-
- def is_ready(self):
- """
- Returns a boolean value indicating is the sample changer is ready for operation.
-
- @return: boolean
- """
- return (
- self.state == SampleChangerState.Ready
- or self.state == SampleChangerState.Loaded
- or self.state == SampleChangerState.Charging
- or self.state == SampleChangerState.StandBy
- or self.state == SampleChangerState.Disabled
- )
-
- def diff_send_transfer(self):
- """
- Checks if beamline supervisor is in TRANSFER phase (i.e. sample changer in TRANSFER phase too).
- If is not the case, It sends the sample changer to TRANFER phase.
- Returns a boolean value indication if the sample changer is in TRANSFER phase.
-
- @return: boolean
- """
- if self.read_super_phase().upper() == "TRANSFER":
- logging.getLogger("user_level_log").error(
- "Supervisor is already in transfer phase"
- )
- return True
-
- self.go_transfer_cmd()
- ret = self._wait_phase_done("TRANSFER")
- return ret
-
- def diff_send_sampleview(self):
- """
- Checks if beamline supervisor is in SAMPLE phase (i.e. sample changer in SAMPLE phase too).
- If is not the case, It sends the sample changer to SAMPLE phase.
- Returns a boolean value indication if the sample changer is in SAMPLE phase.
-
- @return: boolean
- """
- if self.read_super_phase().upper() == "SAMPLE":
- logging.getLogger("user_level_log").error(
- "Supervisor is already in sample view phase"
- )
- return True
-
- t0 = time.time()
- while True:
- state = str(self.super_state_channel.get_value())
- if str(state) == "ON":
- break
-
- if (time.time() - t0) > TIMEOUT:
- logging.getLogger("user_level_log").error(
- "Supervisor timeout waiting for ON state. Returning"
- )
- return False
-
- time.sleep(0.1)
-
- self.go_sampleview_cmd()
- ret = self._wait_phase_done("SAMPLE")
- return ret
-
- def _wait_super_ready(self):
- while True:
- state = str(self.super_state_channel.get_value())
- if state == "ON":
- logging.getLogger("user_level_log").error(
- "Supervisor is in ON state. Returning"
- )
- break
-
- def _wait_phase_done(self, final_phase):
- """
- Method to wait a phase change. When supervisor reaches the final phase, the diffracometer
- returns True.
-
- @final_phase: target phase
- @return: boolean
- """
- while True:
- state = str(self.super_state_channel.get_value())
- if state == "ON":
- logging.getLogger("user_level_log").error(
- "Supervisor is in ON state. Returning"
- )
- break
- elif str(state) != "MOVING":
- logging.getLogger("user_level_log").error(
- "Supervisor is in a funny state %s" % str(state)
- )
- return False
-
- logging.getLogger("HWR").debug("Supervisor waiting to finish phase change")
- time.sleep(0.2)
-
- time.sleep(0.1)
-
- if self.read_super_phase().upper() != final_phase:
- logging.getLogger("user_level_log").error(
- "Supervisor is not yet in %s phase. Aborting load" % final_phase
- )
- return False
- else:
- return True
-
- def save_detdist_position(self):
- self.detdist_saved = self.detdist_position_channel.get_value()
- logging.getLogger("user_level_log").error(
- "Saving current det.distance (%s)" % self.detdist_saved
- )
-
- def restore_detdist_position(self):
- if abs(self.detdist_saved - self.detdist_position_channel.get_value()) >= 0.1:
- logging.getLogger("user_level_log").error(
- "Restoring det.distance to %s" % self.detdist_saved
- )
- self.detdist_position_channel.set_value(self.detdist_saved)
- time.sleep(0.4)
- self._wait_super_ready()
-
- def read_super_phase(self):
- """
- Returns supervisor phase (CurrentPhase attribute from Beamline Supervisor Tango DS)
-
- @return: str
- """
- return self.phase_channel.get_value()
-
- def load(self, sample=None, wait=False, wash=False):
- """
- Loads a sample. Overides to include ht basket.
-
- @sample: sample to load.
- @wait:
- @wash: wash dring the load opearation.
- @return:
- """
-
- logging.getLogger("HWR").debug(
- "Loading sample %s / type(%s)" % (sample, type(sample))
- )
-
- ret, msg = self._check_coherence()
- if not ret:
- raise Exception(msg)
-
- sample_ht = self.is_ht_sample(sample)
-
- if not sample_ht:
- sample = self._resolve_component(sample)
- self.assert_not_charging()
- use_ht = False
- else:
- sample = sample_ht
- use_ht = True
-
- if self.has_loaded_sample():
- if (wash is False) and self.get_loaded_sample() == sample:
- raise Exception(
- "The sample " + sample.get_address() + " is already loaded"
- )
- else:
- # Unload first / do a chained load
- pass
-
- return self._execute_task(
- SampleChangerState.Loading, wait, self._do_load, sample, None, use_ht
- )
-
- def unload(self, sample_slot=None, wait=False):
- """
- Unload the sample. If sample_slot=None, unloads to the same slot the sample was loaded from.
-
- @sample_slot:
- @wait:
- @return:
- """
- sample_slot = self._resolve_component(sample_slot)
-
- self.assert_not_charging()
-
- # In case we have manually mounted we can command an unmount
- if not self.has_loaded_sample():
- raise Exception("No sample is loaded")
-
- return self._execute_task(
- SampleChangerState.Unloading, wait, self._do_unload, sample_slot
- )
-
- # TODO: this overides identical method from Cats90
- def is_powered(self):
- return self._chnPowered.get_value()
-
- # TODO: this overides identical method from Cats90
- def is_path_running(self):
- return self._chnPathRunning.get_value()
-
- # TODO: this overides method from AbstractSampleChanger
- # def has_loaded_sample(self): # not used. to use it remove _
- # return self._chnSampleIsDetected.get_value()
-
- def _update_running_state(self, value):
- """
- Emits signal with new Running State
-
- @value: New running state
- """
- self.emit("runningStateChanged", (value,))
-
- def _update_powered_state(self, value):
- """
- Emits signal with new Powered State
-
- @value: New powered state
- """
- self.emit("powerStateChanged", (value,))
-
- def _do_load(self, sample=None, shifts=None, use_ht=False):
- """
- Loads a sample on the diffractometer. Performs a simple put operation if the diffractometer is empty, and
- a sample exchange (unmount of old + mount of new sample) if a sample is already mounted on the diffractometer.
- Overides Cats90 method.
-
- @sample: sample to load.
- @shifts: mounting point offsets.
- @use_ht: mount a sample from hot tool.
- """
- if not self._chnPowered.get_value():
- self._cmdPowerOn() # try switching power on
-
- current_tool = self.get_current_tool()
-
- self.save_detdist_position()
- ret = self.diff_send_transfer()
-
- if ret is False:
- logging.getLogger("user_level_log").error(
- "Supervisor cmd transfer phase returned an error."
- )
- self._update_state() # remove transient states like Loading. Reflect hardware state
- raise Exception(
- "CATS cannot get to transfer phase. Aborting sample changer operation."
- )
-
- gevent.sleep(3)
- if not self._chnPowered.get_value():
- raise Exception(
- "CATS power is not enabled. Please switch on arm power before transferring samples."
- )
-
- # obtain mounting offsets from diffr
- shifts = self._get_shifts()
-
- if shifts is None:
- xshift, yshift, zshift = ["0", "0", "0"]
- else:
- xshift, yshift, zshift = map(str, shifts)
-
- # get sample selection
- selected = self.get_selected_sample()
-
- logging.getLogger("HWR").debug(
- " ==========CATS=== selected sample is %s (prev %s)"
- % (str(selected), str(sample))
- )
-
- if not use_ht:
- if sample is not None:
- if sample != selected:
- self._do_select(sample)
- selected = self.get_selected_sample()
- else:
- if selected is not None:
- sample = selected
- else:
- raise Exception("No sample selected")
- else:
- selected = None
-
- # some cancel cases
- if (
- not use_ht
- and self.has_loaded_sample()
- and selected == self.get_loaded_sample()
- ):
- self._update_state() # remove transient states like Loading. Reflect hardware state
- raise Exception(
- "The sample "
- + str(self.get_loaded_sample().get_address())
- + " is already loaded"
- )
-
- if not self.has_loaded_sample() and self.cats_sample_on_diffr() == 1:
- logging.getLogger("HWR").warning(
- " ==========CATS=== sample on diffr, loading aborted"
- )
- self._update_state() # remove transient states like Loading. Reflect hardware state
- raise Exception(
- "The sample "
- + str(self.get_loaded_sample().get_address())
- + " is already loaded"
- )
- return
-
- if self.cats_sample_on_diffr() == -1:
- self._update_state() # remove transient states like Loading. Reflect hardware state
- raise Exception(
- "Conflicting info between diffractometer and on-magnet detection. Consider 'Clear'"
- )
- return
-
- # end some cancel cases
-
- # if load_ht
- loaded_ht = self.is_loaded_ht()
-
- #
- # Loading HT sample
- #
- if use_ht: # loading HT sample
-
- if loaded_ht == -1: # has loaded but it is not HT
- # first unmount (non HT)
- logging.getLogger("HWR").warning(
- " ==========CATS=== mix load/unload dewar vs HT (NOT IMPLEMENTED YET)"
- )
- return
-
- argin = ["2", str(sample), "0", "0", xshift, yshift, zshift]
- logging.getLogger("HWR").warning(
- " ==========CATS=== about to load HT. %s" % str(argin)
- )
- if loaded_ht == 1: # has ht loaded
- cmd_ok = self._execute_server_task(
- self._cmdChainedLoadHT, argin, waitsafe=True
- )
- else:
- cmd_ok = self._execute_server_task(
- self._cmdLoadHT, argin, waitsafe=False
- )
-
- #
- # Loading non HT sample
- #
- else:
- if loaded_ht == 1: # has an HT sample mounted
- # first unmount HT
- logging.getLogger("HWR").warning(
- " ==========CATS=== mix load/unload dewar vs HT (NOT IMPLEMENTED YET)"
- )
- return
-
- # calculate CATS specific lid/sample number
- # lid = ((selected.get_basket_no() - 1) / 3) + 1
- # sample = (((selected.get_basket_no() - 1) % 3) * 10) + selected.get_vial_no()
-
- basketno = selected.get_basket_no()
- sampleno = selected.get_vial_no()
-
- lid, sample = self.basketsample_to_lidsample(basketno, sampleno)
- tool = self.tool_for_basket(basketno)
- stype = self.get_cassette_type(basketno)
-
- if tool != current_tool:
- logging.getLogger("HWR").warning(
- " ==========CATS=== changing tool from %s to %s"
- % (current_tool, tool)
- )
- changing_tool = True
- else:
- changing_tool = False
-
- # we should now check basket type on diffr to see if tool is different...
- # then decide what to do
-
- if shifts is None:
- xshift, yshift, zshift = ["0", "0", "0"]
- else:
- xshift, yshift, zshift = map(str, shifts)
-
- # prepare argin values
- argin = [
- str(tool),
- str(lid),
- str(sample),
- str(stype),
- "0",
- xshift,
- yshift,
- zshift,
- ]
-
- if tool == 2:
- read_barcode = (
- self.read_datamatrix and self._cmdChainedLoadBarcode is not None
- )
- else:
- if self.read_datamatrix:
- logging.getLogger("HWR").warning(
- " ==========CATS=== reading barcode only possible with spine pucks"
- )
- read_barcode = False
-
- if loaded_ht == -1: # has a loaded but it is not an HT
-
- if changing_tool:
- raise Exception(
- "This operation requires a tool change. You should unload sample first"
- )
-
- if read_barcode:
- logging.getLogger("HWR").warning(
- " ==========CATS=== chained load sample (barcode), sending to cats: %s"
- % argin
- )
- cmd_ok = self._execute_server_task(
- self._cmdChainedLoadBarcode, argin, waitsafe=True
- )
- else:
- logging.getLogger("HWR").warning(
- " ==========CATS=== chained load sample, sending to cats: %s"
- % argin
- )
- cmd_ok = self._execute_server_task(
- self._cmdChainedLoad, argin, waitsafe=True
- )
- elif loaded_ht == 0:
- if read_barcode:
- logging.getLogger("HWR").warning(
- " ==========CATS=== load sample (barcode), sending to cats: %s"
- % argin
- )
- cmd_ok = self._execute_server_task(
- self._cmdLoadBarcode, argin, waitsafe=True
- )
- else:
- logging.getLogger("HWR").warning(
- " ==========CATS=== load sample, sending to cats: %s" % argin
- )
- cmd_ok = self._execute_server_task(
- self._cmdLoad, argin, waitsafe=True
- )
-
- if not cmd_ok:
- logging.getLogger("HWR").info(" LOAD Command failed on device server")
- elif self.auto_prepare_diff and not changing_tool:
- logging.getLogger("HWR").info(
- " AUTO_PREPARE_DIFF (On) sample changer is in safe state... preparing diff now"
- )
- # ret = self.diff_send_sampleview()
- self.go_sampleview_cmd()
- logging.getLogger("HWR").info(" restoring detector distance")
- self.restore_detdist_position()
- self._wait_phase_done("SAMPLE")
- else:
- logging.getLogger("HWR").info(
- " AUTO_PREPARE_DIFF (Off) sample loading done / or changing tool (%s)"
- % changing_tool
- )
-
- # load commands are executed until path is safe. Then we have to wait for
- # path to be finished
- self._wait_device_ready()
-
- def _do_unload(self, sample_slot=None, shifts=None):
- """
- Unloads a sample from the diffractometer.
- Overides Cats90 method.
-
- @sample_slot:
- @shifts: mounting position
- """
- if not self._chnPowered.get_value():
- self._cmdPowerOn() # try switching power on
-
- ret = self.diff_send_transfer()
-
- if ret is False:
- logging.getLogger("user_level_log").error(
- "Supervisor cmd transfer phase returned an error."
- )
- return
-
- shifts = self._get_shifts()
-
- if sample_slot is not None:
- self._do_select(sample_slot)
-
- loaded_ht = self.is_loaded_ht()
-
- if shifts is None:
- xshift, yshift, zshift = ["0", "0", "0"]
- else:
- xshift, yshift, zshift = map(str, shifts)
-
- loaded_lid = self._chnLidLoadedSample.get_value()
- loaded_num = self._chnNumLoadedSample.get_value()
-
- if loaded_lid == -1:
- logging.getLogger("HWR").warning(
- " ==========CATS=== unload sample, no sample mounted detected"
- )
- return
-
- loaded_basket, loaded_sample = self.lidsample_to_basketsample(
- loaded_lid, loaded_num
- )
-
- tool = self.tool_for_basket(loaded_basket)
-
- argin = [str(tool), "0", xshift, yshift, zshift]
-
- logging.getLogger("HWR").warning(
- " ==========CATS=== unload sample, sending to cats: %s" % argin
- )
- if loaded_ht == 1:
- cmd_ret = self._execute_server_task(self._cmdUnloadHT, argin)
- else:
- cmd_ret = self._execute_server_task(self._cmdUnload, argin)
-
- def _do_abort(self):
- """
- Aborts a running trajectory on the sample changer.
-
- :returns: None
- :rtype: None
- """
- if self.super_abort_cmd is not None:
- self.super_abort_cmd() # stops super
- self._cmdAbort()
- self._update_state() # remove software flags like Loading.. reflects current hardware state
-
- def _check_coherence(self):
- detected = self._chnSampleIsDetected.get_value()
- loaded_lid = self._chnLidLoadedSample.get_value()
- loaded_num = self._chnNumLoadedSample.get_value()
-
- if -1 in [loaded_lid, loaded_num] and detected:
- return False, "Sample detected on Diffract. but there is no info about it"
-
- return True, ""
-
- def _get_shifts(self):
- """
- Get the mounting position from the Diffractometer DS.
-
- @return: 3-tuple
- """
- if self.shifts_channel is not None:
- shifts = self.shifts_channel.get_value()
- else:
- shifts = None
- return shifts
-
- # def path_running(self):
- # """
- # Overides Cats90 method.
- #
- # @return:
- # """
- # return (self._chnPathSafe.get_value() is not True)
-
- # TODO: fix return type
- def is_ht_sample(self, address):
- """
- Returns is sample address belongs to hot tool basket.
-
- @address: sample address
- @return: int or boolean
- """
- basket, sample = address.split(":")
- try:
- if int(basket) >= 100:
- return int(sample)
- else:
- return False
- except Exception:
- return False
-
- def tool_for_basket(self, basketno):
- """
- Returns the tool corresponding to the basket.
-
- @basketno: basket number
- @return: int
- """
- if basketno == 100:
- return TOOL_SPINE
-
- return Cats90.tool_for_basket(self, basketno)
-
- def is_loaded_ht(self):
- """
- 1 : has loaded ht
- 0 : nothing loaded
- -1 : loaded but not ht
- """
- sample_lid = self._chnLidLoadedSample.get_value()
-
- if self.has_loaded_sample():
- if sample_lid == 100:
- return 1
- else:
- return -1
- else:
- return 0
-
-
-def test_hwo(hwo):
- hwo._update_cats_contents()
- print(" Is path running? ", hwo.is_path_running())
- print(" Loading shifts: ", hwo._get_shifts())
- print(" Sample on diffr : ", hwo.cats_sample_on_diffr())
- print(" Baskets : ", hwo.basket_presence)
- print(" Baskets : ", hwo.get_basket_list())
- if hwo.has_loaded_sample():
- print(" Loaded is: ", hwo.get_loaded_sample().get_coords())
- print(" Is mounted sample: ", hwo.is_mounted_sample((1, 1)))
-
-
-if __name__ == "__main__":
- test()
diff --git a/mxcubecore/HardwareObjects/ALBA/ALBACatsMaint.py b/mxcubecore/HardwareObjects/ALBA/ALBACatsMaint.py
deleted file mode 100644
index bcff58c5fc..0000000000
--- a/mxcubecore/HardwareObjects/ALBA/ALBACatsMaint.py
+++ /dev/null
@@ -1,64 +0,0 @@
-from mxcubecore.HardwareObjects.abstract.sample_changer.CatsMaint import (
- CatsMaint,
-)
-
-
-class ALBACatsMaint(CatsMaint):
- def __init__(self, *args):
- CatsMaint.__init__(self, *args)
-
- def init(self):
- CatsMaint.init(self)
-
- # load ALBA attributes and commands from XML
- self._chnAtHome = self.get_channel_object("_chnAtHome")
- self.super_abort_cmd = self.get_command_object("super_abort")
-
- # channel to ask diffractometer for mounting position
- self.shifts_channel = self.get_channel_object("shifts")
-
- def _do_abort(self):
- if self.super_abort_cmd is not None:
- self.super_abort_cmd()
- self._cmdAbort()
-
- def _do_reset_memory(self):
- """
- Reset CATS memory.
- """
- # Check do_PRO6_RAH first
- if self._chnAtHome.get_value() is True:
- CatsMaint._do_reset_memory(self)
-
- def _do_reset(self):
- """
- Reset CATS system.
- """
- self._cmdAbort()
- self._cmdReset()
- self._do_reset_memory()
-
- def _do_operation_command(self, cmd, pars):
- """
- Send a CATS command
-
- @cmd: command
- @pars: command arguments
- """
- CatsMaint._do_operation_command(self)
-
- def _get_shifts(self):
- """
- Get the mounting position from the Diffractometer DS.
-
- @return: 3-tuple
- """
- if self.shifts_channel is not None:
- shifts = self.shifts_channel.get_value()
- else:
- shifts = None
- return shifts
-
-
-def test_hwo(hwo):
- print(hwo._get_shifts())
diff --git a/mxcubecore/HardwareObjects/ALBA/ALBAClusterJob.py b/mxcubecore/HardwareObjects/ALBA/ALBAClusterJob.py
deleted file mode 100644
index 644eb39522..0000000000
--- a/mxcubecore/HardwareObjects/ALBA/ALBAClusterJob.py
+++ /dev/null
@@ -1,117 +0,0 @@
-from XSDataMXCuBEv1_3 import XSDataResultMXCuBE
-from xaloc import XalocJob
-import os
-import time
-import logging
-
-import sys
-
-sys.path.append("/beamlines/bl13/controls/devel/pycharm/ALBAClusterClient")
-
-
-root = os.environ["POST_PROCESSING_SCRIPTS_ROOT"]
-
-
-class ALBAClusterJob(object):
- def __init__(self, *args):
- self.job = None
-
- def run(self, *args):
- pass
-
- def wait_done(self, wait=True):
-
- if not self.job:
- return
-
- time.sleep(0.5)
-
- state = self.job.state
-
- if not wait:
- return state
-
- while state in ["RUNNING", "PENDING"]:
- logging.getLogger("HWR").debug("Job / is %s" % state)
- time.sleep(0.5)
- state = self.job.state
-
- logging.getLogger("HWR").debug(' job finished with state: "%s"' % state)
- return state
-
- def get_result(self, state):
- pass
-
-
-class ALBAAutoprocJob(ALBAClusterJob):
- sls_script = os.path.join(root, "edna-mx/autoproc/edna-mx.autoproc.sl")
-
- def run(self, *args):
-
- jobname = os.path.basename(os.path.dirname(edna_directory))
- self.job = XalocJob(
- "edna-autoproc", jobname, self.sls_script, input_file, edna_directory
- )
- self.job.submit()
-
-
-class ALBAEdnaProcJob(ALBAClusterJob):
- sls_script = os.path.join(root, "edna-mx/ednaproc/edna-mx.ednaproc.sl")
-
- def run(self, *args):
- collect_id, input_file, output_dir = args
- self.job = XalocJob(
- "edna-ednaproc", str(collect_id), self.sls_script, input_file, output_dir
- )
- self.job.submit()
-
-
-class ALBAStrategyJob(ALBAClusterJob):
-
- sls_script = os.path.join(root, "edna-mx/strategy/edna-mx.strategy.sl")
-
- def run(self, *args):
-
- logging.getLogger("HWR").debug("Starting StrategyJob - ")
-
- input_file, results_file, edna_directory = args
-
- jobname = os.path.basename(os.path.dirname(edna_directory))
-
- self.job = XalocJob(
- "edna-strategy", jobname, self.sls_script, input_file, edna_directory
- )
- self.job.submit()
-
- logging.getLogger("HWR").debug(" StrategyJob - %s" % str(self.job))
-
- self.edna_directory = os.path.dirname(input_file)
- self.results_file = results_file
-
- logging.getLogger("HWR").debug(" input file: %s" % input_file)
- logging.getLogger("HWR").debug(" edna directory: %s" % self.edna_directory)
-
- def get_result(self, state):
- if state == "COMPLETED":
- outfile = os.path.join(
- self.edna_directory, "ControlInterfaceToMXCuBEv1_3_dataOutput.xml"
- )
-
- logging.getLogger("HWR").debug("Job / state is COMPLETED")
- logging.getLogger("HWR").debug(" looking for file: %s" % outfile)
- if os.path.exists(outfile):
- job_output = open(outfile).read()
- open(self.results_file, "w").write(job_output)
- result = XSDataResultMXCuBE.parseFile(self.results_file)
- else:
- logging.getLogger("HWR").debug(
- "EDNA Job finished without success / cannot find output file "
- )
- result = ""
- else:
- logging.getLogger("HWR").debug(
- "EDNA Job finished without success / state was %s" % (job.state)
- )
- result = ""
-
- return result
diff --git a/mxcubecore/HardwareObjects/ALBA/ALBACollect.py b/mxcubecore/HardwareObjects/ALBA/ALBACollect.py
deleted file mode 100644
index 934f9136b4..0000000000
--- a/mxcubecore/HardwareObjects/ALBA/ALBACollect.py
+++ /dev/null
@@ -1,877 +0,0 @@
-# Project: 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 .
-
-"""
-ALBACollect
-"""
-import os
-import time
-import logging
-import sys
-import gevent
-from mxcubecore.TaskUtils import task
-from mxcubecore.HardwareObjects.abstract.AbstractCollect import AbstractCollect
-from mxcubecore import HardwareRepository as HWR
-
-
-__author__ = "Vicente Rey Bakaikoa"
-__credits__ = ["MXCuBE collaboration"]
-__version__ = "2.2."
-
-
-class ALBACollect(AbstractCollect):
- """Main data collection class. Inherited from AbstractMulticollect
- Collection is done by setting collection parameters and
- executing collect command
- """
-
- def __init__(self, name):
- """
-
- :param name: name of the object
- :type name: string
- """
-
- AbstractCollect.__init__(self, name)
- # HardwareObject.__init__(self, name)
-
- self._error_msg = ""
- self.owner = None
- self.osc_id = None
- self._collecting = None
-
- self.helical_positions = None
- self.saved_omega_velocity = None
-
- def init(self):
- """
- Init method
- """
-
- self.ready_event = gevent.event.Event()
-
- self.supervisor_hwobj = self.get_object_by_role("supervisor")
-
- self.slowshut_hwobj = self.get_object_by_role("slow_shutter")
- self.photonshut_hwobj = self.get_object_by_role("photon_shutter")
- self.frontend_hwobj = self.get_object_by_role("frontend")
-
- self.ni_conf_cmd = self.get_command_object("ni_configure")
- self.ni_unconf_cmd = self.get_command_object("ni_unconfigure")
-
- # some extra reading channels to be saved in image header
- self.kappapos_chan = self.get_channel_object("kappapos")
- self.phipos_chan = self.get_channel_object("phipos")
-
- undulators = []
- try:
- for undulator in self["undulators"]:
- undulators.append(undulator)
- except Exception:
- pass
-
- self.exp_type_dict = {"Mesh": "raster", "Helical": "Helical"}
-
- det_px, det_py = HWR.beamline.detector.get_pixel_size()
- beam_div_hor, beam_div_ver = HWR.beamline.beam.get_beam_divergence()
-
- self.set_beamline_configuration(
- synchrotron_name="ALBA",
- directory_prefix=self.get_property("directory_prefix"),
- default_exposure_time=HWR.beamline.detector.get_default_exposure_time(),
- minimum_exposure_time=HWR.beamline.detector.get_minimum_exposure_time(),
- detector_fileext=HWR.beamline.detector.get_file_suffix(),
- detector_type=HWR.beamline.detector.get_detector_type(),
- detector_manufacturer=HWR.beamline.detector.get_manufacturer(),
- detector_model=HWR.beamline.detector.get_model(),
- detector_px=det_px,
- detector_py=det_py,
- undulators=undulators,
- focusing_optic=self.get_property("focusing_optic"),
- monochromator_type=self.get_property("monochromator"),
- beam_divergence_vertical=beam_div_ver,
- beam_divergence_horizontal=beam_div_hor,
- polarisation=self.get_property("polarisation"),
- input_files_server=self.get_property("input_files_server"),
- )
-
- self.emit("collectConnected", (True,))
- self.emit("collectReady", (True,))
-
- def data_collection_hook(self):
- """Main collection hook
- """
-
- logging.getLogger("HWR").info("Running ALBA data collection hook")
-
- logging.getLogger("HWR").info(" -- wait for devices to finish moving --")
- logging.getLogger("HWR").info(" + wait for resolution...")
- HWR.beamline.resolution.wait_end_of_move()
- logging.getLogger("HWR").info(" + wait for detector distance...")
- HWR.beamline.detector.wait_move_distance_done()
- logging.getLogger("HWR").info(" + wait for energy...")
- HWR.beamline.energy.wait_move_energy_done()
-
- if self.aborted_by_user:
- self.emit_collection_failed("Aborted by user")
- self.aborted_by_user = False
- return
-
- ### EDNA_REF, OSC, MESH, HELICAL
-
- exp_type = self.current_dc_parameters["experiment_type"]
- logging.getLogger("HWR").debug("Running a collect (exp_type=%s)" % exp_type)
-
- if exp_type == "Characterization":
- logging.getLogger("HWR").debug("Running a collect (CHARACTERIZATION)")
- elif exp_type == "Helical":
- logging.getLogger("HWR").debug("Running a helical collection")
- logging.getLogger("HWR").debug(
- " helical positions are: %s" % str(self.helical_positions)
- )
- hpos = self.helical_positions
- logging.getLogger("HWR").debug(
- " phiy from %3.4f to %3.4f" % (hpos[0], hpos[4])
- )
- logging.getLogger("HWR").debug(
- " phiz from %3.4f to %3.4f" % (hpos[1], hpos[5])
- )
- logging.getLogger("HWR").debug(
- " sampx from %3.4f to %3.4f" % (hpos[2], hpos[6])
- )
- logging.getLogger("HWR").debug(
- " sampy from %3.4f to %3.4f" % (hpos[3], hpos[7])
- )
- elif exp_type == "Mesh":
- logging.getLogger("HWR").debug("Running a raster collection ()")
- logging.getLogger("HWR").debug(
- " number of lines are: %s" % self.mesh_num_lines
- )
- logging.getLogger("HWR").debug(
- " total nb of frames: %s" % self.mesh_total_nb_frames
- )
- logging.getLogger("HWR").debug(
- " mesh range : %s" % self.mesh_range
- )
- logging.getLogger("HWR").debug(
- " mesh center : %s" % self.mesh_center
- )
- else:
- logging.getLogger("HWR").debug("Running a collect (STANDARD)")
-
- osc_seq = self.current_dc_parameters["oscillation_sequence"][0]
-
- image_range = osc_seq["range"]
- nb_images = osc_seq["number_of_images"]
- total_range = image_range * nb_images
-
- ready = self.prepare_acquisition()
-
- if not ready:
- self.collection_failed("Cannot prepare collection")
- self.stop_collect()
- return
-
- self._collecting = True
- # for progressBar brick
- self.emit("progressInit", "Collection", osc_seq["number_of_images"])
-
- omega_pos = osc_seq["start"]
-
- logging.getLogger("HWR").info("Starting detector")
- self.emit("collectStarted", (self.owner, 1))
-
- first_image_no = osc_seq["start_image_number"]
-
- if exp_type == "OSC" or (exp_type == "Characterization" and nb_images == 1):
- final_pos = self.prepare_collection(
- start_angle=omega_pos,
- nb_images=nb_images,
- first_image_no=first_image_no,
- )
- HWR.beamline.detector.start_collection()
- self.collect_images(final_pos, nb_images, first_image_no)
- elif exp_type == "Characterization" and nb_images > 1: # image one by one
- for imgno in range(nb_images):
- final_pos = self.prepare_collection(
- start_angle=omega_pos, nb_images=1, first_image_no=first_image_no
- )
- HWR.beamline.detector.start_collection()
- self.collect_images(final_pos, 1, first_image_no)
- first_image_no += 1
- omega_pos += 90
-
- def collect_images(self, final_pos, nb_images, first_image_no):
- #
- # Run
- #
- logging.getLogger("HWR").info(
- "collecting images, by moving omega to %s" % final_pos
- )
- HWR.beamline.diffractometer.omega.set_value(final_pos)
- self.wait_collection_done(nb_images, first_image_no)
- self.data_collection_end()
- self.collection_finished()
-
- def data_collection_end(self):
- HWR.beamline.fast_shutter.cmdOut()
- HWR.beamline.diffractometer.omega.set_velocity(60)
- self.unconfigure_ni()
-
- def data_collection_failed(self):
- logging.getLogger("HWR").info(
- "Data collection failed. recovering sequence should go here"
- )
-
- def prepare_acquisition(self):
-
- fileinfo = self.current_dc_parameters["fileinfo"]
-
- basedir = fileinfo["directory"]
-
- # save omega velocity
- self.saved_omega_velocity = HWR.beamline.diffractometer.omega.get_velocity()
-
- # create directories if needed
- self.check_directory(basedir)
-
- # check fast shutter closed. others opened
- shutok = self.check_shutters()
-
- if not shutok:
- logging.getLogger("user_level_log").error(
- " Shutters are not ready. BYPASSED. Comment line in ALBACollect.py"
- )
- else:
- logging.getLogger("user_level_log").error(
- " Shutters ready but code is BYPASSED. Comment line in ALBACollect.py"
- )
-
- shutok = True # DELETE THIS AFTER TESTS
-
- if not shutok:
- logging.getLogger("user_level_log").error(" Shutters not ready")
- return False
-
- gevent.sleep(1)
- logging.getLogger("HWR").info(
- " Waiting for diffractometer to be ready. Now %s"
- % str(HWR.beamline.diffractometer.current_state)
- )
- HWR.beamline.diffractometer.wait_device_ready(timeout=10)
- logging.getLogger("HWR").info(" diffractometer is now ready.")
-
- # go to collect phase
- if not self.is_collect_phase():
- logging.getLogger("HWR").info(
- " Not in collect phase. Asking supervisor to go"
- )
- logging.getLogger("HWR").info(
- " diffractometer is now ready. Now %s"
- % str(HWR.beamline.diffractometer.current_state)
- )
- success = self.go_to_collect()
- if not success:
- logging.getLogger("user_level_log").error(
- "Cannot set COLLECT phase for diffractometer"
- )
- return False
-
- detok = HWR.beamline.detector.prepare_acquisition(self.current_dc_parameters)
-
- return detok
-
- def prepare_collection(self, start_angle, nb_images, first_image_no):
- # move omega to start angle
- osc_seq = self.current_dc_parameters["oscillation_sequence"][0]
-
- # start_angle = osc_seq['start']
- # nb_images = osc_seq['number_of_images']
-
- img_range = osc_seq["range"]
- exp_time = osc_seq["exposure_time"]
-
- total_dist = nb_images * img_range
- total_time = nb_images * exp_time
- omega_speed = float(total_dist / total_time)
-
- logging.getLogger("HWR").info(" prepare detector was not ok.")
- self.write_image_headers(start_angle)
-
- logging.getLogger("HWR").info(
- " nb_images: %s / img_range: %s / exp_time: %s / total_distance: %s / speed: %s"
- % (nb_images, img_range, exp_time, total_dist, omega_speed)
- )
- logging.getLogger("HWR").info(
- " setting omega velocity to 60 to go to intial position"
- )
- HWR.beamline.diffractometer.omega.set_velocity(60)
-
- omega_acceltime = HWR.beamline.diffractometer.omega.get_acceleration()
-
- safe_delta = 9.0 * omega_speed * omega_acceltime
-
- init_pos = start_angle - safe_delta
- final_pos = start_angle + total_dist + safe_delta
-
- logging.getLogger("HWR").info("Moving omega to initial position %s" % init_pos)
- HWR.beamline.diffractometer.omega.set_value(init_pos)
-
- HWR.beamline.detector.prepare_collection(nb_images, first_image_no)
-
- HWR.beamline.diffractometer.omega.wait_end_of_move(timeout=10)
-
- logging.getLogger("HWR").info(
- "Moving omega finished at %s"
- % HWR.beamline.diffractometer.omega.get_value()
- )
-
- # program omega speed depending on exposure time
-
- logging.getLogger("HWR").info("Setting omega velocity to %s" % omega_speed)
- HWR.beamline.diffractometer.omega.set_velocity(omega_speed)
- if omega_speed != 0:
- self.configure_ni(start_angle, total_dist)
-
- return final_pos
-
- def write_image_headers(self, start_angle):
- fileinfo = self.current_dc_parameters["fileinfo"]
- basedir = fileinfo["directory"]
-
- exp_type = self.current_dc_parameters["experiment_type"]
- osc_seq = self.current_dc_parameters["oscillation_sequence"][0]
-
- nb_images = osc_seq["number_of_images"]
- # start_angle = osc_seq['start']
-
- img_range = osc_seq["range"]
-
- if exp_type == "Characterization":
- angle_spacing = 90
- else:
- angle_spacing = img_range
-
- exp_time = osc_seq["exposure_time"]
-
- # PROGRAM Image Headers
- # latency_time = 0.003
- latency_time = HWR.beamline.detector.get_latency_time()
- limaexpt = exp_time - latency_time
-
- self.image_headers = {}
-
- angle_info = [start_angle, img_range, angle_spacing]
-
- self.image_headers["nb_images"] = nb_images
- self.image_headers["Exposure_time"] = "%.4f" % limaexpt
- self.image_headers["Exposure_period"] = "%.4f" % exp_time
- self.image_headers["Start_angle"] = "%f deg." % start_angle
- self.image_headers["Angle_increment"] = "%f deg." % img_range
- self.image_headers["Wavelength"] = HWR.beamline.energy.get_wavelength()
-
- self.image_headers["Detector_distance"] = "%.5f m" % (
- HWR.beamline.detector.distance.get_value() / 1000.0
- )
- self.image_headers["Detector_Voffset"] = "0 m"
-
- beamx, beamy = HWR.beamline.detector.get_beam_position()
- self.image_headers["Beam_xy"] = "(%.2f, %.2f) pixels" % (beamx, beamy)
-
- self.image_headers["Filter_transmission"] = "%.4f" % (
- HWR.beamline.transmission.get_value() / 100.0
- )
- self.image_headers["Flux"] = "%.4g" % HWR.beamline.flux.get_value()
- self.image_headers["Detector_2theta"] = "0.0000"
- self.image_headers["Polarization"] = "0.99"
- self.image_headers["Alpha"] = "0 deg."
-
- self.image_headers["Kappa"] = "%.4f deg." % self.kappapos_chan.get_value()
- self.image_headers["Phi"] = "%.4f deg." % self.phipos_chan.get_value()
-
- self.image_headers["Chi"] = "0 deg."
- self.image_headers["Oscillation_axis"] = "X, CW"
- self.image_headers["N_oscillations"] = "1"
- self.image_headers["Detector_2theta"] = "0.0000 deg"
-
- self.image_headers["Image_path"] = ": %s" % basedir
-
- self.image_headers["Threshold_setting"] = (
- "%0f eV" % HWR.beamline.detector.get_threshold()
- )
- self.image_headers["Gain_setting"] = "%s" % str(
- HWR.beamline.detector.get_threshold_gain()
- )
-
- self.image_headers["Tau"] = "%s s" % str(199.1e-09)
- self.image_headers["Count_cutoff"] = "%s counts" % str(370913)
- self.image_headers["N_excluded_pixels"] = "= %s" % str(1178)
- self.image_headers["Excluded_pixels"] = ": %s" % str("badpix_mask.tif")
- self.image_headers["Trim_file"] = ": %s" % str(
- "p6m0108_E12661_T6330_vrf_m0p20.bin"
- )
-
- HWR.beamline.detector.set_image_headers(self.image_headers, angle_info)
-
- def wait_collection_done(self, nb_images, first_image_no):
-
- osc_seq = self.current_dc_parameters["oscillation_sequence"][0]
-
- # first_image_no = osc_seq['start_image_number']
- # nb_images = osc_seq['number_of_images']
- last_image_no = first_image_no + nb_images - 1
-
- if nb_images > 1:
- self.wait_save_image(first_image_no)
- HWR.beamline.diffractometer.omega.wait_end_of_move(timeout=720)
- self.wait_save_image(last_image_no)
-
- def wait_save_image(self, frame_number, timeout=25):
-
- fileinfo = self.current_dc_parameters["fileinfo"]
- basedir = fileinfo["directory"]
- template = fileinfo["template"]
-
- filename = template % frame_number
- fullpath = os.path.join(basedir, filename)
-
- start_wait = time.time()
-
- logging.getLogger("HWR").debug(" waiting for image on disk: %s", fullpath)
-
- while not os.path.exists(fullpath):
- dirlist = os.listdir(basedir) # forces directory flush ?
- if (time.time() - start_wait) > timeout:
- logging.getLogger("HWR").debug(" giving up waiting for image")
- return False
- time.sleep(0.2)
-
- self.last_saved_image = fullpath
-
- # generate thumbnails
- archive_dir = fileinfo["archive_directory"]
- self.check_directory(archive_dir)
-
- jpeg_filename = os.path.splitext(filename)[0] + ".jpeg"
- thumb_filename = os.path.splitext(filename)[0] + ".thumb.jpeg"
-
- thumb_fullpath = os.path.join(archive_dir, thumb_filename)
- jpeg_fullpath = os.path.join(archive_dir, jpeg_filename)
-
- logging.getLogger("HWR").debug(
- " creating thumbnails for %s in: %s and %s"
- % (fullpath, jpeg_fullpath, thumb_fullpath)
- )
- cmd = "adxv_thumb 0.4 %s %s" % (fullpath, jpeg_fullpath)
- os.system(cmd)
- cmd = "adxv_thumb 0.1 %s %s" % (fullpath, thumb_fullpath)
- os.system(cmd)
-
- logging.getLogger("HWR").debug(" writing thumbnails info in LIMS")
- self._store_image_in_lims(frame_number)
-
- return True
-
- def check_shutters(self):
-
- # Check fast shutter
- if HWR.beamline.fast_shutter.get_state() != 0:
- return False
-
- # Check slow shutter
- if self.slowshut_hwobj.get_state() != 1:
- return False
-
- # Check photon shutter
- if self.photonshut_hwobj.get_state() != 1:
- return False
-
- # Check front end
- if self.frontend_hwobj.get_state() != 1:
- return False
-
- return True
-
- def get_image_headers(self):
- headers = []
- return headers
-
- def collection_end(self):
- #
- # data collection end (or abort)
- #
- logging.getLogger("HWR").info(" finishing data collection ")
- HWR.beamline.fast_shutter.cmdOut()
- self.emit("progressStop")
-
- def check_directory(self, basedir):
- if not os.path.exists(basedir):
- try:
- os.makedirs(basedir)
- except OSError as e:
- import errno
-
- if e.errno != errno.EEXIST:
- raise
-
- def collect_finished(self, green):
- logging.info("Data collection finished")
-
- def collect_failed(self, par):
- logging.exception("Data collection failed")
- self.current_dc_parameters["status"] = "failed"
- exc_type, exc_value, exc_tb = sys.exc_info()
- failed_msg = "Data collection failed!\n%s" % exc_value
- self.emit(
- "collectOscillationFailed",
- (
- self.owner,
- False,
- failed_msg,
- self.current_dc_parameters.get("collection_id"),
- 1,
- ),
- )
-
- HWR.beamline.detector.stop_collection()
- HWR.beamline.diffractometer.omega.stop()
- self.data_collection_end()
-
- def go_to_collect(self, timeout=180):
- logging.getLogger("HWR").debug("sending supervisor to collect phase")
- self.supervisor_hwobj.go_collect()
- logging.getLogger("HWR").debug("supervisor sent to collect phase")
-
- gevent.sleep(0.5)
-
- t0 = time.time()
- while True:
- super_state = str(self.supervisor_hwobj.get_state()).upper()
- cphase = self.supervisor_hwobj.get_current_phase().upper()
- if super_state != "MOVING" and cphase == "COLLECT":
- break
- if time.time() - t0 > timeout:
- logging.getLogger("HWR").debug(
- "timeout sending supervisor to collect phase"
- )
- break
- gevent.sleep(0.5)
-
- logging.getLogger("HWR").debug(
- "supervisor finished go collect phase task. phase is now: %s" % cphase
- )
-
- return self.is_collect_phase()
-
- def is_collect_phase(self):
- return self.supervisor_hwobj.get_current_phase().upper() == "COLLECT"
-
- def go_to_sampleview(self, timeout=180):
- logging.getLogger("HWR").debug("sending supervisor to sample view phase")
- self.supervisor_hwobj.go_sample_view()
- logging.getLogger("HWR").debug("supervisor sent to sample view phase")
-
- gevent.sleep(0.5)
-
- t0 = time.time()
- while True:
- super_state = str(self.supervisor_hwobj.get_state()).upper()
- cphase = self.supervisor_hwobj.get_current_phase().upper()
- if super_state != "MOVING" and cphase == "SAMPLE":
- break
- if time.time() - t0 > timeout:
- logging.getLogger("HWR").debug(
- "timeout sending supervisor to sample view phase"
- )
- break
- gevent.sleep(0.5)
-
- logging.getLogger("HWR").debug(
- "supervisor finished go sample view phase task. phase is now: %s" % cphase
- )
-
- return self.is_sampleview_phase()
-
- def is_sampleview_phase(self):
- return self.supervisor_hwobj.get_current_phase().upper() == "SAMPLE"
-
- def configure_ni(self, startang, total_dist):
- logging.getLogger("HWR").debug(
- "Configuring NI660 with pars 0, %s, %s, 0, 1" % (startang, total_dist)
- )
- self.ni_conf_cmd(0.0, startang, total_dist, 0, 1)
-
- def unconfigure_ni(self):
- self.ni_unconf_cmd()
-
- def open_safety_shutter(self):
- """ implements prepare_shutters in collect macro """
-
- # prepare ALL shutters
-
- # close fast shutter
- if HWR.beamline.fast_shutter.get_state() != 0:
- HWR.beamline.fast_shutter.close()
-
- # open slow shutter
- if self.slowshut_hwobj.get_state() != 1:
- self.slowshut_hwobj.open()
-
- # open photon shutter
- if self.photonshut_hwobj.get_state() != 1:
- self.photonshut_hwobj.open()
-
- # open front end
- if self.frontend_hwobj.get_state() != 0:
- self.frontend_hwobj.open()
-
- def open_detector_cover(self):
- self.supervisor_hwobj.open_detector_cover()
-
- def open_fast_shutter(self):
- # HWR.beamline.fast_shutter.open()
- # this function is empty for ALBA. we are not opening the fast shutter.
- # on the contrary open_safety_shutter (equivalent to prepare_shutters in original
- # collect macro will first close the fast shutter and open the other three
- pass
-
- def close_fast_shutter(self):
- HWR.beamline.fast_shutter.cmdOut()
-
- def close_safety_shutter(self):
- # we will not close safety shutter during collections
- pass
-
- def close_detector_cover(self):
- # we will not close detcover during collections
- # self.supervisor.close_detector_cover()
- pass
-
- def set_helical_pos(self, arg):
- """
- Descript. : 8 floats describe
- p1AlignmY, p1AlignmZ, p1CentrX, p1CentrY
- p2AlignmY, p2AlignmZ, p2CentrX, p2CentrY
- """
- self.helical_positions = [
- arg["1"]["phiy"],
- arg["1"]["phiz"],
- arg["1"]["sampx"],
- arg["1"]["sampy"],
- arg["2"]["phiy"],
- arg["2"]["phiz"],
- arg["2"]["sampx"],
- arg["2"]["sampy"],
- ]
-
- def setMeshScanParameters(self, num_lines, num_images_per_line, mesh_range):
- """
- Descript. :
- """
- pass
-
- @task
- def _take_crystal_snapshot(self, filename):
- """
- Descript. :
- """
- if not self.is_sampleview_phase():
- self.go_to_sampleview()
-
- HWR.beamline.sample_view.save_snapshot(filename)
- logging.getLogger("HWR").debug(" - snapshot saved to %s" % filename)
-
- @task
- def move_motors(self, motor_position_dict):
- """
- Descript. :
- """
- HWR.beamline.diffractometer.move_motors(motor_position_dict)
-
- def create_file_directories(self):
- """
- Method create directories for raw files and processing files.
- Directorie for xds.input and auto_processing are created
- """
- self.create_directories(
- self.current_dc_parameters["fileinfo"]["directory"],
- self.current_dc_parameters["fileinfo"]["process_directory"],
- )
-
- """create processing directories and img links"""
- xds_directory, auto_directory, ednaproc_directory = self.prepare_input_files()
-
- try:
- self.create_directories(xds_directory, auto_directory, ednaproc_directory)
- os.system(
- "chmod -R 777 %s %s %s"
- % (xds_directory, auto_directory, ednaproc_directory)
- )
- """todo, create link of imgs for auto_processing
- try:
- os.symlink(files_directory, os.path.join(process_directory, "img"))
- except os.error, e:
- if e.errno != errno.EEXIST:
- raise
- """
- # os.symlink(files_directory, os.path.join(process_directory, "img"))
- except Exception:
- logging.exception("Could not create processing file directory")
- return
-
- if xds_directory:
- self.current_dc_parameters["xds_dir"] = xds_directory
-
- if auto_directory:
- self.current_dc_parameters["auto_dir"] = auto_directory
-
- # pass wavelength needed in auto processing input files
-
- osc_pars = self.current_dc_parameters["oscillation_sequence"][0]
- osc_pars["wavelength"] = HWR.beamline.energy.get_wavelength()
-
- HWR.beamline.offline_processing.create_input_files(
- xds_directory, auto_directory, self.current_dc_parameters
- )
-
- def prepare_input_files(self):
- """
- Descript. :
- """
- i = 1
- log = logging.getLogger("user_level_log")
-
- while True:
- xds_input_file_dirname = "xds_%s_%s_%d" % (
- self.current_dc_parameters["fileinfo"]["prefix"],
- self.current_dc_parameters["fileinfo"]["run_number"],
- i,
- )
- xds_directory = os.path.join(
- self.current_dc_parameters["fileinfo"]["process_directory"],
- xds_input_file_dirname,
- )
- if not os.path.exists(xds_directory):
- break
- i += 1
-
- self.current_dc_parameters["xds_dir"] = xds_directory
-
- mosflm_input_file_dirname = "mosflm_%s_%s_%d" % (
- self.current_dc_parameters["fileinfo"]["prefix"],
- self.current_dc_parameters["fileinfo"]["run_number"],
- i,
- )
- mosflm_directory = os.path.join(
- self.current_dc_parameters["fileinfo"]["process_directory"],
- mosflm_input_file_dirname,
- )
-
- log.info(" - xds: %s / mosflm: %s" % (xds_directory, mosflm_directory))
-
- while True:
- ednaproc_dirname = "ednaproc_%s_%s_%d" % (
- self.current_dc_parameters["fileinfo"]["prefix"],
- self.current_dc_parameters["fileinfo"]["run_number"],
- i,
- )
- ednaproc_directory = os.path.join(
- self.current_dc_parameters["fileinfo"]["process_directory"],
- ednaproc_dirname,
- )
- if not os.path.exists(ednaproc_directory):
- break
- i += 1
-
- self.current_dc_parameters["ednaproc_dir"] = ednaproc_directory
-
- return xds_directory, mosflm_directory, ednaproc_directory
-
- def get_undulators_gaps(self):
- """
- Descript. : return triplet with gaps. In our case we have one gap,
- others are 0
- """
- # TODO
- try:
- if self.chan_undulator_gap:
- und_gaps = self.chan_undulator_gap.get_value()
- if type(und_gaps) in (list, tuple):
- return und_gaps
- else:
- return und_gaps
- except Exception:
- pass
- return {}
-
- def get_slit_gaps(self):
- """
- Descript. :
- """
- if HWR.beamline.beam is not None:
- return HWR.beamline.beam.get_slits_gap()
- return None, None
-
- def get_beam_shape(self):
- """
- Descript. :
- """
- if HWR.beamline.beam is not None:
- return HWR.beamline.beam.get_beam_shape()
-
- def get_machine_current(self):
- """
- Descript. :
- """
- if HWR.beamline.machine_info:
- return HWR.beamline.machine_info.get_current()
- else:
- return 0
-
- def get_machine_message(self):
- """
- Descript. :
- """
- if HWR.beamline.machine_info:
- return HWR.beamline.machine_info.get_message()
- else:
- return ""
-
- def get_machine_fill_mode(self):
- """
- Descript. :
- """
- if HWR.beamline.machine_info:
- return "FillMode not/impl"
- # fill_mode = str(self.machine_info_hwobj.get_message())
- # return fill_mode[:20]
- else:
- return ""
-
- def trigger_auto_processing(self, event, frame):
- if event == "after":
- dc_pars = self.current_dc_parameters
- HWR.beamline.offline_processing.trigger_auto_processing(dc_pars)
-
-
-def test_hwo(hwo):
- print("Shutters (ready for collect): ", hwo.check_shutters())
- print("Supervisor(collect phase): ", hwo.is_collect_phase())
-
- print("Kappa ", hwo.kappapos_chan.get_value())
- print("Phi ", hwo.phipos_chan.get_value())
diff --git a/mxcubecore/HardwareObjects/ALBA/ALBADataAnalysis.py b/mxcubecore/HardwareObjects/ALBA/ALBADataAnalysis.py
deleted file mode 100644
index 143c775033..0000000000
--- a/mxcubecore/HardwareObjects/ALBA/ALBADataAnalysis.py
+++ /dev/null
@@ -1,178 +0,0 @@
-from xaloc import XalocJob
-from XSDataCommon import XSDataFile, XSDataString
-from XSDataMXCuBEv1_3 import XSDataResultMXCuBE
-from mxcubecore.HardwareObjects.EDNACharacterisation import EDNACharacterisation
-from PyTango import DeviceProxy
-import os
-import time
-import logging
-
-import sys
-
-sys.path.append("/beamlines/bl13/controls/devel/pycharm/ALBAClusterClient")
-
-
-root = os.environ["POST_PROCESSING_SCRIPTS_ROOT"]
-
-sls_script = os.path.join(root, "edna-mx/strategy/edna-mx.strategy.sl")
-
-
-class ALBADataAnalysis(EDNACharacterisation):
- def init(self):
- EDNACharacterisation.init(self)
-
- def prepare_input(self, edna_input):
-
- # used for strategy calculation (characterization) using data analysis cluster
- # ALBA specific
-
- firstImage = None
-
- for dataSet in edna_input.getDataSet():
- for imageFile in dataSet.imageFile:
- if imageFile.getPath() is None:
- continue
- firstImage = imageFile.path.value
- break
-
- listImageName = os.path.basename(firstImage).split("_")
- prefix = "_".join(listImageName[:-2])
- run_number = listImageName[-2]
- i = 1
-
- if hasattr(edna_input, "process_directory"):
- edna_directory = os.path.join(
- edna_input.process_directory,
- "characterisation_%s_run%s_%d" % (prefix, run_number, i),
- )
- while os.path.exists(edna_directory):
- i += 1
- edna_directory = os.path.join(
- edna_input.process_directory,
- "characterisation_%s_run%s_%d" % (prefix, run_number, i),
- )
- os.makedirs(edna_directory)
- else:
- raise RuntimeError("No process directory specified in edna_input")
-
- edna_input.process_directory = edna_directory
-
- output_dir = XSDataFile()
- path = XSDataString()
- path.set_value(edna_directory)
- output_dir.setPath(path)
- edna_input.setOutputFileDirectory(output_dir)
-
- def run_edna(self, input_file, results_file, edna_directory):
- return self.run(input_file, results_file, edna_directory)
-
- def run(self, *args):
- input_file, results_file, edna_directory = args
-
- jobname = os.path.basename(os.path.dirname(edna_directory))
-
- logging.getLogger("HWR").debug(" XalocJob submiting ")
- logging.getLogger("HWR").debug(" job_name: %s" % jobname)
- logging.getLogger("HWR").debug(" sls_script: %s, " % sls_script)
- logging.getLogger("HWR").debug(" input file: %s" % input_file)
- logging.getLogger("HWR").debug(" results file: %s" % results_file)
- logging.getLogger("HWR").debug(" edna directory: %s" % edna_directory)
-
- self.job = XalocJob(
- "edna-strategy", jobname, sls_script, input_file, edna_directory
- )
- self.job.submit()
-
- logging.getLogger("HWR").debug(" XalocJob submitted %s" % self.job.id)
-
- self.edna_directory = os.path.dirname(input_file)
- self.input_file = os.path.basename(input_file)
- # self.results_file = self.fix_path(results_file)
- self.results_file = results_file
- logging.getLogger("HWR").debug(
- " self.results file: %s" % self.results_file
- )
-
- state = self.wait_done()
-
- if state == "COMPLETED":
- logging.getLogger("HWR").debug("EDNA Job completed")
- time.sleep(0.5)
- result = self.get_result()
- else:
- logging.getLogger("HWR").debug(
- "EDNA Job finished without success / state was %s" % (self.job.state)
- )
- result = ""
-
- return result
-
- def fix_path(self, path):
- outpath = path.replace("PROCESS_DATA", "PROCESS_DATA/RESULTS")
- # dirname = os.path.dirname(path)
- # basename = os.path.basename(path)
- # outpath = os.path.join(dirname,'RESULTS',basename)
- return outpath
-
- def wait_done(self):
-
- logging.getLogger("HWR").debug("Polling for Job state")
- time.sleep(0.5)
- logging.getLogger("HWR").debug("Polling for Job state 2")
-
- try:
- state = self.job.state
- logging.getLogger("HWR").debug("Job / is %s" % str(state))
- except Exception:
- import traceback
-
- logging.getLogger("HWR").debug(
- "Polling for Job state 3. exception happened"
- )
- logging.getLogger("HWR").debug(" %s " % traceback.format_exc())
-
- while state in ["RUNNING", "PENDING"]:
- logging.getLogger("HWR").debug("Job / is %s" % state)
- time.sleep(0.5)
- state = self.job.state
-
- logging.getLogger("HWR").debug("Returning")
- logging.getLogger("HWR").debug("Returning %s" % str(state))
- return state
-
- def get_result(self):
-
- jobstatus = self.job.status
-
- # outname = self.input_file.replace("Input", "Output")
- # outfile = os.path.join( self.edna_directory, outname)
-
- logging.getLogger("HWR").debug("Job / state is COMPLETED")
- logging.getLogger("HWR").debug(" job status dump: %s" % jobstatus)
- logging.getLogger("HWR").debug(" looking for file: %s" % self.results_file)
-
- if os.path.exists(self.results_file):
- # job_output = open(outfile).read()
- # logging.getLogger("HWR").debug(" EDNA results file found. loading it")
- # open(self.results_file, "w").write(job_output)
- logging.getLogger("HWR").debug(" EDNA results file found 2")
- result = XSDataResultMXCuBE.parseFile(self.results_file)
- logging.getLogger("HWR").debug(" EDNA results file found 3")
- logging.getLogger("HWR").debug(
- "EDNA Result loaded from file / result is=%s" % str(type(result))
- )
- else:
- logging.getLogger("HWR").debug(
- "EDNA Job finished without success / cannot find output file "
- )
- result = ""
-
- return result
-
-
-def test_hwo(hwo):
- ofile = "/tmp/edna/edna_result"
- odir = "/tmp/edna"
- test_input_file = "/beamlines/bl13/projects/cycle2018-I/2018012551-bcalisto/mx2018012551/DATA/20180131/PROCESS_DATA/characterisation_ref-Thrombin-TB-TTI1_A_run1_1/EDNAInput_2004391.xml"
- result = hwo.run_edna(test_input_file, ofile, odir)
- print(result)
diff --git a/mxcubecore/HardwareObjects/ALBA/ALBAEnergy.py b/mxcubecore/HardwareObjects/ALBA/ALBAEnergy.py
deleted file mode 100644
index 8109f99414..0000000000
--- a/mxcubecore/HardwareObjects/ALBA/ALBAEnergy.py
+++ /dev/null
@@ -1,74 +0,0 @@
-import logging
-
-from mxcubecore.BaseHardwareObjects import Device
-from mxcubecore import HardwareRepository as HWR
-
-
-class ALBAEnergy(Device):
- def __init__(self, *args):
- Device.__init__(self, *args)
- self.energy_position = None
- self.wavelength_position = None
-
- def init(self):
- self.wavelength_hwobj = self.get_object_by_role("wavelength")
-
- HWR.beamline.energy.connect("valueChanged", self.energy_position_changed)
- self.wavelength_hwobj.connect("valueChanged", self.wavelength_position_changed)
-
- def is_ready(self):
- return True
-
- def get_value(self):
- if self.energy_position is None:
- self.energy_position = HWR.beamline.energy.get_value()
- return self.energy_position
-
- def get_wavelength(self):
- if self.wavelength_position is None:
- self.wavelength_position = self.wavelength_hwobj.get_value()
- return self.wavelength_position
-
- def re_emit_values(self):
- HWR.beamline.energy.re_emit_values()
-
- def energy_position_changed(self, value):
- self.energy_position = value
- if None not in [self.energy_position, self.wavelength_position]:
- self.emit("energyChanged", self.energy_position, self.wavelength_position)
-
- def wavelength_position_changed(self, value):
- self.wavelength_position = value
- if None not in [self.energy_position, self.wavelength_position]:
- self.emit("energyChanged", self.energy_position, self.wavelength_position)
-
- def set_value(self, value):
- current_egy = self.get_value()
-
- logging.getLogger("HWR").debug(
- "moving energy to %s. now is %s" % (value, current_egy)
- )
- HWR.beamline.energy.set_value(value)
-
- def wait_move_energy_done(self):
- HWR.beamline.energy.wait_end_of_move()
-
- def set_wavelength(self, value):
- self.wavelength_hwobj.set_value(value)
-
- def get_limits(self):
- return HWR.beamline.energy.get_limits()
-
- def get_wavelength_limits(self):
- return self.wavelength_hwobj.get_limits()
-
-
-def test_hwo(hwo):
-
- print("Wavelength is: ", hwo.get_wavelength())
- print("Energy limits are: ", hwo.get_limits())
- print("Wavelength limits are: ", hwo.get_wavelength_limits())
-
-
-if __name__ == "__main__":
- test()
diff --git a/mxcubecore/HardwareObjects/ALBA/ALBAEpsActuator.py b/mxcubecore/HardwareObjects/ALBA/ALBAEpsActuator.py
deleted file mode 100644
index 7edbb9b583..0000000000
--- a/mxcubecore/HardwareObjects/ALBA/ALBAEpsActuator.py
+++ /dev/null
@@ -1,156 +0,0 @@
-"""Tango Shutter Hardware Object
-Example XML::
-
-
- Photon Shutter
- bl13/ct/eps-plc-01
- pshu
- Open,Closed
-
-
-
-Public Interface:
- Commands:
- int get_state()
- Description:
- returns current state
- Output:
- integer value describing the state
- current states correspond to:
- 0: out
- 1: in
- 9: moving
- 11: alarm
- 13: unknown
- 23: fault
-
- string getStatus()
- Description:
- returns current state as a string that can contain a more
- descriptive information about current state
-
- Output:
- status string
-
- cmdIn()
- Executes the command associated to the "In" action
- cmdOut()
- Executes the command associated to the "Out" action
-
- Signals:
- stateChanged
-
-"""
-
-from mxcubecore import HardwareRepository as HWR
-from mxcubecore import BaseHardwareObjects
-import logging
-
-STATE_OUT, STATE_IN, STATE_MOVING, STATE_FAULT, STATE_ALARM, STATE_UNKNOWN = (
- 0,
- 1,
- 9,
- 11,
- 13,
- 23,
-)
-
-
-class ALBAEpsActuator(BaseHardwareObjects.Device):
-
- states = {
- STATE_OUT: "out",
- STATE_IN: "in",
- STATE_MOVING: "moving",
- STATE_FAULT: "fault",
- STATE_ALARM: "alarm",
- STATE_UNKNOWN: "unknown",
- }
-
- default_state_strings = ["Out", "In"]
-
- def __init__(self, name):
- BaseHardwareObjects.Device.__init__(self, name)
-
- def init(self):
- self.actuator_state = STATE_UNKNOWN
-
- try:
- self.actuator_channel = self.get_channel_object("actuator")
- self.actuator_channel.connect_signal("update", self.stateChanged)
- except KeyError:
- logging.getLogger().warning(
- "%s: cannot report EPS Actuator State", self.name()
- )
-
- try:
- state_string = self.get_property("states")
- if state_string is None:
- self.state_strings = self.default_state_strings
- else:
- states = state_string.split(",")
- self.state_strings = states[1].strip(), states[0].strip()
- except Exception:
- import traceback
-
- logging.getLogger("HWR").warning(traceback.format_exc())
- self.state_strings = self.default_state_strings
-
- def get_state(self):
- state = self.actuator_channel.get_value()
- self.actuator_state = self.convert_state(state)
- return self.actuator_state
-
- def convert_state(self, state):
- if state == 0:
- act_state = STATE_OUT
- elif state == 1:
- act_state = STATE_IN
- else:
- act_state = STATE_UNKNOWN
- return act_state
-
- def stateChanged(self, value):
- #
- # emit signal
- #
- self.actuator_state = self.convert_state(value)
- self.emit("stateChanged", ((self.actuator_state),))
-
- def getUserName(self):
- return self.username
-
- def getStatus(self):
- """
- """
- state = self.get_state()
-
- if state in [STATE_OUT, STATE_IN]:
- return self.state_strings[state]
- elif state in self.states:
- return self.states[state]
- else:
- return "Unknown"
-
- def open(self):
- self.cmdIn()
-
- def close(self):
- self.cmdOut()
-
- def cmdIn(self):
- self.actuator_channel.set_value(1)
-
- def cmdOut(self):
- self.actuator_channel.set_value(0)
-
-
-def test_hwo(hwo):
- print("Name is: ", hwo.getUserName())
- print("Shutter state is: ", hwo.get_state())
- print("Shutter status is: ", hwo.getStatus())
-
- # print "Opening it"
- # print hwo.open()
- # print "Closing it"
- # print hwo.close()
diff --git a/mxcubecore/HardwareObjects/ALBA/ALBAFastShutter.py b/mxcubecore/HardwareObjects/ALBA/ALBAFastShutter.py
deleted file mode 100644
index 3848a6aeb0..0000000000
--- a/mxcubecore/HardwareObjects/ALBA/ALBAFastShutter.py
+++ /dev/null
@@ -1,227 +0,0 @@
-"""Tango Shutter Hardware Object
-Example XML::
-
-
- Photon Shutter
- bl13/ct/eps-plc-01
- pshu
- Open,Closed
-
-
-
-Public Interface:
- Commands:
- int get_state()
- Description:
- returns current state
- Output:
- integer value describing the state
- current states correspond to:
- 0: out
- 1: in
- 9: moving
- 11: alarm
- 13: unknown
- 23: fault
-
- string getStatus()
- Description:
- returns current state as a string that can contain a more
- descriptive information about current state
-
- Output:
- status string
-
- cmdIn()
- Executes the command associated to the "In" action
- cmdOut()
- Executes the command associated to the "Out" action
-
- Signals:
- stateChanged
-
-"""
-
-from mxcubecore import HardwareRepository as HWR
-from mxcubecore import BaseHardwareObjects
-import logging
-import time
-
-STATE_OUT, STATE_IN, STATE_MOVING, STATE_FAULT, STATE_ALARM, STATE_UNKNOWN = (
- 0,
- 1,
- 9,
- 11,
- 13,
- 23,
-)
-
-
-class ALBAFastShutter(BaseHardwareObjects.Device):
-
- states = {
- STATE_OUT: "out",
- STATE_IN: "in",
- STATE_MOVING: "moving",
- STATE_FAULT: "fault",
- STATE_ALARM: "alarm",
- STATE_UNKNOWN: "unknown",
- }
-
- default_state_strings = ["Out", "In"]
-
- def __init__(self, name):
- BaseHardwareObjects.Device.__init__(self, name)
-
- def init(self):
-
- self.actuator_state = STATE_UNKNOWN
- self.actuator_value = None
- self.motor_position = None
- self.motor_state = None
-
- try:
- self.nistart_cmd = self.get_command_object("nistart")
- self.nistop_cmd = self.get_command_object("nistop")
-
- self.actuator_channel = self.get_channel_object("actuator")
- self.motorpos_channel = self.get_channel_object("motorposition")
- self.motorstate_channel = self.get_channel_object("motorstate")
-
- self.actuator_channel.connect_signal("update", self.stateChanged)
- self.motorpos_channel.connect_signal("update", self.motor_positions_changed)
- self.motorstate_channel.connect_signal("update", self.motorStateChanged)
- except KeyError:
- logging.getLogger().warning("%s: cannot report FrontEnd State", self.name())
-
- try:
- state_string = self.get_property("states")
- if state_string is None:
- self.state_strings = self.default_state_strings
- else:
- states = state_string.split(",")
- self.state_strings = states[1].strip(), states[0].strip()
- except Exception:
- import traceback
-
- logging.getLogger("HWR").warning(traceback.format_exc())
- self.state_strings = self.default_state_strings
-
- def get_state(self):
- if self.actuator_state == STATE_UNKNOWN:
- self.actuator_value = self.actuator_channel.get_value()
- self.motor_position = self.motorpos_channel.get_value()
- self.motor_state = self.motorstate_channel.get_value()
- self.update_state()
- return self.actuator_state
-
- def update_state(self):
-
- if None in [self.actuator_value, self.motor_position, self.motor_state]:
- act_state = STATE_UNKNOWN
- elif str(self.motor_state) == "MOVING":
- act_state = STATE_MOVING
- elif str(self.motor_state) != "ON" or abs(self.motor_position) > 0.01:
- act_state = STATE_ALARM
- else:
- state = self.actuator_value.lower()
-
- if state == "high":
- act_state = STATE_OUT
- else:
- act_state = STATE_IN
-
- if act_state != self.actuator_state:
- self.actuator_state = act_state
- self.emitStateChanged()
-
- def stateChanged(self, value):
- self.actuator_value = value
- self.update_state()
-
- def motor_positions_changed(self, value):
- self.motor_position = value
- self.update_state()
-
- def motorStateChanged(self, value):
- self.motor_state = value
- self.update_state()
-
- def emitStateChanged(self):
- #
- # emit signal
- #
- self.emit("fastStateChanged", ((self.actuator_state),))
-
- def getMotorPosition(self):
- if self.motor_position is None:
- self.motor_position = self.motorpos_channel.get_value()
- return self.motor_position
-
- def getMotorState(self):
- if self.motor_state is None:
- self.motor_state = self.motorstate_channel.get_value()
- return self.motor_state
-
- def getUserName(self):
- return self.username
-
- def getStatus(self):
- """
- """
- state = self.get_state()
-
- if state in [STATE_OUT, STATE_IN]:
- return self.state_strings[state]
- elif state in self.states:
- return self.states[state]
- else:
- return "Unknown"
-
- def cmdIn(self):
- self.open()
-
- def cmdOut(self):
- self.close()
-
- def close(self):
- self.motorpos_channel.set_value(0)
- self.set_ttl("High")
-
- def open(self):
- self.motorpos_channel.set_value(0)
- self.set_ttl("Low")
-
- def set_ttl(self, value):
- self.nistop_cmd()
- self.actuator_channel.set_value(value)
- self.nistart_cmd()
-
- def is_open(self):
- if self.actuator_state == STATE_IN:
- return True
- else:
- return False
-
- def is_close(self):
- if self.actuator_state == STATE_OUT:
- return True
- else:
- return False
-
-
-def test_hwo(hwo):
- print("Name is: ", hwo.getUserName())
-
- print("Shutter state is: ", hwo.get_state())
- print("Shutter status is: ", hwo.getStatus())
- print("Motor position is: ", hwo.getMotorPosition())
- print("Motor state is: ", hwo.getMotorState())
- # hwo.open()
- # time.sleep(2)
- # print "is_open?" , hwo.is_open()
- # print "is_close?" , hwo.is_close()
-
-
-if __name__ == "__main__":
- test()
diff --git a/mxcubecore/HardwareObjects/ALBA/ALBAFlux.py b/mxcubecore/HardwareObjects/ALBA/ALBAFlux.py
deleted file mode 100644
index 2e3dca2b78..0000000000
--- a/mxcubecore/HardwareObjects/ALBA/ALBAFlux.py
+++ /dev/null
@@ -1,43 +0,0 @@
-from mxcubecore.HardwareObjects.abstract import AbstractFlux
-from mxcubecore.BaseHardwareObjects import Device
-import taurus
-import logging
-
-
-class ALBAFlux(Device, AbstractFlux.AbstractFlux):
- def init(self):
- super(ALBAFlux, self).init()
- self.current_dev = taurus.Device("pc/mach_attrpc_ctrl/1")
- self.vars_dev = taurus.Device("bl13/ct/variables")
- self.trans_mot = taurus.Device("mbattrans")
-
- def get_value(self):
- fluxlast = self.vars_dev["fluxlast"].value
-
- try:
- if fluxlast > 1e7:
- return self.last_current_trans()
- except Exception:
- pass
-
- logging.getLogger("HWR").debug(
- " Abnormally low value of flux. Returning default value"
- )
- default_flux = 6e11 * self.get_transmission()
- return default_flux
-
- def get_transmission(self):
- """ returns transmission between 0 and 1"""
- return self.trans_mot.position / 100.0
-
- def last_current_trans(self):
- current = self.current_dev.value
- fluxlastnorm = self.vars_dev["fluxlastnorm"].value
-
- last_current = (fluxlastnorm / 250.0) * current
-
- return last_current * self.get_transmission()
-
-
-def test_hwo(hwo):
- print(hwo.get_value())
diff --git a/mxcubecore/HardwareObjects/ALBA/ALBAFrontEnd.py b/mxcubecore/HardwareObjects/ALBA/ALBAFrontEnd.py
deleted file mode 100644
index ce507fb146..0000000000
--- a/mxcubecore/HardwareObjects/ALBA/ALBAFrontEnd.py
+++ /dev/null
@@ -1,52 +0,0 @@
-"""
-The ALBAFastShutter hardware object is a variation of the ALBAEpsActuator
-where the command to open/close is done on a different channel than the
-reading of the shutter state.
-
-The interface is otherwise exactly the same as the ALBAEpsActuator
-
-Example XML::
-
-
- Front Shutter
- bl13/ct/eps-plc-01
- fe_open
- OPEN_FE
- CLOSE_FE
- Open,Closed
-
-
-"""
-
-from mxcubecore import HardwareRepository as HWR
-from mxcubecore import BaseHardwareObjects
-import logging
-
-from ALBAEpsActuator import ALBAEpsActuator
-
-
-class ALBAFrontEnd(ALBAEpsActuator):
- def init(self):
- ALBAEpsActuator.init(self)
-
- self.open_channel = self.get_channel_object("open_command")
- self.close_channel = self.get_channel_object("close_command")
-
- def cmdIn(self):
- self.open_channel.set_value(True)
- # self.actuator_channel.set_value(1)
-
- def cmdOut(self):
- self.close_channel.set_value(True)
- # self.actuator_channel.set_value(0)
-
-
-def test_hwo(hwo):
- print("Name is: ", hwo.getUserName())
- print("Shutter state is: ", hwo.get_state())
- print("Shutter status is: ", hwo.getStatus())
-
- # print "Opening it"
- # print hwo.open()
- # print "Closing it"
- # print hwo.close()
diff --git a/mxcubecore/HardwareObjects/ALBA/ALBAFrontLight.py b/mxcubecore/HardwareObjects/ALBA/ALBAFrontLight.py
deleted file mode 100644
index 1c9024dc89..0000000000
--- a/mxcubecore/HardwareObjects/ALBA/ALBAFrontLight.py
+++ /dev/null
@@ -1,132 +0,0 @@
-from mxcubecore import HardwareRepository as HWR
-from mxcubecore.BaseHardwareObjects import Device
-import logging
-
-
-class ALBAFrontLight(Device):
- def __init__(self, *args):
- Device.__init__(self, *args)
- self.limits = [None, None]
-
- self.state = None
- self.register_state = None
-
- self.current_level = None
- self.memorized_level = None
- self.previous_level = None
-
- self.default_off_threshold = 0.01
- self.off_threshold = None
-
- def init(self):
-
- self.level_channel = self.get_channel_object("light_level")
- self.state_channel = self.get_channel_object("state")
- threshold = self.get_property("off_threshold")
-
- if threshold is not None:
- try:
- self.off_threshold = float(threshold)
- except Exception:
- self.off_threshold = self.default_threshold
- logging.getLogger("HWR").info(
- "OFF Threshold for front light is not valid. Using %s"
- % self.off_threshold
- )
-
- limits = self.get_property("limits")
- if limits is not None:
- lims = limits.split(",")
- if len(lims) == 2:
- self.limits = map(float, lims)
-
- self.level_channel.connect_signal("update", self.level_changed)
- self.state_channel.connect_signal("update", self.register_state_changed)
-
- def is_ready(self):
- return True
-
- def level_changed(self, value):
- self.current_level = value
- self.update_current_state()
-
- self.emit("levelChanged", self.current_level)
-
- def register_state_changed(self, value):
- self.register_state = str(value).lower()
- self.update_current_state()
-
- def update_current_state(self):
- if self.register_state == "on":
- if (
- self.off_threshold is not None
- and self.current_level < 0.9 * self.off_threshold
- ):
- newstate = "off"
- else:
- newstate = "on"
- elif self.register_state == "off":
- newstate = "off"
- else:
- newstate = "fault"
-
- if newstate != self.state:
- if newstate == "off":
- self.memorized_level = self.previous_level
-
- self.state = newstate
- self.emit("stateChanged", self.state)
-
- self.previous_level = self.current_level
-
- def get_limits(self):
- return self.limits
-
- def get_state(self):
- self.register_state = str(self.state_channel.get_value()).lower()
- self.update_current_state()
- return self.state
-
- def getUserName(self):
- return self.username
-
- def getLevel(self):
- self.current_level = self.level_channel.get_value()
- return self.current_level
-
- def setLevel(self, level):
- logging.getLogger("HWR").debug(
- "Setting level in %s to %s" % (self.username, level)
- )
- self.level_channel.set_value(float(level))
-
- def setOn(self):
- logging.getLogger("HWR").debug("Setting front light on")
- if self.memorized_level is not None:
- if self.memorized_level < self.off_threshold:
- value = self.off_threshold
- else:
- value = self.memorized_level
- logging.getLogger("HWR").debug(" setting value to")
- self.level_channel.set_value(value)
- else:
- self.level_channel.set_value(self.off_threshold)
-
- def setOff(self):
- logging.getLogger("HWR").debug("Setting front light off")
- self.level_channel.set_value(0.0)
-
-
-def test():
- hwr = HWR.get_hardware_repository()
- hwr.connect()
-
- light = hwr.get_hardware_object("/frontlight")
- print('\nLight control for "%s"\n' % light.getUserName())
- print(" Level limits are:", light.get_limits())
- print(" Current level is:", light.getLevel())
- print(" Current state is:", light.get_state())
-
-
-if __name__ == "__main__":
- test()
diff --git a/mxcubecore/HardwareObjects/ALBA/ALBAISPyBClient.py b/mxcubecore/HardwareObjects/ALBA/ALBAISPyBClient.py
deleted file mode 100644
index a9259d0df6..0000000000
--- a/mxcubecore/HardwareObjects/ALBA/ALBAISPyBClient.py
+++ /dev/null
@@ -1,87 +0,0 @@
-import logging
-from mxcubecore import HardwareRepository as HWR
-
-from ISPyBClient import ISPyBClient
-
-
-class ALBAISPyBClient(ISPyBClient):
- def ldap_login(self, login_name, psd, ldap_connection):
- # overwrites standard ldap login is ISPyBClient.py
- # to query for homeDirectory
-
- if ldap_connection is None:
- ldap_connection = self.ldapConnection
-
- ok, msg = ldap_connection.login(
- login_name, psd, fields=["uid", "homeDirectory"]
- )
-
- if ok:
- vals = ldap_connection.get_field_values()
- if "homeDirectory" in vals:
- home_dir = vals["homeDirectory"][0]
- logging.getLogger("HWR").debug(
- " homeDirectory for user %s is %s" % (login_name, home_dir)
- )
- # HWR.beamline.session.set_base_data_directories(home_dir, home_dir, home_dir)
- HWR.beamline.session.set_ldap_homedir(home_dir)
- else:
- home_dir = "/tmp"
- HWR.beamline.session.set_ldap_homedir(home_dir)
-
- return ok, msg
-
- def translate(self, code, what):
- """
- Given a proposal code, returns the correct code to use in the GUI,
- or what to send to LDAP, user office database, or the ISPyB database.
- """
- logging.getLogger("HWR").debug("translating %s %s" % (code, what))
- if what == "ldap":
- if code == "mx":
- return "u"
-
- if what == "ispyb":
- if code == "u":
- return "mx"
-
- return code
-
- def prepare_collect_for_lims(self, mx_collect_dict):
- # Attention! directory passed by reference. modified in place
-
- for i in range(4):
- try:
- prop = "xtalSnapshotFullPath%d" % (i + 1)
- path = mx_collect_dict[prop]
- ispyb_path = HWR.beamline.session.path_to_ispyb(path)
- logging.debug("ALBA ISPyBClient - %s is %s " % (prop, ispyb_path))
- mx_collect_dict[prop] = ispyb_path
- except Exception:
- pass
-
- def prepare_image_for_lims(self, image_dict):
- for prop in ["jpegThumbnailFileFullPath", "jpegFileFullPath"]:
- try:
- path = image_dict[prop]
- ispyb_path = HWR.beamline.session.path_to_ispyb(path)
- image_dict[prop] = ispyb_path
- except Exception:
- pass
-
-
-def test_hwo(hwo):
- proposal = "mx2018012551"
- proposal = "mx2018002222"
- pasw = "2222008102"
-
- info = hwo.login(proposal, pasw)
- # info = hwo.get_proposal(proposal_code, proposal_number)
- # info = hwo.get_proposal_by_username("u2020000007")
- print(info["status"])
-
- print("Getting associated samples")
- session_id = 58248
- proposal_id = 8250
- samples = hwo.get_samples(proposal_id, session_id)
- print(samples)
diff --git a/mxcubecore/HardwareObjects/ALBA/ALBAMachineInfo.py b/mxcubecore/HardwareObjects/ALBA/ALBAMachineInfo.py
deleted file mode 100644
index 6b480dca64..0000000000
--- a/mxcubecore/HardwareObjects/ALBA/ALBAMachineInfo.py
+++ /dev/null
@@ -1,208 +0,0 @@
-#
-# Project: 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 .
-
-"""
-[Name]
-ALBAMachineInfo
-
-[Description]
-Hardware Object is used to get relevant machine information
-(machine current, time to next injection, status, etc)
-Based on EMBL HwObj
-
-[Channels]
-- MachineCurrent
-- TopUpRemaining
-- State
-
-[Commands]
-
-[Emited signals]
-- valuesChanged
-
-[Functions]
-- None
-
-[Included Hardware Objects]
-- None
-
-
-Example Hardware Object XML file :
-==================================
-
- Mach
- mach/ct/gateway
- State
- Current
- TopUpRemaining
-
-"""
-
-import logging
-import time
-from gevent import spawn
-from urllib2 import urlopen
-from datetime import datetime, timedelta
-from mxcubecore import HardwareRepository as HWR
-from mxcubecore.BaseHardwareObjects import Equipment
-
-
-__author__ = "Jordi Andreu"
-__credits__ = ["MXCuBE collaboration"]
-
-__version__ = "2.2."
-__maintainer__ = "Jordi Andreu"
-__email__ = "jandreu[at]cells.es"
-__status__ = "Draft"
-
-
-class ALBAMachineInfo(Equipment):
- """
- Descript. : Displays actual information about the machine status.
- """
-
- def __init__(self, name):
- Equipment.__init__(self, name)
- self.logger = logging.getLogger("HWR MachineInfo")
- self.logger.info("__init__()")
-
- """
- Descript. :
- """
- # Parameters values
- self.values_dict = {}
- self.values_dict["mach_current"] = None
- self.values_dict["mach_status"] = ""
- self.values_dict["topup_remaining"] = ""
- # Dictionary for booleans indicating if values are in range
- # self.values_in_range_dict = {}
- self.chan_mach_current = None
- self.chan_mach_status = None
- self.chan_topup_remaining = None
-
- def init(self):
- """
- Descript. : Inits channels from xml configuration.
- """
- try:
- self.chan_mach_current = self.get_channel_object("MachCurrent")
- if self.chan_mach_current is not None:
- self.chan_mach_current.connect_signal(
- "update", self.mach_current_changed
- )
-
- self.chan_mach_status = self.get_channel_object("MachStatus")
- if self.chan_mach_status is not None:
- self.chan_mach_status.connect_signal("update", self.mach_status_changed)
-
- self.chan_topup_remaining = self.get_channel_object("TopUpRemaining")
- if self.chan_topup_remaining is not None:
- self.chan_topup_remaining.connect_signal(
- "update", self.topup_remaining_changed
- )
- except KeyError:
- self.logger.warning("%s: cannot read machine info", self.name())
-
- def mach_current_changed(self, value):
- """
- Descript. : Function called if the machine current is changed
- Arguments : new machine current (float)
- Return : -
- """
- if (
- self.values_dict["mach_current"] is None
- or abs(self.values_dict["mach_current"] - value) > 0.10
- ):
- self.values_dict["mach_current"] = value
- self.re_emit_values()
- self.logger.debug("New machine current value=%smA" % value)
-
- def mach_status_changed(self, status):
- """
- Descript. : Function called if machine status is changed
- Arguments : new machine status (string)
- Return : -
- """
- self.values_dict["mach_status"] = str(status)
- self.re_emit_values()
- self.logger.debug("New machine status=%s" % status)
-
- def topup_remaining_changed(self, value):
- """
- Descript. : Function called if topup ramaining is changed
- Arguments : new topup remainin (float)
- Return : -
- """
- self.values_dict["topup_remaining"] = value
- self.re_emit_values()
- self.logger.debug("New top-up remaining time=%ss" % value)
-
- def re_emit_values(self):
- """
- Descript. : Updates storage disc information, detects if intensity
- and storage space is in limits, forms a value list
- and value in range list, both emited by qt as lists
- Arguments : -
- Return : -
- """
-
- values_to_send = []
- values_to_send.append(self.values_dict["mach_current"])
- values_to_send.append(self.values_dict["mach_status"])
- values_to_send.append(self.values_dict["topup_remaining"])
-
- self.emit("valuesChanged", values_to_send)
- self.logger.debug("SIGNAL valuesChanged emitted")
-
- def get_mach_current(self):
- try:
- value = self.chan_mach_current.get_value()
- except Exception as e:
- self.logger.error("Cannot read machine current value, returning 0")
- value = 0
- finally:
- return value
- # return self.values_dict['mach_current']
-
- def get_current(self):
- return self.get_mach_current()
-
- def get_message(self):
- return "Machinfo status: %s" % self.get_mach_status()
-
- # def get_current_value(self):
- # """
- # Descript. :
- # """
- # return self.values_dict['current']
-
- def get_mach_status(self):
- return self.chan_mach_status.get_value()
-
- # return self.values_dict['mach_status']
-
- def get_topup_remaining(self):
- return self.chan_topup_remaining.get_value()
-
-
-# return self.values_dict['remaining']
-
-
-def test_hwo(hwo):
- print("Current is", hwo.get_current())
diff --git a/mxcubecore/HardwareObjects/ALBA/ALBAMiniDiff.py b/mxcubecore/HardwareObjects/ALBA/ALBAMiniDiff.py
deleted file mode 100644
index a69e7bf193..0000000000
--- a/mxcubecore/HardwareObjects/ALBA/ALBAMiniDiff.py
+++ /dev/null
@@ -1,565 +0,0 @@
-#
-# Project: 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 .
-
-"""
-[Name]
-ALBAMiniDiff
-
-[Description]
-Specific HwObj for M2D2 diffractometer @ ALBA
-
-[Channels]
-- N/A
-
-[Commands]
-- N/A
-
-[Emited signals]
-- pixelsPerMmChanged
-- phiMotorMoved
-- stateChanged
-- zoomMotorPredefinedPositionChanged
-
-
-[Functions]
-- None
-
-[Included Hardware Objects]
-- None
-"""
-
-import logging
-import time
-from mxcubecore.HardwareObjects.GenericDiffractometer import (
- GenericDiffractometer,
- DiffractometerState,
-)
-import gevent
-
-from mxcubecore.HardwareObjects import queue_model_objects
-
-
-__author__ = "Jordi Andreu"
-__credits__ = ["MXCuBE collaboration"]
-
-__version__ = "2.2."
-__maintainer__ = "Jordi Andreu"
-__email__ = "jandreu[at]cells.es"
-__status__ = "Draft"
-
-
-class ALBAMiniDiff(GenericDiffractometer):
- """
- Specific diffractometer HwObj for XALOC beamline.
- """
-
- def __init__(self, *args):
- GenericDiffractometer.__init__(self, *args)
- self.centring_hwobj = None
- self.super_hwobj = None
-
- def init(self):
-
- self.calibration = self.get_object_by_role("calibration")
-
- self.centring_hwobj = self.get_object_by_role("centring")
- self.super_hwobj = self.get_object_by_role("beamline-supervisor")
-
- if self.centring_hwobj is None:
- logging.getLogger("HWR").debug("ALBAMinidiff: Centring math is not defined")
-
- if self.super_hwobj is not None:
- self.connect(
- self.super_hwobj, "stateChanged", self.supervisor_state_changed
- )
- self.connect(
- self.super_hwobj, "phaseChanged", self.supervisor_phase_changed
- )
-
- self.state_channel = self.get_channel_object("State")
- self.connect(self.state_channel, "update", self.state_changed)
- # This is not used
- self.cmd_start_auto_focus = self.get_command_object("startAutoFocus")
-
- self.phi_motor_hwobj = self.get_object_by_role("phi")
- self.phiz_motor_hwobj = self.get_object_by_role("phiz")
- self.phiy_motor_hwobj = self.get_object_by_role("phiy")
- self.zoom_motor_hwobj = self.get_object_by_role("zoom")
- self.focus_motor_hwobj = self.get_object_by_role("focus")
- self.sample_x_motor_hwobj = self.get_object_by_role("sampx")
- self.sample_y_motor_hwobj = self.get_object_by_role("sampy")
-
- if self.phi_motor_hwobj is not None:
- self.connect(
- self.phi_motor_hwobj, "stateChanged", self.phi_motor_state_changed
- )
- self.connect(self.phi_motor_hwobj, "valueChanged", self.phi_motor_moved)
- else:
- logging.getLogger("HWR").error("ALBAMiniDiff: Phi motor is not defined")
-
- if self.phiz_motor_hwobj is not None:
- self.connect(
- self.phiz_motor_hwobj, "stateChanged", self.phiz_motor_state_changed
- )
- self.connect(self.phiz_motor_hwobj, "valueChanged", self.phiz_motor_moved)
- else:
- logging.getLogger("HWR").error("ALBAMiniDiff: Phiz motor is not defined")
-
- if self.phiy_motor_hwobj is not None:
- self.connect(
- self.phiy_motor_hwobj, "stateChanged", self.phiy_motor_state_changed
- )
- self.connect(self.phiy_motor_hwobj, "valueChanged", self.phiy_motor_moved)
- else:
- logging.getLogger("HWR").error("ALBAMiniDiff: Phiy motor is not defined")
-
- if self.zoom_motor_hwobj is not None:
- 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.connect(
- self.zoom_motor_hwobj, "stateChanged", self.zoom_motor_state_changed
- )
- else:
- logging.getLogger("HWR").error("ALBAMiniDiff: Zoom motor is not defined")
-
- if self.sample_x_motor_hwobj is not None:
- self.connect(
- self.sample_x_motor_hwobj,
- "stateChanged",
- self.sampleX_motor_state_changed,
- )
- self.connect(
- self.sample_x_motor_hwobj, "valueChanged", self.sampleX_motor_moved
- )
- else:
- logging.getLogger("HWR").error("ALBAMiniDiff: Sampx motor is not defined")
-
- if self.sample_y_motor_hwobj is not None:
- self.connect(
- self.sample_y_motor_hwobj,
- "stateChanged",
- self.sampleY_motor_state_changed,
- )
- self.connect(
- self.sample_y_motor_hwobj, "valueChanged", self.sampleY_motor_moved
- )
- else:
- logging.getLogger("HWR").error("ALBAMiniDiff: Sampx motor is not defined")
-
- if self.focus_motor_hwobj is not None:
- self.connect(self.focus_motor_hwobj, "valueChanged", self.focus_motor_moved)
-
- GenericDiffractometer.init(self)
-
- queue_model_objects.CentredPosition.set_diffractometer_motor_names(
- "phi", "phiy", "phiz", "sampx", "sampy", "kappa"
- )
-
- def state_changed(self, state):
- """
- Overides method to map Tango ON state to Difractaometer State Ready.
-
- @state: Tango state
- """
-
- if str(state) == "ON":
- state = DiffractometerState.tostring(DiffractometerState.Ready)
-
- if state != self.current_state:
- logging.getLogger("HWR").debug(
- "ALBAMinidiff: State changed %s (was: %s)"
- % (str(state), self.current_state)
- )
- self.current_state = state
- self.emit("minidiffStateChanged", (self.current_state))
-
- def getCalibrationData(self, offset=None):
- """
- Get pixel size for OAV system
-
- @offset: Unused
- @return: 2-tuple float
- """
- calibx, caliby = self.calibration.getCalibration()
- return 1000.0 / caliby, 1000.0 / caliby
- # return 1000./self.md2.CoaxCamScaleX, 1000./self.md2.CoaxCamScaleY
-
- def get_pixels_per_mm(self):
- """
- Returns the pixel/mm for x and y. Overrides GenericDiffractometer method.
- """
- px_x, px_y = self.getCalibrationData()
- return (px_x, px_y)
-
- def update_pixels_per_mm(self, *args):
- """
- Emit signal with current pixel/mm values.
- """
- self.pixels_per_mm_x, self.pixels_per_mm_y = self.getCalibrationData()
- self.emit("pixelsPerMmChanged", ((self.pixels_per_mm_x, self.pixels_per_mm_y),))
-
- # TODO: looks quite bizarre.
- def motor_positions_to_screen(self, centred_positions_dict):
- """
- Convert motor positions contained in a dictionary to screen (canvas) positions.
- Overrides GenericDiffractometer method.
-
- @centered_positions_dict: dictionary to be converted
- @return: position
- """
- c = centred_positions_dict
-
- # if self.head_type == GenericDiffractometer.HEAD_TYPE_MINIKAPPA:
- # kappa = self.motor_hwobj_dict["kappa"]
- # phi = self.motor_hwobj_dict["kappa_phi"]
-
- xy = self.centring_hwobj.centringToScreen(c)
- if xy is None:
- return None
-
- x = xy["X"] * self.pixels_per_mm_x + self.zoom_centre["x"]
-
- y = xy["Y"] * self.pixels_per_mm_y + self.zoom_centre["y"]
-
- # logging.getLogger("HWR").debug(" motor_positions_to_screen ")
- # logging.getLogger("HWR").debug(" positions = %s " % str(centred_positions_dict))
- # logging.getLogger("HWR").debug(" x,y = %s, %s " % (x,y))
-
- return x, y
-
- # TODO: Must be implemented correctly.
- def get_centred_point_from_coord(self, x, y, return_by_names=None):
- """
- Returns a dictionary with motors name ans positions centred.
- It is expected in start_move_to_beam and move_to_beam methods in
- GenericDIffractometer HwObj.
-
- @return: dict
- """
- return {"omega": [200, 200]}
-
- def getBeamInfo(self, update_beam_callback):
- """
- Update beam info (position and shape) ans execute callback.
-
- @update_beam_callback: callback method passed as argument.
- """
- calibx, caliby = self.calibration.getCalibration()
-
- size_x = self.get_channel_object("beamInfoX").get_value() / 1000.0
- size_y = self.get_channel_object("beamInfoY").get_value() / 1000.0
-
- data = {"size_x": size_x, "size_y": size_y, "shape": "ellipse"}
-
- update_beam_callback(data)
-
- # TODO:Implement dynamically
- def use_sample_changer(self):
- """
- Overrides GenericDiffracometer method.
- """
- return True
-
- # TODO:Implement dynamically
- def in_plate_mode(self):
- """
- Overrides GenericDiffracometer method.
- """
- return False
-
- # We are using the sample_centring module. this is not used anymore
- def start_manual_centring(self, *args, **kwargs):
- """
- Start manual centring. Overrides GenericDiffracometer method.
- Prepares diffractometer for manual centring.
- """
- if self.prepare_centring():
- GenericDiffractometer.start_manual_centring(self, *args, **kwargs)
- else:
- logging.getLogger("HWR").info(
- " Failed to prepare diffractometer for centring"
- )
- self.invalidate_centring()
-
- def start_auto_centring(self, *args, **kwargs):
- """
- Start manual centring. Overrides GenericDiffracometer method.
- Prepares diffractometer for manual centring.
- """
- if self.prepare_centring():
- GenericDiffractometer.start_auto_centring(self, *args, **kwargs)
- else:
- logging.getLogger("HWR").info(
- " Failed to prepare diffractometer for centring"
- )
- self.invalidate_centring()
-
- def prepare_centring(self):
- """
- Prepare beamline for to sample_view phase.
- """
- if not self.is_sample_view_phase():
- logging.getLogger("HWR").info(
- " Not in sample view phase. Asking supervisor to go"
- )
- success = self.go_sample_view()
- if not success:
- logging.getLogger("HWR").info("Cannot set SAMPLE VIEW phase")
- return False
-
- return True
-
- # def manual_centring(self):
- # """
- # We are using the sample_centring module. this is not used anymore
- # """
- # self.centring_hwobj.initCentringProcedure()
-
- # # self.head_type = self.chan_head_type.get_value()
- # # Say diffractometer to go to SampleView phase
-
- # # go to sample_view phase
- # if not self.is_sample_view_phase():
- # logging.getLogger("HWR").info(" Not in sample view phase. Asking supervisor to go")
- # success = self.go_sample_view()
- # if not success:
- # logging.getLogger("HWR").info("Cannot set SAMPLE VIEW phase")
- # return False
-
- # phi_init_position = self.phi_motor_hwobj.get_value()
-
- # for click in range(3):
- # self.user_clicked_event = gevent.event.AsyncResult()
- # x, y = self.user_clicked_event.get()
- # self.centring_hwobj.appendCentringDataPoint(
- # {"X": (x - self.zoom_centre['x'])/ self.pixels_per_mm_x,
- # "Y": (y - self.zoom_centre['y'])/ self.pixels_per_mm_y})
-
- # if self.in_plate_mode():
- # dynamic_limits = self.phi_motor_hwobj.get_dynamic_limits()
- # if click == 0:
- # self.phi_motor_hwobj.set_value(dynamic_limits[0])
- # elif click == 1:
- # self.phi_motor_hwobj.set_value(dynamic_limits[1])
- # else:
- # if click < 2:
- # self.phi_motor_hwobj.set_value_relative(-90, timeout=None)
-
- # #logging.getLogger("HWR").info(" Returning phi to initial position %s" % phi_init_position)
- # #self.phi_motor_hwobj.set_value(phi_init_position, timeout=None)
- #
- # return self.centring_hwobj.centeredPosition(return_by_name=False)
-
- def is_sample_view_phase(self):
- """
- Returns boolean by comparing the supervisor current phase and SAMPLE view phase.
-
- @return: boolean
- """
- return self.super_hwobj.get_current_phase().upper() == "SAMPLE"
-
- def go_sample_view(self):
- """
- Go to sample view phase.
- """
- self.super_hwobj.go_sample_view()
-
- while True:
- super_state = str(self.super_hwobj.get_state()).upper()
- if super_state != "MOVING":
- logging.getLogger("HWR").debug(
- "ALBAMinidiff: go_sample_view done . super_state is %s"
- % super_state
- )
- return True
- gevent.sleep(0.2)
-
- def supervisor_state_changed(self, state):
- """
- Emit stateChanged signal according to supervisor current state.
- """
- return
- self.current_state = state
- self.emit("stateChanged", (self.current_state,))
-
- # TODO: Review override current_state by current_phase
- def supervisor_phase_changed(self, phase):
- """
- Emit stateChanged signal according to supervisor current phase.
- """
- # self.current_state = phase
- self.emit("minidiffPhaseChanged", (phase,))
-
- def phi_motor_moved(self, pos):
- """
- Emit phiMotorMoved signal with position value.
- """
- self.current_motor_positions["phi"] = pos
- # self.emit_diffractometer_moved()
- self.emit("phiMotorMoved", pos)
- # self.emit('stateChanged', (self.current_motor_states["phi"], ))
-
- def phi_motor_state_changed(self, state):
- """
- Emit stateChanged signal with state value.
- """
- self.current_motor_states["phi"] = state
- self.emit("stateChanged", (state,))
-
- def phiz_motor_moved(self, pos):
- """
- """
- self.current_motor_positions["phiz"] = pos
- # if time.time() - self.centring_time > 3.0:
- # self.invalidate_centring()
- # self.emit_diffractometer_moved()
-
- def phiz_motor_state_changed(self, state):
- """
- Emit stateChanged signal with state value.
- """
- self.emit("stateChanged", (state,))
-
- def phiy_motor_state_changed(self, state):
- """
- Emit stateChanged signal with state value.
- """
- self.emit("stateChanged", (state,))
-
- def phiy_motor_moved(self, pos):
- """
- """
- self.current_motor_positions["phiy"] = pos
- # if time.time() - self.centring_time > 3.0:
- # self.invalidate_centring()
- # self.emit_diffractometer_moved()
-
- def zoom_position_changed(self, value):
- """
- Update positions after zoom changed.
-
- @value: zoom position.
- """
- self.update_pixels_per_mm()
- self.current_motor_positions["zoom"] = value
- self.refresh_omega_reference_position()
-
- def zoom_motor_predefined_position_changed(self, position_name, offset):
- """
- Update pixel size and emit signal.
- """
- self.update_pixels_per_mm()
- self.emit("zoomMotorPredefinedPositionChanged", (position_name, offset))
-
- def zoom_motor_state_changed(self, state):
- """
- Emit signal for motor zoom changed
-
- @state: new state value to emit.
- """
- self.emit("stateChanged", (state,))
-
- def sampleX_motor_moved(self, pos):
- """
- """
- self.current_motor_positions["sampx"] = pos
- # if time.time() - self.centring_time > 3.0:
- # self.invalidate_centring()
- # self.emit_diffractometer_moved()
-
- def sampleX_motor_state_changed(self, state):
- """
- Emit stateChanged signal with state value.
- """
- self.current_motor_states["sampx"] = state
- self.emit("stateChanged", (state,))
-
- def sampleY_motor_moved(self, pos):
- """
- """
- self.current_motor_positions["sampy"] = pos
- # if time.time() - self.centring_time > 3.0:
- # self.invalidate_centring()
- # self.emit_diffractometer_moved()
-
- def sampleY_motor_state_changed(self, state):
- """
- Emit stateChanged signal with state value.
- """
- self.current_motor_states["sampy"] = state
- self.emit("stateChanged", (state,))
-
- def focus_motor_moved(self, pos):
- """
- """
- self.current_motor_positions["focus"] = pos
-
- # TODO: The command is not configured in the xml. Unused
- def start_auto_focus(self):
- self.cmd_start_auto_focus()
-
- def move_omega(self, pos, velocity=None):
- """
- Move omega to absolute position.
-
- @pos: target position
- """
- # turn it on
- if velocity is not None:
- self.phi_motor_hwobj.set_velocity(velocity)
- self.phi_motor_hwobj.set_value(pos)
- time.sleep(0.2)
- # it should wait here
-
- def move_omega_relative(self, relpos):
- """
- Move omega to relative position.
-
- @relpos: target relative position
- """
- self.wait_device_ready()
- self.phi_motor_hwobj.set_value_relative(relpos, timeout=None)
-
- # TODO: define phases as enum members.
- def set_phase(self, phase):
- """
- General function to set phase by using supervisor commands.
- """
- if phase == "Transfer":
- self.super_hwobj.go_transfer()
- elif phase == "Collect":
- self.super_hwobj.go_collect()
- elif phase == "BeamView":
- self.super_hwobj.go_beam_view()
- elif phase == "Centring":
- self.super_hwobj.go_sample_view()
- else:
- logging.getLogger("HWR").warning(
- "Diffractometer set_phase asked for un-handled phase: %s" % phase
- )
-
-
-def test_hwo(hwo):
- print(hwo.get_phase_list())
diff --git a/mxcubecore/HardwareObjects/ALBA/ALBAPilatus.py b/mxcubecore/HardwareObjects/ALBA/ALBAPilatus.py
deleted file mode 100644
index a39b24a80f..0000000000
--- a/mxcubecore/HardwareObjects/ALBA/ALBAPilatus.py
+++ /dev/null
@@ -1,290 +0,0 @@
-#
-# Project: 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 .
-
-from __future__ import print_function
-import logging
-import time
-
-from mxcubecore.HardwareObjects.abstract.AbstractDetector import (
- AbstractDetector,
-)
-from mxcubecore.BaseHardwareObjects import HardwareObject
-
-from PyTango.gevent import DeviceProxy
-
-__author__ = "Vicente Rey"
-__credits__ = ["ALBA"]
-__version__ = "2.3."
-__category__ = "General"
-
-
-class ALBAPilatus(AbstractDetector, HardwareObject):
- """Detector class. Contains all information about detector
- - states are 'OK', and 'BAD'
- - status is busy, exposing, ready, etc.
- - physical property is RH for pilatus, P for rayonix
- """
-
- def __init__(self, name):
- AbstractDetector.__init__(self)
- HardwareObject.__init__(self, name)
-
- self.distance_motor_hwobj = None
- self.default_distance = None
- self.default_distance_limits = None
-
- self.default_latency_time = 0.003
-
- self.exp_time_limits = None
-
- self.headers = {}
-
- def init(self):
- self.distance_motor_hwobj = self.get_object_by_role("distance_motor")
- self.devname = self.get_property("tangoname")
-
- try:
- self.latency_time = float(self.get_property("latency_time"))
- except Exception:
- self.latency_time = None
-
- if self.latency_time is None:
- logging.getLogger("HWR").debug(
- "Cannot obtain latency time from Pilatus XML. Using %s"
- % self.default_latency_time
- )
- self.latency_time = self.default_latency_time
-
- self.devspecific = self.get_property("device_specific")
-
- exp_time_limits = self.get_property("exposure_limits")
- self.exp_time_limits = map(float, exp_time_limits.strip().split(","))
-
- self.device = DeviceProxy(self.devname)
- self.device_specific = DeviceProxy(self.devspecific)
- self.device.set_timeout_millis(30000)
-
- self.beamx_chan = self.get_channel_object("beamx")
- self.beamy_chan = self.get_channel_object("beamy")
-
- def start_acquisition(self):
- self.device.startAcq()
-
- def stop_acquisition(self):
- self.device.abortAcq()
-
- def wait_move_distance_done(self):
- self.distance_motor_hwobj.wait_end_of_move()
-
- def get_threshold(self):
- return self.device_specific.threshold
-
- def get_threshold_gain(self):
- return self.device_specific.threshold_gain
-
- def has_shutterless(self):
- """Return True if has shutterless mode"""
- return True
-
- def get_beam_position(self, distance=None, wavelength=None):
- """Returns beam center coordinates"""
- beam_x = 0
- beam_y = 0
- try:
- beam_x = self.beamx_chan.get_value()
- beam_y = self.beamy_chan.get_value()
- except Exception:
- pass
- return beam_x, beam_y
-
- def get_manufacturer(self):
- return self.get_property("manufacturer")
- return "Dectris"
-
- def get_model(self):
- return self.get_property("model")
-
- def get_detector_type(self):
- return self.get_property("type")
-
- def get_default_exposure_time(self):
- return self.get_property("default_exposure_time")
-
- def get_minimum_exposure_time(self):
- return self.get_property("minimum_exposure_time")
-
- def get_exposure_time_limits(self):
- """Returns exposure time limits as list with two floats"""
- return self.exp_time_limits
-
- def get_file_suffix(self):
- return self.get_property("file_suffix")
-
- def get_pixel_size(self):
- return self.get_property("px"), self.get_property("py")
-
- # methods for data collection
- def set_energy_threshold(self):
- eugap_ch = self.get_channel_object("eugap")
-
- try:
- currentenergy = eugap_ch.get_value()
- except Exception:
- currentenergy = 12.6
-
- det_energy = self.get_threshold()
-
- # threshold = det_energy / 2.
- # limitenergy = threshold / 0.8
-
- if round(currentenergy, 6) < 7.538:
- currentenergy = 7.538
-
- kev_diff = abs(det_energy - currentenergy)
-
- if kev_diff > 1.2:
- logging.getLogger("HWR").debug(
- "programming energy_threshold on pilatus to: %s" % currentenergy
- )
- # if self.wait_standby():
- # self.device_specific.energy_threshold = currentenergy
-
- def get_latency_time(self):
- return self.latency_time
-
- def wait_standby(self, timeout=300):
- t0 = time.time()
- while self.device_specific.cam_state == "STANDBY":
- if time.time() - t0 > timeout:
- print("timeout waiting for Pilatus to be on STANDBY")
- return False
- time.sleep(0.1)
- return True
-
- def prepare_acquisition(self, dcpars):
-
- self.set_energy_threshold()
- # self.wait_standby()
-
- osc_seq = dcpars["oscillation_sequence"][0]
- file_pars = dcpars["fileinfo"]
-
- basedir = file_pars["directory"]
- prefix = "%s_%s_" % (file_pars["prefix"], file_pars["run_number"])
-
- first_img_no = osc_seq["start_image_number"]
- nb_frames = osc_seq["number_of_images"]
- exp_time = osc_seq["exposure_time"]
-
- fileformat = "CBF"
- trig_mode = "EXTERNAL_TRIGGER"
- # latency_time = 0.003
-
- logging.getLogger("HWR").debug(
- " Preparing detector (dev=%s) for data collection" % self.devname
- )
-
- logging.getLogger("HWR").debug(" /saving directory: %s" % basedir)
- logging.getLogger("HWR").debug(" /prefix : %s" % prefix)
- logging.getLogger("HWR").debug(" /saving_format : %s" % fileformat)
- logging.getLogger("HWR").debug(" /trigger_mode : %s" % trig_mode)
- logging.getLogger("HWR").debug(" /acq_nb_frames : %s" % nb_frames)
- logging.getLogger("HWR").debug(
- " /acq_expo_time : %s" % str(exp_time - self.latency_time)
- )
- logging.getLogger("HWR").debug(" /latency_time : %s" % self.latency_time)
-
- self.device.write_attribute("saving_mode", "AUTO_FRAME")
- self.device.write_attribute("saving_directory", basedir)
- self.device.write_attribute("saving_prefix", prefix)
- self.device.write_attribute("saving_format", fileformat)
-
- # set ROI and header in limaserver
- # TODO
-
- TrigList = [
- "INTERNAL_TRIGGER",
- "EXTERNAL_TRIGGER",
- "EXTERNAL_TRIGGER_MULTI",
- "EXTERNAL_GATE",
- "EXTERNAL_START_STOP",
- ]
-
- self.device.write_attribute("acq_trigger_mode", trig_mode)
- self.device.write_attribute("acq_expo_time", exp_time - self.latency_time)
- self.device.write_attribute("latency_time", self.latency_time)
-
- return True
-
- def prepare_collection(self, nb_frames, first_img_no):
- logging.getLogger("HWR").debug(
- "ALBAPilatus. preparing collection. nb_images: %s, first_no: %s"
- % (nb_frames, first_img_no)
- )
- self.device.write_attribute("acq_nb_frames", nb_frames)
- self.device.write_attribute("saving_next_number", first_img_no)
- self.device.prepareAcq()
- return True
-
- def start_collection(self):
- self.start_acquisition()
-
- def stop_collection(self):
- self.stop_acquisition()
-
- def set_image_headers(self, image_headers, angle_info):
-
- nb_images = image_headers["nb_images"]
- angle_inc = image_headers["Angle_increment"]
- start_angle = image_headers["Start_angle"]
-
- startangles_list = list()
- ang_start, ang_inc, spacing = angle_info
- for i in range(nb_images):
- startangles_list.append("%0.4f deg." % (ang_start + spacing * i))
-
- headers = list()
- for i, sa in enumerate(startangles_list):
- header = (
- "_array_data.header_convention PILATUS_1.2\n"
- "# Detector: PILATUS 6M, S/N 60-0108, Alba\n"
- "# %s\n"
- "# Pixel_size 172e-6 m x 172e-6 m\n"
- "# Silicon sensor, thickness 0.000320 m\n"
- % time.strftime("%Y/%b/%d %T")
- )
-
- # Acquisition values (headers dictionary) but overwrites start angle
- image_headers["Start_angle"] = sa
- for key, value in image_headers.items():
- if key == "nb_images":
- continue
- header += "# %s %s\n" % (key, value)
- headers.append("%d : array_data/header_contents|%s;" % (i, header))
-
- self.device.write_attribute("saving_header_delimiter", ["|", ";", ":"])
- self.device.resetCommonHeader()
- self.device.resetFrameHeaders()
- self.device.setImageHeader(headers)
-
-
-def test_hwo(hwo):
- print("Detector Distance is: ", hwo.distance.get_value())
- print(" Beam X: %s / Beam Y: %s" % hwo.get_beam_position())
- # print("going to 490 : ", hwo.distance.set_value(490))
diff --git a/mxcubecore/HardwareObjects/ALBA/ALBASession.py b/mxcubecore/HardwareObjects/ALBA/ALBASession.py
deleted file mode 100644
index c01382306d..0000000000
--- a/mxcubecore/HardwareObjects/ALBA/ALBASession.py
+++ /dev/null
@@ -1,71 +0,0 @@
-import os
-import time
-import logging
-
-from mxcubecore.HardwareObjects import Session
-from mxcubecore.HardwareObjects import queue_model_objects
-
-
-class ALBASession(Session.Session):
- def get_base_data_directory(self):
- """
- Returns the base data directory for ALBA
- In ALBA the base directory already includes the user
- home directory. So
- information into account, such as if the current user
- is inhouse.
-
- :returns: The base data path.
- :rtype: str
- """
- if self.session_start_date:
- start_time = self.session_start_date.split(" ")[0].replace("-", "")
- else:
- start_time = time.strftime("%Y%m%d")
-
- # directory = os.path.join(self.base_directory, self.get_proposal(), 'DATA', start_time)
- if self.base_directory is not None:
- directory = os.path.join(self.base_directory, start_time)
- else:
- directory = "/tmp"
- return directory
-
- def get_archive_directory(self, directory=None):
- if directory is None:
- thedir = self.get_base_data_directory()
- else:
- thedir = directory
-
- parts = thedir.split(os.path.sep)
- user_dir = parts[5]
- session_date = parts[6]
- # remove RAW_DATA from da
- try:
- more = parts[8:]
- except Exception:
- more = []
-
- archive_dir = os.path.join(
- self.base_archive_directory, user_dir, session_date, *more
- )
- # if 'RAW_DATA' in thedir:
- # thedir = thedir.replace('RAW_DATA','ARCHIVE')
- # else:
- # thedir = os.path.join(thedir, 'ARCHIVE')
-
- logging.getLogger("HWR").debug(
- "ALBASession. returning archive directory: %s" % archive_dir
- )
- return archive_dir
-
- def set_ldap_homedir(self, homedir):
- self.base_directory = homedir
- self.base_process_directory = homedir
-
- queue_model_objects.PathTemplate.set_data_base_path(self.base_directory)
-
-
-def test_hwo(hwo):
- print(hwo.get_base_data_directory())
- print(hwo.get_process_directory())
- print(hwo.get_archive_directory())
diff --git a/mxcubecore/HardwareObjects/ALBA/ALBASupervisor.py b/mxcubecore/HardwareObjects/ALBA/ALBASupervisor.py
deleted file mode 100644
index 42074ef1c1..0000000000
--- a/mxcubecore/HardwareObjects/ALBA/ALBASupervisor.py
+++ /dev/null
@@ -1,76 +0,0 @@
-from mxcubecore import HardwareRepository as HWR
-from mxcubecore.BaseHardwareObjects import Device
-import logging
-
-
-class ALBASupervisor(Device):
- def __init__(self, *args):
- Device.__init__(self, *args)
-
- def init(self):
- self.state_chan = self.get_channel_object("state")
- self.go_collect_cmd = self.get_command_object("go_collect")
- self.go_sample_view_cmd = self.get_command_object("go_sample_view")
- self.go_transfer_cmd = self.get_command_object("go_transfer")
- self.go_beam_view_cmd = self.get_command_object("go_beam_view")
-
- self.phase_chan = self.get_channel_object("phase")
- self.detector_cover_chan = self.get_channel_object("detector_cover_open")
-
- self.state_chan.connect_signal("update", self.state_changed)
- self.phase_chan.connect_signal("update", self.phase_changed)
- self.detector_cover_chan.connect_signal("update", self.detector_cover_changed)
-
- def is_ready(self):
- return True
-
- def getUserName(self):
- return self.username
-
- def state_changed(self, value):
- self.current_state = value
- self.emit("stateChanged", self.current_state)
-
- def phase_changed(self, value):
- if value == "Sample":
- value = "Centring"
- self.current_phase = value
- self.emit("phaseChanged", self.current_phase)
-
- def get_current_phase(self):
- return self.phase_chan.get_value()
-
- def go_collect(self):
- return self.go_collect_cmd()
-
- def go_transfer(self):
- return self.go_transfer_cmd()
-
- def go_sample_view(self):
- return self.go_sample_view_cmd()
-
- def go_beam_view(self):
- return self.go_beam_view_cmd()
-
- def get_state(self):
- return self.state_chan.get_value()
-
- def detector_cover_changed(self, value):
- self.detector_cover_opened = value
- # self.emit('levelChanged', self.current_level)
-
- def open_detector_cover(self):
- self.detector_cover_chan.set_value(True)
-
- def close_detector_cover(self, value):
- self.detector_cover_chan.set_value(False)
-
- def is_detector_cover_opened(self):
- return self.detector_cover_chan.get_value()
-
-
-def test_hwo(hwo):
- print('\nSupervisor control "%s"\n' % hwo.getUserName())
- print(" Detector Cover opened:", hwo.is_detector_cover_opened())
- print(" Current Phase is:", hwo.get_current_phase())
- print(" Current State is:", str(hwo.get_state()))
diff --git a/mxcubecore/HardwareObjects/ALBA/ALBATransmission.py b/mxcubecore/HardwareObjects/ALBA/ALBATransmission.py
deleted file mode 100644
index a1aaf1041f..0000000000
--- a/mxcubecore/HardwareObjects/ALBA/ALBATransmission.py
+++ /dev/null
@@ -1,44 +0,0 @@
-from mxcubecore import HardwareRepository as HWR
-from mxcubecore.BaseHardwareObjects import Device
-
-
-class ALBATransmission(Device):
- def __init__(self, *args):
- Device.__init__(self, *args)
- self.transmission = None
-
- def init(self):
- self.transmissionChannel = self.get_channel_object("transmission")
- self.stateChannel = self.get_channel_object("state")
-
- self.transmissionChannel.connect_signal("update", self.transmissionChanged)
- self.stateChannel.connect_signal("update", self.stateChanged)
-
- def is_ready(self):
- return True
-
- def transmissionChanged(self, value):
- self.transmission = value
- self.emit("attFactorChanged", self.transmission)
-
- def stateChanged(self, value):
- self.state = str(value)
- self.emit("attStateChanged", self.state)
-
- def getAttState(self):
- self.state = self.stateChannel.get_value()
- return self.state
-
- def get_value(self):
- return self.transmissionChannel.get_value()
-
- def _set_value(self, value):
- self.transmissionChannel.set_value(value)
-
- def re_emit_values(self):
- value = self.get_value()
- self.emit("attFactorChanged", value)
-
-
-def test_hwo(hwo):
- print("Transmission is: ", hwo.get_value())
diff --git a/mxcubecore/HardwareObjects/ALBA/ALBAZoomMotor.py b/mxcubecore/HardwareObjects/ALBA/ALBAZoomMotor.py
deleted file mode 100755
index fa1ab2774d..0000000000
--- a/mxcubecore/HardwareObjects/ALBA/ALBAZoomMotor.py
+++ /dev/null
@@ -1,191 +0,0 @@
-#
-# Project: 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 .
-
-"""
-[Name]
-ALBAZoomMotor
-
-[Description]
-Hardware Object is used to manipulate the zoom of the OAV camera.
-
-[Channels]
-- position
-- state
-- labels
-
-[Commands]
-
-[Emited signals]
-- stateChanged
-- predefinedPositionChanged
-
-[Functions]
-- None
-
-[Included Hardware Objects]
-- None
-
-Example Hardware Object XML file :
-==================================
-
- Zoom
- ioregister/eh_zoom_tangoior_ctrl/2
- zoom
- Zoom
- Value
- State
- Labels
- 200
- 0.001
-
-"""
-
-from mxcubecore import BaseHardwareObjects
-from mxcubecore.HardwareObjects.abstract.AbstractMotor import AbstractMotor
-import logging
-import PyTango
-
-__author__ = "Bixente Rey"
-__credits__ = ["MXCuBE collaboration"]
-
-__version__ = "2.2."
-__maintainer__ = "Jordi Andreu"
-__email__ = "jandreu[at]cells.es"
-__status__ = "Draft"
-
-
-class ALBAZoomMotor(BaseHardwareObjects.Device, AbstractMotor):
-
- INIT, FAULT, READY, MOVING, ONLIMIT = range(5)
-
- def __init__(self, name):
- BaseHardwareObjects.Device.__init__(self, name)
-
- def init(self):
- logging.getLogger("HWR").debug("Initializing zoom motor IOR")
- self.positionChannel = self.get_channel_object("position")
- self.stateChannel = self.get_channel_object("state")
- self.labelsChannel = self.get_channel_object("labels")
- self.currentposition = 0
- self.currentstate = None
-
- self.positionChannel.connect_signal("update", self.positionChanged)
- self.stateChannel.connect_signal("update", self.stateChanged)
-
- def get_predefined_positions_list(self):
- labels = self.labelsChannel.get_value()
- labels = labels.split()
- retlist = []
- for label in labels:
- # label, pos = label.split(":")
- # retlist.append(int(pos))
- pos = str(label.replace(":", " "))
- retlist.append(pos)
- logging.getLogger("HWR").debug("Zoom positions list: %s" % repr(retlist))
- new_retlist = []
- for n, e in enumerate(retlist):
- name = e.split()
- new_retlist.append("%s %s" % (n + 1, name[0]))
- logging.getLogger("HWR").debug("Zoom positions list: %s" % repr(new_retlist))
-
- # retlist = ["z1 1","z2 2"]
- # logging.getLogger("HWR").debug("Zoom positions list: %s" % repr(retlist))
- return new_retlist
-
- def moveToPosition(self, posno):
- no = posno.split()[0]
- logging.getLogger("HWR").debug("type %s" % type(no))
- # no = posno
- logging.getLogger("HWR").debug("Moving to position %s" % no)
- state = self.positionChannel.set_value(int(no))
-
- def motorIsMoving(self):
- if str(self.get_state()) == "MOVING":
- return True
- else:
- return False
-
- def get_limits(self):
- return (1, 12)
-
- def get_state(self):
- state = self.stateChannel.get_value()
- curr_pos = self.get_value()
- if state == PyTango.DevState.ON:
- return ALBAZoomMotor.READY
- elif state == PyTango.DevState.MOVING or state == PyTango.DevState.RUNNING:
- return ALBAZoomMotor.MOVING
- elif curr_pos in self.get_limits():
- return ALBAZoomMotor.ONLIMIT
- else:
- return ALBAZoomMotor.FAULT
- return state
-
- def get_value(self):
- try:
- return self.positionChannel.get_value()
- except Exception:
- return self.currentposition
-
- def get_current_position_name(self):
- try:
- n = int(self.positionChannel.get_value())
- value = "%s z%s" % (n, n)
- logging.getLogger("HWR").debug(
- "get_current_position_name: %s" % repr(value)
- )
- return value
- except Exception:
- logging.getLogger("HWR").debug("cannot get name zoom value")
- return None
-
- def stateChanged(self, state):
- logging.getLogger("HWR").debug("stateChanged emitted: %s" % state)
- the_state = self.get_state()
- if the_state != self.currentstate:
- self.currentstate = the_state
- self.emit("stateChanged", (the_state,))
-
- def positionChanged(self, currentposition):
- previous_position = self.currentposition
- self.currentposition = self.get_current_position_name()
- if self.currentposition != previous_position:
- logging.getLogger("HWR").debug(
- "predefinedPositionChanged emitted: %s" % self.currentposition
- )
- self.emit("predefinedPositionChanged", (self.currentposition, 0))
-
- def is_ready(self):
- state = self.get_state()
- return state == ALBAZoomMotor.READY
-
-
-def test_hwo(zoom):
-
- print(type(zoom.get_state()))
-
- print(" Zoom position is : ", zoom.get_value())
- print("Zoom position name is : ", zoom.get_current_position_name())
- print(" Moving : ", zoom.motorIsMoving())
- print(" State : ", zoom.get_state())
- print(" Positions : ", zoom.get_predefined_positions_list())
-
-
-if __name__ == "__main__":
- test()
diff --git a/mxcubecore/HardwareObjects/ALBA/ALBAZoomMotorAutoBrightness.py b/mxcubecore/HardwareObjects/ALBA/ALBAZoomMotorAutoBrightness.py
deleted file mode 100755
index 4d0d8d5f38..0000000000
--- a/mxcubecore/HardwareObjects/ALBA/ALBAZoomMotorAutoBrightness.py
+++ /dev/null
@@ -1,171 +0,0 @@
-#
-# Project: 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 .
-
-"""
-[Name]
-ALBAZoomMotorAutoBrightness
-
-[Description]
-Hardware Object is used to manipulate the zoom IOR and the
-paired backlight intensity (slave IOR)
-
-[Channels]
-- None
-
-[Commands]
-
-[Emited signals]
-- stateChanged
-- predefinedPositionChanged
-
-[Functions]
-- None
-
-[Included Hardware Objects]
-- zoom
-- blight
-
-Example Hardware Object XML file :
-==================================
-
-
-
-
-"""
-
-from mxcubecore import BaseHardwareObjects
-from mxcubecore.HardwareObjects.abstract.AbstractMotor import AbstractMotor
-import logging
-
-__author__ = "Jordi Andreu"
-__credits__ = ["MXCuBE collaboration"]
-
-__version__ = "2.2."
-__maintainer__ = "Jordi Andreu"
-__email__ = "jandreu[at]cells.es"
-__status__ = "Draft"
-
-
-class ALBAZoomMotorAutoBrightness(BaseHardwareObjects.Device, AbstractMotor):
-
- INIT, FAULT, READY, MOVING, ONLIMIT = range(5)
-
- def __init__(self, name):
- BaseHardwareObjects.Device.__init__(self, name)
-
- def init(self):
- logging.getLogger("HWR").debug("Initializing zoom motor autobrightness IOR")
-
- self.zoom = self.get_object_by_role("zoom")
- self.blight = self.get_object_by_role("blight")
-
- self.zoom.positionChannel.connect_signal("update", self.positionChanged)
- self.zoom.stateChannel.connect_signal("update", self.stateChanged)
-
- def get_predefined_positions_list(self):
- retlist = self.zoom.get_predefined_positions_list()
- logging.getLogger("HWR").debug("Zoom positions list: %s" % repr(retlist))
- return retlist
-
- def moveToPosition(self, posno):
- # no = posno.split()[0]
- # logging.getLogger("HWR").debug("Moving to position %s" % no)
-
- # self.blight.moveToPosition(posno)
- self.zoom.moveToPosition(posno)
- state = self.zoom.get_state()
- # state = self.positionChannel.set_value(int(no))
-
- def motorIsMoving(self):
- return self.zoom.motorIsMoving()
-
- # if str(self.get_state()) == "MOVING":
- # return True
- # else:
- # return False
-
- def get_limits(self):
- # return (1,12)
- return self.zoom.get_limits()
-
- def get_state(self):
- # state = self.stateChannel.get_value()
- # curr_pos = self.get_value()
- # if state == PyTango.DevState.ON:
- # return ALBAZoomMotor.READY
- # elif state == PyTango.DevState.MOVING or state == PyTango.DevState.RUNNING:
- # return ALBAZoomMotor.MOVING
- # elif curr_pos in self.get_limits():
- # return ALBAZoomMotor.ONLIMIT
- # else:
- # return ALBAZoomMotor.FAULT
- # return state
- return self.zoom.get_state()
-
- def get_value(self):
- return self.zoom.get_value()
-
- def get_current_position_name(self):
- # n = int(self.positionChannel.get_value())
- # value = "%s z%s" % (n, n)
- # logging.getLogger("HWR").debug("get_current_position_name: %s" % repr(value))
- # return value
- return self.zoom.get_current_position_name()
-
- def stateChanged(self, state):
- logging.getLogger("HWR").debug("stateChanged emitted: %s" % state)
- self.emit("stateChanged", (self.get_state(),))
-
- def positionChanged(self, currentposition):
- currentposition = self.get_current_position_name()
- logging.getLogger("HWR").debug(
- "predefinedPositionChanged emitted: %s" % currentposition
- )
- # Update light brightness step-by-step
- posno = currentposition.split()[0]
- logging.getLogger("HWR").debug("Moving brightness to: %s" % posno)
-
- self.blight.moveToPosition(posno)
-
- self.emit("predefinedPositionChanged", (currentposition, 0))
-
- def is_ready(self):
- state = self.get_state()
- return state == ALBAZoomMotorAutoBrightness.READY
-
-
-def test():
- from mxcubecore import HardwareRepository as HWR
-
- hwr = HWR.get_hardware_repository()
- hwr.connect()
-
- zoom = hwr.get_hardware_object("/zoom-auto-brightness")
-
- print(type(zoom.get_state()))
-
- print(" Zoom position is : ", zoom.get_value())
- print("Zoom position name is : ", zoom.get_current_position_name())
- print(" Moving : ", zoom.motorIsMoving())
- print(" State : ", zoom.get_state())
- print(" Positions : ", zoom.get_predefined_positions_list())
-
-
-if __name__ == "__main__":
- test()
diff --git a/mxcubecore/HardwareObjects/ALBA/ALBABackLight.py b/mxcubecore/HardwareObjects/ALBA/XalocBackLight.py
similarity index 52%
rename from mxcubecore/HardwareObjects/ALBA/ALBABackLight.py
rename to mxcubecore/HardwareObjects/ALBA/XalocBackLight.py
index f13b75347e..373c1d7ce7 100644
--- a/mxcubecore/HardwareObjects/ALBA/ALBABackLight.py
+++ b/mxcubecore/HardwareObjects/ALBA/XalocBackLight.py
@@ -1,13 +1,56 @@
-from mxcubecore import HardwareRepository as HWR
-from mxcubecore.BaseHardwareObjects import Device
+#
+# Project: 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 .
+
+"""
+[Name]
+XalocBackLight
+
+[Description]
+Hardware Object used to operate the diffractometer backlight.
+
+[Emitted signals]
+- levelChanged
+- stateChanged
+"""
+
+#from __future__ import print_function
+
+import time
import logging
import gevent
-import time
+
+from mxcubecore.BaseHardwareObjects import Device
+
+__credits__ = ["ALBA Synchrotron"]
+__version__ = "3"
+__category__ = "General"
-class ALBABackLight(Device):
+class XalocBackLight(Device):
+
def __init__(self, *args):
Device.__init__(self, *args)
+ self.logger = logging.getLogger("HWR.XalocBackLight")
+
+ self.backlightin_channel = None
+ self.level_channel = None
+
self.limits = [None, None]
self.state = None
self.current_level = None
@@ -15,14 +58,18 @@ def __init__(self, *args):
self.register_state = None
self.memorized_level = None
+ self.rest_level = None
self.default_rest_level = 0.0
- self.default_minimum_level = 7.0
+ self.minimum_level = None
+ self.default_minimum_level = 30.0
def init(self):
-
+ self.logger.debug("Initializing {0}".format(self.__class__.__name__))
self.backlightin_channel = self.get_channel_object("backlightin")
self.level_channel = self.get_channel_object("light_level")
+ self.set_name('backlight')
+
limits = self.get_property("limits")
if limits is not None:
@@ -48,62 +95,60 @@ def init(self):
def is_ready(self):
return True
+
+ isReady = is_ready
def level_changed(self, value):
self.current_level = value
- self.emit("levelChanged", self.current_level)
+ self.emit('levelChanged', self.current_level)
def state_changed(self, value):
+ #self.logger.debug("Backlight state is %s" % value)
state = value
if state != self.state:
self.state = state
- if state:
- self.emit("stateChanged", "on")
- else:
- self.emit("stateChanged", "off")
+ self.emit('stateChanged', value)
def _current_state(self):
-
- state = None
-
if self.actuator_status:
- state = "off"
+ return False
else:
- state = "on"
-
- return state
+ return True
def get_limits(self):
return self.limits
def get_state(self):
_state = self.backlightin_channel.get_value()
- if _state:
- return "on"
+ _level_on = self.level_channel.get_value() > 0
+ if _state and _level_on:
+ return True
else:
- return "off"
+ return False
- def getUserName(self):
+ def get_user_name(self):
return self.username
- def getLevel(self):
+ def get_level(self):
self.current_level = self.level_channel.get_value()
return self.current_level
- def setLevel(self, level):
+ def set_level(self, level):
self.level_channel.set_value(float(level))
- def setOn(self):
+ def set_on(self):
+ #self.logger.debug("backlight in %s", self.backlightin_channel.get_value() )
self.on_task = gevent.spawn(self._setOn)
self.on_task.link(self._task_finished)
self.on_task.link_exception(self._task_failed)
def _setOn(self):
if self.backlightin_channel.get_value() is False:
+ #self.logger.debug( "Set backlight in" )
self.set_backlight_in()
wait_ok = self.wait_backlight_in()
if not wait_ok:
- logging.getLogger("HWR").debug("could not set backlight in")
+ self.logger.debug("Could not set backlight in")
return
level = None
@@ -113,8 +158,8 @@ def _setOn(self):
if not level or level < self.minimum_level:
level = self.minimum_level
- logging.getLogger("HWR").debug("setting light level to : %s" % level)
- self.setLevel(level)
+ #self.logger.debug("Setting light level to : %s" % level)
+ self.set_level(level)
def set_backlight_in(self):
self.backlightin_channel.set_value(True)
@@ -125,53 +170,37 @@ def wait_backlight_in(self, state=True, timeout=10):
while elapsed < timeout:
isin = self.backlightin_channel.get_value()
if isin == state:
- logging.getLogger("HWR").debug(
- "waiting for backlight took %s . In is: %s" % (elapsed, isin)
- )
+ self.logger.debug(
+ "Waiting for backlight took %s. In is: %s" %
+ (elapsed, isin))
return True
gevent.sleep(0.1)
elapsed = time.time() - t0
- logging.getLogger("HWR").debug("Timeout waiting for backlight In")
+ self.logger.debug("Timeout waiting for backlight In")
return False
def _task_finished(self, g):
- logging.getLogger("HWR").debug("Backlight task finished")
+ self.logger.debug("Backlight task finished")
self._task = None
def _task_failed(self, g):
- logging.getLogger("HWR").debug("Backlight task failed")
+ self.logger.debug("Backlight task failed")
self._task = None
- def setOff(self):
+ def set_off(self):
if self.current_level:
self.memorized_level = self.current_level
- self.setLevel(self.rest_level)
+ self.set_level(self.rest_level)
self.backlightin_channel.set_value(False)
+ def re_emit_values(self):
+ self.emit("stateChanged", self.state )
+ self.emit("levelChanged", self.current_level )
def test_hwo(hwo):
- import sys
-
- print('\nLight control for "%s"\n' % hwo.getUserName())
- print(" Level limits are:", hwo.get_limits())
- print(" Current level is:", hwo.getLevel())
- print(" Current state is:", hwo.get_state())
- print(" Setting backlight in")
-
- print(sys.argv)
- if sys.argv[3] == "0":
- print("Setting backlight off")
- n = False
- hwo.setOff()
- else:
- print("Setting backlight on")
- n = True
- hwo.setOn()
-
- hwo.wait_backlight_in(state=n)
- # while gevent.wait(timeout=0.1):
- # print "Waiting"
- # gevent.sleep(0.1)
-
- print(" Current state is:", hwo.get_state())
+
+ print("Light control for \"%s\"\n" % hwo.get_user_name())
+ print("Level limits are:", hwo.get_limits())
+ print("Current level is:", hwo.get_level())
+ print("Current state is:", hwo.get_state())
diff --git a/mxcubecore/HardwareObjects/ALBA/XalocBeam.py b/mxcubecore/HardwareObjects/ALBA/XalocBeam.py
new file mode 100755
index 0000000000..7225f4b94c
--- /dev/null
+++ b/mxcubecore/HardwareObjects/ALBA/XalocBeam.py
@@ -0,0 +1,157 @@
+#
+# Project: 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 .
+
+"""
+[Name] BeamInfo
+
+[Description]
+BeamInfo hardware object is used to define final beam size and shape.
+It can include aperture, slits and/or other beam definer (lenses or other eq.)
+
+[Signals]
+beamInfoChanged
+beamSizeChanged
+"""
+
+#from __future__ import print_function
+
+import logging
+from mxcubecore.HardwareObjects.BeamInfo import BeamInfo
+#from mxcubecore.HardwareObjects.abstract import AbstractBeam
+
+__credits__ = ["ALBA Synchrotron"]
+__version__ = "3"
+__category__ = "General"
+
+
+class XalocBeam(BeamInfo):
+
+ def __init__(self, *args):
+ BeamInfo.__init__(self, *args)
+ self.logger = logging.getLogger("HWR.XalocBeamInfo")
+
+ self.chan_beam_width = None
+ self.chan_beam_height = None
+ self.chan_beam_posx = None
+ self.chan_beam_posy = None
+
+ def init(self):
+ self.logger.debug("Initializing {0}".format(self.__class__.__name__))
+ BeamInfo.init(self)
+
+ self.chan_beam_width = self.get_channel_object("BeamWidth")
+ self.chan_beam_height = self.get_channel_object("BeamHeight")
+ self.chan_beam_posx = self.get_channel_object("BeamPositionHorizontal")
+ self.chan_beam_posy = self.get_channel_object("BeamPositionVertical")
+
+ # Initialize these values BEFORE connecting the signals, they are needed in
+ self.beam_info_dict["size_x"] = self.chan_beam_width.get_value() / 1000.
+ self.beam_info_dict["size_y"] = self.chan_beam_height.get_value() / 1000.
+ self.logger.debug("self.beam_info_dict[\"size_x\"] %s" % self.beam_info_dict["size_x"] )
+ self.logger.debug("self.beam_info_dict[\"size_y\"] %s" % self.beam_info_dict["size_y"] )
+
+ self.chan_beam_height.connect_signal('update', self.beam_height_changed)
+ self.chan_beam_width.connect_signal('update', self.beam_width_changed)
+ self.chan_beam_posx.connect_signal('update', self.beam_posx_changed)
+ self.chan_beam_posy.connect_signal('update', self.beam_posy_changed)
+
+ self.beam_position = self.chan_beam_posx.get_value(),\
+ self.chan_beam_posy.get_value()
+
+ #def connect_notify(self, *args):
+ #self.evaluate_beam_info()
+ #self.emit_beam_info_changed()
+
+ #def get_beam_divergence_hor(self):
+ #return self.default_beam_divergence[0]
+
+ #def get_beam_divergence_ver(self):
+ #return self.default_beam_divergence[1]
+
+ def get_beam_position(self):
+ self.beam_position = self.chan_beam_posx.get_value(),\
+ self.chan_beam_posy.get_value()
+ return self.beam_position
+
+ #def get_slits_gap(self):
+ #return None, None
+
+ def set_beam_position(self, beam_x, beam_y):
+ self.beam_position = (beam_x, beam_y)
+
+ def get_beam_info(self):
+ return self.evaluate_beam_info()
+
+ #def get_beam_size(self):
+ #self.evaluate_beam_info()
+ #return self.beam_info_dict["size_x"], self.beam_info_dict["size_y"]
+
+ #def get_beam_shape(self):
+ #return self.beam_info_dict["shape"]
+
+ def beam_width_changed(self, value):
+ self.beam_info_dict['size_x'] = value / 1000.
+ #self.logger.debug("New beam width %.3f" % value)
+
+ self.evaluate_beam_info()
+ self.emit_beam_info_changed()
+
+ def beam_height_changed(self, value):
+ self.beam_info_dict['size_y'] = value / 1000.
+ self.evaluate_beam_info()
+ self.emit_beam_info_changed()
+
+ def beam_posx_changed(self, value):
+ self.beam_position = ( value, self.beam_position[1] )
+ self.emit_beam_info_changed()
+
+ def beam_posy_changed(self, value):
+ self.beam_position = ( self.beam_position[0], value )
+ self.emit_beam_info_changed()
+
+ ##def evaluate_beam_info(self):
+ ##self.beam_info_dict["size_x"] = self.chan_beam_width.get_value() / 1000.0
+ ##self.beam_info_dict["size_y"] = self.chan_beam_height.get_value() / 1000.0
+ ##self.beam_info_dict["shape"] = "rectangular"
+ ##return self.beam_info_dict
+
+ def get_beam_position_on_screen(self):
+ """Get the beam position
+ Returns:
+ (tuple): Position (x, y) [pixel]
+ """
+ # TODO move this method to AbstractSampleView
+ # What is the difference between beam_position and beam_position_on_screen??
+ #return self._beam_position_on_screen
+ return self.get_beam_position()
+
+ def emit_beam_info_changed(self):
+ #self.logger.debug(" emitting beam info")
+ if self.beam_info_dict["size_x"] != 9999 and \
+ self.beam_info_dict["size_y"] != 9999:
+ self.emit("beamSizeChanged", ((self.beam_info_dict["size_x"],
+ self.beam_info_dict["size_y"]), ))
+ self.emit("beamInfoChanged", (self.beam_info_dict, ))
+
+
+
+
+def test_hwo(hwo):
+ print(hwo.get_beam_info())
+ print(hwo.get_beam_position())
diff --git a/mxcubecore/HardwareObjects/ALBA/XalocCats.py b/mxcubecore/HardwareObjects/ALBA/XalocCats.py
new file mode 100755
index 0000000000..0b0fdf92c7
--- /dev/null
+++ b/mxcubecore/HardwareObjects/ALBA/XalocCats.py
@@ -0,0 +1,1430 @@
+#
+# Project: 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 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with MXCuBE. If not, see .
+
+"""
+[Name] XalocCats
+
+[Description]
+HwObj used to control the CATS sample changer via Tango.
+
+[Signals]
+- powerStateChanged
+- runningStateChanged
+
+Comments:
+In case of failed put push button, CatsMaint calls the reset command in the DS
+In case of failed get push button, CatsMaint calls the recoverFailure command in the DS
+"""
+
+#from __future__ import print_function
+
+import logging
+import time
+import PyTango
+import gevent
+
+from mxcubecore.HardwareObjects.Cats90 import Cats90, SampleChangerState#, TOOL_SPINE
+from mxcubecore import HardwareRepository as HWR
+
+__credits__ = ["ALBA Synchrotron"]
+__version__ = "3"
+__category__ = "General"
+__author__ = "Vicente Rey, Jordi Andreu, Roeland Boer"
+
+TIMEOUT = 3
+DOUBLE_GRIPPER_DRY_WAIT_TIME = 80 # time the double gripper takes in going from home to midway soak during a dry
+
+TOOL_FLANGE, TOOL_UNIPUCK, TOOL_SPINE, TOOL_PLATE, \
+ TOOL_LASER, TOOL_DOUBLE_GRIPPER = (0,1,2,3,4,5)
+BASKET_UNKNOWN, BASKET_SPINE, BASKET_UNIPUCK = (0, 1, 2)
+#
+# Number of samples per puck type
+#
+SAMPLES_SPINE = 10
+SAMPLES_UNIPUCK = 16
+
+class XalocCats(Cats90):
+ """
+ Main class used @ ALBA to integrate the CATS-IRELEC sample changer.
+ """
+
+ def __init__(self, *args, **kwargs):
+ Cats90.__init__(self, *args, **kwargs)
+ #super(XalocCats, self).__init__(self.__TYPE__, False, *args, **kwargs)
+
+ self.logger = logging.getLogger("HWR.XalocCats")
+ self.detdist_saved = None
+
+ self.shifts_channel = None
+ self.diff_phase_channel = None
+ self.diff_state_channel = None
+ self.detdist_position_channel = None
+ self.omega_position_channel = None
+ self.kappa_position_channel = None
+ self._chnisDetDistSafe = None
+
+ self._chnCollisionSensorOK = None
+ self._chnIsCatsIdle = None
+ self._chnIsCatsHome = None
+ self._chnIsCatsRI1 = None
+ self._chnIsCatsRI2 = None
+ self._chnNBSoakings = None
+ self._chnLidSampleOnTool = None
+ self._chnNumSampleOnTool = None
+ self._chnPath = None
+
+ self.diff_go_sampleview_cmd = None
+ self.super_go_sampleview_cmd = None
+ self.super_abort_cmd = None
+
+ self._cmdLoadHT = None
+ self._cmdChainedLoadHT = None
+ self._cmdUnloadHT = None
+ self._cmdClearMemory = None
+ self._cmdSetTool = None
+
+ self._cmdCATSRecovery = None
+
+ self.cats_ri2 = None
+
+ self.auto_prepare_diff = None
+ self.next_pick_sample_location = [-1,-1]
+ self.sample_can_be_centered = None
+
+ self.sample_lid_on_tool = None
+ self.sample_num_on_tool = None
+ self.changing_tool = None
+
+ self.logger.debug("unipuck_tool property = %s" % self.get_property("unipuck_tool") )
+
+ def init(self):
+ self.logger.debug("Initializing {0}".format(self.__class__.__name__))
+ #Cats90.init(self)
+ super(XalocCats,self).init()
+
+ # TODO: Migrate to taurus channels instead of tango channels
+ self.shifts_channel = self.get_channel_object("shifts")
+ self.diff_phase_channel = self.get_channel_object("diff_phase")
+ self.diff_state_channel = self.get_channel_object("diff_state")
+ self.detdist_position_channel = self.get_channel_object("detdist_position")
+ self.super_cryopos_channel = self.get_channel_object("super_cryo_position")
+ self.omega_position_channel = self.get_channel_object("omega_position") # position of the omega axis
+ self.kappa_position_channel = self.get_channel_object("kappa_position") # position of the kappa axis
+ self._chnisDetDistSafe = self.get_channel_object("DetDistanceSafe")
+
+ self._chnCollisionSensorOK = self.get_channel_object("_chnCollisionSensorOK")
+ self._chnIsCatsIdle = self.get_channel_object( "_chnIsCatsIdle" )
+ self._chnIsCatsHome = self.get_channel_object( "_chnIsCatsHome" )
+ self._chnIsCatsRI1 = self.get_channel_object( "_chnIsCatsRI1" )
+ self._chnIsCatsRI2 = self.get_channel_object( "_chnIsCatsRI2" )
+ self._chnNBSoakings = self.get_channel_object( "_chnNBSoakings" )
+ self._chnLidSampleOnTool = self.get_channel_object( "_chnLidSampleOnTool" )
+ self._chnNumSampleOnTool = self.get_channel_object( "_chnNumSampleOnTool" )
+ self._chnPath = self.get_channel_object( "_chnPath" )
+
+ self.diff_go_sampleview_cmd = self.get_command_object("diff_go_sampleview")
+ self.super_go_sampleview_cmd = self.get_command_object("super_go_sampleview")
+ self.super_abort_cmd = self.get_command_object("super_abort")
+
+ self._cmdLoadHT = self.get_command_object("_cmdLoadHT")
+ self._cmdChainedLoadHT = self.get_command_object("_cmdChainedLoadHT")
+ self._cmdUnloadHT = self.get_command_object("_cmdUnloadHT")
+ self._cmdPick = self.get_command_object("_cmdPick")
+ self._cmdChainedLoadPick = self.get_command_object("_cmdChainedLoadPick")
+
+ self._cmdClearMemory = self.get_command_object("_cmdClearMemory")
+ self._cmdSetTool = self.get_command_object("_cmdSetTool")
+ self._cmdSetTool2 = self.get_command_object("_cmdSetTool2")
+
+ self._cmdCATSRecovery = self.get_command_object("macro_cats_recovery")
+
+ self.auto_prepare_diff = self.get_property("auto_prepare_diff")
+ self.sample_can_be_centered = True
+
+ self.logger.debug("unipuck_tool property = %s" % self.get_property("unipuck_tool") )
+
+ self.sample_lid_on_tool = -1
+ self.sample_num_on_tool = -1
+
+ if self._chnPath is not None:
+ #self.current_path = self._chnPath.get_value()
+ self._chnPath.connect_signal("update", self._update_path)
+
+ if self._chnPathRunning is not None:
+ self._chnPathRunning.connect_signal("update", self._update_running_state)
+
+ if self._chnIsCatsRI2 is not None:
+ self._chnIsCatsRI2.connect_signal("update", self._cats_ri2_changed)
+
+ if self._chnLidSampleOnTool is not None:
+ self._chnLidSampleOnTool.connect_signal("update", self.sample_lid_on_tool_changed)
+
+ if self._chnNumSampleOnTool is not None:
+ self._chnNumSampleOnTool.connect_signal("update", self.sample_num_on_tool_changed)
+
+ ret,msg = self._check_coherence()
+ if not ret:
+ logging.getLogger('user_level_log').warning( msg )
+
+ # quick fix to get Cats to accept the unipuck_tool
+ # the property is set in Cats90, but the property unipuck_tool is somehow not read properly
+ self.set_unipuck_tool(5)
+
+
+ #def cats_state_changed(self, value):
+
+ #logging.getLogger("HWR").debug("Cats90 cats_state_changed chnState value is %s, value == PyTango.DevState.ON %s, type %s" % \
+ #(str(value) , value == PyTango.DevState.ON, type(value) )
+ #)
+ #timeout = 1
+ #if self.cats_state != value:
+ ## hack for transient states
+
+ #t0 = time.time()
+ #while value in [PyTango.DevState.ALARM, PyTango.DevState.ON]:
+ #time.sleep(0.1)
+ #self.logger.warning(
+ #"SAMPLE CHANGER could be in transient state (state is %s). trying again"
+ #% self.cats_state
+ #)
+ #value = self._chnState.get_value()
+ #if (time.time() - t0) > timeout:
+ ##self.logger.warning("SAMPLE CHANGER state change timed out %s)" % self.cats_state )
+ ##logging.getLogger('user_level_log').error("SAMPLE CHANGER state is not ready")
+ #break
+
+ #logging.getLogger("HWR").debug("Cats90. cats_state_changed, updating power state to %s " % value)
+
+ #self.cats_state = value
+ #self._update_state()
+
+ def _cats_ri2_changed(self, value):
+ logging.getLogger("HWR").debug("Cats ri2 change, is %s" %
+ str(value)
+ )
+
+ if value is not None:
+ self.cats_ri2 = value
+
+ def is_ready(self):
+ """
+ Returns a boolean value indicating is the sample changer is ready for operation.
+
+ @return: boolean
+ """
+ return self.state == SampleChangerState.Ready or \
+ self.state == SampleChangerState.Loaded or \
+ self.state == SampleChangerState.Charging or \
+ self.state == SampleChangerState.StandBy or \
+ self.state == SampleChangerState.Disabled
+
+ def send_beamline_to_transfer(self, timeout = 36):
+ """
+ Checks if beamline diff is in TRANSFER phase (i.e. sample changer in
+ TRANSFER phase too). If it is not the case, It sends the supervisor to TRANSFER
+ phase. Then waits for the minimal conditions of the beamline to start the transfer
+
+ @return: boolean
+ """
+ msg = ""
+
+ if HWR.beamline.supervisor.is_detector_cover_opened():
+ self.logger.debug("Closing detcover.")
+ HWR.beamline.supervisor.close_detector_cover()
+
+ if HWR.beamline.supervisor.get_current_phase().upper() == "TRANSFER": # The cover is not taken into account for transfer phase
+ self.logger.debug("Supervisor is already in transfer phase")
+ else:
+ # First wait till the supervisor is ready to accept a sample transfer
+ try:
+ HWR.beamline.supervisor.wait_ready(timeout)
+ time.sleep(0.1)
+ HWR.beamline.supervisor.set_phase("TRANSFER")
+ except Exception as e:
+ msg = "Supervisor cannot get to transfer phase.\n %s" % str(e)
+ logging.getLogger("HWR").error( msg )
+ return False,msg # a return False, in order to update the state in case of an Exception
+
+ # To improve the speed of sample mounting, the wait for phase done was removed.
+ # Rationale: the time it takes the diff to go to transfer phase is about 7-9 seconds.
+ # The limiting factor is actually the detector safe position (-70), which takes 19.1 seconds to reach from the minimal distance
+ # The fastest mouting time with pick is in the 7-9 secs range, so mounting without pick
+ # will take much longer before arriving at the diff
+ # NOTE For pick mounting, a time sleep may be required.
+ # Another potentially limiting step is omega movement. At an max omega of 2160, it takes 36 seconds to reach 0
+ # omega is somehow involved in calculating the diff mounting position, so omega should be at zero before continuing
+ # TODO check if we can improve the involvement of omega in the calculations.
+ # kappa should also be considered. Max kappa angle is 255, speed 17. Thus, at most kappa to zero takes 15 secs
+ #ret = self._wait_diff_phase_done('TRANSFER')
+ ret1 = self._wait_kappa_zero()
+ ret2 = self._wait_omega_zero()
+ ret3 = self._wait_det_safe()
+ if not ret1: msg = "Cannot move kappa to zero"
+ if not ret2: msg = "Cannot move omega to zero"
+ if not ret3: msg = "Cannot move detector to safety"
+
+ return ( ret1 and ret2 and ret3 ), msg
+
+ #TODO: remove and replace with diffractometer.wait_ready()
+ def _wait_diff_on(self, timeout = 36):
+ t0 = time.time()
+ while True:
+ state = self.diff_state_channel.get_value()
+ if state == PyTango.DevState.ON:
+ break
+
+ if (time.time() - t0) > timeout:
+ self.logger.error("Diff timeout waiting for ON state. Returning")
+ return False
+
+ return True
+
+ def _wait_super_cryoposition_out(self, timeout = 2):
+ stime = time.time()
+ ret = False
+ while time.time() - stime < timeout:
+ cryopos = str(self.super_cryopos_channel.get_value())
+ if cryopos.upper() == "SAMPOUT":
+ self.logger.debug("Cryo position is in SAMPOUT. Returning")
+ ret = True
+ break
+ time.sleep(0.02)
+ return ret
+
+ def _wait_cats_idle(self):
+ while True:
+ if self._chnIsCatsIdle.get_value():
+ self.logger.debug("_chnIsCatsIdle %s, type %s" % ( str(self._chnIsCatsIdle.get_value()), type(self._chnIsCatsIdle.get_value()) ) )
+ self.logger.debug("CATS is idle. Returning")
+ break
+ time.sleep(0.2)
+
+ def _wait_cats_home(self, timeout):
+ t0 = time.time()
+ while True:
+ if self._chnIsCatsHome.get_value():
+ self.logger.debug("CATS is home. Returning")
+ break
+ time.sleep(0.2)
+ if time.time() - t0 > timeout: return False
+
+ return True
+
+ def _wait_det_safe(self, timeout=30):
+ t0 = time.time()
+ while True:
+ if self._chnisDetDistSafe.get_value():
+ self.logger.debug("Detector is in a safe position. Returning")
+ break
+ time.sleep(0.2)
+ if time.time() - t0 > timeout: return False
+
+ return True
+
+ def _wait_kappa_zero(self, timeout = 15.):
+ #self.logger.debug("_wait_kappa_zero timeout %.2f kappa pos %.4f" % (timeout, self.kappa_position_channel.get_value() ) )
+ t0 = time.time()
+ while True:
+ if abs( self.kappa_position_channel.get_value() ) < 0.1:# the error in position is very high (0.07 um) when starting from 2160
+ self.logger.debug("kappa is zero. Returning")
+ break
+ time.sleep(0.5)
+ if time.time() - t0 > timeout: return False
+
+ return True
+
+ def _wait_omega_zero(self, timeout = 37.):
+ #self.logger.debug("_wait_omega_zero timeout %.2f omega pos %.4f" % (timeout, self.omega_position_channel.get_value() ) )
+ t0 = time.time()
+ while True:
+ if abs( self.omega_position_channel.get_value() ) < 0.1:# the error in position is very high (0.07 um) when starting from 2160
+ self.logger.debug("Omega is zero. Returning")
+ break
+ time.sleep(0.5)
+ if time.time() - t0 > timeout: return False
+
+ return True
+
+ def _wait_super_moving(self):
+ allokret = True # No problems
+ while allokret:
+ state = str( HWR.beamline.supervisor.get_state() )
+ if not self._chnCollisionSensorOK.get_value():
+ self._update_state()
+ raise Exception ("The robot had a collision, call your LC or floor coordinator")
+ elif state == "MOVING":
+ self.logger.debug("Supervisor is in MOVING state. Returning")
+ return allokret
+ time.sleep(0.1)
+
+ return allokret
+
+ def _wait_diff_phase_done(self, final_phase, timeout = 20 ):
+ """
+ Method to wait a phase change. When supervisor reaches the final phase, the
+ method returns True.
+
+ @final_phase: target phase
+ @return: boolean
+ """
+
+ t0 = time.time()
+ while self.read_diff_phase().upper() != final_phase:
+ state = self.diff_state_channel.get_value()
+ phase = self.read_diff_phase().upper()
+ if not state in [ PyTango.DevState.ON , PyTango.DevState.MOVING ]:
+ self.logger.error("Diff is in a funny state %s" % str(state))
+ return False
+
+ self.logger.debug("Diff waiting to finish phase change")
+ time.sleep(0.2)
+ if time.time() - t0 > timeout: break
+
+ if self.read_diff_phase().upper() != final_phase:
+ self.logger.error("Diff is not yet in %s phase. Aborting load" %
+ final_phase)
+ return False
+ else:
+ self.logger.info(
+ "Diff is in %s phase. Beamline ready for the next step..." %
+ final_phase)
+ return True
+
+ def _wait_phase_done(self, final_phase, timeout = 20 ):
+ """
+ Method to wait a phase change. When supervisor reaches the final phase, the
+ method returns True.
+
+ @final_phase: target phase
+ @return: boolean
+ """
+
+ t0 = time.time()
+ while HWR.beamline.supervisor.get_current_phase().upper() != final_phase:
+ state = str( HWR.beamline.supervisor.get_state() )
+ phase = HWR.beamline.supervisor.get_current_phase().upper()
+ if not str(state) in [ "MOVING", "ON" ]:
+ self.logger.error("Supervisor is in a funny state %s" % str(state))
+ return False
+
+ self.logger.debug("Supervisor waiting to finish phase change")
+ time.sleep(0.2)
+
+ t0 = time.time()
+ timeout = 5
+ while HWR.beamline.supervisor.get_current_phase().upper() != final_phase or timeout > time.time() - t0:
+ logging.getLogger("HWR").warning(
+ "Phase changed done. Waiting phase change....")
+ time.sleep(0.2)
+
+ if HWR.beamline.supervisor.get_current_phase().upper() != final_phase:
+ self.logger.error("Supervisor is not yet in %s phase. Aborting load" %
+ final_phase)
+ return False
+ else:
+ self.logger.info(
+ "Supervisor is in %s phase. Beamline ready to start sample loading..." %
+ final_phase)
+ return True
+
+ def save_detdist_position(self):
+ self.detdist_saved = self.detdist_position_channel.get_value()
+ self.logger.error("Saving current det.distance (%s)" % self.detdist_saved)
+
+ def restore_detdist_position(self):
+ if abs(self.detdist_saved - self.detdist_position_channel.get_value()) >= 0.1:
+ self.logger.error(
+ "Restoring det.distance to %s" % self.detdist_saved)
+ self.detdist_position_channel.set_value(self.detdist_saved)
+
+ def read_diff_phase(self):
+ """
+ Returns diff phase (CurrentPhase attribute from Beamline Diffractometer
+ TangoDS)
+
+ @return: str
+ """
+ return self.diff_phase_channel.get_value()
+
+ def load(self, sample=None, wait=False):
+ """
+ Loads a sample. Overides to include ht basket.
+
+ @sample: sample to load. a string is passed with format "%d:%d" % (basketnr:samplenr)
+ @wait:
+ @wash: wash dring the load opearation.
+ @return:
+ """
+
+ sample_location_str = sample
+ self.sample_can_be_centered = True
+
+ #self.logger.debug(
+ #"Loading sample %s / type(%s)" %
+ #( sample_location_str, type(sample_location_str) )
+ #)
+
+ ok, msg = self._check_incoherent_sample_info()
+ if not ok:
+ self.sample_can_be_centered = False
+ raise Exception(msg)
+
+ sample_ht = self.is_ht_sample(sample_location_str) # sample number in HT basket
+
+ if not sample_ht:
+ sample = self._resolve_component(sample_location_str)
+ self.assert_not_charging()
+ use_ht = False
+ else:
+ sample = sample_ht
+ use_ht = True
+
+ # end some cancel cases
+
+ if self.has_loaded_sample():
+ if self.get_loaded_sample() == sample:
+ raise Exception(
+ "The sample %s is already loaded" % sample.get_address()
+ )
+
+ #self.logger.debug(
+ #"Loading sample %s / type(%s)" %
+ #( sample.get_address(), type(sample) )
+ #)
+
+
+ # This runs the AbstractSampleChanger method!
+ ok = self._execute_task(SampleChangerState.Loading,
+ wait, self._do_load_xaloc, sample, use_ht)
+ #if not ok: self.sample_can_be_centered = False
+
+ if ok: HWR.beamline.diffractometer.sample_has_been_centred = False
+
+ return ok
+
+ def unload(self, sample_slot=None, shifts=None, wait=False):
+ """
+ Unload the sample. If sample_slot=None, unloads to the same slot the sample was
+ loaded from.
+
+ @sample_slot:
+ @wait:
+ @return:
+ """
+
+ self.sample_can_be_centered = True
+
+ sample_slot = self._resolve_component(sample_slot)
+
+ self.assert_not_charging()
+
+ # In case we have manually mounted we can command an unmount
+ if not self.has_loaded_sample():
+ self.sample_can_be_centered = False
+ raise Exception("No sample is loaded")
+
+ # This runs the AbstractSampleChanger method!
+ ok = self._execute_task(SampleChangerState.Unloading,
+ wait, self._do_unload, sample_slot)
+ if not ok: self.sample_can_be_centered = False
+
+ return ok
+
+ def _update_path(self, value):
+ self.current_path = value
+
+ def _update_running_state(self, value):
+ """
+ Emits signal with new Running State
+
+ @value: New running state
+ """
+ self.path_running = value
+ self.emit('runningStateChanged', (value, ))
+
+ def _update_powered_state(self, value):
+ """
+ Emits signal with new Powered State
+
+ @value: New powered state
+ """
+ self.emit('powerStateChanged', (value, ))
+
+ def _do_load_xaloc(self, sample=None, use_ht=False):
+ """
+ Loads a sample on the diffractometer. Performs a simple put operation if the
+ diffractometer is empty, and a sample exchange (unmount of old + mount of new
+ sample) if a sample is already mounted on the diffractometer.
+
+ If the pick parameters are true
+
+ Overides Cats90 method.
+
+ @sample: sample to load. Either a sample object in case of SPINE/UNIPUCK, or an int in case of hot tool sample
+ @shifts: mounting point offsets.
+ @use_ht: mount a sample from hot tool.
+ """
+ if not self._chnPowered.get_value():
+ # TODO: implement a wait with timeout method.
+ self.logger.debug("CATS power is OFF. Trying to switch the power ON...")
+ self._cmdPowerOn() # try switching power on
+ gevent.sleep(2) # gevent.sleep(2)??
+
+ current_tool = self.get_current_tool()
+
+ self.save_detdist_position()
+ self.logger.debug("Sending supervisor to transfer phase.")
+ ret,msg = self.send_beamline_to_transfer()
+
+ if ret is False:
+ self.logger.error(
+ "Supervisor cmd transfer phase returned an error: %s" % msg)
+ self._update_state()
+ raise Exception(
+ "Supervisor cannot get to transfer phase, error is\n %s\nAborting sample changer operation. Ask LC or floor coordinator to check the supervisor and diff device servers" % msg)
+
+ if not self._chnPowered.get_value():
+ self._update_state()
+ raise Exception(
+ "CATS power is not enabled. Please interlock the EH and set the CATS switches to the right position before "
+ "transferring samples."
+ )
+
+ self.logger.debug("Selected sample is %s " % sample.get_address() )
+
+ selected = self.get_selected_sample()
+ self.logger.debug("Selected sample object is %s " % selected )
+ if not use_ht:
+ if sample is not None:
+ if sample != selected:
+ self._do_select(sample)
+ selected = self.get_selected_sample()
+ else:
+ if selected is not None:
+ sample = selected
+ else:
+ raise Exception("No sample selected")
+ else:
+ selected = None
+
+ # get sample selection
+ prev_address = None
+ if self.get_loaded_sample() != None:
+ prev_address = self.get_loaded_sample().get_address()
+ self.logger.debug("Selected sample is %s (prev %s)" %
+ ( selected.get_address(), prev_address )
+ )
+
+ # some cancel cases
+ if not use_ht and self.has_loaded_sample() and selected == self.get_loaded_sample(): # sample on diff is the one loaded
+ self._update_state()
+ raise Exception("The sample " +
+ str(self.get_loaded_sample().get_address()) +
+ " is already loaded")
+
+ if self.cats_sample_on_diffr() == -1 and self.has_loaded_sample(): # no sample on diff, but cats has sample info
+ self._update_state()
+ raise Exception(
+ "Conflicting info between diffractometer and on-magnet detection."
+ "Consider 'Clear'")
+
+ # obtain mounting offsets from diffr
+ shifts = self._get_shifts()
+
+ if shifts is None:
+ xshift, yshift, zshift = ["0", "0", "0"]
+ else:
+ xshift, yshift, zshift = map(str, shifts)
+
+ if use_ht: # loading HT sample
+ #
+ # Loading HT sample
+ #
+ if self.is_loaded_ht() == 1: # has an HT sample mounted
+ self._do_load_ht( selected, xshift, yshift, zshift )
+ else: #TODO no execption??
+ self.logger.error("Mixing load/unload dewar vs HT, Unload sample first")
+ return
+ else:
+ #
+ # Loading non HT sample
+ #
+ if self.is_loaded_ht() == 1: # has an HT sample mounted
+ # first unmount HT TODO: no exception??
+ self.logger.warning(
+ "Mixing load/unload dewar vs HT, unload sample first")
+ return
+ else: # either no sample or non HT sample
+ pick_after_mount, cmd_ok = self._do_load_dewar(selected, xshift, yshift, zshift)
+
+ # At this point, due to the waitsafe, we can be sure that the robot has left RI2 and will not return
+ # TODO: check if the diff should be prepared or not
+ collision_occurred = False
+ if not self._chnCollisionSensorOK.get_value():
+ collision_occurred = True
+
+ # A time sleep is needed to get updates on the sample status etc.
+ #time.sleep(3)
+ if self.get_current_tool() == TOOL_DOUBLE_GRIPPER and self._chnNBSoakings.get_value() == 0:
+ self.logger.info("A dry will now be done" )
+
+ if not cmd_ok:
+ self.logger.info("Load Command failed on device server")
+ return False
+ elif self.auto_prepare_diff and not self.changing_tool and not collision_occurred:
+ self.logger.info("AUTO_PREPARE_DIFF is on preparing diff now")
+ allok, msg = self._check_coherence()
+ if allok:
+ logging.getLogger('user_level_log').info( 'Sample successfully loaded' )
+ self.logger.info("Opening detcover")
+ HWR.beamline.supervisor.open_detector_cover()
+ self.logger.info("Restoring detector distance")
+ self.restore_detdist_position()
+ else:
+ # Now recover failed put for double gripper
+ # : double should be in soak, single should be ??
+ #isPathRunning amd cats_idle dont work for tool 5, becuase cats stays in running state after failed put.
+ #_wait_cats_home followed by immediate abort fails because double tool passed through home on the way to soak
+ # time.sleep(5) fails because of a possible dry for double
+ # When doing a dry, CATS passes through home, so a double wait_cats_home is necessary, with a time.sleep of a couple of seconds in between so CATS starts drying
+ # An alternative is to abort at arriving home, clear memeory and move to soak
+ if not self._check_incoherent_sample_info()[0] :
+ msg = "Your sample was NOT loaded! Click OK to recover, please make sure your sample is present in the puck"
+ else:
+ msg = "The CATS device indicates there was a problem in unmounting the sample, click ok to recover from a Fix Fail Get"
+ self.emit("taskFailed", str(msg))
+ logging.getLogger('user_level_log').error(
+ 'There was a problem loading your sample, please wait for the system to recover'
+ )
+ self._wait_cats_home(10) # wait for robot to return from diff
+ time.sleep( 5 ) # give it time to move, if it goes for a dry, the _chnNBSoakings is set to 0
+ #self.logger.debug("self._chnNBSoakings %d " % self._chnNBSoakings.get_value() )
+ if self.get_current_tool() == TOOL_DOUBLE_GRIPPER:
+ if self._chnNBSoakings.get_value() == 0:
+ self.logger.info("A dry will now be done, waiting %d seconds" % DOUBLE_GRIPPER_DRY_WAIT_TIME)
+ time.sleep( DOUBLE_GRIPPER_DRY_WAIT_TIME ) # long timeout because of possible dry of the double gripper
+ else:
+ #self.logger.info("no dry, waiting 3 seconds" )
+ time.sleep( 3 ) # allow the gripper time to move on
+ if not self._check_incoherent_sample_info()[0] : # this could be replaced by checking return value of _check_coherence, see TODO there
+ # the behaviour of the SPINE gripper is different when failing put or when failing get. For put, it does a dry, for get, it doesnt
+ if self.get_current_tool() == TOOL_SPINE:
+ time.sleep( 16 )
+ self.recover_cats_from_failed_put()
+ else:
+ self._do_recover_failure() # recover from failed get
+ msg = "The CATS device indicates there was a problem in unmounting the sample, click ok to recover from a Fix Fail Get"
+ self._update_state()
+ #raise Exception( msg )
+
+ else:
+ self.logger.info(
+ "AUTO_PREPARE_DIFF not activated. sample loading done / or changing tool (%s)" %
+ self.changing_tool
+ )
+
+ # Check again the collision sensor in case the robot collided after being in a safe position
+ if not self._chnCollisionSensorOK.get_value() or collision_occurred:
+ self._update_state()
+ msg = "The robot had a collision, call your LC or floor coordinator"
+ self.emit("taskFailed", str(msg))
+ raise Exception ( msg )
+
+ if pick_after_mount:
+ load_command = self._cmdPick
+ lid, sampleno = self.basketsample_to_lidsample(
+ self.next_pick_sample_location[0], self.next_pick_sample_location[1]
+ )
+ tool = self.tool_for_basket( self.next_pick_sample_location[0] )
+ stype = self.get_cassette_type( self.next_pick_sample_location[0] )
+
+ self.logger.info(
+ "next_pick_sample_location %s:%s" %
+ (self.next_pick_sample_location[0], self.next_pick_sample_location[1])
+ )
+ argin = [
+ str(tool),
+ str(lid),
+ str(sampleno),
+ str(stype),
+ ]
+ gevent.spawn (
+ self._execute_server_task,load_command, argin, waitsafe=True
+ )
+
+ self.next_pick_sample_location = [-1,-1] # Dont use pick for the next mounting cycle unless requested
+
+ return cmd_ok
+
+ def _do_load_ht(self, sample, xshift, yshift, zshift):
+
+ tool = self.tool_for_basket(100) # basketno)
+
+ if tool != self.get_current_tool():
+ self.logger.warning("Changing tool from %s to %s" %
+ (self.get_current_tool(), tool))
+ self.changing_tool = True
+ else:
+ self.changing_tool = False
+
+ argin = ["2", str(sample), "0", "0", xshift, yshift, zshift]
+ self.logger.warning("Loading HT sample, %s" % str(argin))
+ if loaded_ht == 1: # has ht loaded
+ cmd_ok = self._execute_server_task(self._cmdChainedLoadHT,
+ argin, waitsafe=True)
+ else:
+ cmd_ok = self._execute_server_task(self._cmdLoadHT, argin, waitsafe=False)
+
+ def _do_load_dewar(self, selected, xshift, yshift, zshift):
+ """
+ Load sample from the cold dewar, not the hot tools
+ Selected is of type sample
+ """
+
+ self.logger.debug("_do_chain_load_dewar, selected sample is %s" % selected.get_address() )
+
+ pick_after_mount = False
+ cmd_ok = False
+
+ basketno = selected.get_basket_no()
+ sampleno = selected.get_vial_no()
+
+ lid, sampleno = self.basketsample_to_lidsample(basketno, sampleno)
+ tool = self.tool_for_basket(basketno)
+ stype = self.get_cassette_type(basketno)
+
+ if tool != self.get_current_tool():
+ self.logger.warning("Changing tool from %s to %s" %
+ (self.get_current_tool(), tool)
+ )
+ self.changing_tool = True
+ else:
+ self.changing_tool = False
+
+ if tool == TOOL_SPINE:
+ read_barcode = self.read_datamatrix and \
+ self._cmdChainedLoadBarcode is not None
+ self.next_pick_sample_location = [-1,-1] # pick not compatible with SPINE single gripper
+ else:
+ if self.read_datamatrix:
+ self.logger.error("Reading barcode only possible with spine pucks, no barcode will be read")
+ read_barcode = False
+
+ if self.has_loaded_sample(): # has a loaded but it is not an HT
+ if self.changing_tool:
+ self._update_state()
+ raise Exception(
+ "This operation requires a tool change. You should unload"
+ "sample first")
+ pick_after_mount, cmd_ok = self._do_chain_load_dewar(
+ selected,
+ self.next_pick_sample_location,
+ tool,
+ read_barcode,
+ xshift,
+ yshift,
+ zshift
+ )
+
+ else: # no loaded sample
+ cmd_ok = self._do_nochain_load_dewar(selected, tool, read_barcode, xshift, yshift, zshift)
+ pick_after_mount = ( not -1 in self.next_pick_sample_location )
+
+ return pick_after_mount, cmd_ok
+
+ def _do_chain_load_dewar(self, selected, pick_sample_location, tool, read_barcode, xshift, yshift, zshift ):
+ """
+ do an unload followd by a load. If requested, followed by a pick
+ pick_sample_location is an array, like location
+ Return pick_required true if the pick needs a separate, consecutive operation
+ """
+
+ self.logger.debug("_do_chain_load_dewar, pick_sample_location %s" % str(pick_sample_location) )
+
+ pick_required = False
+
+ basketno = selected.get_basket_no()
+ sampleno = selected.get_vial_no()
+
+ lid, sampleno = self.basketsample_to_lidsample(basketno, sampleno)
+ tool = self.tool_for_basket(basketno)
+ stype = self.get_cassette_type(basketno)
+
+ # First check if there is a mount request where the sample on tool is not the selected sample
+ if self.sample_lid_on_tool != -1 and self.sample_num_on_tool != -1:
+ if self.sample_lid_on_tool != lid or self.sample_num_on_tool != sampleno:
+ # there is a sample on the tool and it does not match the requested pick sample.
+ # Unload required, which will return the sample to the dewar
+ # The operation should be waited for, so waitsafe = False
+ argin = [str(tool), "0", xshift, yshift, zshift]
+ cmd_ok = self._execute_server_task( self._cmdUnload, argin, waitsafe=False )
+
+ if self.sample_lid_on_tool == -1 and self.sample_num_on_tool == -1:
+ self.logger.debug("_do_chain_load_dewar, no sample on tool")
+ # no sample on tool, just load the requested sample using a standard chain load
+ # NOTE, a subsequent pick should still be done if pick_sample_location is not None!
+ if self.has_loaded_sample(): # no picked sample, but sample on diff, just exchange
+ pick_required = ( not -1 in pick_sample_location )
+ self.logger.debug("_do_chain_load_dewar, sample on diff")
+ if read_barcode:
+ chained_load_command = self._cmdChainedLoadBarcode
+ self.logger.warning(
+ "Chained load sample using barcode requested" )
+ else:
+ chained_load_command = self._cmdChainedLoad
+ argin = [
+ str(tool),
+ str(lid),
+ str(sampleno),
+ str(stype),
+ "0",
+ xshift,
+ yshift,
+ zshift]
+ else: # no picked sample, no sample on diff, we got here because the picked sample was not the one requested, so do load
+ if read_barcode:
+ chained_load_command = self._cmdLoadBarcode
+ self.logger.warning(
+ "Load sample using barcode requested" )
+ else:
+ chained_load_command = self._cmdLoad
+ argin = [
+ str(tool),
+ str(lid),
+ str(sampleno),
+ str(stype),
+ "0",
+ xshift,
+ yshift,
+ zshift]
+ elif self.sample_lid_on_tool == lid or self.sample_num_on_tool == sampleno:
+ # There is a sample on the tool, and it coincides with the requested sample.
+ # pick is included in the sequence, the robot will pick the smaple in the arguments after loading the requested sample
+ if not -1 in pick_sample_location:
+ # A pick is requested, so do a chainloadpick and pass as sample parameters the pick sample
+ # This is crazy fast, so a sleep is introduced to give the diff and detector time to move
+ #self.logger.debug("Doing sleep before getputpick")
+ gevent.sleep(0.5)
+ #self.logger.debug("Doing getputpick")
+ chained_load_command = self._cmdChainedLoadPick
+ lid, sampleno = self.basketsample_to_lidsample(
+ pick_sample_location[0], pick_sample_location[1]
+ )
+ argin = [
+ str(tool),
+ str(lid),
+ str(sampleno),
+ str(stype),
+ "0",
+ xshift,
+ yshift,
+ zshift]
+ else:
+ # no pick requested, simply pass the selected sample loaded on the tool as sample arguments to a normal chain load
+ # no subsequent pick required
+ chained_load_command = self._cmdChainedLoad
+ argin = [
+ str(tool),
+ str(self.sample_lid_on_tool),
+ str(self.sample_num_on_tool),
+ str(stype),
+ "0",
+ xshift,
+ yshift,
+ zshift]
+
+ self.logger.info("Doing a chained load using command %s" % str( self._cmdChainedLoad.name() ) )
+ self.logger.warning("Arguments for cats: %s" % argin)
+
+ cmd_ok = self._execute_server_task(
+ chained_load_command, argin, waitsafe=True)
+
+ return pick_required, cmd_ok
+
+ def _do_nochain_load_dewar(self, selected, tool, read_barcode, xshift, yshift, zshift ):
+ """
+ Do a simple load, no sample to unload. If a pick is required, this should be done in a subsequent operation
+ """
+
+ basketno = selected.get_basket_no()
+ sampleno = selected.get_vial_no()
+
+ lid, sampleno = self.basketsample_to_lidsample(basketno, sampleno)
+ tool = self.tool_for_basket(basketno)
+ stype = self.get_cassette_type(basketno)
+
+ # in case that there is a sample on the tool, the sample info in the arguments is ignored by CATS.
+ # in case that there is no sample on the tool, the selected sample is mounted.
+ load_command = self._cmdLoad
+
+ if read_barcode:
+ self.logger.info( "Load sample and read barcode" )
+ load_command = self._cmdLoadBarcode
+
+ argin = [
+ str(tool),
+ str(lid),
+ str(sampleno),
+ str(stype),
+ "0",
+ xshift,
+ yshift,
+ zshift]
+
+ # No need to wait for the robot to finish
+ cmd_ok = self._execute_server_task(
+ load_command, argin, waitsafe=True)
+
+ return cmd_ok
+
+ def _wait_device_safe(self,timeout=10):
+ """
+ Waits until the samle changer HO is safe, aka not returning to diff.
+
+ :returns: None
+ :rtype: None
+ """
+ with gevent.Timeout(timeout, Exception("Timeout waiting for device ready")):
+ while not self.path_safe():
+ gevent.sleep(0.01)
+
+ def _do_unload(self, sample_slot=None):
+ """
+ Unloads a sample from the diffractometer.
+ Overides Cats90 method.
+
+ @sample_slot:
+ """
+ self.logger.debug("checking power")
+ if not self._chnPowered.get_value():
+ try:
+ self._cmdPowerOn() # try switching power on
+ except Exception as e:
+ self._update_state()
+ raise Exception(e)
+
+ #TODO: wait for cats poweron
+
+ ret, msg = self.send_beamline_to_transfer()
+
+ if ret is False:
+ self.logger.error(
+ "Supervisor cmd transfer phase returned an error: %s" % msg)
+ raise Exception(
+ "Supervisor cannot get to transfer phase, error is\n %s\nAborting sample changer operation. Ask LC or floor coordinator to check the supervisor and diff device servers" % msg)
+
+ shifts = self._get_shifts()
+
+ if sample_slot is not None:
+ self._do_select(sample_slot)
+
+ loaded_ht = self.is_loaded_ht()
+
+ if shifts is None:
+ xshift, yshift, zshift = ["0", "0", "0"]
+ else:
+ xshift, yshift, zshift = map(str, shifts)
+
+ loaded_lid = self._chnLidLoadedSample.get_value()
+ loaded_num = self._chnNumLoadedSample.get_value()
+
+ if loaded_lid == -1:
+ self.logger.warning("Unload sample, no mounted sample detected")
+ return False
+
+ loaded_basket, loaded_sample = self.lidsample_to_basketsample(
+ loaded_lid, loaded_num)
+
+ tool = self.tool_for_basket(loaded_basket)
+
+ argin = [str(tool), "0", xshift, yshift, zshift]
+
+ self.logger.warning("Unload sample, sending to cats: %s" %
+ argin)
+ if loaded_ht == 1:
+ cmd_ret = self._execute_server_task(self._cmdUnloadHT, argin, waitsafe=True)
+ else:
+ cmd_ret = self._execute_server_task(self._cmdUnload, argin, waitsafe=True)
+
+ # At this point, due to the waitsafe, we can be sure that the robot has left RI2 and will not return
+ # A time sleep is needed to get updates on the sample status etc.
+ #gevent.sleep(3)
+
+
+ allok = self._check_coherence()[0]
+ if not allok:
+ HWR.beamline.supervisor.wait_ready()
+ if not self.has_loaded_sample() and self.cats_sample_on_diffr():
+ msg = "The CATS device indicates there was a problem in unmounting the sample, click on Fix Fail Get"
+ self._update_state()
+ raise Exception( msg )
+
+ return True
+
+ def sample_lid_on_tool_changed(self, value):
+ self.sample_lid_on_tool = value
+
+ def sample_num_on_tool_changed(self, value):
+ self.sample_num_on_tool = value
+
+ def set_next_pick_sample(self, pick_sample_location):
+ self.next_pick_sample_location = pick_sample_location
+ if self.next_pick_sample_location == None: self.next_pick_sample_location = [-1,-1]
+
+ def _do_abort(self):
+ """
+ Aborts a running trajectory on the sample changer.
+
+ :returns: None
+ :rtype: None
+ """
+ if self.super_abort_cmd is not None:
+ self.super_abort_cmd() # stops super
+ self._cmdAbort()
+ self._update_state() # remove software flags like Loading.. reflects current hardware state
+
+ def _check_coherence(self):
+
+ sampinfobool, sampinfomessage = self._check_incoherent_sample_info()
+ unknownsampbool, unknownsampmessage = self._check_unknown_sample_presence()
+ msg = sampinfomessage + unknownsampmessage
+ return ( sampinfobool and unknownsampbool ), msg
+
+ def _check_unknown_sample_presence(self):
+
+ detected = self._chnSampleIsDetected.get_value()
+ loaded_lid = self._chnLidLoadedSample.get_value()
+ loaded_num = self._chnNumLoadedSample.get_value()
+ #self.logger.debug("detected %s, type detected %s, loaded_lid %d, loaded_num %d, loaded_num type %s" % ( str(detected), type(detected), loaded_lid, loaded_num, type(loaded_num) ) )
+ #self.logger.debug("-1 in [loaded_lid, loaded_num] %s, detected %s" % ( -1 in [loaded_lid, loaded_num], detected ) )
+ #self.logger.debug("-1 in [loaded_lid, loaded_num] and detected: %s" % ( -1 in [loaded_lid, loaded_num] and detected ) )
+
+
+ if -1 in [loaded_lid, loaded_num] and detected:
+ return False, "Sample detected on Diffract. but there is no info about it"
+
+ return True, ""
+
+ def _check_incoherent_sample_info(self):
+ """
+ Check for sample info in CATS but no physically mounted sample
+ (Fix failed PUT)
+ Returns False in case of incoherence, True if all is ok
+ """
+ #self.logger.debug('self._chnSampleIsDetected %s' % self._chnSampleIsDetected.get_value() )
+ detected = self._chnSampleIsDetected.get_value()
+ loaded_lid = self._chnLidLoadedSample.get_value()
+ loaded_num = self._chnNumLoadedSample.get_value()
+ #self.logger.debug("detected %s, loaded_lid %d, loaded_num %d" % ( str(detected), loaded_lid, loaded_num ) )
+
+ if not detected and not ( -1 in [loaded_lid, loaded_num] ):
+ return False, "There is info about a sample in CATS but it is not detected on the diffract."
+
+ return True, ""
+
+ def _update_loaded_sample(self, sample_num=None, lid=None):
+ """
+ Reads the currently mounted sample basket and pin indices from the CATS Tango DS,
+ translates the lid/sample notation into the basket/sample notation and marks the
+ respective sample as loaded.
+
+ :returns: None
+ :rtype: None
+ """
+ if not self._chnSampleIsDetected.get_value():
+ Cats90._update_loaded_sample(self, -1, -1)
+ else:
+ Cats90._update_loaded_sample(self, sample_num, lid)
+
+ def _get_shifts(self):
+ """
+ Get the mounting position from the Diffractometer DS.
+
+ @return: 3-tuple
+ """
+ if self.shifts_channel is not None:
+ shifts = self.shifts_channel.get_value()
+ else:
+ shifts = None
+ self.logger.debug('Shifts of the diffractometer position: %s' % str(shifts) )
+ return shifts
+
+ # TODO: fix return type
+ def is_ht_sample(self, address):
+ """
+ Returns is sample address belongs to hot tool basket.
+
+ @address: sample address
+ @return: int or boolean
+ """
+ try: basket, sample = address.split(":") # address is string (when loading from tree)
+ except: basket, sample = address # address is tuple (when loading from sample changer tab)
+
+ try:
+ if int(basket) >= 100:
+ return int(sample)
+ else:
+ return False
+ except Exception as e:
+ self._update_state()
+ self.logger.debug("Cannot identify sample in hot tool")
+ return False
+
+ def tool_for_basket(self, basketno):
+ """
+ Returns the tool corresponding to the basket.
+
+ @basketno: basket number
+ @return: int
+ """
+ if basketno == 100:
+ return TOOL_SPINE
+
+ return Cats90.tool_for_basket(self, basketno)
+
+ def is_loaded_ht(self):
+ """
+ 1 : has loaded ht
+ 0 : nothing loaded
+ -1 : loaded but not ht
+ """
+ sample_lid = self._chnLidLoadedSample.get_value()
+
+ if self.has_loaded_sample():
+ if sample_lid == 100:
+ return 1
+ else:
+ return -1
+ else:
+ return 0
+
+ def _do_reset(self):
+ """
+ Called when user pushes "Fix fail PUT" button
+ Overrides the _doReset in CatsMaint, adding checks whether calling this method is justified
+ """
+ self.recover_cats_from_failed_put()
+
+ def recover_cats_blocked_in_RI2(self):
+ self._cmdCATSRecovery(wait = True)
+
+ def recover_cats_from_failed_put(self):
+ """
+ Deletes sample info on diff, but should retain info of samples on tools, eg when doing picks
+ TODO: tool2 commands are not working, eg SampleNumberInTool2
+ """
+ self.logger.debug("XalocCats recovering from failed put. Failed put is %s" % str( self._check_incoherent_sample_info() ) )
+
+ if not self._check_incoherent_sample_info()[0]:
+ self._cmdAbort()
+ savelidsamptool = self._chnLidSampleOnTool.get_value()
+ savenumsamptool = self._chnNumSampleOnTool.get_value()
+ #savelidsamptool2 = self._chnLidSampleOnTool2() # Not implemented yet
+ #savenumsamptool2 = self._chnNumSampleOnTool2() # Not implemented yet
+ self._cmdClearMemory()
+ if not -1 in [savelidsamptool, savenumsamptool ]:
+ basketno, bsampno = self.lidsample_to_basketsample(
+ savelidsamptool,savenumsamptool
+ )
+ argin = [ str(savelidsamptool),
+ str(savenumsamptool),
+ str( self.get_cassette_type( basketno ) )
+ ]
+ self.logger.debug("XalocCats recover from failed put. Sending to robot %s" % argin )
+ cmdok = self._execute_server_task( self._cmdSetTool, argin )
+ #if not -1 in [savelidsamptool2, savenumsamptool2 ]:
+ # basketno, bsampno = self.lidsample_to_basketsample(savelidsamptool2,savenumsamptool2) # Not implemented yet
+ # argin = [ str(savelidsamptool2), str(savenumsamptool2), str(self.get_cassette_type(basketno)) ]
+ # self._execute_server_task( self._cmdSetTool2, argin )
+ else: raise Exception("The conditions of the beamline do not fit a failed put situation, "
+ "Fixed failed PUT is not justified. Find another solution.")
+
+ def _do_recover_failure(self):
+ """
+ Called when user pushes "Fix fail GET" button
+ Overrides the _do_recover_failure in CatsMaint, adding checks whether calling this method is justified
+ """
+ self.logger.debug("XalocCats recovering from failed get")
+ self.recover_cats_from_failed_get()
+
+ def recover_cats_from_failed_get(self):
+ """
+ Deletes sample info on diff, but should retain info of samples on tools, eg when doing picks
+ TODO: tool2 commands are not working, eg SampleNumberInTool2
+ """
+ if not self._check_unknown_sample_presence()[0]:
+ self._cmdRecoverFailure()
+ else: raise Exception("The conditions of the beamline do not fit a failed get situation, "
+ "Fixed failed GET is not justified. Find another solution.")
+
+
+ def lidsample_to_basketsample(self, lid, num):
+ if self.is_isara():
+ return lid, num
+ else:
+ if lid == 100:
+ return lid, num
+
+ lid_base = (lid - 1) * self.baskets_per_lid # nb of first basket in lid
+ basket_type = self.basket_types[lid_base]
+
+ if basket_type == BASKET_UNIPUCK:
+ samples_per_basket = SAMPLES_UNIPUCK
+ elif basket_type == BASKET_SPINE:
+ samples_per_basket = SAMPLES_SPINE
+ else:
+ samples_per_basket = self.samples_per_basket
+
+ lid_offset = ((num - 1) / samples_per_basket) + 1
+ sample_pos = ((num - 1) % samples_per_basket) + 1
+ basket = lid_base + lid_offset
+ return basket, sample_pos
+
+ def basketsample_to_lidsample(self, basket, num):
+ if self.is_isara():
+ return basket, num
+ else:
+ if basket == 100:
+ return basket, num
+
+ lid = ((basket - 1) / self.baskets_per_lid) + 1
+
+ basket_type = self.basket_types[basket - 1]
+ if basket_type == BASKET_UNIPUCK:
+ samples_per_basket = SAMPLES_UNIPUCK
+ elif basket_type == BASKET_SPINE:
+ samples_per_basket = SAMPLES_SPINE
+ else:
+ samples_per_basket = self.samples_per_basket
+
+ sample = (((basket - 1) % self.baskets_per_lid) * samples_per_basket) + num
+ return lid, sample
+
+
+
+ def _execute_server_task(self, method, *args, **kwargs):
+ """
+ Executes a task on the CATS Tango device server
+ Xaloc: added collision detection while waiting for safe
+
+ :returns: None
+ :rtype: None
+ """
+ #logging.getLogger("HWR").debug("XalocCats. executing method %s " % str( method.name() ))
+ self._wait_device_ready(timeout = 60) #TODO adjust time out according to times needed for dries etc?
+ try:
+ task_id = method(*args)
+ except:
+ import traceback
+ self.logger.debug("XalocCats exception while executing server task")
+ self.logger.debug(traceback.format_exc())
+ task_id = None
+ self._update_state()
+ raise Exception("The command could not be sent to the robot, check its state.")
+ #TODO: why not return with an Exception here to inform there is a problem with the CATS?
+
+ waitsafe = kwargs.get('waitsafe',False)
+ waitfinished = kwargs.get('waitfinished',False)
+ logging.getLogger("HWR").debug("XalocCats. executing method %s / task_id %s / waiting only for safe status is %s" % (str(method), task_id, waitsafe))
+
+ # What does the first part of the if do? It's not resetting anything...
+ ret=None
+ if task_id is None: #Reset
+ while self._is_device_busy():
+ gevent.sleep(0.1)
+ return False
+ else:
+ # introduced wait because it takes some time before the attribute PathRunning is set
+ # after launching a transfer. This is only necessary if the trajectory is not safe
+ #if task_id not in ['pick']:
+ #self.logger.debug("Going to sleep for 6 seconds, task_id is %s" % task_id)
+ #gevent.sleep(4.0)
+ self.logger.debug("Waiting for the HO to be busy")
+ while not self._is_device_busy():
+ gevent.sleep(0.1)
+ self.logger.debug("Starting error detection loop")
+ while self._is_device_busy():
+ if waitsafe:
+ #TODO: when a sample is loaded but not present, detect this...
+ if self.get_loaded_sample() == self.get_selected_sample() and not self.cats_ri2:
+ logging.getLogger("HWR").debug("Server execution polling finished as requested sample is mounted and cats left diff ")
+ break
+ #if self.path_safe(): # this doesnt work for getputpick, pathsafe is not handled well for this trajectory in the cats DS
+ #logging.getLogger("HWR").debug("Server execution polling finished as path is safe")
+ #break
+ #if self.get_loaded_sample() == self.get_selected_sample():
+ #logging.getLogger("HWR").debug("Cats90. server execution polling finished as loaded sample is the requested one")
+ #gevent.sleep(1) # adjust according to need: this is the time needed for the robot to retreat from the diff
+ #break
+ elif not self.path_running():
+ logging.getLogger("HWR").debug("server execution polling finished as path is not running")
+ break
+ if not self._check_incoherent_sample_info()[0] and not self.cats_ri2:
+ logging.getLogger("HWR").debug("server execution polling finished as cats thinks there is a sample on the diff, but there is not")
+ break
+ if not self._chnCollisionSensorOK.get_value():
+ # Should the exception be raised here?? It is also done in _do_load
+ self._update_state()
+ logging.getLogger("HWR").debug("Cats90. server execution polling finished as path is safe")
+ raise Exception ("The robot had a collision, call your LC or floor coordinator")
+ elif not self.cats_powered and self.cats_ri2:
+ # CATS is blocked in front of diff
+ logging.getLogger("HWR").debug("Cats90. Robot blocked in front of diff, attempting a recovery")
+ self.recover_cats_blocked_in_RI2()
+ gevent.sleep(2.0)
+ # in case nothing is happening. The check for RI1 is because there is a transient loss of sample info when changing samples
+ #if not self._check_unknown_sample_presence()[0] and not self._chnIsCatsRI1.get_value():
+ #break
+ gevent.sleep(0.3)
+ ret = True
+ logging.getLogger("HWR").debug("XalocCats. return value from method _execute_server_task is %s" % str( ret ) )
+ return ret
+
+ def assert_can_execute_task(self):
+ """
+ Raises:
+ (Exeption): If sample changer cannot execute a task
+ """
+ if not self.is_ready():
+ error_msg = ""
+ state_str = SampleChangerState.tostring(self.state)
+ if state_str == "Loading" or state_str == "Unloading":
+ error_msg = "The robot is busy, please wait till the robot finishes and try again."
+ elif state_str == "Unknown":
+ error_msg = "The robot is busy, you may need to use the sample changer details tab to unload the sample"
+ elif state_str == "Moving":
+ error_msg = "The robot is doing a %s trajectory, please wait and try again" % self.current_path
+ else:
+ error_msg = "Cannot execute task, robot is not ready"
+ raise Exception(
+ error_msg + " ( state is "
+ + SampleChangerState.tostring(self.state)
+ + ")"
+ )
+
+def test_hwo(hwo):
+ hwo._updateCatsContents()
+ print("Is path running? ", hwo.is_path_running())
+ print("Loading shifts: ", hwo._get_shifts())
+ print("Sample on diffr : ", hwo.cats_sample_on_diffr())
+ print("Baskets : ", hwo.basket_presence)
+ print("Baskets : ", hwo.get_basket_list())
+ if hwo.has_loaded_sample():
+ print("Loaded is: ", hwo.get_loaded_sample().getCoords())
+ print("Is mounted sample: ", hwo.is_mounted_sample((1, 1)))
diff --git a/mxcubecore/HardwareObjects/ALBA/XalocCatsMaint.py b/mxcubecore/HardwareObjects/ALBA/XalocCatsMaint.py
new file mode 100755
index 0000000000..88068c3e99
--- /dev/null
+++ b/mxcubecore/HardwareObjects/ALBA/XalocCatsMaint.py
@@ -0,0 +1,124 @@
+#
+# Project: 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 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with MXCuBE. If not, see .
+
+"""
+[Name] XalocCatsMaint
+
+[Description]
+HwObj used to operate the CATS sample changer via Tango in maintenance mode
+
+[Signals]
+- None
+"""
+
+#from __future__ import print_function
+import logging
+from mxcubecore.HardwareObjects.CatsMaint import CatsMaint
+
+__credits__ = ["ALBA Synchrotron"]
+__version__ = "3"
+__category__ = "General"
+
+
+class XalocCatsMaint(CatsMaint):
+
+ def __init__(self, *args, **kwargs):
+ CatsMaint.__init__(self, *args, **kwargs)
+ self.logger = logging.getLogger("HWR.XalocCatsMaint")
+ self.chan_shifts = None
+ self.chan_at_home = None
+ self.cmd_super_abort = None
+
+ def init(self):
+ self.logger.debug("Initializing {0}".format(self.__class__.__name__))
+ CatsMaint.init(self)
+
+ # channel to ask diffractometer for mounting position
+ self.chan_shifts = self.get_channel_object("shifts")
+ self.chan_at_home = self.get_channel_object("_chnAtHome")
+ self.cmd_super_abort = self.get_command_object("super_abort")
+
+ # To get acces to recovery functions
+ self.Cats90 = self.get_object_by_role("cats90")
+
+ def _do_abort(self):
+ if self.cmd_super_abort is not None:
+ self.cmd_super_abort()
+ self._cmdAbort()
+
+ def _do_reset_memory(self):
+ """
+ Reset CATS memory.
+ """
+ # Check do_PRO6_RAH first
+ if self.chan_at_home.get_value() is True:
+ CatsMaint._do_reset_memory(self)
+
+ def _check_unknown_sample_presence(self):
+ self.Cats90._check_unknown_sample_presence()
+
+ def _check_incoherent_sample_info(self):
+ """
+ Check for sample info in CATS but no physically mounted sample
+ (Fix failed PUT)
+ Returns False in case of incoherence, True if all is ok
+ """
+ self.Cats90._check_incoherent_sample_info()
+
+ def _do_recover_failure(self):
+ """
+ Failed get
+ """
+ self.Cats90._do_recover_failure()
+
+ def _do_reset(self):
+ """
+ Reset CATS system after failed put
+ Deletes sample info on diff, but should retain info of samples on tools, eg when doing picks
+ TODO: tool2 commands are not working, eg SampleNumberInTool2
+ """
+ self.Cats90._do_reset()
+
+ def _get_shifts(self):
+ """
+ Get the mounting position from the Diffractometer DS.
+
+ @return: 3-tuple
+ """
+ if self.chan_shifts is not None:
+ shifts = self.chan_shifts.get_value()
+ else:
+ shifts = None
+ return shifts
+
+ def re_emit_signals(self):
+ self.emit("runningStateChanged", (self._running,))
+ self.emit("powerStateChanged", (self._powered,))
+ self.emit("toolStateChanged", (self._toolopen,))
+ self.emit("messageChanged", (self._message,))
+ self.emit("barcodeChanged", (self._barcode,))
+ self.emit("lid1StateChanged", (self._lid1state,))
+ self.emit("lid2StateChanged", (self._lid2state,))
+ self.emit("lid3StateChanged", (self._lid3state,))
+ self.emit("regulationStateChanged", (self._regulating,))
+
+
+
+def test_hwo(hwo):
+ print(hwo._get_shifts())
diff --git a/mxcubecore/HardwareObjects/ALBA/XalocCluster.py b/mxcubecore/HardwareObjects/ALBA/XalocCluster.py
new file mode 100755
index 0000000000..b26d4150f8
--- /dev/null
+++ b/mxcubecore/HardwareObjects/ALBA/XalocCluster.py
@@ -0,0 +1,178 @@
+#
+# Project: 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 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with MXCuBE. If not, see .
+#
+#
+# Job submission to the ALBA cluster is managed by the slurm_client
+# The USER / SCRATCH keyword sets if the files are copied first to local disk on the cluster (SCRATCH)
+# or if the file I/O during the characterization job is done directly on the directorires of the user (USER)
+#
+
+
+"""
+[Name] XalocCluster
+
+[Description]
+HwObj providing access to the ALBA cluster.
+
+[Signals]
+- None
+"""
+
+from __future__ import print_function
+
+import os
+import time
+import logging
+
+from mxcubecore.BaseHardwareObjects import HardwareObject
+from slurm_client import EDNAJob, Manager, Account
+from slurm_client.utils import create_edna_yml
+
+
+__credits__ = ["ALBA Synchrotron"]
+__version__ = "2.3"
+__category__ = "General"
+__author__ = "Jordi Andreu"
+
+
+class XalocCluster(HardwareObject):
+ def __init__(self, name):
+ HardwareObject.__init__(self, name)
+ self.logger = logging.getLogger("HWR.XalocCluster")
+ self.account = None
+ self.manager = None
+ self.use_env_scripts_root = True
+ self._scripts_root = None
+ self.pipelines = {}
+ self._jobs = None
+
+ def init(self):
+ self.logger.debug("Initializing {0}".format(self.__class__.__name__))
+ user = self.get_property("user")
+ cla = self.get_property("cla")
+
+ self._scripts_root = self.get_property("pipelines_scripts_root")
+
+ if self._scripts_root:
+ self.use_env_scripts_root = False
+
+ for name in ['strategy', 'ednaproc', 'autoproc', 'xia2']:
+ if self.get_property("{}_pipeline".format(name)):
+ _pipeline = eval(self.get_property("{}_pipeline".format(name)))
+ if _pipeline:
+ self.pipelines[name] = _pipeline
+ self.logger.debug("Adding {0} pipeline {1}".format(name, _pipeline))
+
+ self.account = Account(user=user, cla=cla, scripts_root=self._scripts_root)
+ self.manager = Manager([self.account])
+ self.logger.debug("cluster user: {0}".format(self.account.user))
+ self.logger.debug("cluster CLA: {0}".format(self.account.cla))
+ try: self.logger.debug("scripts root: {0}".format( self.account.scripts_root ) )
+ except: pass
+
+ def run(self, job):
+ self.manager.submit(job)
+
+ def wait_done(self, job):
+ state = self.manager.get_job_state(job)
+ self.logger.debug("Job state is %s" % state)
+
+ while state in ["RUNNING", "PENDING"]:
+ self.logger.debug("Job / is %s" % state)
+ time.sleep(0.5)
+ state = self.manager.get_job_state(job)
+
+ self.logger.debug(" job finished with state: \"%s\"" % state)
+ return state
+
+ def create_strategy_job(self, collect_id, input_file, output_dir):
+
+ plugin_name = self.pipelines['strategy']['plugin']
+ slurm_script = os.path.join(self._scripts_root,
+ self.pipelines['strategy']['script'])
+
+ _yml_file = create_edna_yml(str(collect_id),
+ plugin_name,
+ input_file,
+ slurm_script,
+ workarea='SCRATCH',
+ benchmark=False,
+ dest=output_dir,
+ use_scripts_root=self.use_env_scripts_root,
+ xds=None,
+ configdef=None)
+ return EDNAJob(_yml_file)
+
+ def create_autoproc_job(self, collect_id, input_file, output_dir):
+
+ plugin_name = self.pipelines['autoproc']['plugin']
+ slurm_script = os.path.join(self._scripts_root,
+ self.pipelines['autoproc']['script'])
+ configdef = os.path.join(self._scripts_root,
+ self.pipelines['autoproc']['configdef'])
+
+ self.logger.debug("configDef is %s" % configdef)
+
+ _yml_file = create_edna_yml(str(collect_id),
+ plugin_name,
+ input_file,
+ slurm_script,
+ workarea='SCRATCH',
+ benchmark=False,
+ dest=output_dir,
+ use_scripts_root=self.use_env_scripts_root,
+ xds=None,
+ configdef=configdef)
+ return EDNAJob(_yml_file)
+
+ def create_xia2_job(self, collect_id, input_file, output_dir):
+
+ plugin_name = self.pipelines['xia2']['plugin']
+ slurm_script = os.path.join(self._scripts_root,
+ self.pipelines['xia2']['script'])
+
+ _yml_file = create_edna_yml(str(collect_id),
+ plugin_name,
+ input_file,
+ slurm_script,
+ workarea='SCRATCH',
+ benchmark=False,
+ dest=output_dir,
+ use_scripts_root=self.use_env_scripts_root,
+ xds=None,
+ configdef=None)
+ return EDNAJob(_yml_file)
+
+ def create_ednaproc_job(self, collect_id, input_file, output_dir):
+
+ plugin_name = self.pipelines['ednaproc']['plugin']
+ slurm_script = os.path.join(self._scripts_root,
+ self.pipelines['ednaproc']['script'])
+
+ _yml_file = create_edna_yml(str(collect_id),
+ plugin_name,
+ input_file,
+ slurm_script,
+ workarea='SCRATCH',
+ benchmark=False,
+ dest=output_dir,
+ use_scripts_root=self.use_env_scripts_root,
+ xds=None,
+ configdef=None)
+ return EDNAJob(_yml_file)
diff --git a/mxcubecore/HardwareObjects/ALBA/XalocCollect.py b/mxcubecore/HardwareObjects/ALBA/XalocCollect.py
new file mode 100755
index 0000000000..f5054c5f23
--- /dev/null
+++ b/mxcubecore/HardwareObjects/ALBA/XalocCollect.py
@@ -0,0 +1,2347 @@
+# Project: 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 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with MXCuBE. If not, see .
+
+"""
+[Name] XalocCollect
+
+[Description]
+Specific implementation of the collection methods for ALBA synchrotron.
+Basic Flow:
+ do_collect in AbstractCollect:
+ data_collection_hook in XalocCollect
+ prepare_acquisition in XalocCollect
+ detector_hwobj.prepare_acquisition
+ prepare_collection in XalocCollect <-- Repeated for each test image in case of characterization
+ detector_hwobj.prepare_collection <-- Repeated for each test image in case of characterization
+ collect_images
+ wait_collection_done
+ collection_finished (AbstractCollect) if collection works
+ collection_failed if there is a problem
+ data_collection_cleanup is always called from do_collect (supersedes AbstractCollect method with same name)
+
+ IMPORTANT: the stop button in mxcube throughs an exception in the queue, so there is no need to throw exceptions in Collect
+
+
+TODO: dc has a parameter run_processing_after which is not used in collection_finished
+ should we reimplement collection_finished to add an if statement to decide to run?
+ If we do, run_online_processing_cbox should be selected by default in the processing_widget
+
+There are currently three routines used for when a collection fails
+ data_collection_failed in XalocCollect
+ calls stop_collect (is this explicit call necessary?)
+ collection_failed in AbstractCollect is called from do_collect in case of failure
+
+In case the user aborts data collection, stopCollect is called, then stop_collect then data_collection_cleanup
+ In that case, is post processing prevented?
+
+[Signals]
+- progressInit
+- collectConnected
+- collectStarted
+- collectReady
+- progressStop
+- collectOscillationFailed
+
+Implementation of Sardana collects uses Macros, as defined in ./HardwareRepository/Command/Sardana.py
+We need to investigate how to stop Macros
+"""
+
+# RB 2020102: data collection sweeps to be done through a Sardana Macro
+
+from __future__ import print_function
+
+import os
+import sys
+import time
+import gevent
+import logging
+import math
+import glob
+
+from mxcubecore.TaskUtils import task
+from mxcubecore.HardwareObjects.abstract.AbstractCollect import AbstractCollect
+from taurus.core.tango.enums import DevState
+#from xaloc.resolution import get_dettaby, get_resolution
+from mxcubecore import HardwareRepository as HWR
+from datetime import datetime
+
+__credits__ = ["ALBA Synchrotron"]
+__version__ = "3"
+__category__ = "General"
+
+
+class XalocCollect(AbstractCollect):
+ """Main data collection class. Inherited from AbstractMulticollect class
+ Collection is done by setting collection parameters and
+ executing collect command
+ """
+
+ def __init__(self, name):
+ AbstractCollect.__init__(self, name)
+ self.logger = logging.getLogger("HWR.XalocCollect")
+ self.user_logger = logging.getLogger("user_level_log")
+ self.supervisor_hwobj = None
+ self.fastshut_hwobj = None
+ self.slowshut_hwobj = None
+ self.photonshut_hwobj = None
+ self.frontend_hwobj = None
+ self.diffractometer_hwobj = None
+ self.omega_hwobj = None
+ self.lims_client_hwobj = None
+ self.image_tracking_hwobj = None
+
+ self.machine_info_hwobj = None
+ self.energy_hwobj = None
+ self.resolution_hwobj = None
+ self.transmission_hwobj = None
+ self.detector_hwobj = None
+ self.beam_info_hwobj = None
+ #self.graphics_manager_hwobj = None
+ self.autoprocessing_hwobj = None
+ self.flux_hwobj = None
+ self.aborted_by_user = None
+
+ self.cmd_ni_conf = None
+ self.cmd_ni_unconf = None
+
+ self.set_pilatus_saving_pattern = None
+ self.ascanct = None
+ self.meshct = None
+ self.senv = None
+ self.mxcube_sardanascan_running = None
+
+ self.chan_kappa_pos = None
+ self.chan_phi_pos = None
+
+ self.chan_undulator_gap = None
+
+ self.scan_motors_hwobj = {}
+ self.xaloc_motor_names_dict = {}
+
+ self._error_msg = ""
+ self.osc_id = None
+ self._collecting = None
+
+ self.omega_hwobj = None
+
+ self.use_sardana_scan = None
+ self.scan_start_positions = {}
+ self.scan_end_positions = {}
+ self.scan_velocities = {}
+ self.scan_init_velocities = {}
+ self.scan_init_positions = {}
+ self.scan_motors_hwobj = {}
+ self.scan_move_motor_names = []
+ self.scan_all_motor_names = []
+
+ self.mesh_mxcube_horizontal_motor_name = None
+ self.mesh_mxcube_vertical_motor_name = None
+ self.mesh_fast_index = None
+ self.mesh_slow_index = None
+ self.mesh_horizontal_index = None
+ self.mesh_vertical_index = None
+ self.mesh_sshaped_bool = None # True: up and down scans, False: only up scans
+ self.mesh_fast_motor_max_velocity = None
+
+ #self.helical_positions = None
+ #self.saved_omega_velocity = None
+
+ self.bypass_shutters = False
+ self.rescorner = None
+
+ self.symbolic_link_image_destination = None
+
+ def init(self):
+ self.logger.debug("Initializing {0}".format(self.__class__.__name__))
+ self.ready_event = gevent.event.Event()
+
+ self.supervisor_hwobj = self.get_object_by_role("supervisor")
+ self.fastshut_hwobj = self.get_object_by_role("fast_shutter")
+ self.slowshut_hwobj = self.get_object_by_role("slow_shutter")
+ self.photonshut_hwobj = self.get_object_by_role("photon_shutter")
+ self.frontend_hwobj = self.get_object_by_role("frontend")
+ self.diffractometer_hwobj = self.get_object_by_role("diffractometer")
+ self.omega_hwobj = self.get_object_by_role("omega")
+ self.lims_client_hwobj = self.get_object_by_role("lims_client")
+ self.image_tracking_hwobj = self.get_object_by_role("image_tracking")
+ self.machine_info_hwobj = self.get_object_by_role("machine_info")
+ self.energy_hwobj = self.get_object_by_role("energy")
+ self.resolution_hwobj = self.get_object_by_role("resolution")
+ self.transmission_hwobj = self.get_object_by_role("transmission")
+ self.detector_hwobj = self.get_object_by_role("detector")
+ self.beam_info_hwobj = self.get_object_by_role("beam_info")
+ #self.graphics_manager_hwobj = self.get_object_by_role("graphics_manager")
+ self.autoprocessing_hwobj = self.get_object_by_role("offline_processing")
+ self.flux_hwobj = self.get_object_by_role("flux")
+ self.aborted_by_user = False
+
+ #
+ #
+ # START of 20210218: Lines only necessary for ni660 collects, remove when switching to pure meshct/ascanct scans
+ self.cmd_ni_conf = self.get_command_object("ni_configure")
+ self.cmd_ni_unconf = self.get_command_object("ni_unconfigure")
+ # END of lines for ni660 scans
+ #
+ #
+
+ self.set_pilatus_saving_pattern = self.get_command_object("set_pilatus_saving_pattern")
+ self.ascanct = self.get_command_object("ascanct")
+ self.meshct = self.get_command_object("meshct")
+ self.senv = self.get_command_object("senv")
+ self.mxcube_sardanascan_running = False # Is set equal to the macro running whem mecessary
+
+
+ self.chan_kappa_pos = self.get_channel_object("kappapos")
+ self.chan_phi_pos = self.get_channel_object("phipos")
+
+ self.xaloc_motor_names_dict = {'phi': 'omega',
+ 'phiy' : 'omegax',
+ 'phiz': 'omegaz',
+ 'kappa': 'kappa',
+ 'kappaphi': 'phi',
+ 'sampx': 'centx',
+ 'sampy': 'centy'}
+
+ self.use_sardana_scan = self.get_property('use_sardana_scan')
+ #self.scan_all_motor_names = ['phiy', 'phiz', 'sampx', 'sampy', 'kappa', 'kappa_phi']
+ self.scan_all_motor_names = ['phiy', 'phiz', 'sampx', 'sampy']
+ #TODO get rid of hardcoded max and minvelocity numbers
+ for scan_motor in self.scan_all_motor_names:
+ self.scan_motors_hwobj[scan_motor] = self.get_object_by_role(scan_motor)
+
+ self.mesh_mxcube_horizontal_motor_name = 'phiy' # omegax
+ self.mesh_mxcube_vertical_motor_name = 'phiz' # omegaz
+ self.mesh_horizontal_index = 0
+ self.mesh_vertical_index = 1
+ self.mesh_fast_motor_max_velocity = 1.5 # mm/sec. Physically the motor should be fine up to 3.0 mm/sec
+
+ self.mesh_sshaped_bool = self.get_property('mesh_sshape') # False: only up scans
+
+ self.symbolic_link_image_destination = self.get_property('symbolic_link_image_destination')
+ #self.chan_undulator_gap = self.get_channel_object("chanUndulatorGap")
+
+ self.scan_motors_hwobj = {}
+ #TODO 20200921 kappa_phi is broken
+ #self.scan_all_motor_names = ['phiy', 'phiz', 'sampx', 'sampy', 'kappa', 'kappa_phi']
+ self.scan_all_motor_names = ['phiy', 'phiz', 'sampx', 'sampy']
+ #TODO get rid of hardcoded max and minvelocity numbers
+ self.scan_motors_min_velocity = {'phiy': 6E-6, 'phiz': 1.3E-4, 'sampx': 7E-6, 'sampy': 7E-6, 'kappa': 4, 'kappaphi': 7} # see XALOC elog 925
+ self.scan_motors_max_velocity = {'phiy': 3.0, 'phiz': 0.5, 'sampx': 0.15, 'sampy': 0.15, 'kappa': 17, 'kappaphi': 70}
+ for scan_motor in self.scan_all_motor_names:
+ self.scan_motors_hwobj[scan_motor] = self.get_object_by_role(scan_motor)
+
+ undulators = []
+ try:
+ for undulator in self["undulators"]:
+ undulators.append(undulator)
+ except BaseException:
+ pass
+
+ self.exp_type_dict = {'Mesh': 'raster',
+ 'Helical': 'Helical'}
+
+ self.omega_init_pos = self.omega_hwobj.get_value()
+ self.omega_init_vel = 60
+
+
+ det_px, det_py = self.detector_hwobj.get_pixel_size()
+
+ self.set_beamline_configuration(
+ synchrotron_name="ALBA",
+ directory_prefix=self.get_property("directory_prefix"),
+ default_exposure_time=self.detector_hwobj.get_default_exposure_time(),
+ minimum_exposure_time=self.detector_hwobj.get_minimum_exposure_time(),
+ detector_fileext=self.detector_hwobj.get_file_suffix(),
+ detector_type=self.detector_hwobj.get_detector_type(),
+ detector_manufacturer=self.detector_hwobj.get_manufacturer(),
+ detector_model=self.detector_hwobj.get_model(),
+ detector_px=det_px,
+ detector_py=det_py,
+ detector_binning_mode=self.detector_hwobj.get_binning_mode(),
+ undulators=undulators,
+ focusing_optic=self.get_property('focusing_optic'),
+ monochromator_type=self.get_property('monochromator'),
+ beam_divergence_vertical=self.beam_info_hwobj.get_beam_divergence_hor(),
+ beam_divergence_horizontal=self.beam_info_hwobj.get_beam_divergence_ver(),
+ polarisation=self.get_property('polarisation'),
+ input_files_server=self.get_property("input_files_server"))
+
+ self.emit("collectConnected", (True,))
+ self.emit("collectReady", (True, ))
+
+ #self.logger.debug('*** bypass shutters: %s', type(os.environ.get('MXCUBE_BYPASS_SHUTTERS')))
+ self.bypass_shutters = os.environ.get('MXCUBE_BYPASS_SHUTTERS')
+ #self.logger.debug('*** bypass shutters: %s', self.bypass_shutters)
+ if self.bypass_shutters and self.bypass_shutters.lower() == 'true':
+ self.logger.warning("Simulation mode: BYPASSING the SHUTTERS")
+ self.bypass_shutters = True
+
+ self.rescorner = self.get_channel_object("rescorner_position")
+
+ def pre_collect_check(self):
+ #CHECK if files exist, exit if true
+ full_path = self.get_image_file_name(
+ self.current_dc_parameters['oscillation_sequence'][0]['start_image_number']
+ )
+ if os.path.exists( full_path ):
+ msg = "Filename already exists : %s" % full_path
+ self.data_collection_failed( Exception(msg) , msg )
+
+ if HWR.beamline.session.get_proposal() == 'local-user':
+ msg = "You are not logged in, log in first"
+ self.data_collection_failed( Exception(msg) , msg )
+
+
+ def do_collect(self, owner):
+ """
+ Actual collect sequence
+ """
+
+ log = logging.getLogger("user_level_log")
+ log.info("Collection: Preparing to collect")
+
+ try:
+
+ self.pre_collect_check()
+
+ self.emit("collectReady", (False,))
+ self.emit(
+ "collectOscillationStarted",
+ (owner, None, None, None, self.current_dc_parameters, None),
+ )
+ self.emit("progressInit", ("Collection", 100, False))
+ self.collection_id = None
+
+ ## ----------------------------------------------------------------
+ ## Prepare data collection
+
+ self.open_detector_cover()
+ self.open_safety_shutter()
+ #self.open_fast_shutter() # done through trigger for external trigger, open_fast_shutter_for_internal_trigger is used for internal trigger
+
+ self.current_dc_parameters["status"] = "Running"
+ self.current_dc_parameters["collection_start_time"] = time.strftime(
+ "%Y-%m-%d %H:%M:%S"
+ )
+
+ # ----------------------------------------------------------------
+ # Set data collection parameters
+
+ if "transmission" in self.current_dc_parameters:
+ log.info(
+ "Collection: Setting transmission to %.2f",
+ self.current_dc_parameters["transmission"],
+ )
+ self.set_transmission(self.current_dc_parameters["transmission"])
+
+ if "wavelength" in self.current_dc_parameters:
+ log.info(
+ "Collection: Setting wavelength to %.4f",
+ self.current_dc_parameters["wavelength"],
+ )
+ self.set_wavelength(self.current_dc_parameters["wavelength"])
+
+ elif "energy" in self.current_dc_parameters:
+ log.info(
+ "Collection: Setting energy to %.4f",
+ self.current_dc_parameters["energy"],
+ )
+ self.set_energy(self.current_dc_parameters["energy"])
+
+ dd = self.current_dc_parameters.get("resolution")
+ if dd and dd.get('upper'):
+ resolution = dd["upper"]
+ log.info("Collection: Setting resolution to %.3f", resolution)
+ self.set_resolution(resolution)
+
+ elif "detector_distance" in self.current_dc_parameters:
+ log.info(
+ "Collection: Moving detector to %.2f",
+ self.current_dc_parameters["detector_distance"],
+ )
+ self.move_detector(self.current_dc_parameters["detector_distance"])
+
+ # ----------------------------------------------------------------
+ # Store information in LIMS
+
+ log.info("Collection: Storing data collection in LIMS")
+ self.store_data_collection_in_lims()
+
+ logging.getLogger("HWR").info(
+ "Collection parameters: %s" % str(self.current_dc_parameters)
+ )
+
+ if (
+ self.current_dc_parameters['processing_online']
+ and HWR.beamline.online_processing is not None
+ ):
+ HWR.beamline.online_processing.params_dict["collection_id"] = self.current_dc_parameters["collection_id"]
+ self.online_processing_task = gevent.spawn(
+ HWR.beamline.online_processing.run_processing,
+ self.current_dc_parameters
+ )
+
+ log.info(
+ "Collection: Creating directories for raw images and processing files"
+ )
+ self.create_file_directories()
+
+ log.info("Collection: Getting sample info from parameters")
+ self.get_sample_info()
+
+ log.info("Collection: Storing sample info in LIMS")
+ self.store_sample_info_in_lims()
+
+ if all(
+ item is None for item in self.current_dc_parameters["motors"].values()
+ ):
+ # No centring point defined
+ # create point based on the current position
+ current_diffractometer_position = (
+ HWR.beamline.diffractometer.get_positions()
+ )
+ for motor in self.current_dc_parameters["motors"].keys():
+ self.current_dc_parameters["motors"][
+ motor
+ ] = current_diffractometer_position.get(motor)
+
+ # ----------------------------------------------------------------
+ # Move to the centered position and take crystal snapshots
+
+ log.info("Collection: Moving to centred position")
+ self.move_to_centered_position()
+ self.take_crystal_snapshots()
+ self.move_to_centered_position()
+
+ self.prepare_acquisition()
+
+ # ----------------------------------------------------------------
+ # Site specific implementation of a data collection
+
+ # In order to call the hook with original parameters
+ # before update_data_collection_in_lims changes them
+ # TODO check why this happens
+
+ self.data_collection_hook()
+
+ # ----------------------------------------------------------------
+ # Store information in LIMS
+
+ log.info("Collection: Updating data collection in LIMS")
+ self.update_data_collection_in_lims()
+
+ except:
+ exc_type, exc_value, exc_tb = sys.exc_info()
+ failed_msg = "Data collection failed!\n%s" % exc_value
+ import traceback
+ failed_msg += traceback.format_exc()
+ self.collection_failed(failed_msg)
+ else:
+ self.collection_finished()
+ finally:
+ self.data_collection_cleanup()
+
+ def data_collection_hook(self):
+ """Main collection hook, called from do_collect in AbstractCollect
+ """
+
+ self.logger.info("Running Xaloc data collection hook")
+
+ #if not self.resolution_hwobj.is_ready():
+ #self.logger.info("Waiting for resolution ready...")
+ #self.resolution_hwobj.wait_ready()
+ #if not self.detector_hwobj.is_ready():
+ self.logger.info("Waiting for detector distance ready...")
+ self.detector_hwobj.wait_move_distance_done()
+ if not self.energy_hwobj.is_ready():
+ self.logger.info("Waiting for energy ready...")
+ self.energy_hwobj.wait_move_energy_done()
+
+ # First, save current parameters to revert back when done/fails
+ for motorname in self.scan_all_motor_names: # TODO: check if this is the right place to add these values. Ideally this should be done right after the collect click
+ self.logger.info('Inital motor velocity of motor %s = %.4f' % (
+ motorname,
+ self.scan_motors_hwobj[motorname].get_velocity()
+ )
+ )
+ self.scan_init_velocities[motorname] = self.scan_motors_hwobj[motorname].get_velocity()
+ self.scan_init_positions[motorname] = self.scan_motors_hwobj[motorname].get_value()
+ self.omega_init_pos = self.omega_hwobj.get_value()
+ self.omega_init_vel = 60 # self.omega_hwobj.get_velocity()
+
+ #self.logger.info('Inital motor velocities dict %s' % str(self.scan_init_velocities) )
+ #self.logger.info('Inital omega velocity value %.1f' % self.omega_init_vel )
+
+ # pass wavelength needed in auto processing input files
+ osc_seq = self.current_dc_parameters['oscillation_sequence'][0]
+ osc_seq['wavelength'] = self.get_wavelength()
+ self.logger.info('osc_seq %s' % str(osc_seq) )
+ self.logger.debug("current_dc_parameters %s" % str( self.current_dc_parameters ) )
+
+ self.current_dc_parameters['detector_binning_mode'] = ['EXTERNAL_TRIGGER']
+
+ first_image_no = osc_seq['start_image_number']
+ exp_period = osc_seq['exposure_time']
+ img_range = osc_seq['range']
+ omega_speed = 60 # initial the speed value, this will be recalculated later on in prepare_acquisition
+ omega_pos = osc_seq['start']
+ nb_images = osc_seq['number_of_images']
+ sweep_nb_images = nb_images
+ total_collection_time = exp_period * nb_images
+
+ if self.aborted_by_user:
+ self.emit_collection_failed("Aborted by user")
+ self.aborted_by_user = False
+ return
+
+
+ self.prepare_detector_for_acquisition()
+
+ ### EDNA_REF, OSC, MESH, HELICAL
+
+ exp_type = self.current_dc_parameters['experiment_type']
+ self.logger.debug("Collection method selected is %s" % exp_type)
+
+ if exp_type == "Characterization":
+ self.logger.debug("Running a collect (CHARACTERIZATION)")
+ elif exp_type == "Helical":
+ self.scan_move_motor_names = []
+ self.logger.debug("Running a helical collection")
+ self.logger.debug(
+ "\thelical start positions are: %s" % str(
+ self.scan_start_positions))
+ self.logger.debug(
+ "\thelical end positions are: %s" % str(
+ self.scan_end_positions))
+ self.scan_move_motor_names = []
+ self.set_scan_move_motors(self.scan_start_positions, self.scan_end_positions)
+ self.scan_velocities = self.calculate_scan_velocities(
+ self.scan_start_positions, self.scan_end_positions, total_collection_time
+ )
+ self.logger.info('Preliminary helical setup completed')
+ elif exp_type == "Mesh":
+ slow_mxcube_motor_name, fast_mxcube_motor_name, fast_motor_nr_images, slow_motor_nr_images = \
+ self.setMeshScanParameters(
+ osc_seq,
+ self.mesh_mxcube_horizontal_motor_name,
+ self.mesh_mxcube_vertical_motor_name,
+ self.mesh_center,
+ self.mesh_range
+ )
+ else:
+ self.logger.debug("Running a collect (STANDARD)")
+
+ if self.check_scan_velocities( self.scan_velocities ): # There are motors that cant work at required speed
+ msg = 'Cant reach the required velocities'
+ self.data_collection_failed( Exception( msg ), msg )
+
+ try:
+ init_pos, final_pos, total_dist, omega_speed = self.calc_omega_scan_values(
+ omega_pos,
+ sweep_nb_images
+ )
+
+ # RB init_pos and final_pos include the ramp up and run out range for omega
+ except Exception as e:
+ self.user_logger.error("calc_omega_scan_values failed")
+ self.logger.error('error %s' % str(e) )
+ #self.user_logger.error('error %s' % repr( e ) )
+ self.data_collection_failed( e, "calc_omega_scan_values failed" )
+
+ self.logger.debug(' Sweep parameters omega: init %s start %s total dist %s speed %s' %
+ (init_pos, omega_pos, total_dist, omega_speed )
+ )
+
+ self._collecting = True
+ # for progressBar brick
+ self.emit("progressInit", "Collection", osc_seq['number_of_images'])
+
+ self.emit("collectStarted", (None, 1)) # parameters required are owner and nr of sweeps
+
+ if exp_type == 'OSC' or (exp_type == 'Characterization' and nb_images == 1) or exp_type == 'Helical':
+ # prepare input files for autoprocessing
+ if exp_type != "Characterization":
+ self.autoprocessing_hwobj.create_input_files(self.current_dc_parameters)
+
+ # Sardana collect: run ascanct
+ self.collect_prepare_omega( init_pos, omega_speed )
+ final_pos = self.prepare_collection(
+ start_angle=omega_pos,
+ nb_images=nb_images,
+ img_range=img_range,
+ first_image_no=first_image_no,
+ exp_time = exp_period - self.detector_hwobj.get_latency_time(),
+ omega_speed = omega_speed
+ )
+ # omega_speed, start_pos, final_pos, nb_images, first_image_no
+ self.collect_images(
+ omega_speed, omega_pos, final_pos, nb_images,first_image_no
+ )
+ elif exp_type == 'Characterization' and nb_images > 1: # image one by one
+ for imgno in range(nb_images):
+ # Sardana collect, run ascanct
+ self.collect_prepare_omega( init_pos, omega_speed )
+ final_pos = self.prepare_collection(
+ start_angle=omega_pos,
+ nb_images=1,
+ img_range=img_range,
+ first_image_no=first_image_no,
+ exp_time = exp_period - self.detector_hwobj.get_latency_time(),
+ omega_speed = omega_speed
+ )
+ self.collect_images(
+ omega_speed, omega_pos, final_pos, 1, first_image_no
+ )
+ first_image_no += 1
+ omega_pos += 90
+
+ #
+ #
+ # START of 20210218: Lines only necessary for ni660 collects, remove when switching to pure meshct/ascanct scans
+
+ init_pos, final_pos, total_dist, omega_speed = self.calc_omega_scan_values( omega_pos, nb_images )
+ # END of lines for ni660 scans
+ #
+ #
+
+ elif exp_type == 'Mesh': # combine all collections
+ self.logger.debug("Running a raster collection")
+ #self.write_image_headers(omega_pos)
+ self.collect_mesh(
+ 'test_pilatus_omegax_scan',
+ first_image_no,
+ fast_mxcube_motor_name,
+ fast_motor_nr_images,
+ slow_mxcube_motor_name,
+ slow_motor_nr_images,
+ self.mesh_range,
+ exp_period,
+ self.mesh_center
+ )
+ #self.finalize_mesh_scan()
+
+ # Collect images using direct configuration of the ni660 card
+ def collect_images(self, omega_speed, start_pos, final_pos, nb_images, first_image_no):
+ """
+ Run a single wedge.
+ Start position is the omega position where images should be collected.
+ It is assumed omega is already at the initial position, which comes before the start position
+ and allows the mechanics to get up to speed
+ """
+ self.logger.info("collect_images: Collecting images, by moving omega to %s" % final_pos)
+ total_time = (final_pos - self.omega_hwobj.get_value() ) / omega_speed # assumes omega is already at start position for collection
+ self.logger.info(" Total collection time = %s" % total_time)
+
+ margin_deg = 0.1
+ final_pos += margin_deg
+
+ # Now collect the data
+ self.detector_hwobj.start_collection()
+
+ if omega_speed != 0:
+ try:
+ self.logger.info(" Moving omega to final position = %.4f" % final_pos )
+ self.omega_hwobj.set_value( final_pos )
+ except Exception as e:
+ self.data_collection_failed( e, 'Cant move omega to position %.6f' % final_pos )
+ else:
+ try:
+ self.open_fast_shutter_for_internal_trigger()
+ except Exception as e:
+ self.data_collection_failed( e, 'MXCuBE is not prepared to collect still images' )
+
+ if self.current_dc_parameters['experiment_type'] == 'Helical':
+ self.wait_start_helical_motors()
+
+ self.wait_collection_done(first_image_no, nb_images + first_image_no - 1, total_time)
+
+ def collect_mesh(
+ self,
+ measurement_group, # ised only for sardana scans
+ first_image_no,
+ mesh_mxcube_fast_motor_name,
+ mesh_num_frames_per_line,
+ mesh_mxcube_slow_motor_name,
+ mesh_num_lines,
+ mesh_range,
+ time_interval,
+ mesh_center
+ ):
+ """
+ mesh scan using Sardana ascanct. It is assumed that the fast motor and slow motor move in a positive direction
+ The mesh scan does an S shape when sshape is true.
+ """
+
+ # Since pilatus3 the images do not start with number 1
+ #self.detector_hwobj.chan_saving_next_number.set_value(first_image_no)
+ # Calculate motor steps
+ mov_fast_step = mesh_range[self.mesh_fast_index] / float( mesh_num_frames_per_line )
+ mov_slow_step = 0
+ if mesh_num_lines > 1: mov_slow_step = mesh_range[self.mesh_slow_index] / float( mesh_num_lines - 1 )
+
+ local_slow_start_pos = self.scan_start_positions[ mesh_mxcube_slow_motor_name ]
+ local_first_image_no = first_image_no
+ mesh_xaloc_fast_motor_name = self.xaloc_motor_names_dict[ mesh_mxcube_fast_motor_name ]
+ fast_motor_hwo = self.scan_motors_hwobj[ mesh_mxcube_fast_motor_name ]
+ # Calculate motor margin to start up
+ # x_constant_vel = vel_0 * t_acc + 1 / 2. * (acc) * (t_acc**2)
+ #margin_mm = fast_motor_hwo.get_acceleration()
+ margin_mm = 0.025 # margin in mm for the motor to get to speed
+
+ # final_pos is end of omega range (not including safedelta)
+ detdeadtime = self.detector_hwobj.get_latency_time()
+ total_time = mesh_num_frames_per_line * mesh_num_lines * time_interval
+
+ local_fast_start_pos = self.scan_start_positions[ mesh_mxcube_fast_motor_name ]
+ local_fast_end_pos = self.scan_end_positions[ mesh_mxcube_fast_motor_name ]
+ self.scan_motors_hwobj[ mesh_mxcube_slow_motor_name ].set_value( local_slow_start_pos, timeout = 10 )
+
+ self.logger.debug("Running a raster collection, fast motor range is from %.4f to %.4f " % (local_fast_start_pos, local_fast_end_pos))
+
+ #TODO fix the numbering of the files
+ self.prepare_sardana_env( measurement_group )
+ sshape = self.mesh_sshaped_bool
+ fast_scan_direction = 1
+
+ if not self.use_sardana_scan:
+ # mv omegax to starting position
+ self.logger.debug("Moving fast scan motor %s to %.4f" % ( mesh_xaloc_fast_motor_name, local_fast_start_pos - margin_mm ) )
+ fast_motor_hwo.set_value(
+ local_fast_start_pos - margin_mm,
+ timeout = 10
+ )
+ fast_motor_hwo.wait_end_of_move( timeout = 30 )
+ fast_motor_hwo.wait_ready( timeout = 5 )
+
+ # Calculate motor velocity
+ saved_scan_motor_velocity = fast_motor_hwo.get_velocity()
+ required_scan_motor_velocity = math.fabs(
+ (local_fast_end_pos - local_fast_start_pos) / (mesh_num_frames_per_line * time_interval)
+ )
+ self.logger.debug("Calculated velocity for the fast scan motor %.4f" % ( required_scan_motor_velocity ) )
+ fast_motor_hwo.set_velocity( required_scan_motor_velocity )
+ fast_motor_hwo.wait_ready( timeout = 5 )
+
+ for lineno in range( mesh_num_lines ):
+ if self.aborted_by_user:
+ self.logger.info("User interruption of data collection during mesh scan detected, aborting mesh scan" )
+ break # cleanup will be handled in stop_collect
+ else:
+ self.logger.debug("\t line %s out of %s" % ( lineno + 1, mesh_num_lines ) )
+
+ #TODO: fix image headers
+ self.write_image_headers( 0 )
+
+ #TODO move omegax/phiy to starting position of collection (OR is this done in the MxCube sequence somewhere???
+ # Sardana will move the motor back to the inital position after the scan. Two consecuences:
+ # the fast motor will always go back the same position after each scan, so better move it to the start position of the scan to prevent excessive movements
+
+
+ self.logger.debug("mesh_xaloc_fast_motor_name = %s\nlocal_fast_start_pos = %.4f\nlocal_fast_end_pos = %.4f\nmov_fast_step = %.4f\ntime_interval - detdeadtime = %.4f\ndetdeadtime = %.4f\nfirst_image_no = %d\nmesh_num_frames_per_line = %d" % (
+ mesh_xaloc_fast_motor_name,
+ local_fast_start_pos,
+ local_fast_end_pos,
+ mov_fast_step,
+ time_interval - detdeadtime,
+ detdeadtime,
+ local_first_image_no,
+ mesh_num_frames_per_line
+ )
+ )
+ gevent.sleep(0.1)
+ if self.use_sardana_scan:
+ self.run_ascanct(
+ mesh_xaloc_fast_motor_name,
+ local_fast_start_pos,
+ local_fast_end_pos,
+ mov_fast_step,
+ time_interval,
+ detdeadtime,
+ local_first_image_no,
+ mesh_num_frames_per_line
+ )
+ else:
+ self.run_line_scan(
+ mesh_xaloc_fast_motor_name,
+ mesh_mxcube_fast_motor_name,
+ local_fast_start_pos,
+ local_fast_end_pos,
+ time_interval, # exp period
+ detdeadtime,
+ local_first_image_no,
+ mesh_num_frames_per_line,
+ margin_mm,
+ fast_scan_direction
+ )
+
+ local_first_image_no += mesh_num_frames_per_line
+ if lineno == mesh_num_lines-1:
+ break
+
+ self.scan_motors_hwobj[ mesh_mxcube_slow_motor_name ].set_value(
+ self.scan_motors_hwobj[ mesh_mxcube_slow_motor_name ].get_value() \
+ + mov_slow_step ,
+ timeout = 10
+ )
+
+ if sshape:
+ dummy = local_fast_start_pos
+ local_fast_start_pos = local_fast_end_pos
+ local_fast_end_pos = dummy
+ fast_scan_direction *= -1
+
+ self.scan_motors_hwobj[ mesh_mxcube_slow_motor_name ].wait_ready()
+ # move motors to center of scan
+ if not self.use_sardana_scan:
+ fast_motor_hwo.wait_end_of_move( timeout = ( time_interval * mesh_num_frames_per_line) + 5 )
+ fast_motor_hwo.wait_ready( timeout = (time_interval * mesh_num_frames_per_line) + 5 )
+ # Calculate motor velocity
+ self.logger.debug("Resetting velocity of the fast scan motor %.4f" % ( saved_scan_motor_velocity ) )
+ fast_motor_hwo.set_velocity( saved_scan_motor_velocity )
+ fast_motor_hwo.wait_ready( timeout = 5 )
+
+ if self.current_dc_parameters['processing_online'] != "XrayCentering":
+ self.move_motors( mesh_center.as_dict() )
+ self.go_to_sampleview()
+
+ self.wait_collection_done(first_image_no, first_image_no + ( mesh_num_frames_per_line * mesh_num_lines ) - 1, total_time + 5)
+ if self.current_dc_parameters['processing_online'] == "XrayCentering":
+ self.wait_online_processing_done()
+
+ # omega_speed and det_trigger are not necessary for sardanized collections
+ def prepare_collection(self, start_angle, nb_images, img_range, first_image_no, exp_time, omega_speed ):
+ osc_seq = self.current_dc_parameters['oscillation_sequence'][0]
+
+ total_dist = float ( nb_images * img_range )
+ final_pos = start_angle + total_dist
+
+ self.logger.info("nb_images: %s / total_distance: %s " %
+ ( nb_images, total_dist )
+ )
+
+ self.write_image_headers(start_angle)
+
+ for scanmovemotorname in self.scan_move_motor_names:
+ self.logger.info("Setting %s velocity to %.4f" % (scanmovemotorname, self.scan_velocities[scanmovemotorname]) )
+ try:
+ #self._motor_persistently_set_velocity(self.scan_motors_hwobj[scanmovemotorname], self.scan_velocities[scanmovemotorname])
+ self.scan_motors_hwobj[scanmovemotorname].set_velocity( self.scan_velocities[scanmovemotorname] )
+ except Exception as e:
+ self.logger.info("Cant set the scan velocity of motor %s" % scanmovemotorname )
+ self.data_collection_failed( e, "Cant set the scan velocity of motor %s" % scanmovemotorname )
+
+ #
+ #
+ # START of 20210218: Lines only necessary for ni660 collects, remove when switching to pure meshct/ascanct scans
+ try:
+ self.detector_hwobj.prepare_collection( nb_images, first_image_no, exp_time )
+ except Exception as e :
+ self.logger.error( str(e) )
+ self.user_logger.error("Cannot prepare the detector, does the image exist? If not, check the detector state" )
+ self.data_collection_failed( e, "Cannot prepare the detector" )
+
+ if self.current_dc_parameters['experiment_type'] != 'Mesh':
+ self.logger.debug( "Setting detector binning mode %s" % self.current_dc_parameters['detector_binning_mode'][0] )
+ self.detector_hwobj.set_binning_mode( self.current_dc_parameters['detector_binning_mode'][0] )
+ if omega_speed != 0 :
+ self.configure_ni(start_angle, total_dist, 'omega', self.omega_hwobj.get_acceleration() )
+
+ # END of lines for ni660 scans
+ #
+ #
+
+ #TODO it doesnt make sense that prepare_collection returns some of these numbers, reorganize!
+ return final_pos
+
+ def prepare_sardana_env( self, measurement_group ):
+ # This is repeated code: occurs in write_image_headers and wait_save_image
+ # Set the appropriate environment variables
+ # TODO: the time.sleeps are necessary to wait for the door to recover. Make a while loop to check for doors ON. see ./HardwareRepository/Command/Sardana.py
+ fileinfo = self.current_dc_parameters['fileinfo']
+ basedir = fileinfo['directory']
+ template = fileinfo['template'] # prefix_1_%04d.cbf
+ if self.use_sardana_scan:
+ # save the images to the write place
+ sardtemplate = template.split('%')[0] + \
+ "{index:%02d}" % int(template.split('%')[-1].split('d')[0]) + \
+ template.split('%')[-1].split('d')[1]
+ savingpattern = 'file://' + os.path.join( basedir , sardtemplate )
+ self.logger.info("savingpattern = %s" % savingpattern)
+ self.logger.info("setting ActiveMntGrp")
+ self.logger.info("setting pilatus saving pattern")
+ #self.set_pilatus_saving_pattern( measurement_group, savingpattern, wait=True)
+ self.set_pilatus_saving_pattern( 'ValueRefEnabled', True, 'pilatus_image', measurement_group, wait=True)
+ self.set_pilatus_saving_pattern( 'ValueRefPattern', savingpattern, 'pilatus_image', measurement_group, wait=True)
+ #self.logger.debug("set_pilatus_saving_pattern.doorstate = %s" % self.set_pilatus_saving_pattern.doorstate )
+ self.senv('ActiveMntGrp', measurement_group, wait=True)
+ time.sleep(0.1)
+
+
+ # save the collection details
+ self.logger.info("setting ScanDir")
+ self.senv( 'ScanDir', basedir, wait=True )
+ time.sleep(0.1)
+ self.logger.info("setting ScanFile")
+ self.senv( 'ScanFile ' + str( template.split('_%')[0] + '.dat'), wait=True )
+ time.sleep(0.1)
+
+ #def run_meshct(
+ #self,
+ #first_image_no,
+ #mesh_mxcube_horizontal_motor_name,
+ #fast_motor_nr_images,
+ #mesh_mxcube_vertical_motor_name,
+ #slow_motor_nr_images,
+ #time_interval,
+ #sshaped_bool,
+ #deadtime
+ #):
+ ##meshct
+ ##Parameters:
+ ##motor1 : (Moveable) First motor to move (generates triggers, fast motor)
+ ##m1_start_pos : (Float) Scan start position for first motor
+ ##m1_final_pos : (Float) Scan final position for first motor
+ ##m1_nr_interv : (Integer) Number of scan intervals
+ ##motor2 : (Moveable) Second motor to move
+ ##m2_start_pos : (Float) Scan start position for second motor
+ ##m2_final_pos : (Float) Scan final position for second motor
+ ##m2_nr_interv : (Integer) Number of scan intervals
+ ##integ_time : (Float) Integration time
+ ##bidirectional : (Boolean) Save time by scanning s-shaped
+ ##latency_time : (Float) Latency time
+ #self.logger.debug("meshct parameters:")
+ #self.logger.debug(" fast_motor_name: %s" % mesh_mxcube_horizontal_motor_name)
+ #self.logger.debug(" xaloc fast_motor_name: %s" % self.xaloc_motor_names_dict[mesh_mxcube_horizontal_motor_name])
+ #self.logger.debug(" fast_motor_start_pos: %s" % self.scan_start_positions[mesh_mxcube_horizontal_motor_name])
+ #self.logger.debug(" fast_motor_end_pos: %s" % self.scan_end_positions[mesh_mxcube_horizontal_motor_name])
+ #self.logger.debug(" fast_motor_nr_images: %s" % fast_motor_nr_images)
+ #self.logger.debug(" slow_motor_name: %s" % mesh_xaloc_slow_motor_name)
+ #self.logger.debug(" xaloc slow_motor_name: %s" % self.xaloc_motor_names_dict[mesh_mxcube_vertical_motor_name])
+ #self.logger.debug(" slow_motor_start_pos: %s" % self.scan_start_positions[mesh_mxcube_vertical_motor_name])
+ #self.logger.debug(" slow_motor_end_pos: %s" % self.scan_end_positions[mesh_mxcube_vertical_motor_name])
+ #self.logger.debug(" slow_motor_nr_images: %s" % slow_motor_nr_images)
+ #self.logger.debug(" time_interval: %.4f" % time_interval)
+ #self.logger.debug(" sshaped_bool: %s" % sshaped_bool)
+ #self.logger.debug(" deadtime: %.4f" % deadtime)
+
+ # TODO: include the first image as a parameter
+ #self.meshct(
+ #self.xaloc_motor_names_dict[mesh_mxcube_horizontal_motor_name],
+ #self.scan_start_positions[mesh_mxcube_horizontal_motor_name],
+ #self.scan_end_positions[mesh_mxcube_horizontal_motor_name], #start pos of fast motor for last data point
+ #fast_motor_nr_images - 1,
+ #self.xaloc_motor_names_dict[mesh_mxcube_vertical_motor_name],
+ #self.scan_start_positions[mesh_mxcube_vertical_motor_name],
+ #self.scan_end_positions[mesh_mxcube_vertical_motor_name], #start pos of slow motor for last data point
+ #slow_motor_nr_images - 1,
+ #time_interval - deadtime,
+ #sshaped_bool, # True: up and down scans, False: only up scans
+ #deadtime
+ #)
+ #total_time = fast_motor_nr_images * fast_motor_nr_images * ( time_interval + deadtime )
+
+ #self.wait_collection_done(first_image_no-1, fast_motor_nr_images * slow_motor_nr_images - 1, total_time + 5) # TODO: allow for start at higher image numbers
+ #self.collection_finished()
+
+
+ def run_ascanct(self, moveable, start_pos, final_pos, deg_interval, time_interval, deadtime, first_image_no, nb_images):
+ if self.aborted_by_user:
+ self.logger.info("User interruption of data collection during mesh scan detected, aborting ascanct" )
+ return # cleanup will be handled in data_collection_cleanup
+
+ self.logger.info( "Collecting images using the ascanct macro" )
+ total_time = time_interval * (final_pos - start_pos) / deg_interval
+
+ if final_pos < start_pos: deg_interval = - deg_interval
+
+ self.logger.debug("moveable %s" % moveable )
+ self.logger.debug("start_pos %.4f" % start_pos )
+ self.logger.debug("final_pos - deg_interval %.4f " % (final_pos - deg_interval) )
+ self.logger.debug("nb_images - 1 %d" % ( nb_images - 1 ) )
+ self.logger.debug("time_interval - deadtime %.4f" % ( time_interval - deadtime ) )
+ self.logger.debug("deadtime %.4f" % ( deadtime ) )
+
+ #TODO: Set the first image number here
+ self.mxcube_sardanascan_running = True
+ self.ascanct(moveable,
+ start_pos,
+ final_pos - deg_interval,
+ nb_images - 1,
+ time_interval - deadtime,
+ deadtime,
+ wait = True
+ )
+ self.mxcube_sardanascan_running = False
+
+
+ def run_line_scan(
+ self,
+ mesh_xaloc_fast_motor_name,
+ mesh_mxcube_fast_motor_name,
+ local_fast_start_pos,
+ local_fast_end_pos,
+ exp_period,
+ detdeadtime,
+ local_first_image_no,
+ mesh_num_frames_per_line,
+ margin_mm,
+ fast_scan_direction
+ ):
+ #initialize local pars
+ self.mxcube_sardanascan_running = True # tell mxcube that we are running a line scan, not only for sardanascan!
+ manage_shutter_locally = False #TODO: fix the shutterchannel for the ni660 poschan ctr6
+
+ # To show intermediate images
+ intermediate_image_number = local_first_image_no
+ intermediate_image_step = max( int (0.1 / exp_period), 1)
+
+ if mesh_mxcube_fast_motor_name == 'phiz':
+ manage_shutter_locally = False
+
+ fast_motor_hwo = self.scan_motors_hwobj[ mesh_mxcube_fast_motor_name ]
+ fast_motor_hwo.wait_end_of_move( timeout = ( exp_period * mesh_num_frames_per_line) + 5 )
+ fast_motor_hwo.wait_ready( timeout = (exp_period * mesh_num_frames_per_line) + 5 )
+
+ margin_mm *= fast_scan_direction
+ self.logger.debug("Fast scan motor %s at initial position %.4f" %
+ ( mesh_xaloc_fast_motor_name, fast_motor_hwo.get_value() )
+ )
+
+
+ # configure NI6602. TODO: This may not be necessary for each line. Configuring once, and then invert the line direction might be enough
+ try:
+ self.configure_ni(
+ local_fast_start_pos, # position where detector should be triggered
+ math.fabs(local_fast_end_pos - local_fast_start_pos),
+ mesh_xaloc_fast_motor_name,
+ 0.001, # override acceleration. TODO: which acceleration time is correct for omegax?
+ )
+ except Exception as e:
+ self.data_collection_failed( e, "Can't configure the trigger ni660 card")
+
+ # set collection pars in detector
+ try:
+ self.logger.debug("Preparing detector for line scan collection, lima ready is %s" % self.detector_hwobj.chan_lima_ready.get_value() )
+ self.detector_hwobj.prepare_collection( mesh_num_frames_per_line, local_first_image_no, exp_period - detdeadtime )
+ except Exception as e:
+ self.logger.error( str(e) )
+ self.user_logger.error("Cannot prepare the detector, does the image exist? If not, check the detector state" )
+ self.data_collection_failed( e, "Cannot prepare the detector, does the image exist? If not, check the detector state" )
+
+ # arm detector
+ #self.logger.debug("Arm detector for line scan collection" )
+ self.detector_hwobj.start_collection()
+ #gevent.sleep(1)
+ # mv omegax
+ if manage_shutter_locally:#TODO: fix the shutterchannel for the ni660 poschan ctr6
+ self.logger.debug("Opening shutter manually " )
+ self.open_fast_shutter_for_internal_trigger()
+ sleep_time = 0.1
+ self.logger.debug("Sleeping for %.2f secs" % sleep_time )
+ gevent.sleep( sleep_time )
+ self.logger.debug("Waking up" )
+ self.logger.debug("Moving fast scan motor %s from %.4f to end of line at %.4f" % \
+ ( mesh_xaloc_fast_motor_name, fast_motor_hwo.get_value(), local_fast_end_pos + margin_mm )
+ )
+ fast_motor_hwo.set_value(
+ local_fast_end_pos + margin_mm,
+ )
+ # wait collection_done
+ #fast_motor_hwo.wait_end_of_move( timeout = ( exp_period * mesh_num_frames_per_line) + 1 )
+ #fast_motor_hwo.wait_ready( timeout = (exp_period * mesh_num_frames_per_line) + 5 )
+ while fast_scan_direction * ( local_fast_end_pos - fast_motor_hwo.get_value() ) > 0.001 and not self.aborted_by_user:
+ time.sleep(0.005)
+ intermediate_image = self.get_image_file_name( intermediate_image_number )
+ #self.logger.debug("Waiting for intermediate image %s" % ( intermediate_image ) )
+ if intermediate_image_number < mesh_num_frames_per_line:
+ #self.logger.debug(" waiting for image on disk: %s" % intermediate_image)
+ while not os.path.exists(intermediate_image) and not self.aborted_by_user:
+ time.sleep(0.005)
+ self.image_tracking_hwobj.load_image(intermediate_image)
+ intermediate_image_number += intermediate_image_step
+
+ if manage_shutter_locally:#TODO: fix the shutterchannel for the ni660 poschan ctr6
+ self.fastshut_hwobj.close() #TODO: fix the shutterchannel for the ni660 poschan ctr6
+ #self.detector_hwobj.wait_running(timestep = 0.025, timeout = 5)
+ #self.detector_hwobj.wait_standby(timestep = 0.05, timeout = mesh_num_frames_per_line * exp_period + 5)
+ #self.logger.debug("detector cam_state %s, lima ready %s, " %
+ #(self.detector_hwobj.get_cam_state(), self.detector_hwobj.chan_lima_ready.get_value() )
+ #)
+ self.mxcube_sardanascan_running = False # tell mxcube that we are running a line scan, not only for sardanascan!
+
+ #self.detector_hwobj.wait_ready()
+ self.unconfigure_ni()
+ #self.detector_hwobj.stop_collection()
+
+ def calc_omega_scan_values( self, omega_start_pos, nb_images ):
+ """
+ Calculates the values at which the omega should start and end so that
+ during collection it has a constant speed
+ """
+ osc_seq = self.current_dc_parameters['oscillation_sequence'][0]
+
+ img_range = osc_seq['range']
+ exp_time = osc_seq['exposure_time']
+
+ total_dist = float ( nb_images * img_range )
+ total_time = float ( nb_images * exp_time )
+ omega_acceltime = self.omega_hwobj.get_acceleration()
+ omega_speed = float( total_dist / total_time )
+
+ # TODO: for mesh scans, this range is way to big
+ safe_delta = 1
+ if self.current_dc_parameters['experiment_type'] == 'Mesh':
+ safe_delta = 0.5
+ else:
+ safe_delta = 9.0 * omega_speed * omega_acceltime
+
+ init_pos = omega_start_pos - safe_delta
+ final_pos = omega_start_pos + total_dist + safe_delta #TODO adjust the margins to the minimum necessary
+
+ return ( init_pos, final_pos, total_dist, omega_speed )
+
+
+ def collect_prepare_omega(self, omega_pos, omega_speed):
+ '''
+ Prepares omega for sweep.
+ - Sets the velocity to the fast speed
+ - Moves omega to the initial position ( required by ni card)
+ - Sets the velocity to the collect speed
+ '''
+
+ try:
+ self.logger.info("Setting omega velocity to its nominal value")
+ self.omega_hwobj.set_velocity( 60 )
+ except Exception as e :
+ self.logger.error("Error setting omega velocity, state is %s" % str(self.omega_hwobj.get_state()))
+ self.data_collection_failed( e, 'Omega velocity could not be set' )
+
+ self.logger.info("Moving omega to initial position %s" % omega_pos)
+ try:
+ if math.fabs(self.omega_hwobj.get_value() - omega_pos) > 0.0001:
+ self.omega_hwobj.set_value( omega_pos, timeout = 30 )
+ # TODO: check why both of the following checks are necessary for the omega to be ready
+ self.omega_hwobj.wait_end_of_move( timeout = 30 )
+ self.omega_hwobj.wait_ready( timeout = 2 )
+
+ except Exception as e :
+ self.logger.info("Omega state is %s" % str(self.omega_hwobj.get_state()))
+ self.data_collection_failed( e, 'Omega position could not be set' )
+
+ self.logger.info("Setting omega velocity to %s and is ready %s" % (omega_speed, self.omega_hwobj.is_ready() ) )
+ self.logger.info("Omega state is %s, ready is %s" % (str(self.omega_hwobj.get_state()), self.omega_hwobj.is_ready()) )
+
+ try:
+ self.omega_hwobj.set_velocity( omega_speed )
+ except Exception as e:
+ self.logger.debug("Omega state is %s" % str(self.omega_hwobj.get_state()))
+ self.data_collection_failed( e, "Cannot set the omega velocity to %s" % omega_speed )
+
+ return
+
+ def wait_start_helical_motors( self):
+ timestep = 1 # secs
+ timeout = 10 # secs
+ self.detector_hwobj.wait_running( timestep, timeout ) # once the detector is running (collection started), start the helical motors
+ for scanmovemotorname in self.scan_move_motor_names:
+ try:
+ # It might be faster (but more dangerous)
+ self.scan_motors_hwobj[scanmovemotorname].position_channel.set_value( self.scan_end_positions[scanmovemotorname] )
+ # the safer option:
+ #self.scan_motors_hwobj[scanmovemotorname].set_value( self.scan_end_positions[scanmovemotorname] )
+
+ #self.logger.info('Moving motor %s from %.4f to final position %.4f at %.6f velocity' %
+ # (scanmovemotorname, self.scan_start_positions[scanmovemotorname],
+ # self.scan_end_positions[scanmovemotorname],
+ # self.scan_velocities[scanmovemotorname] ) )
+ except Exception as e:
+ self.data_collection_failed( e, 'Cannot move the helical motor %s to its end position' % scanmovemotorname )
+
+
+
+ def data_collection_failed(self, exception, failed_msg="XalocCollect: data_collection_failed"):
+ self.user_logger.error(failed_msg)
+ self.logger.debug("Data collection failed with error %s" % str( exception ) )
+ self.logger.debug(" Initiating recovery sequence")
+ #TODO: this fails with list index out of range QueueManager line 149.
+ # This seems to be related with set_sardana_collect_env (see data_path_widget)
+ raise exception
+
+ def prepare_acquisition(self):
+ """
+ checks shutters, moves supervisor to collect phase, prepares detector and calculates omega start values
+ omega_start_pos should be the value at which the collection starts
+ """
+
+ fileinfo = self.current_dc_parameters['fileinfo']
+ basedir = fileinfo['directory']
+ self.check_directory(basedir)
+
+ # Save omega velocity
+ # self.saved_omega_velocity = self.omega_hwobj.get_velocity()
+ # Better use it nominal velocity (to be properly defined in Sardana motor)
+ # Ensure omega has its nominal velocity to go to the initial position
+ # We have to ensure omega is not moving when setting the velocity
+
+ # create directories if needed
+
+ # check fast shutter closed. others opened
+
+ # go to collect phase
+ if not self.is_collect_phase():
+ self.logger.info("Supervisor not in collect phase, asking to go...")
+ success = self.go_to_collect()
+ if not success:
+ msg = "Supervisor cannot set COLLECT phase. Issue an Init in the diff and supervisor devices. Omegax should be between -1 and +1 mm"
+ self.data_collection_failed( Exception(msg), msg )
+
+ if self.bypass_shutters:
+ self.user_logger.warning("Shutters BYPASSED")
+ else:
+ _ok, failed = self.check_shutters()
+ if not _ok:
+ msg = "Shutter(s) {} NOT READY".format(failed)
+ self.user_logger.error(msg)
+ return _ok, msg
+ else:
+ self.user_logger.info("Shutters READY")
+
+ gevent.sleep(1)
+ self.logger.info(
+ "Waiting diffractometer ready (is %s)" % str(self.diffractometer_hwobj.current_state))
+ self.diffractometer_hwobj.wait_device_ready(timeout=10) # Is an exception generated upon timeout???
+ self.logger.info("Diffractometer is now ready.")
+
+ detok = self.detector_hwobj.get_cam_state() == 'STANDBY'
+ self.logger.info( 'Detector ok %s, cam_state = %s' % ( detok, self.detector_hwobj.get_cam_state() ) )
+
+ if not detok:
+ msg = "Cannot prepare the detector for acquisition, check the Pilatus cam_state. "
+ if self.detector_hwobj.get_cam_state() != 'SETTING_ENERGY':
+ msg += "Issuing a reset command in bl13/eh/pilatuslima, try again"
+ self.detector_hwobj.stop_acquisition()
+ else: msg += "The Pilatus is setting the energy, please be patient!!!"
+ self.user_logger.info( msg )
+ self.data_collection_failed( Exception(msg), msg )
+
+ return
+
+ def prepare_detector_for_acquisition(self):
+
+ detok = False
+ try:
+ detok = self.detector_hwobj.prepare_acquisition(self.current_dc_parameters)
+ self.logger.info("Prepared detector for acquistion, detok = %s" % str( detok ) )
+ except Exception as e:
+ msg = "Cannot prepare the detector for acquisition"
+ self.logger.error( msg )
+ self.data_collection_failed( e, msg )
+
+ if not detok:
+ msg = "Cannot prepare the detector for acquisition"
+ self.logger.error( msg )
+ self.data_collection_failed( Exception(msg), msg )
+
+ return detok
+
+ def write_image_headers(self, start_angle):
+ # maintain for sardana scans?
+ fileinfo = self.current_dc_parameters['fileinfo']
+ basedir = fileinfo['directory']
+
+ exp_type = self.current_dc_parameters['experiment_type']
+ osc_seq = self.current_dc_parameters['oscillation_sequence'][0]
+
+ nb_images = osc_seq['number_of_images']
+ # start_angle = osc_seq['start']
+
+ try: img_range = osc_seq['range']
+ except: img_range = 0
+
+ if exp_type == "Characterization":
+ #TODO set spacing according to the spacing used in collect, not a fixed value
+ angle_spacing = 90
+ else:
+ angle_spacing = img_range
+
+ exp_time = osc_seq['exposure_time']
+
+ # PROGRAM Image Headers
+ #latency_time = 0.003
+ latency_time = self.detector_hwobj.get_latency_time()
+ limaexpt = exp_time - latency_time
+
+ self.image_headers = {}
+
+ angle_info = [start_angle, img_range, angle_spacing]
+
+ self.image_headers['nb_images'] = nb_images
+ self.image_headers['Exposure_time'] = "%.4f" % limaexpt
+ self.image_headers['Exposure_period'] = "%.4f" % exp_time
+ self.image_headers['Start_angle'] = "%f deg." % start_angle
+ self.image_headers['Angle_increment'] = "%f deg." % img_range
+ self.image_headers['Wavelength'] = "%f A" % self.energy_hwobj.get_wavelength()
+
+ self.image_headers["Detector_distance"] = "%.5f m" % (
+ self.detector_hwobj.get_distance() / 1000.0)
+ self.image_headers["Detector_Voffset"] = '0 m'
+
+ beamx, beamy = self.detector_hwobj.get_beam_position()
+ self.image_headers["Beam_xy"] = "(%.2f, %.2f) pixels" % (beamx, beamy)
+
+ self.image_headers["Filter_transmission"] = "%.4f" % (
+ self.transmission_hwobj.get_value() / 100.0)
+ self.image_headers["Flux"] = "%.4g" % self.flux_hwobj.get_flux()
+ self.image_headers["Detector_2theta"] = "0.0000"
+ self.image_headers["Polarization"] = "0.99"
+ self.image_headers["Alpha"] = '0 deg.'
+
+ # TODO add XALOC phi (MXCuBE kappa_phi) to image headers
+ self.image_headers["Kappa"] = "%.4f deg." % self.chan_kappa_pos.get_value()
+ self.image_headers["Phi"] = "%.4f deg." % self.chan_phi_pos.get_value()
+
+ self.image_headers["Chi"] = "0 deg."
+ self.image_headers["Oscillation_axis"] = "omega (X, CW)"
+ self.image_headers["N_oscillations"] = '1'
+ self.image_headers["Detector_2theta"] = "0.0000 deg"
+
+ self.image_headers["Image_path"] = ': %s' % basedir
+
+ self.image_headers["Threshold_setting"] = '%0f eV' %\
+ self.detector_hwobj.get_threshold()
+ #self.image_headers["Gain_setting"] = '%s (vtr)' % str(
+ #self.detector_hwobj.get_gain())
+
+ self.image_headers["Tau"] = '%s s' % str(199.1e-09)
+ self.image_headers["Count_cutoff"] = '%s counts' % str(370913)
+ self.image_headers["N_excluded_pixels"] = '= %s' % str(1178)
+ self.image_headers["Excluded_pixels"] = ': %s' % str("/var/local/lib/dectris/config/calibration/Mask/badpix_mask.tif")
+ #### TODO find trim file for pilatus3X
+ #self.image_headers["Trim_file"] = ': %s' % str(
+ #"p6m0108_E12661_T6330_vrf_m0p20.bin") #TODO: pick up the true trim file!!!!!
+
+ self.detector_hwobj.set_image_headers(self.image_headers, angle_info)
+
+ def wait_collection_done(self, first_image_no, last_image_no, total_time):
+
+ self.logger.info(" Total acquisition time = %.2f s" % total_time )
+ self.logger.info(" last_image_no = %d" % last_image_no )
+
+ self.wait_save_image(first_image_no)
+ if last_image_no != first_image_no:
+ #self.wait_save_image( last_image_no, timeout = total_time+60, show_intermediates = True )
+ self.wait_all_images( timeout = total_time+60, show_intermediates = True )
+ else:
+ if not self.omega_hwobj.is_ready():
+ self.omega_hwobj.wait_ready( timeout= total_time + 5 )
+
+ #self.logger.info(" wait_collection_done last image found" ) # doesnt make much sense when user aborts collection
+ for motorname in self.scan_move_motor_names:
+ self.logger.info(" Motor %s position = %.2f" % ( motorname, self.scan_motors_hwobj[motorname].get_value() ) )
+
+ # Wait for omega to stop moving, it continues further than necessary
+ if not self.aborted_by_user:
+ if self.omega_hwobj.is_ready(): self.omega_hwobj.wait_ready(timeout=40)
+ # Wait for any other motors to stop moving
+ for motorname in self.scan_move_motor_names:
+ if not self.scan_motors_hwobj[motorname].is_ready():
+ self.scan_motors_hwobj[motorname].wait_ready(timeout=40)
+ # Make sure the detector is ready (in stand by and not moving)
+ self.detector_hwobj.wait_ready()
+
+ def wait_save_image(self, frame_number, timeout=600, show_intermediates = False):
+
+ full_path = self.get_image_file_name( frame_number )
+ intermediate_time_step = 0.1
+
+ start_wait = time.time()
+
+ self.logger.debug(" waiting for image on disk: %s with timeout %.2f" % ( full_path, timeout ) )
+
+ while not os.path.exists(full_path) and not self.aborted_by_user:
+ # TODO: review next line for NFTS related issues.
+ if (time.time() - start_wait) > timeout:
+ self.logger.debug(" giving up waiting for image")
+ cam_state = self.detector_hwobj.chan_cam_state.get_value()
+ acq_status = self.detector_hwobj.chan_acq_status.get_value()
+ fault_error = self.detector_hwobj.chan_acq_status_fault_error.get_value()
+ self.detector_hwobj.get_saving_statistics()
+ msg = "cam_state = {}, acq_status = {}, fault_error = {}".format(
+ cam_state, acq_status, fault_error)
+ self.user_logger.error("Incomplete data collection")
+ self.user_logger.error(msg)
+
+ self.data_collection_failed( RuntimeError(msg), msg )
+ #return False
+ #self.logger.debug("self.aborted_by_user %s" % str(self.aborted_by_user) )
+ time.sleep( intermediate_time_step )
+ if show_intermediates:
+ intermediate_image_number = int(
+ (time.time() - start_wait) /
+ self.current_dc_parameters['oscillation_sequence'][0]['exposure_time']
+ )
+ intermediate_image = self.get_image_file_name( intermediate_image_number )
+ if intermediate_image_number < frame_number:
+ #self.logger.debug(" waiting for image on disk: %s" % intermediate_image)
+ while not os.path.exists(intermediate_image) and not self.aborted_by_user:
+ time.sleep(0.01)
+ self.image_tracking_hwobj.load_image(intermediate_image)
+
+ if os.path.exists(full_path): self.image_tracking_hwobj.load_image(full_path)
+ self.detector_hwobj.get_saving_statistics()
+
+ # self.last_saved_image = fullpath
+
+ # generate thumbnails
+ fileinfo = self.current_dc_parameters['fileinfo']
+ template = fileinfo['template']
+ filename = template % frame_number
+ archive_dir = fileinfo['archive_directory']
+ self.check_directory(archive_dir)
+
+ jpeg_filename = os.path.splitext(filename)[0] + ".jpeg"
+ thumb_filename = os.path.splitext(filename)[0] + ".thumb.jpeg"
+
+ thumb_fullpath = os.path.join(archive_dir, thumb_filename)
+ jpeg_fullpath = os.path.join(archive_dir, jpeg_filename)
+
+ self.logger.debug(
+ " creating thumbnails for %s in: %s and %s" %
+ (full_path, jpeg_fullpath, thumb_fullpath))
+ cmd = "adxv -sa -jpeg_scale 0.4 %s %s" % (full_path, jpeg_fullpath)
+ os.system(cmd)
+ cmd = "adxv -sa -jpeg_scale 0.1 %s %s" % (full_path, thumb_fullpath)
+ os.system(cmd)
+
+ self.logger.debug(" writing thumbnails info in LIMS")
+ self.store_image_in_lims(frame_number)
+
+ if not self.aborted_by_user: self.logger.debug(" Found image on disk: %s" % full_path)
+
+ return True
+
+
+ def wait_all_images(self, timeout=600, show_intermediates = False):
+
+ intermediate_time_step = 0.1
+ collect_dir = self.current_dc_parameters['fileinfo']['directory']
+ file_template = self.current_dc_parameters['fileinfo']['template']
+ glob_file_template = file_template.replace('%04d','*')
+ number_of_images = self.current_dc_parameters['oscillation_sequence'][0]['number_of_images']
+
+ start_wait = time.time()
+
+ self.logger.debug(" waiting for %d images with pattern %s with timeout %.2f" % \
+ ( number_of_images, os.path.join(collect_dir,glob_file_template), timeout )
+ )
+
+ while len(glob.glob(os.path.join(collect_dir,glob_file_template) )) < number_of_images \
+ and not self.aborted_by_user:
+ # TODO: review next line for NFTS related issues.
+ if (time.time() - start_wait) > timeout:
+ self.logger.debug(" giving up waiting for image")
+ cam_state = self.detector_hwobj.chan_cam_state.get_value()
+ acq_status = self.detector_hwobj.chan_acq_status.get_value()
+ fault_error = self.detector_hwobj.chan_acq_status_fault_error.get_value()
+ self.detector_hwobj.get_saving_statistics()
+ msg = "cam_state = {}, acq_status = {}, fault_error = {}".format(
+ cam_state, acq_status, fault_error)
+ self.user_logger.error("Incomplete data collection")
+ self.user_logger.error(msg)
+
+ self.data_collection_failed( RuntimeError(msg), msg )
+ #return False
+ #self.logger.debug("self.aborted_by_user %s" % str(self.aborted_by_user) )
+ time.sleep( intermediate_time_step )
+ if show_intermediates:
+ intermediate_image_number = int(
+ (time.time() - start_wait) /
+ self.current_dc_parameters['oscillation_sequence'][0]['exposure_time']
+ )
+ intermediate_image = self.get_image_file_name( intermediate_image_number )
+ if intermediate_image_number < number_of_images:
+ #self.logger.debug(" waiting for image on disk: %s" % intermediate_image)
+ while not os.path.exists(intermediate_image) and not self.aborted_by_user:
+ time.sleep(0.01)
+ self.image_tracking_hwobj.load_image(intermediate_image)
+
+ full_path = self.get_image_file_name( number_of_images )
+ if os.path.exists(full_path): self.image_tracking_hwobj.load_image(full_path)
+ self.detector_hwobj.get_saving_statistics()
+
+ # generate thumbnails
+ fileinfo = self.current_dc_parameters['fileinfo']
+ filename = file_template % number_of_images
+ archive_dir = self.current_dc_parameters['fileinfo']['archive_directory']
+ self.check_directory(archive_dir)
+
+ jpeg_filename = os.path.splitext(filename)[0] + ".jpeg"
+ thumb_filename = os.path.splitext(filename)[0] + ".thumb.jpeg"
+
+ thumb_fullpath = os.path.join(archive_dir, thumb_filename)
+ jpeg_fullpath = os.path.join(archive_dir, jpeg_filename)
+
+ self.logger.debug(
+ " creating thumbnails for %s in: %s and %s" %
+ (full_path, jpeg_fullpath, thumb_fullpath))
+ cmd = "adxv -sa -jpeg_scale 0.4 %s %s" % (full_path, jpeg_fullpath)
+ os.system(cmd)
+ cmd = "adxv -sa -jpeg_scale 0.1 %s %s" % (full_path, thumb_fullpath)
+ os.system(cmd)
+
+ self.logger.debug(" writing thumbnails info in LIMS")
+ self.store_image_in_lims( number_of_images )
+
+ if not self.aborted_by_user: self.logger.debug(" Found image on disk: %s" % full_path)
+
+ return True
+
+ def get_image_file_name( self, frame_number ):
+ fileinfo = self.current_dc_parameters['fileinfo']
+ basedir = fileinfo['directory']
+ template = fileinfo['template']
+
+ filename = template % frame_number
+ full_path = os.path.join(basedir, filename)
+
+ return full_path
+
+ def check_shutters(self):
+
+ # Shutters ready: 1, 1, 1, 1
+
+ # fast shutter closed: State = 1
+ # slow shutter is close: State = 0
+ # photon shutter is close: State = 0
+ # front end is close: State = 0
+ fast_shutter = self.fastshut_hwobj.get_state()
+ slow_shutter = self.slowshut_hwobj.get_state()
+ photon_shutter = self.photonshut_hwobj.get_state()
+ front_end = self.frontend_hwobj.get_state()
+
+ shutters = ['fast', 'slow', 'photon', 'front-end']
+ states = [fast_shutter, slow_shutter, photon_shutter, front_end]
+
+ failed = [s for s, state in zip(shutters, states) if not state]
+
+ self.logger.debug("fast shutter state is: %s" % fast_shutter)
+ self.logger.debug("slow shutter state is: %s" % slow_shutter)
+ self.logger.debug("photon shutter state is: %s" % photon_shutter)
+ self.logger.debug("front_end state is: %s" % front_end)
+
+ return all([fast_shutter, slow_shutter, photon_shutter, front_end]), failed
+
+ def get_image_headers(self):
+ headers = []
+ return headers
+
+ def data_collection_cleanup(self):
+ # this is called from AbstractCollect.do_collect, so it is always called and will be the last step in the data collection
+
+ self.logger.debug("XalocCollect data_collection_cleanup started")
+
+ # Not sure what the following line does, does it remove any errors??
+ if self.detector_hwobj.get_cam_state() == 'ERROR': self.detector_hwobj.stop_collection()
+
+ self.logger.debug("XalocCollect Unconfiguring the NI")
+ self.unconfigure_ni()
+
+ self.logger.info('Initial velocity %s' % self.scan_init_velocities)
+ try:
+ self.omega_hwobj.stop()
+ self.omega_hwobj.set_velocity(60)
+ #if self.omega_init_vel != None: # Sometimes, data collections fails before the initial velocities are set, eg when supervisor or diff DS are in alarm
+ #self.logger.info(' Setting velocity of motor omega')
+ #self.logger.info(' to initial velocity %.6f' % self.omega_init_vel )
+ #self.omega_hwobj.set_velocity( self.omega_init_vel )
+ except:
+ #self.logger.info(' Setting velocity of motor omega to %.1f failed' % self.omega_init_vel)
+ self.logger.info(' Setting velocity of motor omega to 60 deg/secs failed')
+
+ for motorname in self.scan_move_motor_names:
+ self.logger.info(' Setting velocity of motor %s' % motorname )
+ self.logger.info(' to initial velocity %.6f' % self.scan_init_velocities[motorname] )
+ #self._motor_persistently_set_velocity( self.scan_motors_hwobj[motorname], self.scan_init_velocities[motorname] )
+ self.scan_motors_hwobj[motorname].set_velocity( self.scan_init_velocities[motorname] )
+
+ try:
+ #Move omega to initial position to speed up collection process
+ #if self.omega_init_pos != None: # Sometiemes collection fails before omega_init_pos is set, no need to move in those cases
+ #self.omega_hwobj.set_value( self.omega_init_pos )
+ if self.current_dc_parameters['experiment_type'] in ['OSC','Helical']:
+ self.logger.debug("Cleanup: moving omega to zero")
+ self.omega_hwobj.set_value(0)
+ except:
+ self.logger.debug("Omega needs to be stopped before restoring initial position, will try this now")
+ self.omega_hwobj.stop()
+ self.omega_hwobj.set_velocity( self.omega_init_vel )
+ #self.omega_hwobj.set_value(self.omega_init_pos)
+ self.omega_hwobj.set_value( 0 )
+
+ self.scan_delete_motor_data()
+ self.fastshut_hwobj.close() # RB: not sure if it closes when unconfiguring it, just in case
+
+ self._collecting = False
+ self.mxcube_sardanascan_running = False
+ self.aborted_by_user = False
+
+ self.remove_symbolic_link()
+ self.logger.debug("Xaloc data_collection_cleanup finished")
+
+ def check_directory(self, basedir):
+ if not os.path.exists(basedir):
+ try:
+ os.makedirs(basedir)
+ except OSError as e:
+ import errno
+ if e.errno != errno.EEXIST:
+ self.user_logger.error('Directories cannot be made, are the lockdown settings correct?')
+ self.user_logger.error('Directories cannot be made, are the lockdown settings correct?')
+ self.data_collection_failed( e, str(e) )
+
+ def collect_finished(self, green):
+ self.user_logger.info("Data collection finished")
+
+ def go_to_collect(self, timeout=180):
+ self.wait_supervisor_ready(timeout=timeout)
+ self.logger.debug("Sending supervisor to collect phase")
+ self.supervisor_hwobj.go_collect()
+
+ gevent.sleep(0.5)
+
+ t0 = time.time()
+ while True:
+ super_state = self.supervisor_hwobj.get_state()
+ #super_state2 = self.supervisor_hwobj.current_state
+
+ #self.logger.debug("Supervisor get_state() is %s" % super_state)
+ #self.logger.debug("Supervisor current current_state is %s" % super_state2)
+ #TODO: review, sometimes get_current_phase returns None
+ try:
+ cphase = self.supervisor_hwobj.get_current_phase().upper()
+ #self.logger.debug("Supervisor current phase is %s" % cphase)
+ except:
+ cphase = None
+
+ if super_state == DevState.ON and cphase == "COLLECT":
+ break
+ if time.time() - t0 > timeout:
+ msg = "Timeout sending supervisor to collect phase"
+ self.logger.debug(msg)
+ self.data_collection_failed( RuntimeError(msg), msg )
+ if self.aborted_by_user:
+ msg = "Collection aborted by user"
+ self.logger.debug(msg)
+ self.data_collection_failed( Exception(msg), msg )
+ gevent.sleep(0.5)
+
+ self.logger.debug("New supervisor phase is %s (Collect phase was requested)" % cphase)
+ self._collecting = True
+
+ return self.is_collect_phase()
+
+ def is_collect_phase(self):
+ self.logger.debug("In is_collect_phase method")
+ try:
+ return (self.supervisor_hwobj.get_current_phase().upper() == "COLLECT" and self._collecting == True ) # RB added the self._collecting, check if it works
+ #return self.supervisor_hwobj.get_current_phase().upper() == "COLLECT"
+ except Exception as e:
+ msg = "Cannot return current phase from supervisor. Please, restart MXCuBE."
+ self.user_logger.error(msg)
+ self.data_collection_failed( e, msg )
+
+ def go_to_sampleview(self, timeout=180):
+ self.wait_supervisor_ready()
+ self.logger.debug("Sending supervisor to sample view phase")
+ self.close_fast_shutter()
+ #if not self.supervisor_hwobj.is_fast_shutter_in_collect_position():
+ self.close_safety_shutter()
+
+ self.supervisor_hwobj.go_sample_view()
+
+ gevent.sleep(0.5)
+
+ t0 = time.time()
+ while True:
+ #TODO: review, some calls return None for get_current_phase()
+ try:
+ super_state = self.supervisor_hwobj.get_state()
+ cphase = self.supervisor_hwobj.get_current_phase().upper()
+ except:
+ super_state = cphase = None
+ if super_state != DevState.MOVING and cphase == "SAMPLE":
+ break
+ if time.time() - t0 > timeout:
+ self.logger.debug("Timeout sending supervisor to sample view phase")
+ break
+ gevent.sleep(0.5)
+
+ self.logger.debug("New supervisor phase is %s" % cphase)
+
+ return self.is_sampleview_phase()
+
+ def is_sampleview_phase(self):
+ return self.supervisor_hwobj.get_current_phase().upper() == "SAMPLE"
+
+ def wait_supervisor_ready(self, timeout=30):
+ self.logger.debug("Waiting to supervisor ready")
+
+ gevent.sleep(0.5)
+
+ t0 = time.time()
+ while True:
+ super_state = self.supervisor_hwobj.get_state()
+ self.logger.debug("Supervisor state is %s" % super_state)
+ if super_state == DevState.ON:
+ break
+ elif super_state == None:
+ self.logger.debug("Supervisor state is None, probably a temporary problem")
+ #break
+ if time.time() - t0 > timeout:
+ msg = "Timeout waiting for supervisor ready, call your LC"
+ self.user_logger.error(msg)
+ self.data_collection_failed( RuntimeError("Supervisor cannot be operated (state %s)" % super_state), msg)
+ break
+ gevent.sleep(0.5)
+ gevent.sleep(1)
+
+
+ def configure_ni(self, start_scan_pos, scan_total_dist, xaloc_scan_motor_name,
+ override_motor_acceleration):
+ """
+ Sets up the ni660 for triggering detector and fast shutter
+ the current position of the xaloc_scan_motor_name is used to calculate trigger positions
+ The motor should be positioned correctly to
+ - leave sufficient distance to accelerate
+ - open the fast shutter
+
+ """
+ fast_shutter_delay_time = self.fastshut_hwobj.get_shutter_delay_sec()
+ self.logger.debug(
+ "Configuring NI660 with pars %.5f %.4f %.4f 0 1 %s %.4f" %
+ (fast_shutter_delay_time, start_scan_pos, scan_total_dist,
+ xaloc_scan_motor_name, override_motor_acceleration)
+ )
+
+ self.cmd_ni_conf(
+ fast_shutter_delay_time,
+ start_scan_pos, # motor scan start position
+ scan_total_dist, # distance covered by the scan
+ 0, # trigger_low distance
+ 1, # trigger count
+ xaloc_scan_motor_name, # for now either omega or omegax
+ override_motor_acceleration, # if acceleration is not correct in sardana
+ wait = True
+ )
+
+ def unconfigure_ni(self):
+ self.cmd_ni_unconf( wait = True )
+ # END of lines for ni660 scans
+ #
+ #
+
+
+ def open_safety_shutter(self):
+ """ implements prepare_shutters in collect macro """
+
+ # prepare ALL shutters
+
+ if self.fastshut_hwobj.get_state() != 0:
+ self.fastshut_hwobj.close()
+
+ if self.slowshut_hwobj.get_state() != 1:
+ self.slowshut_hwobj.open()
+
+ if self.photonshut_hwobj.get_state() != 1:
+ self.photonshut_hwobj.open()
+
+ if self.frontend_hwobj.get_state() != 0:
+ self.frontend_hwobj.open()
+
+ def open_detector_cover(self):
+ self.supervisor_hwobj.open_detector_cover()
+
+ def open_fast_shutter_for_internal_trigger(self):
+ # self.fastshut_hwobj.open()
+ # this function is empty for Xaloc. we are not opening the fast shutter.
+ # on the contrary open_safety_shutter (equivalent to prepare_shutters in
+ # original collect macro will first close the fast shutter and open the
+ # other three
+ if self.is_collect_phase():
+ self.fastshut_hwobj.open()
+
+ def close_fast_shutter(self):
+ self.fastshut_hwobj.cmd_out()
+
+ def close_safety_shutter(self):
+ # we will not close safety shutter during collections
+ pass
+
+ def close_detector_cover(self):
+ # we will not close detector cover during collections
+ # self.supervisor.close_detector_cover()
+ pass
+
+ def scan_delete_motor_data(self):
+ self.scan_move_motor_names = []
+ self.scan_velocities = {}
+ self.scan_end_positions = {}
+ self.scan_start_positions = {}
+ self.scan_init_positions = {}
+
+ def scan_delete_motor_data(self):
+ self.scan_move_motor_names = []
+ self.scan_velocities = {}
+ self.scan_end_positions = {}
+ self.scan_start_positions = {}
+ self.scan_init_positions = {}
+
+ def set_helical_pos(self, arg):
+ """
+ Descript. : 8 floats describe
+ p1AlignmY, p1AlignmZ, p1CentrX, p1CentrY
+ p2AlignmY, p2AlignmZ, p2CentrX, p2CentrY
+ At XALOC, the phiz motor is not moved
+ """
+ self.logger.info('Setting helical motor positions')
+ self.logger.info('Helical motor positions %s' % str(arg))
+ try:
+ for motorname in self.scan_all_motor_names: # phiy (omegax), phiz (omegaz), sampx (centx), sampy (centy)
+ if arg["1"][motorname] != None: self.scan_start_positions[motorname] = arg["1"][motorname]
+ else: self.logger.info('Helical motor %s not added, position is None' % arg["1"][motorname])
+ if arg["2"][motorname] != None: self.scan_end_positions[motorname] = arg["2"][motorname]
+ else: self.logger.info('Helical motor %s not added, position is None' % arg["2"][motorname])
+ except Exception as e :
+ self.logger.error('FAILED TO SET HELICAL MOTOR POSITIONS')
+ self.data_collection_failed( e, "Cannot interpret helical motor start/end positions")
+
+ def set_scan_move_motors(self, scan_start_pos, scan_end_pos, cutoff=0.005): #cutoff in microns
+ self.logger.info(' Checking which motors should move for the helical data collection')
+ for motorname in self.scan_all_motor_names:
+ self.logger.info(' Motor : %s' % motorname)
+ self.logger.info(' Start pos: %.4f' % scan_start_pos[motorname])
+ self.logger.info(' End pos : %.4f' % scan_end_pos[motorname])
+ self.logger.info(' Diff pos : %.4f' % math.fabs(scan_start_pos[motorname] - scan_end_pos[motorname]))
+ if math.fabs(scan_start_pos[motorname] - scan_end_pos[motorname]) > cutoff and scan_start_pos[motorname] != None and scan_end_pos[motorname] != None:
+ self.logger.info(' Add helical motor %s' % motorname)
+ self.scan_move_motor_names.append(motorname)
+
+ def calculate_scan_velocities(self, scan_start_pos, scan_end_pos, total_collection_time):
+ self.logger.info(' Calculating the velocities for the helical data collection')
+ self.logger.info(' Calculating the required velocities for the helical motors')
+ scan_velocities = {}
+ for motorname in self.scan_move_motor_names:
+ self.logger.info(' Motor : %s' % motorname)
+ self.logger.info(' Start pos: %.4f' % scan_start_pos[motorname])
+ self.logger.info(' End pos : %.4f' % scan_end_pos[motorname])
+ scan_velocities[motorname] = math.fabs ( scan_start_pos[motorname] - scan_end_pos[motorname] ) / total_collection_time
+ self.logger.info(' Velocity : %.7f' % scan_velocities[motorname])
+
+ return scan_velocities
+
+ def check_scan_velocities(self, scan_velocities):
+ self.logger.info(' Checking the velocities for the helical data collection')
+ scan_motor_velo_keys = scan_velocities.keys()
+ self.logger.info(' Helical motor list: %s' % scan_motor_velo_keys )
+ scan_motor_too_fast = [] # list of motors that cannot go fast enough for the proposed scan
+ scan_motor_too_slow = [] # list of motors that cannot go slow enough for the proposed scan
+ for motorname in scan_motor_velo_keys:
+ self.logger.info(' %7s velocity : %.4f' % (motorname, scan_velocities[motorname]) )
+ if scan_velocities[motorname] < self.scan_motors_min_velocity[motorname]:
+ scan_motor_too_slow.append(motorname)
+ elif scan_velocities[motorname] > self.scan_motors_max_velocity[motorname]:
+ scan_motor_too_fast.append(motorname)
+
+ for motorname in scan_motor_too_fast:
+ self.logger.error('Helical collection error: Stop data collection cause %s cant go fast enough. TIP reduce the range or increase the total data collection time' % motorname)
+ self.user_logger.error('Helical collection error: Stop data collection cause %s cant go fast enough.' % motorname)
+ self.user_logger.error(' TIP reduce the distance between starting and ending points, or increase the total data collection time' )
+ for motorname in scan_motor_too_slow:
+ self.logger.error('stop data collection cause %s cant go slow enough. TIP increase the range or reduce the total data collection time' % motorname)
+ self.user_logger.error('stop data collection cause %s cant go slow enough.' % motorname)
+ self.user_logger.error(' TIP increase the distance between starting and ending points, or reduce the total data collection time')
+
+ return len(scan_motor_too_fast)+len(scan_motor_too_slow)
+
+ def set_mesh_scan_parameters(self, num_lines, total_nb_frames, mesh_center_param, mesh_range_param):
+ """
+ sets the mesh scan parameters :
+ - vertcal range
+ - horizontal range
+ - nb lines
+ - nb frames per line
+ - invert direction (boolean) # NOT YET DONE
+ """
+
+
+ # num_lines are the number of vertical lines
+ self.mesh_num_lines = num_lines
+ self.mesh_total_nb_frames = total_nb_frames
+ # mesh_range is a list of two values in fast en slow direction: the range is actually the total interval!
+ self.mesh_range = mesh_range_param
+ # mesh_center is a dictionary holding centered positions of motors
+ self.mesh_center = mesh_center_param
+ self.logger.debug( "mesh_num_lines : %s" % self.mesh_num_lines )
+ self.logger.debug( "mesh_total_nb_frames : %s" % self.mesh_total_nb_frames )
+ self.logger.debug( "mesh_range : %s" % self.mesh_range )
+ self.logger.debug( "mesh_center : %s" % self.mesh_center )
+
+
+ def setMeshScanParameters(self, osc_seq, mesh_mxcube_horizontal_motor_name, mesh_mxcube_vertical_motor_name, mesh_center, mesh_range):
+ """
+ Calculates velocity, starting and end position of the phiy (omegax) motor for each horizontal line scan
+ the step size for the vertical direction
+
+
+ mesh_scan_dict['fast_motor_start_pos'],
+ mesh_scan_dict['fast_motor_final_pos'],
+ mesh_scan_dict['fast_motor_nr_images'],
+ mesh_xaloc_slow_motor_name,
+ mesh_scan_dict['slow_motor_start_pos'],
+ mesh_scan_dict['slow_motor_final_pos'],
+ mesh_scan_dict['slow_motor_nr_images'],
+./hardware_objects.xml/mini-diff.xml: {"fast": (1, 0), "slow": (0, -1)}
+
+
+ """
+
+ #TODO: CHECK IF THE SPEED OF THE FAST MOTOR IS NOT TOO FAST!
+
+ # mesh_center is a Centering_Point, which fails to work as a dictionary, following lines needed
+ if not type(mesh_center) is dict:
+ mesh_center = mesh_center.as_dict()
+ #mesh_step_x = mesh_range[0] / float(self.mesh_num_lines)
+ #mesh_step_y = mesh_range[1] / float(self.mesh_total_nb_frames) / float(self.mesh_num_lines)
+
+ beam_size = self.get_beam_size() # TODO get beam size
+ self.logger.debug('\t beam size: %s' % str(beam_size))
+
+ slow_mxcube_motor_name = mesh_mxcube_vertical_motor_name
+ fast_mxcube_motor_name = mesh_mxcube_horizontal_motor_name
+ slow_motor_nr_images = self.mesh_num_lines
+ fast_motor_nr_images = self.mesh_total_nb_frames / self.mesh_num_lines
+ self.mesh_slow_index = self.mesh_vertical_index
+ self.mesh_fast_index = self.mesh_horizontal_index
+
+ if self.mesh_num_lines == self.mesh_total_nb_frames: # vertical scan
+ slow_mxcube_motor_name = mesh_mxcube_horizontal_motor_name
+ fast_mxcube_motor_name = mesh_mxcube_vertical_motor_name
+ self.mesh_fast_index = self.mesh_vertical_index
+ self.mesh_slow_index = self.mesh_horizontal_index
+ dummy = slow_motor_nr_images
+ slow_motor_nr_images = fast_motor_nr_images
+ fast_motor_nr_images = dummy
+
+ self.logger.debug('setMeshScanParameters')
+ slow_index = self.mesh_slow_index
+ fast_index = self.mesh_fast_index
+
+
+ self.logger.debug('\t mesh_center: %s' % str(mesh_center))
+ self.logger.debug('\t mesh_range: %s' % str(mesh_range))
+ self.logger.debug('\t fast_index %s' % ( fast_index) )
+ self.logger.debug('\t slow_index %s' % ( slow_index) )
+
+ #TODO: index 0 is fast for mxcube?? Is this configured somewhere?
+ self.scan_start_positions[ fast_mxcube_motor_name ] = \
+ mesh_center [ fast_mxcube_motor_name ] - ( mesh_range[fast_index] / 2.0 ) - ( beam_size[fast_index] / 2.0 )
+ self.scan_end_positions[fast_mxcube_motor_name] = \
+ self.scan_start_positions[fast_mxcube_motor_name] + mesh_range[fast_index] + beam_size[fast_index]
+ self.scan_start_positions[slow_mxcube_motor_name] = \
+ mesh_center [ slow_mxcube_motor_name ] - ( mesh_range[slow_index] / 2.0 )
+ self.scan_end_positions[slow_mxcube_motor_name] = \
+ self.scan_start_positions[slow_mxcube_motor_name] + mesh_range[slow_index]
+
+ self.logger.debug('\t slow_mxcube_motor_name: %s' % slow_mxcube_motor_name )
+ self.logger.debug('\t fast_mxcube_motor_name: %s' % fast_mxcube_motor_name )
+
+ self.logger.debug('\t scan_start_positions: %s' % str(self.scan_start_positions))
+ self.logger.debug('\t scan_end_positions: %s' % str(self.scan_end_positions))
+
+ self.logger.debug('\t fast_motor_nr_images: %s' % str( fast_motor_nr_images ) )
+ self.logger.debug('\t slow_motor_nr_images: %s' % str( slow_motor_nr_images ) )
+
+ return slow_mxcube_motor_name, fast_mxcube_motor_name, fast_motor_nr_images, slow_motor_nr_images
+
+ @task
+ def _take_crystal_snapshot(self, filename):
+ """
+ Descript. :
+ """
+ if not self.is_sampleview_phase():
+ self.go_to_sampleview()
+
+ #self.graphics_manager_hwobj.save_scene_snapshot(filename)
+ HWR.beamline.sample_view.save_scene_snapshot(filename)
+ self.logger.debug("Crystal snapshot saved (%s)" % filename)
+
+ def set_energy(self, value):
+ """
+ Descript. : This is Synchronous to be able to calculate the resolution @ Xaloc
+ """
+ # program energy
+ # prepare detector for diffraction
+ #self.user_logger.warning("Setting beamline energy it can take a while, please be patient")
+ self.energy_hwobj.move_energy(value)
+ self.energy_hwobj.wait_move_energy_done()
+
+ def set_wavelength(self, value):
+ """
+ Descript. :
+ """
+ # program energy
+ # prepare detector for diffraction
+ self.energy_hwobj.move_wavelength(value)
+ #self.energy_hwobj.wait_move_wavelength_done()
+
+ def get_energy(self):
+ return self.energy_hwobj.get_energy()
+
+ def set_transmission(self, value):
+ """
+ Descript. :
+ """
+ self.transmission_hwobj.set_value(value)
+
+ def set_resolution(self, value, energy=None):
+ """
+ Descript. : resolution is a motor in out system
+ """
+ # Current resolution non valid since depends on energy and detector distance!!
+ #current_resolution = self.resolution_hwobj.get_value()
+ #self.logger.debug("Current resolution is %s, moving to %s" % (current_resolution, value))
+ self.logger.debug("Moving resolution to %s" % value)
+
+ if energy:
+ # calculate the detector position to achieve the desired resolution
+ _det_pos = get_dettaby(value, energy=energy)
+ # calulate the corresponding resolution
+ value = get_resolution(_det_pos, energy=energy)
+
+ self.resolution_hwobj.set_value(value)
+ #self.detector_hwobj.wait_move_distance_done()
+
+ def move_detector(self, value):
+ self.detector_hwobj.move_distance(value)
+
+ def stop_collect(self):
+ """
+ Stops data collection when interrupted by user
+ overrides AbstractCollect.stop_collect
+
+ This is called from the queue_entry, from the stop method in the DataCollectionQueueEntry class.
+ The queue_entry stop method is called from the QueueManager when the user clicks stop
+
+ """
+ self.logger.debug("XalocCollect stop_collect, colletion stopped by user")
+ self.aborted_by_user = True
+
+ # Before killing the process, wait for a line scan to stop. self.aborted_by_user is read in the mesh scan methods to decide to go on or not
+ self.logger.info(" Wait for line scan to finish ")
+ start_wait = time.time()
+ timeout = 100 #TODO set a more educated guess for the timeout, depending on the time needed for the scan
+ while self.mxcube_sardanascan_running == True and (time.time() - start_wait) < timeout:
+ time.sleep(0.01)
+ if (time.time() - start_wait) > timeout:
+ self.user_logger.error("Timeout waiting for scan to stop. Is the Macroserver ok?")
+ self.logger.debug(" Line scan finished in %s secs " % ( time.time()-start_wait ) )
+
+ self.logger.info(" Stopping detector")
+ self.detector_hwobj.stop_collection()
+ self.logger.info(" Stopping omega motor")
+ self.omega_hwobj.stop()
+ for helmovemotorname in self.scan_move_motor_names:
+ self.scan_motors_hwobj[helmovemotorname].stop()
+
+ AbstractCollect.stop_collect(self) # this kills the collect job
+
+ @task
+ def move_motors(self, motor_position_dict):
+ """
+ Descript. :
+ """
+ self.diffractometer_hwobj.move_motors(motor_position_dict)
+
+ def create_file_directories(self):
+ """
+ Method create directories for raw files and processing files.
+ Directories for xds, mosflm, ednaproc and autoproc
+ """
+ self.create_directories(
+ self.current_dc_parameters['fileinfo']['directory'],
+ self.current_dc_parameters['fileinfo']['process_directory']
+ )
+
+ self.remove_symbolic_link()
+
+ try:
+ os.symlink(
+ self.current_dc_parameters['fileinfo']['directory'],
+ self.symbolic_link_image_destination,
+ )
+ except Exception as e:
+ self.user_logger.error('Cannot create the symlink for the images destination, images will not be copied' )
+ self.user_logger.error('It is exists, remove the file/directory %s' % self.symbolic_link_image_destination)
+ self.data_collection_failed( e, str(e) )
+
+ # create processing directories for each post process
+ if self.current_dc_parameters['experiment_type'] in ["OSC","Helical"]:
+ for proc in ['xds', 'mosflm', 'ednaproc', 'autoproc', 'xia2', 'xia2chem']:
+ self._create_proc_files_directory(proc)
+
+ def remove_symbolic_link(self):
+ try:
+ if os.path.exists(self.symbolic_link_image_destination):
+ os.remove(self.symbolic_link_image_destination)
+ except Exception as e:
+ base_dir_name = os.path.dirname(self.symbolic_link_image_destination)
+ temp_dir_name = os.path.join(
+ base_dir_name,
+ "%s-%s" % (HWR.beamline.session.get_proposal(), datetime.now().strftime("%Y%m%d-%H%M%S"))
+ )
+ self.user_logger.error('Cannot remove the symlink for the images destination' )
+ self.user_logger.error('Trying to rename to %s' %
+ temp_dir_name
+ )
+ os.rename(
+ self.symbolic_link_image_destination, \
+ temp_dir_name
+ )
+ if os.path.exists(self.symbolic_link_image_destination):
+ self.user_logger.error('Cannot update the symlink for the images destination, images will not be copied' )
+ self.user_logger.error('Remove the file/directory %s' % self.symbolic_link_image_destination)
+ self.data_collection_failed( e, str(e) )
+
+
+ # The following methods are copied to improve error logging, the functionality is the same
+ def create_directories(self, *args):
+ """
+ Descript. :
+ """
+ for directory in args:
+ self.logger.debug('Creating directory: %s' % str(directory) )
+ try:
+ os.makedirs(directory)
+ except OSError as e:
+ import errno
+ if e.errno != errno.EEXIST:
+ self.user_logger.error('Error in making the directories, has the permission lockdown been setup properly?' )
+ self.data_collection_failed( e, str(e) )
+
+ def _create_proc_files_directory(self, proc_name):
+
+ i = 1
+
+ while True:
+ _dirname = "%s_%s_%s_%d" % (
+ proc_name,
+ self.current_dc_parameters['fileinfo']['prefix'],
+ self.current_dc_parameters['fileinfo']['run_number'],
+ i)
+ _directory = os.path.join(
+ self.current_dc_parameters['fileinfo']['process_directory'],
+ _dirname)
+ if not os.path.exists(_directory):
+ break
+ i += 1
+
+ try:
+ self.logger.debug('Creating proc directory: %s' % _directory)
+ self.create_directories(_directory)
+ os.system("chmod -R 777 %s" % _directory)
+ except Exception as e:
+ msg = "Could not create directory %s, are the file permissions setup correctly?\n%s" % (_directory, str(e))
+ self.logger.exception(msg)
+ self.data_collection_failed( e, msg)
+
+ # save directory names in current_dc_parameters. They will later be used
+ # by autoprocessing.
+ key = "%s_dir" % proc_name
+ self.current_dc_parameters[key] = _directory
+ self.logger.debug("dc_pars[%s] = %s" % (key, _directory))
+ return _directory
+
+
+ def get_wavelength(self):
+ """
+ Descript. :
+ Called to save wavelength in lims
+ """
+ if self.energy_hwobj is not None:
+ return self.energy_hwobj.get_wavelength()
+
+ def get_detector_distance(self):
+ """
+ Descript. :
+ Called to save detector_distance in lims
+ """
+ if self.detector_hwobj is not None:
+ return self.detector_hwobj.get_distance()
+
+ def get_resolution(self):
+ """
+ Descript. :
+ Called to save resolution in lims
+ """
+ if self.resolution_hwobj is not None:
+ return self.resolution_hwobj.get_value()
+
+ def get_transmission(self):
+ """
+ Descript. :
+ Called to save transmission in lims
+ """
+ if self.transmission_hwobj is not None:
+ return self.transmission_hwobj.get_value()
+
+ def get_undulators_gaps(self):
+ """
+ Descript. : return triplet with gaps. In our case we have one gap,
+ others are 0
+ """
+ # TODO
+ try:
+ if self.chan_undulator_gap:
+ und_gaps = self.chan_undulator_gap.get_value()
+ if type(und_gaps) in (list, tuple):
+ return und_gaps
+ else:
+ return (und_gaps)
+ except BaseException as e:
+ self.logger.debug("Get undulator gaps error\n%s" % str(e))
+ pass
+ return {}
+
+ def get_beam_size(self):
+ """
+ Descript. :
+ """
+ if self.beam_info_hwobj is not None:
+ return self.beam_info_hwobj.get_beam_size()
+
+ def get_slit_gaps(self):
+ """
+ Descript. :
+ """
+ if self.beam_info_hwobj is not None:
+ return self.beam_info_hwobj.get_slits_gap()
+ return None, None
+
+ def get_beam_shape(self):
+ """
+ Descript. :
+ """
+ if self.beam_info_hwobj is not None:
+ return self.beam_info_hwobj.get_beam_shape()
+
+ def get_measured_intensity(self):
+ """
+ Descript. :
+ """
+ if self.flux_hwobj is not None:
+ return self.flux_hwobj.get_flux()
+
+ def get_machine_current(self):
+ """
+ Descript. :
+ """
+ if self.machine_info_hwobj:
+ return self.machine_info_hwobj.get_current()
+ else:
+ return 0
+
+ def get_machine_message(self):
+ """
+ Descript. :
+ """
+ if self.machine_info_hwobj:
+ return self.machine_info_hwobj.get_message()
+ else:
+ return ''
+ # TODO: implement fill mode
+ def get_machine_fill_mode(self):
+ """
+ Descript. :
+ """
+ if self.machine_info_hwobj:
+ return "FillMode not/impl"
+ else:
+ return ''
+
+ def get_flux(self):
+ """
+ Descript. :
+ """
+ return self.get_measured_intensity()
+
+ def trigger_auto_processing(self, event, frame):
+ pass
+ if event == "after":
+ dc_pars = self.current_dc_parameters
+ self.autoprocessing_hwobj.trigger_auto_processing(dc_pars)
+
+ # TODO: Copied from EMBL, need to be evaluated
+ def update_lims_with_workflow(self, workflow_id, grid_snapshot_filename):
+ """Updates collection with information about workflow
+
+ :param workflow_id: workflow id
+ :type workflow_id: int
+ :param grid_snapshot_filename: grid snapshot file path
+ :type grid_snapshot_filename: string
+ """
+ if self.lims_client_hwobj is not None:
+ try:
+ self.current_dc_parameters["workflow_id"] = workflow_id
+ if grid_snapshot_filename:
+ self.current_dc_parameters["xtalSnapshotFullPath3"] =\
+ grid_snapshot_filename
+ self.lims_client_hwobj.update_data_collection(
+ self.current_dc_parameters)
+ except Exception as e:
+ logging.getLogger("HWR").error(
+ "Could not store data collection into ISPyB\n%s" % e)
+
+ def _store_image_in_lims_by_frame_num(self, frame_number):
+ """Store image in lims
+
+ :param frame: dict with frame parameters
+ :type frame: dict
+ :param motor_position_id: position id
+ :type motor_position_id: int
+ """
+ #self.trigger_auto_processing("image", frame_number)
+ return self.store_image_in_lims(frame_number)
+
+ def get_value_at_corner(self):
+ if self.rescorner is not None:
+ return self.rescorner.get_value()
+ return None
+
+ def collect_experiment_type(self):
+ return self.current_dc_parameters["experiment_type"]
+
+def test_hwo(hwo):
+ print("Energy: ", hwo.get_energy())
+ print("Transmission: ", hwo.get_transmission())
+ print("Resolution: ", hwo.get_resolution())
+ print("Shutters (ready for collect): ", hwo.check_shutters())
+ print("Supervisor(collect phase): ", hwo.is_collect_phase())
+
+ print("Flux ", hwo.get_flux())
+ print("Kappa ", hwo.kappapos_chan.get_value())
+ print("Phi ", hwo.phipos_chan.get_value())
diff --git a/mxcubecore/HardwareObjects/ALBA/XalocCryostream.py b/mxcubecore/HardwareObjects/ALBA/XalocCryostream.py
new file mode 100644
index 0000000000..bfe5b0badb
--- /dev/null
+++ b/mxcubecore/HardwareObjects/ALBA/XalocCryostream.py
@@ -0,0 +1,93 @@
+#
+# Project: 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 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with MXCuBE. If not, see .
+
+"""
+[Name]
+Liquid nitrogen shower hardware object
+
+[Description]
+Specific HwObj for the liquid nitrogen pump installed at XALOC to wash the crystal
+
+[Emitted signals]
+- ln2showerIsPumpingChanged
+- ln2showerFault
+
+TODO: when the dewar is empty, the operation is INVALID and the State is FAULT
+"""
+
+import logging
+import PyTango
+import time
+
+from taurus.core.tango.enums import DevState
+
+from mxcubecore import HardwareRepository as HWR
+from mxcubecore.BaseHardwareObjects import Device
+
+__credits__ = ["ALBA Synchrotron"]
+__version__ = "3"
+__category__ = "General"
+__author__ = "Roeland Boer"
+
+class XalocCryostream(Device):
+ """
+ Specific liquid nitrogen shower HwObj for XALOC beamline.
+ """
+
+ def __init__(self, name):
+ Device.__init__(self, name)
+
+ self.logger = logging.getLogger("HWR.XalocCryostream")
+ self.userlogger = logging.getLogger("user_level_log")
+
+ self.username = None
+ self.chn_state = None
+ self.chn_gas_temp= None
+ self.state = None
+ self.gas_temp = None
+
+ def init(self):
+ self.logger.debug("Initializing {0}".format(self.__class__.__name__))
+
+ self.username = self.get_property("username")
+ self.chn_gas_temp = self.get_channel_object("gas_temp")
+ self.chn_state = self.get_channel_object("State")
+
+ self.connect(self.chn_gas_temp, "update", self.gas_temp_changed)
+ self.connect(self.chn_state, "update", self.state_changed)
+
+ def state_changed(self, value):
+ """
+ value can be DevState.FAULT, DevState.ON
+ """
+ if value is not None:
+ if self.state != value:
+ self.state = value
+ self.emit("stateChanged", (self.state,) )
+ if value in [DevState.FAULT]:
+ self.emit("cryostreamFault", (True,) )
+ else:
+ self.emit("cryostreamFault", (False,) )
+
+ def gas_temp_changed(self, value):
+ if value is not None:
+ if self.gas_temp != value:
+ self.gas_temp = value
+ self.emit("gasTempChanged", (self.gas_temp,) )
+
diff --git a/mxcubecore/HardwareObjects/ALBA/XalocDigitalZoom.py b/mxcubecore/HardwareObjects/ALBA/XalocDigitalZoom.py
new file mode 100755
index 0000000000..43f103a778
--- /dev/null
+++ b/mxcubecore/HardwareObjects/ALBA/XalocDigitalZoom.py
@@ -0,0 +1,268 @@
+#
+# Project: 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 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with MXCuBE. If not, see .
+
+"""
+XalocDigitalZoom
+
+Hardware Object used to integrate the zoom capabilities of the Bzoom system from
+ARINAX using the TANGO layer.
+
+Signals:
+- stateChanged
+- predefinedPositionChanged
+
+"""
+from __future__ import print_function
+import logging
+
+from enum import IntEnum, unique
+
+from mxcubecore.BaseHardwareObjects import Device
+from taurus.core.tango.enums import DevState
+
+__credits__ = ["ALBA Synchrotron"]
+__licence__ = "LGPLv3+"
+__version__ = "3"
+__category__ = "General"
+
+
+@unique
+class DigitalZoomState(IntEnum):
+ """
+ Defines valid digital zoom states
+ """
+
+ UNKNOWN = 0
+ READY = 1
+ LOW_LIMIT = 2
+ HIGH_LIMIT = 3
+ DISABLED = 4
+ FAULT = -1
+
+
+class XalocDigitalZoom(Device):
+ """Hardware object used to control the zoom capabilities."""
+
+ STATE = DigitalZoomState
+
+ def __init__(self, name):
+ """ Define variables """
+ Device.__init__(self, name)
+ self.logger = logging.getLogger("HWR.XalocDigitalZoom")
+ self.user_level_log = logging.getLogger("user_level_log")
+ self.chan_state = None
+ self.chan_labels = None
+ self.chan_blight = None
+
+ self.current_position = 0
+ self.current_state = None
+
+ def init(self):
+ """ Initialize variables """
+ self.logger.debug("Initializing {0}".format(self.__class__.__name__))
+ # TODO: This is not an IOR anymore
+ self.chan_pos = self.get_channel_object("position")
+ self.chan_state = self.get_channel_object("state")
+ # TODO: labels must be harcoded or read as a property
+ # self.chan_labels = self.get_channel_object("labels")
+ # TODO: This has to be calibrated with zoom values in the [0,1] range
+ # self.chan_blight = self.get_channel_object('blight')
+
+ self.chan_pos.connect_signal("update", self.position_changed)
+ self.chan_state.connect_signal("update", self.state_changed)
+
+ self.current_position = self.get_value()
+ self.logger.debug('Initial Digital Zoom Position: %s',self.get_value())
+ self.current_state = self.get_state()
+ self.set_name("BZoom")
+
+ def get_predefined_positions_list(self):
+ """
+ It returns the corresponding to the zoom positions. In our case,
+ ['1', '2', ..., 'n']. This values should be gathered from the Arinax server
+
+ :return: [str,]
+
+ """
+ return [str(i) for i in range(1, 8)]
+
+ def move_to_position(self, position):
+ """
+ Move to one of the predefined positions defined in the predefined positions
+ list. In this case, position names correspont to zoom values and only a
+ casting to int is required.
+
+ :param position: string value indicating the zoom position.
+ :return: None
+
+ """
+ self.logger.debug("Moving digital zoom to position %s" % position)
+ self.chan_pos.set_value(int(position))
+
+ def get_limits(self):
+ """
+ Get zoom limits (i.e. the position name corresponding to the maximum and
+ minimum values).
+
+ Returns: str, str
+
+ """
+ _min = self.get_predefined_positions_list()[0]
+ _max = self.get_predefined_positions_list()[-1]
+ return _min, _max
+
+ def get_state(self):
+ """
+ Get the Digital Zoom state (enum) mapping from current Tango state.
+
+ Returns: DigitalZoomState
+
+ # TODO: servers returns always UNKNWON
+ # TODO: Review type and values returned by Arinax server
+
+ """
+
+ state = self.chan_state.get_value()
+ curr_pos = self.get_value()
+ if state == DevState.ON:
+ return self.STATE.READY
+ elif curr_pos == self.get_limits()[0]:
+ return self.STATE.LOW_LIMIT
+ elif curr_pos == self.get_limits()[-1]:
+ return self.STATE.HIGH_LIMIT
+ if state == DevState.UNKNOWN:
+ # TODO: Bug in Arinax server: always in UNKNOWN
+ return self.STATE.READY
+ # return self.STATE.UNKNOWN
+ else:
+ return self.STATE.FAULT
+
+ def get_value(self):
+ """
+ Get the position index from the server.
+
+ Returns: int
+
+ """
+ return self.chan_pos.get_value()
+
+ def get_current_position_name(self):
+ """
+ Returns the current zoom position name.
+
+ Returns: str
+
+ """
+ return str(self.chan_pos.get_value())
+
+ def state_changed(self, state):
+ """
+ Slot receiving the zoom state changed and emitting the signal
+
+ Args:
+ state: Zoom Tango State
+
+ Returns: None
+
+ """
+ # TODO: Arrives a Tango State, emits DigitalZoom State
+ # We should use the state received!
+ state = self.get_state()
+
+ if state != self.current_state:
+ self.logger.debug(
+ "State changed: {} -> {})".format(self.current_state, state)
+ )
+ self.current_state = state
+ self.emit("stateChanged", (state,))
+
+ def position_changed(self, position):
+ """
+ Slot receiving the zoom position changed and emitting the signal.
+ Additionally, we could also actuate the backlight intensity here.
+
+ Args:
+ position: Zoom int position
+
+ Returns: None
+
+ """
+ # TODO: Arrives an int, emits string
+ # We should use the position received.
+ position = self.get_current_position_name()
+
+ if position != self.current_position:
+ #self.logger.debug(
+ #"Zoom changed: {} -> {}".format(self.current_position, position)
+ #)
+ self.current_position = position
+ self.emit("valueChanged", position)
+ self.emit("predefinedPositionChanged", (position, 0))
+
+ def is_ready(self):
+ """
+ Returns: Boolean
+
+ """
+ # state = self.get_state()
+ # return state == self.STATE.READY
+ # TODO: Bug in Arinax server: state is ALWAYS UNKNOWN
+ return True
+
+ def get_calibration_pixels_per_mm(self):
+ """
+ Returns the pixel size in um for the current zoom level (self.current_position)
+ """
+ x = None
+ _zoom_lut = {}
+ _zoom_lut[1] = 0.0000
+ _zoom_lut[2] = 0.1810
+ _zoom_lut[3] = 0.3620
+ _zoom_lut[4] = 0.5430
+ #_zoom_lut[5] = 0.9088
+ #_zoom_lut[6] = 0.9540
+ #_zoom_lut[7] = 1.0000
+ # 20230123: XALOC changed the calibration based on motor movements and pin centering on camera
+ _zoom_lut[5] = 0.9147579
+ _zoom_lut[6] = 0.9573539
+ _zoom_lut[7] = 1.0051203277009728
+
+ #x = 2.0040 + (-1.8370 * _zoom_lut[int(self.current_position)])
+ if self.current_position != None:
+ x = 2.784 + (-2.604 * _zoom_lut[int(self.current_position)])
+ else:
+ self.user_level_log.error("No zoom position available, the bzoom camera DS probably needs to be restarted")
+ #TODO improve calibration.
+ #self.logger.debug("Getting calibration from zoom hwobj: position (level) {} pix size (um) {}".
+ #format(self.current_position,x)
+ #)
+ return 1000.0/x, 1000.0/x
+
+ def get_calibration_microns_per_pixel(self):
+ """
+ Returns the pixel size in um for the current zoom level (self.current_position)
+ """
+ x,x = self.get_calibration_pixels_per_mm()
+ return x * 1000.0, x * 1000.0
+
+ def get_calibration(self):
+ """
+ Maintained for compatibility. Use get_calibration_pixels_per_mm or get_calibration_microns_per_pixel
+ """
+ return self.get_calibration_microns_per_pixel()
diff --git a/mxcubecore/HardwareObjects/ALBA/XalocEDNACharacterisation.py b/mxcubecore/HardwareObjects/ALBA/XalocEDNACharacterisation.py
new file mode 100644
index 0000000000..0b8ea6375c
--- /dev/null
+++ b/mxcubecore/HardwareObjects/ALBA/XalocEDNACharacterisation.py
@@ -0,0 +1,465 @@
+# Project: 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 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with MXCuBE. If not, see .
+
+"""
+[Name] XalocEDNACharacterisation
+
+[Description]
+Prepare files and launch strategy pipeline (online) to the ALBA cluster
+
+[Signals]
+- None
+"""
+
+from __future__ import print_function
+
+import os
+import time
+import subprocess
+
+import logging
+
+from mxcubecore import HardwareRepository as HWR
+from EDNACharacterisation import EDNACharacterisation
+from XSDataMXCuBEv1_3 import XSDataResultMXCuBE
+from XSDataCommon import XSDataFile, XSDataString
+
+from slurm_client.utils import create_edna_yml
+
+__credits__ = ["ALBA Synchrotron"]
+__version__ = "3"
+__category__ = "General"
+
+
+class XalocEDNACharacterisation(EDNACharacterisation):
+
+ def __init__(self, name):
+ EDNACharacterisation.__init__(self, name)
+ self.logger = logging.getLogger("HWR.XalocEDNACharacterisation")
+ self.userlogger = logging.getLogger('user_level_log')
+ self.job = None
+ self.output_dir = None
+ self.input_file = None
+ self.results_file = None
+ self.cluster = None
+
+ self.use_cluster_queue = None
+ self.ssh_user = None
+ self.ssh_host = None
+ self.secondary_ssh_host = None
+ self.ssh_bash_script = None
+ self.ssh_cluster_bash_script = None
+ self.edna_source_dir = None
+
+ self.last_processed_dc_id = None
+ self.proceed = None
+
+ def init(self):
+ self.logger.debug("Initializing {0}".format(self.__class__.__name__))
+ EDNACharacterisation.init(self)
+ self.cluster = self.get_object_by_role("cluster")
+
+ self.use_cluster_queue = self.get_property("use_cluster_queue")
+ self.ssh_user = self.get_property("ssh_user")
+ self.ssh_host = self.get_property("ssh_host")
+ self.secondary_ssh_host = self.get_property("secondary_ssh_host")
+ self.ssh_bash_script = self.get_property("ssh_bash_script")
+ self.ssh_cluster_bash_script = self.get_property("ssh_cluster_bash_script")
+ self.edna_source_dir = self.get_property("edna_source_dir")
+
+ self.proceed = False
+
+ self.connect(
+ HWR.beamline.collect, "collectOscillationFailed", self.collect_failed
+ )
+ self.connect(
+ HWR.beamline.collect, "collectOscillationStarted", self.collect_started
+ )
+
+ def collect_failed(self, owner, state, message, *args):
+ self.logger.debug( "Collection failed, unsetting event" )
+ self.processing_done_event.clear()
+ self.proceed = False
+
+ def collect_started(self, owner, state, message, *args):
+ self.logger.debug( "Collection started, enabling characterisation" )
+ self.proceed = True
+
+ def prepare_edna_input(self, input_file, output_dir):
+ # used for strategy calculation (characterization) using data analysis cluster
+ # Xaloc specific
+ input_file.process_directory = output_dir
+ output_dir = XSDataFile(XSDataString(output_dir))
+ input_file.setOutputFileDirectory(output_dir)
+
+ #def _run_edna(self, dc_id, input_file, results_file, output_dir):
+ #return self.run(dc_id, input_file, results_file, output_dir)
+
+ #def run(self, *args):
+
+ #log = logging.getLogger('user_level_log')
+ #dc_id, input_file, results_file, output_dir = args
+ #jobname = os.path.basename(os.path.dirname(output_dir))
+
+ #self.logger.debug("Submitting Job")
+ #self.logger.debug(" job_name: %s" % jobname)
+ #self.logger.debug(" input file: %s" % input_file)
+ #self.logger.debug(" results file: %s" % results_file)
+ #self.logger.debug(" output directory: %s" % output_dir)
+
+ #self.job = self.cluster.create_strategy_job(dc_id, input_file, output_dir)
+ #self.cluster.run(self.job)
+
+ #log.info("Characterization Job ID: %s" % self.job.id)
+
+ #self.output_dir = os.path.dirname(input_file)
+ #self.input_file = os.path.basename(input_file)
+ ## self.results_file = self.fix_path(results_file)
+ #self.results_file = results_file
+ #self.logger.debug("Results file: %s" % self.results_file)
+
+ #state = self.cluster.wait_done(self.job)
+
+ #if state == "COMPLETED":
+ #log.info("Job completed")
+ #time.sleep(0.5)
+ #result = self.get_result()
+ #else:
+ #log.info("Job finished without success / state was %s" %
+ #state)
+ #result = ""
+
+ #return result
+
+ # TODO: Deprecated
+ #def fix_path(self, path):
+ #out_path = path.replace('PROCESS_DATA', 'PROCESS_DATA/RESULTS')
+ ## dirname = os.path.dirname(path)
+ ## basename = os.path.basename(path)
+ ## outpath = os.path.join(dirname,'RESULTS',basename)
+ #return out_path
+
+ # TODO: Unused??
+ def wait_done(self):
+
+ state = None
+ time.sleep(0.5)
+ self.logger.debug("Polling for Job state")
+
+ try:
+ state = self.job.state
+ self.logger.debug("Job / is %s" % str(state))
+ except Exception as e:
+ self.logger.debug(
+ "Polling for Job state, exception happened\n%s" % str(e))
+
+ while state in ["RUNNING", "PENDING"]:
+ self.logger.debug("Job / is %s" % state)
+ time.sleep(0.5)
+ state = self.job.state
+
+ self.logger.debug("Returning %s" % str(state))
+ return state
+
+ def get_result(self):
+
+ # To test diffraction plan handling, uncomment the nex line
+ # self.results_file = "/beamlines/bl13/projects/cycle2018-I/2018002222-ispybtest/20230329/PROCESSED_DATA/manually-mbounted/characterisation_ref-manually-mbounted_run1_89155/EDNAOutput_89155.xml"
+ self.logger.debug("Characterization Job COMPLETED")
+ if self.job != None:
+ self.logger.debug("Status: %s" % self.job.status)
+ else:
+ self.logger.debug("Job run through ssh")
+ self.logger.debug("Results file: %s" % self.results_file)
+ if os.path.exists(self.results_file):
+ result = XSDataResultMXCuBE.parseFile(self.results_file)
+ self.logger.debug("EDNA Result loaded from file (type is %s" %
+ str(type(result)))
+ else:
+ self.logger.debug(
+ "Cannot find output file, returning empty string.")
+ result = ""
+
+ return result
+
+ def characterise(self, edna_input):
+ """
+ Args:
+ input (EDNAInput) EDNA input object
+
+ Returns:
+ (str) The Characterisation result
+ """
+ if self.proceed and self.collect_obj.current_dc_parameters["status"] != "Failed":
+ self.processing_done_event.set()
+ else:
+ self.processing_done_event.clear()
+ self.userlogger.error( "Collection failed, not doing the characterisation" )
+ return 'NOT DONE'
+
+ self.prepare_input(edna_input)
+ path = edna_input.process_directory
+
+ # if there is no data collection id, the id will be a random number
+ # this is to give a unique number to the EDNA input and result files;
+ # something more clever might be done to give a more significant
+ # name, if there is no dc id.
+ try:
+ dc_id = edna_input.getDataCollectionId().getValue()
+ except Exception:
+ dc_id = id(edna_input)
+
+ token = self.generate_new_token()
+ edna_input.token = XSDataString(token)
+
+ firstImage = None
+ #for dataSet in edna_input.dataSet:
+ for dataSet in edna_input.getDataSet():
+ for imageFile in dataSet.imageFile:
+ if imageFile.getPath() is None:
+ continue
+ firstImage = imageFile.path.value
+ break
+
+ listImageName = os.path.basename(firstImage).split("_")
+ prefix = "_".join(listImageName[:-2])
+ run_number = listImageName[-2]
+
+ if hasattr(edna_input, "process_directory"):
+ edna_directory = os.path.join(
+ edna_input.process_directory,
+ "characterisation_%s_run%s_%s" % (prefix, run_number, dc_id )
+ )
+ os.makedirs(edna_directory)
+ else:
+ raise RuntimeError("No process directory specified in edna_input")
+
+ edna_input_file = os.path.join(edna_directory, "EDNAInput_%s.xml" % dc_id)
+
+ self.prepare_edna_input(edna_input, edna_directory)
+
+ try:
+ edna_input.exportToFile(edna_input_file)
+ except:
+ import traceback
+ self.logger.debug("Problem generating input file:")
+ self.logger.debug(" %s " % traceback.format_exc())
+
+ edna_results_file = os.path.join(edna_directory, "EDNAOutput_%s.xml" % dc_id)
+
+ msg = "Starting EDNA using xml file %r", edna_input_file
+ self.logger.info(msg)
+ #TODO: ALBA used local version of _run_edna to pass dc_id.
+ # Not sure why the implemented method is not used,
+ # self.result = self._run_edna(edna_input_file, edna_results_file, path)
+ self.result = self._run_edna_xaloc(dc_id, edna_input_file, edna_results_file, edna_directory)
+
+ self.processing_done_event.clear()
+ return self.result
+
+ def _run_edna_xaloc_cluster(self, dc_id, input_file, results_file, output_dir):
+ """
+ Starts EDNA
+ Job Submission managed by slurm client.
+ Note that XalocCluster by default sends the file to SCRATCH
+ """
+ if self.collect_obj.current_dc_parameters["status"] == "Failed":
+ self.userlogger.error("Collection failed, no characterisation done")
+ return ''
+
+ msg = "Starting EDNA characterisation using xml file %s" % input_file
+ self.logger.info(msg)
+
+ jobname = os.path.basename( os.path.dirname(output_dir) )
+
+ self.logger.debug("Submitting Job")
+ self.logger.debug(" job_name: %s" % jobname)
+ self.logger.debug(" input file: %s" % input_file)
+ self.logger.debug(" results file: %s" % results_file)
+ self.logger.debug(" output directory: %s" % output_dir)
+
+ self.job = self.cluster.create_strategy_job(dc_id, input_file, output_dir)
+ self.cluster.run(self.job)
+
+ self.userlogger.info("Characterization Job ID: %s" % self.job.id)
+
+ self.output_dir = os.path.dirname(input_file)
+ self.input_file = os.path.basename(input_file)
+ self.results_file = results_file
+ self.logger.debug("Results file: %s" % self.results_file)
+
+ self.last_processed_dc_id = dc_id
+
+ #state = self.cluster.wait_done(self.job)
+ results_file_exists = self.wait_results_file(results_file)
+
+ #if state == "COMPLETED":
+ if results_file_exists:
+ self.logger.info("Job completed")
+ time.sleep(0.5)
+ result = self.get_result()
+ self.logger.info("HTML in results file %s" % result.getHtmlPage().getPath().getValue() )
+ else:
+ #self.logger.info("Job finished without success / state was %s" %
+ #state)
+ self.logger.info("Job did not run properly, no analysis done, check with your LC ")
+ result = ""
+
+ return result
+
+ def _run_edna_xaloc_ssh(self, dc_id, input_file, results_file, output_dir):
+ """
+ Starts EDNA using ssh protocol, directly to cluster.
+ """
+ if self.collect_obj.current_dc_parameters["status"] == "Failed":
+ self.logger.error("Collection failed, no characterisation done")
+ return ''
+
+ msg = "Starting EDNA characterisation using xml file %s" % input_file
+ self.logger.info(msg)
+
+ jobname = os.path.basename( os.path.dirname(output_dir) )
+
+ self.logger.debug("Submitting Job")
+ self.logger.debug(" job_name: %s" % jobname)
+ self.logger.debug(" input file: %s" % input_file)
+ self.logger.debug(" results file: %s" % results_file)
+ self.logger.debug(" output directory: %s" % output_dir)
+
+ _yml_file = create_edna_yml(str(dc_id),
+ self.cluster.pipelines['strategy']['plugin'],
+ input_file,
+ self.ssh_cluster_bash_script,
+ workarea='SCRATCH',
+ benchmark=False,
+ dest=output_dir,
+ use_scripts_root=False,
+ xds=None,
+ configdef=None)
+
+
+
+ #proc_command = "ssh %s@%s %s %s" % (self.ssh_user, self.ssh_host, self.ssh_bash_script, ssh_parameters)
+ #self.logger.info( "Executing command: %s" % proc_command )
+ #os.system(proc_command)
+ self.last_processed_dc_id = dc_id
+
+ if self.ssh_host != None and self.ssh_host != '':
+ ssh_parameters = "%s %s %s %s %s %s %s %s %s %s" % (
+ self.ssh_user,
+ self.secondary_ssh_host,
+ self.ssh_cluster_bash_script,
+ self.cluster.pipelines['strategy']['plugin'],
+ input_file,
+ results_file,
+ output_dir,
+ "SCRATCH",
+ False,
+ self.edna_source_dir
+ )
+ proc_command = "%s %s" % (self.ssh_bash_script, ssh_parameters)
+ self.logger.info( "Executing command: ssh %s@%s %s" % (self.ssh_user, self.ssh_host, proc_command ) )
+ subprocess.call(['ssh', '%s@%s' % (self.ssh_user, self.ssh_host), proc_command])
+ else:
+ ssh_parameters = "%s %s %s %s %s %s %s %s" % (
+ self.ssh_cluster_bash_script,
+ self.cluster.pipelines['strategy']['plugin'],
+ input_file,
+ results_file,
+ output_dir,
+ "LOCAL",# for pcbl1309
+ False,
+ self.edna_source_dir
+ )
+ self.logger.info( "Executing command: ssh %s@%s %s" % (self.ssh_user, self.secondary_ssh_host, ssh_parameters) )
+ subprocess.call(['ssh', '%s@%s' % (self.ssh_user, self.secondary_ssh_host), ssh_parameters])
+
+ #self.logger.info("Characterization Job ID: %s" % job_id)
+
+ self.output_dir = os.path.dirname(input_file)
+ self.input_file = os.path.basename(input_file)
+ self.results_file = results_file
+ self.logger.debug("Results file: %s" % self.results_file)
+
+ results_file_exists = self.wait_results_file(results_file)
+ if results_file_exists:
+ result = self.get_result()
+ else:
+ self.logger.info("Job did not run properly, no analysis done, check with your LC ")
+ result = ""
+
+ return result
+
+ def _run_edna_xaloc(self, dc_id, input_file, results_file, output_dir):
+ self.job = None # reset job name
+ self.last_processed_dc_id = None
+
+ result = ''
+ if self.use_cluster_queue:
+ result = self._run_edna_xaloc_cluster(dc_id, input_file, results_file, output_dir)
+ else:
+ result = self._run_edna_xaloc_ssh(dc_id, input_file, results_file, output_dir)
+
+ return result
+
+ def wait_results_file(self, results_file, timeout = 30):
+ sttime = time.time()
+ while not os.path.exists(results_file) and \
+ time.time() - sttime < timeout:
+ time.sleep(0.2)
+ return os.path.exists(results_file)
+
+ def get_html_report(self, edna_result):
+ """
+ Args:
+ output (EDNAResult) EDNAResult object
+
+ Returns:
+ (str) The path to the html result report generated by the characterisation
+ software
+
+ /beamlines/bl13/projects/cycle2023-I/2022086950-acamara-artigas/20230131/PROCESSED_DATA/RESULTS/B1X4/characterisation_ref-B1X4_run1_84450/proc_ 71573656/
+ /beegfs/scratch/strategy_ 71573693/EDApplication_20230131-190222/ControlInterfaceToMXCuBEv1_3/SimpleHTML/index.html
+ """
+ html_report = None
+
+ try:
+ # Chapuza alert! the characterisation is run locally on the cluster, and the path of the html report in the EDNA output xml is also local
+ # This path is reset within the script that runs the characterisation, after EDNA is done. So we have to wait for the file to appera
+ # Solution: read directly from cluster beegfs from pcbl1307
+ html_report = str( edna_result.getHtmlPage().getPath().getValue() )
+ while not os.path.exists(html_report):
+ time.sleep(0.2)
+ result = XSDataResultMXCuBE.parseFile(self.results_file)
+ html_report = str(result.getHtmlPage().getPath().getValue())
+ except AttributeError:
+ logging.getLogger("Cant find html page in edna_result %s" % edna_result)
+ pass
+
+ return html_report
+
+
+def test_hwo(hwo):
+ ofile = "/tmp/edna/edna_result"
+ odir = "/tmp/edna"
+ test_input_file = "/beamlines/bl13/projects/cycle2018-I/2018012551-bcalisto/" \
+ "mx2018012551/DATA/20180131/PROCESS_DATA/" \
+ "characterisation_ref-Thrombin-TB-TTI1_A_run1_1/" \
+ "EDNAInput_2004391.xml"
+ result = hwo.run_edna(test_input_file, ofile, odir)
+ print(result)
diff --git a/mxcubecore/HardwareObjects/ALBA/XalocEnergy.py b/mxcubecore/HardwareObjects/ALBA/XalocEnergy.py
new file mode 100644
index 0000000000..b065560209
--- /dev/null
+++ b/mxcubecore/HardwareObjects/ALBA/XalocEnergy.py
@@ -0,0 +1,184 @@
+# Project: 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 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with MXCuBE. If not, see .
+
+"""
+[Name] XalocEnergy
+
+[Description]
+HwObj used to configure the beamline energy.
+
+[Signals]
+- energyChanged
+"""
+
+#from __future__ import print_function
+
+import logging
+
+from mxcubecore.HardwareObjects.Energy import Energy
+
+__credits__ = ["ALBA Synchrotron"]
+__version__ = "3"
+__category__ = "General"
+
+
+class XalocEnergy(Energy):
+
+ def __init__(self, name):
+ Energy.__init__(self, name)
+ self.logger = logging.getLogger("HWR.XalocEnergy")
+ #self.energy_motor = None
+ self.wavelength_motor = None
+ self.is_tunable = None
+
+ self.energy_position = None
+ self.wavelength_position = None
+
+ def init(self):
+ #Energy.init(self)
+ self.logger.debug("Initializing {0}".format(self.__class__.__name__))
+ #self.energy_motor = self.get_object_by_role("energy")
+ self.wavelength_motor = self.get_object_by_role("wavelength")
+
+ try:
+ self.energy_motor = self.get_object_by_role("energy")
+ except KeyError:
+ logging.getLogger("HWR").warning("Energy: error initializing energy motor")
+
+ try:
+ self.is_tunable = self.get_property("tunable_energy")
+ except KeyError:
+ self.is_tunable = False
+ logging.getLogger("HWR").warning("Energy: will be set to fixed energy")
+
+ if self.energy_motor is not None:
+ #self.connect(self.wavelength_motor, "valueChanged",
+ #self.energy_position_changed)
+ self.connect(self.energy_motor, "valueChanged",
+ self.energy_position_changed)
+ self.energy_motor.connect("stateChanged", self.energyStateChanged)
+
+
+ def is_ready(self):
+ try:
+ if self.energy_motor is not None:
+ return self.energy_motor.is_ready()
+ else: return True
+ except Exception as e:
+ logging.getLogger("HWR").warning("Energy error %s" % str(e) )
+ return True
+
+ def can_move_energy(self):
+ #if self.energy_motor is not none:
+ #return not self.energy_motor.is_moving()
+ #else: return True
+ return True
+
+ def get_value(self):
+ if self.energy_motor is not None:
+ try:
+ return self.energy_motor.get_value()
+ except Exception:
+ logging.getLogger("HWR").exception(
+ "EnergyHO: could not read current energy"
+ )
+ return None
+ return self.default_en
+
+ def get_wavelength(self):
+ if self.wavelength_motor != None:
+ self.wavelength_position = self.wavelength_motor.get_value()
+ return self.wavelength_position
+
+ def update_values(self):
+ self.energy_position_changed()
+
+ #TODO update resolution. Resolution has a method called energyChanged, which takes a egy but doenst use it
+ # this calls updateResolution, which also calls update_beam_center, but probably this doesnt affect Xaloc
+ # as the beam center is taken from Variables just before a collect. Check though...
+ def energy_position_changed(self, value):
+ self.energy_position = self.energy_motor.get_value()
+ self.wavelength_position = self.wavelength_motor.get_value()
+ if None not in [self.energy_position, self.wavelength_position]:
+ self.emit('energyChanged', self.energy_position, self.wavelength_position)
+ self.emit("valueChanged", (self.energy_position,))
+
+ #def wavelength_position_changed(self, value):
+ #wavelength_position = value
+ #energy_position = energy_motor.get_value()
+ #if None not in [energy_position, wavelength_position]:
+ #self.emit('energyChanged', energy_position, wavelength_position)
+
+ def move_energy(self, value, timeout=0):
+ current_egy = self.get_value()
+
+ self.logger.debug("Moving energy to %s. now is %s" % (value, current_egy))
+
+ if abs(value-current_egy) > self.energy_motor.move_threshold:
+ self.energy_motor.set_value(value, timeout)
+ else:
+ self.logger.debug("Change below threshold. not moved")
+
+ set_value = move_energy
+ #_set_value = move_energy
+
+ def wait_move_energy_done(self):
+ self.logger.debug("wait_move_energy_done energ_motor state is %s" % (self.energy_motor.get_state() ) )
+ self.energy_motor.wait_ready(timeout = 30)
+
+ def move_wavelength(self, value):
+ # convert wavelength to energy and move energy
+
+ current_lambda = self.get_wavelength()
+ kV_from_lambda = 12.398419303652055 / value
+ self.logger.debug("Requested wavelength change, moving wavelength to %s (E %s). now is %s" %
+ (value, kV_from_lambda, current_lambda)
+ )
+
+ self.move_energy( kV_from_lambda )
+ #self.wavelength_motor.set_value(value)
+
+ def wait_move_wavelength_done(self):
+ self.wavelength_motor.wait_ready()
+
+ def get_energy_limits(self):
+ return self.energy_motor.get_limits()
+
+ get_limits=get_energy_limits
+
+ def get_wavelength_limits(self):
+ return self.wavelength_motor.get_limits()
+
+ set_wavelength = move_wavelength
+
+ def stop(self):
+ self.energy_motor.stop()
+ self.energy_motor.update_values()
+
+ def energyStateChanged(self, state):
+ """
+ state is a MotorState
+ state.value[0] retrieves HardwareObjectState from MotorState
+ """
+ self.emit("stateChanged", (state.value[0],))
+
+def test_hwo(hwo):
+ print("Energy is: ", hwo.get_energy())
+ print("Wavelength is: ", hwo.get_wavelength())
+ print("Energy limits are: ", hwo.get_energy_limits())
+ print("Wavelength limits are: ", hwo.get_wavelength_limits())
diff --git a/mxcubecore/HardwareObjects/ALBA/XalocEpsActuator.py b/mxcubecore/HardwareObjects/ALBA/XalocEpsActuator.py
new file mode 100644
index 0000000000..6c6463862b
--- /dev/null
+++ b/mxcubecore/HardwareObjects/ALBA/XalocEpsActuator.py
@@ -0,0 +1,153 @@
+# Project: 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 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with MXCuBE. If not, see .
+
+
+"""
+[Name] XalocEpsActuator
+
+[Description]
+Tango Shutter Hardware Object
+
+Public Interface:
+ Commands:
+ int get_state()
+ Description:
+ returns current state
+ Output:
+ integer value describing the state
+ current states correspond to:
+ 0: out
+ 1: in
+ 9: moving
+ 11: alarm
+ 13: unknown
+ 23: fault
+
+ string get_status()
+ Description:
+ returns current state as a string that can contain a more
+ descriptive information about current state
+
+ Output:
+ status string
+
+ cmd_in()
+ Executes the command associated to the "In" action
+ cmd_out()
+ Executes the command associated to the "Out" action
+
+ [Signals]
+ stateChanged
+
+"""
+
+from __future__ import print_function
+
+import logging
+
+from mxcubecore import BaseHardwareObjects
+
+__credits__ = ["ALBA Synchrotron"]
+__version__ = "3"
+__category__ = "General"
+
+STATE_IN, STATE_OUT, STATE_MOVING, STATE_FAULT, STATE_ALARM, STATE_UNKNOWN = \
+ (0, 1, 9, 11, 13, 23)
+
+
+class XalocEpsActuator(BaseHardwareObjects.Device):
+
+ states = {
+ STATE_OUT: "out",
+ STATE_IN: "in",
+ STATE_MOVING: "moving",
+ STATE_FAULT: "fault",
+ STATE_ALARM: "alarm",
+ STATE_UNKNOWN: "unknown",
+ }
+
+ default_state_strings = ["In", "Out"]
+
+ def __init__(self, name):
+ BaseHardwareObjects.Device.__init__(self, name)
+ self.logger = logging.getLogger("HWR.XalocEpsActuator")
+ self.chan_actuator = None
+
+ self.actuator_state = None
+ self.state_strings = None
+
+ def init(self):
+ self.logger.debug("Initializing {0}".format(self.__class__.__name__))
+ self.actuator_state = STATE_UNKNOWN
+
+ try:
+ self.chan_actuator = self.get_channel_object("actuator")
+ self.chan_actuator.connect_signal("update", self.state_changed)
+ except KeyError:
+ self.logger.warning('Cannot report EPS Actuator State for %s' % self.name())
+
+ try:
+ state_string = self.get_property("states")
+ if state_string is None:
+ self.state_strings = self.default_state_strings
+ else:
+ self.state_strings = state_string.split(",")
+ except Exception as e:
+ self.logger.warning("%s" % str(e))
+ self.state_strings = self.default_state_strings
+
+ def get_state(self):
+ self.actuator_state = self.chan_actuator.force_get_value()
+ return self.actuator_state
+
+ def state_changed(self, value):
+ self.actuator_state = value
+ self.logger.debug("State change for actuator %s, new state is %s" % (self.name(), value) )
+ self.emit('stateChanged', (self.actuator_state,))
+
+ def get_user_name(self):
+ return self.username
+
+ def get_status(self):
+ """
+ """
+ state = self.get_state()
+
+ if state in [STATE_OUT, STATE_IN]:
+ return self.state_strings[state]
+ elif state in self.states:
+ return self.states[state]
+ else:
+ return "Unknown"
+
+ def open(self):
+ self.cmd_out()
+
+ def close(self):
+ self.cmd_in()
+
+ def cmd_in(self):
+ self.chan_actuator.set_value( STATE_IN )
+
+ def cmd_out(self):
+ self.chan_actuator.set_value( STATE_OUT )
+
+def test_hwo(hwo):
+ print("Name is: ", hwo.getUserName())
+ print("Shutter state is: ", hwo.get_state())
+ print("Shutter status is: ", hwo.get_status())
diff --git a/mxcubecore/HardwareObjects/ALBA/XalocFastShutter.py b/mxcubecore/HardwareObjects/ALBA/XalocFastShutter.py
new file mode 100755
index 0000000000..a24a0b6951
--- /dev/null
+++ b/mxcubecore/HardwareObjects/ALBA/XalocFastShutter.py
@@ -0,0 +1,233 @@
+# Project: 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 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with MXCuBE. If not, see .
+
+"""
+[Name] XalocFastShutter
+
+[Description]
+HwObj used to operate the Fast Shutter
+
+[Signals]
+- fastStateChanged
+"""
+
+from __future__ import print_function
+
+import logging
+import time
+
+from mxcubecore import BaseHardwareObjects
+from taurus.core.tango.enums import DevState
+
+
+__credits__ = ["ALBA Synchrotron"]
+__version__ = "2.3"
+__category__ = "General"
+
+STATE_OUT, STATE_IN, STATE_MOVING, STATE_FAULT, STATE_ALARM, STATE_UNKNOWN = \
+ (0, 1, 9, 11, 13, 23)
+
+
+class XalocFastShutter(BaseHardwareObjects.Device):
+ """
+ Shutter IN: motor position is 0 and IDLE state is High.
+ Shutter OUT: motor position is 0 and IDLE state is Low.
+ Shutter Fault: motor position is not 0.
+ """
+
+ states = {
+ STATE_OUT: "out",
+ STATE_IN: "in",
+ STATE_MOVING: "moving",
+ STATE_FAULT: "fault",
+ STATE_ALARM: "alarm",
+ STATE_UNKNOWN: "unknown",
+ }
+
+ default_state_strings = ["Out", "In"]
+
+ def __init__(self, name):
+ BaseHardwareObjects.Device.__init__(self, name)
+ self.logger = logging.getLogger("HWR.XalocFastShutter")
+ self.cmd_ni_start = None
+ self.cmd_ni_stop = None
+
+ self.chan_actuator = None
+ self.chan_motor_pos = None
+ self.chan_motor_state = None
+
+ self.actuator_state = STATE_UNKNOWN
+ self.actuator_value = None
+ self.motor_position = None
+ self.motor_state = None
+ self.state_strings = None
+
+ self.shutter_delay_time_sec = None
+
+ def init(self):
+ self.logger.debug("Initializing {0}".format(self.__class__.__name__))
+ try:
+ self.shutter_delay_time_sec = self.get_property('shutter_delay_time_sec')
+ self.cmd_ni_start = self.get_command_object("nistart")
+ self.cmd_ni_stop = self.get_command_object("nistop")
+
+ self.chan_actuator = self.get_channel_object('actuator')
+ self.chan_motor_pos = self.get_channel_object('motorposition')
+ self.chan_motor_state = self.get_channel_object('motorstate')
+
+ self.chan_actuator.connect_signal('update', self.state_changed)
+ self.chan_motor_pos.connect_signal('update', self.motor_position_changed)
+ self.chan_motor_state.connect_signal('update', self.motor_state_changed)
+ except Exception:
+ self.logger.warning('Error when initilaizing')
+
+ try:
+ state_string = self.get_property("states")
+ if state_string is None:
+ self.state_strings = self.default_state_strings
+ else:
+ states = state_string.split(",")
+ self.state_strings = states[1].strip(), states[0].strip()
+ except Exception as e:
+ self.logger.warning("%s" % str(e))
+ self.state_strings = self.default_state_strings
+
+ def get_state(self):
+ if self.actuator_state == STATE_UNKNOWN:
+ self.actuator_value = self.chan_actuator.get_value()
+ self.motor_position = self.chan_motor_pos.get_value()
+ self.motor_state = self.chan_motor_state.get_value()
+ self.update_state(value)
+ return self.actuator_state
+
+ def update_state(self, state_unused):
+
+ if None in [self.actuator_value, self.motor_position, self.motor_state]:
+ act_state = STATE_UNKNOWN
+ elif self.motor_state == DevState.MOVING:
+ act_state = STATE_MOVING
+ elif self.motor_state != DevState.ON or abs(self.motor_position) > 0.01:
+ act_state = STATE_ALARM
+ else:
+ state = self.actuator_value.lower()
+
+ if state == 'high':
+ act_state = STATE_IN
+ else:
+ act_state = STATE_OUT
+
+ if act_state != self.actuator_state:
+ self.actuator_state = act_state
+ self.emit_state_changed()
+
+ def state_changed(self, value):
+ self.actuator_value = value
+ self.update_state(value)
+
+ def motor_position_changed(self, value):
+ self.motor_position = value
+ self.update_state(value)
+
+ def motor_state_changed(self, value):
+ self.motor_state = value
+ self.update_state(value)
+
+ def emit_state_changed(self):
+ self.emit('fastStateChanged', (self.actuator_state,))
+
+ def get_motor_position(self):
+ if self.motor_position is None:
+ self.motor_position = self.chan_motor_pos.get_value()
+ return self.motor_position
+
+ def get_motor_state(self):
+ if self.motor_state is None:
+ self.motor_state = self.chan_motor_state.get_value()
+ return self.motor_state
+
+ def get_user_name(self):
+ return self.username
+
+ def get_shutter_delay_sec(self):
+ return self.shutter_delay_time_sec
+
+ def get_status(self):
+ state = self.getState()
+
+ if state in [STATE_OUT, STATE_IN]:
+ return self.state_strings[state]
+ elif state in self.states:
+ return self.states[state]
+ else:
+ return "Unknown"
+
+ def cmd_in(self):
+ self.open()
+
+ def cmd_out(self):
+ self.close()
+
+ def close(self):
+ self.logger.debug("Closing the fast shutter")
+ #self.logger.debug("value = %s, state = %s" %
+ #(self.chan_motor_pos.get_value(),
+ #self.actuator_state))
+ if abs(self.chan_motor_pos.get_value()) > 0.01:
+ while self.get_motor_state() != DevState.ON:
+ time.sleep(0.5)
+ # closed position is 0
+ self.chan_motor_pos.set_value(0)
+ self.set_ttl('High')
+
+ def open(self):
+ self.logger.debug("Opening the fast shutter")
+ #self.logger.debug("value = %s, state = %s" %
+ #(self.chan_motor_pos.get_value(),
+ #self.actuator_state))
+
+ if abs(self.chan_motor_pos.get_value()) > 0.01:
+ self.chan_motor_pos.set_value(0)
+ self.set_ttl('Low')
+
+ def set_ttl(self, value):
+ self.cmd_ni_stop()
+ self.chan_actuator.set_value(value)
+ self.cmd_ni_start()
+
+ def is_open(self):
+ if self.actuator_state == STATE_IN:
+
+ return True
+ else:
+ return False
+
+ def is_close(self):
+ if self.actuator_state == STATE_OUT:
+ return True
+ else:
+ return False
+
+
+def test_hwo(hwo):
+ print("Name is: ", hwo.get_user_name())
+ print("Shutter state is: ", hwo.get_state())
+ print("Shutter status is: ", hwo.get_status())
+ print("Motor position is: ", hwo.get_motor_position())
+ print("Motor state is: ", hwo.get_motor_state())
+ print("Is shutter open: ", hwo.is_open())
+ print("Is shutter close: ", hwo.is_close())
diff --git a/mxcubecore/HardwareObjects/ALBA/XalocFlux.py b/mxcubecore/HardwareObjects/ALBA/XalocFlux.py
new file mode 100644
index 0000000000..839203ea73
--- /dev/null
+++ b/mxcubecore/HardwareObjects/ALBA/XalocFlux.py
@@ -0,0 +1,116 @@
+# Project: 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 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with MXCuBE. If not, see .
+
+"""
+[Name] XalocFlux
+
+[Description]
+HwObj used to get the flux
+
+[Signals]
+- None
+"""
+
+from __future__ import print_function
+
+import logging
+
+from mxcubecore.HardwareObjects.abstract.AbstractFlux import AbstractFlux
+from mxcubecore import HardwareRepository as HWR
+#from HardwareRepository.BaseHardwareObjects import Device
+
+__credits__ = ["ALBA Synchrotron"]
+__version__ = "3"
+__category__ = "General"
+
+
+class XalocFlux(AbstractFlux):
+
+ def __init__(self, name):
+ self.logger = logging.getLogger("HWR.XalocFlux")
+ AbstractFlux.__init__(self, name)
+ self.current_chn = None
+ self.transmission_chn = None
+ self.last_flux_chn = None
+ self.last_flux_norm_chn = None
+ self.default_flux = None
+
+ def init(self):
+ self.logger.debug("Initializing {0}".format(self.__class__.__name__))
+ self.transmission_chn = self.get_channel_object("transmission")
+ self.last_flux_chn = self.get_channel_object("last_flux")
+ self.last_flux_norm_chn = self.get_channel_object("last_flux_norm")
+ self.default_flux = self.get_property('default_flux')
+ if self.default_flux == None:
+ self.default_flux = 1.5E12
+ self.logger.debug("Default flux set to %8.3f" % self.default_flux)
+
+ def get_value(self):
+ return self.get_flux()
+
+ def get_flux(self):
+ last_flux = self.last_flux_chn.get_value()
+ try:
+ if last_flux != None:
+ if last_flux > 1e7:
+ return self.get_flux_from_last_measured() * self.get_transmission()
+ else:
+ self.logger.debug( "Flux value abnormally low" )
+ else:
+ self.logger.debug( "Flux value is None" )
+
+
+ except Exception as e:
+ self.logger.error("Cannot read flux\n%s" % str(e))
+ #logging.getLogger("user_level_log").error("Cannot read flux\n%s" % str(e))
+
+ self.logger.debug( "Returning default flux value %8.3f" % self.default_flux )
+
+ return self.default_flux
+
+
+ def get_transmission(self):
+ """ returns transmission between 0 and 1"""
+ return self.transmission_chn.get_value() / 100.
+
+ def get_flux_from_last_measured(self):
+ last_flux_norm = self.last_flux_norm_chn.get_value()
+ current = HWR.beamline.machine_info.get_mach_current()
+ self.logger.debug("XalocFlux machine current %s" % current)
+
+ last_current = (last_flux_norm / 250.) * current
+ return last_current
+
+ def get_dose_rate(self, energy=None):
+ """
+ Get dose rate in kGy/s for a standard crystal at current settings.
+ Assumes Gaussian beam with beamsize giving teh FWHH in both dimensions.
+
+ :param energy: float Energy for calculation of dose rate, in keV.
+ :return: float
+ """
+
+ # The factor 1.25 converts from the average value over the beamsize
+ # to an estimated flux density at the peak.
+ return 1.25 * AbstractFlux.AbstractFlux.get_dose_rate_per_photon_per_mmsq(self, energy=energy)
+
+
+def test_hwo(hwo):
+ print("Flux = %.4e" % hwo.get_flux())
+ print("Last current = %.4e" % hwo.get_last_current())
+ print("Transmission = %.2f" % hwo.get_transmission())
diff --git a/mxcubecore/HardwareObjects/ALBA/XalocFrontEnd.py b/mxcubecore/HardwareObjects/ALBA/XalocFrontEnd.py
new file mode 100644
index 0000000000..4312e631ee
--- /dev/null
+++ b/mxcubecore/HardwareObjects/ALBA/XalocFrontEnd.py
@@ -0,0 +1,70 @@
+# Project: 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 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with MXCuBE. If not, see .
+
+"""
+[Name] XalocFrontEnd
+
+[Description]
+The XalocFastShutter hardware object is a variation of the XalocEpsActuator
+where the command to open/close is done on a different channel than the
+reading of the shutter state.
+
+The interface is otherwise exactly the same as the XalocEpsActuator
+
+[Signals]
+- None
+"""
+
+from __future__ import print_function
+
+import logging
+
+from XalocEpsActuator import XalocEpsActuator
+
+__credits__ = ["ALBA Synchrotron"]
+__version__ = "2.3"
+__category__ = "General"
+
+
+class XalocFrontEnd(XalocEpsActuator):
+ def __init__(self, name):
+ XalocEpsActuator.__init__(self, name)
+ self.logger = logging.getLogger("HWR.XalocFrontEnd")
+ self.logger.debug("__init__()")
+ self.chan_open = None
+ self.chan_close = None
+
+ def init(self):
+ self.logger.debug("Initializing {0}".format(self.__class__.__name__))
+ XalocEpsActuator.init(self)
+
+ self.chan_open = self.get_channel_object('open_command')
+ self.chan_close = self.get_channel_object('close_command')
+
+ def cmd_out(self):
+ self.chan_close.set_value(False)
+ self.chan_open.set_value(True)
+
+ def cmd_in(self):
+ self.chan_open.set_value(False)
+ self.chan_close.set_value(True)
+
+def test_hwo(hwo):
+ print("Name is: ", hwo.getUserName())
+ print("Shutter state is: ", hwo.get_state())
+ print("Shutter status is: ", hwo.get_status())
diff --git a/mxcubecore/HardwareObjects/ALBA/XalocFrontLight.py b/mxcubecore/HardwareObjects/ALBA/XalocFrontLight.py
new file mode 100755
index 0000000000..0ead1265d0
--- /dev/null
+++ b/mxcubecore/HardwareObjects/ALBA/XalocFrontLight.py
@@ -0,0 +1,155 @@
+# Project: 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 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with MXCuBE. If not, see .
+
+"""
+[Name] XalocFrontLight
+
+[Description]
+HwObj used to control the diffractometer front light.
+
+[Signals]
+- levelChanged
+- stateChanged
+"""
+
+#from __future__ import print_function
+
+import logging
+
+from mxcubecore.BaseHardwareObjects import Device
+from taurus.core.tango.enums import DevState
+
+__credits__ = ["ALBA Synchrotron"]
+__version__ = "3"
+__category__ = "General"
+
+
+class XalocFrontLight(Device):
+
+ def __init__(self, *args):
+ Device.__init__(self, *args)
+ self.logger = logging.getLogger("HWR.XalocFrontLight")
+
+ self.chan_level = None
+ self.chan_state = None
+
+ self.limits = [None, None]
+
+ self.state = None
+ self.dev_server_state = None # state of the device server controlling the light
+
+ self.current_level = None
+
+ self.default_off_threshold = 1 # threshold is 1 click above off value
+ self.off_threshold = None
+
+ def init(self):
+ self.logger.debug("Initializing {0}".format(self.__class__.__name__))
+ self.chan_level = self.get_channel_object("light_level")
+ self.chan_state = self.get_channel_object("state")
+ self.off_threshold = self.get_property("off_threshold", self.default_off_threshold)
+ self.logger.debug("Off_threshold value = %s" % self.off_threshold)
+
+ self.set_name('frontlight')
+
+ limits = self.get_property("limits")
+ if limits is not None:
+ lims = limits.split(",")
+ if len(lims) == 2:
+ self.limits = map(float, lims)
+
+ self.chan_level.connect_signal("update", self.level_changed)
+ self.chan_state.connect_signal("update", self.dev_server_state_changed)
+
+ def is_ready(self):
+ return True
+
+ def level_changed(self, value):
+ #self.logger.debug("FrontLight level changed, value = %s" % value)
+ self.current_level = float( value )
+ self.update_current_state()
+
+ self.emit('levelChanged', self.current_level)
+
+ def dev_server_state_changed(self, value):
+ #self.logger.debug("Device server state changed, value = %s" % value)
+ self.dev_server_state = value
+ if value != DevState.ON:
+ self.logger.error("The device server of the front light is not ON")
+ logging.getLogger('user_level_log').error("The device server of the front light is not ON. Call your LC")
+ self.update_current_state()
+
+ def update_current_state(self):
+ #self.logger.debug("FrontLight state is %s, off_threshold = %s, state == DevState.ON %s" % ( str(self.dev_server_state), \
+ #str(self.off_threshold), (self.dev_server_state == DevState.ON ) )
+ #)
+ newstate = False
+ if self.dev_server_state == DevState.ON:
+ if self.off_threshold is not None:
+ if self.current_level < 0.9 * self.off_threshold:
+ newstate = False
+ else:
+ newstate = True
+ else:
+ newstate = True
+ elif self.dev_server_state == DevState.OFF:
+ newstate = False
+ else:
+ newstate = False
+
+ if newstate != self.state:
+ self.state = newstate
+ self.emit('stateChanged', self.state)
+
+ def get_limits(self):
+ return self.limits
+
+ def get_state(self):
+ self.dev_server_state = str(self.chan_state.get_value()).lower()
+ self.update_current_state()
+ return self.state
+
+ def get_user_name(self):
+ return self.username
+
+ def get_level(self):
+ self.current_level = self.chan_level.get_value()
+ return self.current_level
+
+ def set_level(self, level):
+ #self.logger.debug("Setting level in %s to %s" % (self.username, level))
+ self.chan_level.set_value(float(level))
+
+ def set_on(self):
+ #self.logger.debug("Setting front light on with intensity %s" % str(self.limits[1] ) )
+ self.chan_level.set_value( float( self.limits[1] ) )
+
+ def set_off(self):
+ #self.logger.debug("Setting front light off")
+ self.chan_level.set_value( float( self.limits[0] ) )
+
+ def re_emit_values(self):
+ self.emit("stateChanged", self.state )
+ self.emit("levelChanged", self.current_level )
+
+
+def test_hwo(hwo):
+ print("Light control for \"%s\"\n" % hwo.get_user_name())
+ print("Level limits are:", hwo.get_limits())
+ print("Current level is:", hwo.get_level())
+ print("Current state is:", hwo.get_state())
diff --git a/mxcubecore/HardwareObjects/ALBA/XalocISPyBClient.py b/mxcubecore/HardwareObjects/ALBA/XalocISPyBClient.py
new file mode 100755
index 0000000000..06fdca51a4
--- /dev/null
+++ b/mxcubecore/HardwareObjects/ALBA/XalocISPyBClient.py
@@ -0,0 +1,231 @@
+# Project: 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 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with MXCuBE. If not, see .
+
+"""
+[Name] XalocISPyBClient
+
+[Description]
+HwObj used to interface the ISPyB database
+
+[Signals]
+- None
+"""
+
+#from __future__ import print_function
+
+import logging
+
+from mxcubecore.HardwareObjects.ISPyBClient import ISPyBClient, trace, utf_encode
+from mxcubecore import HardwareRepository as HWR
+from suds import WebFault
+try:
+ from urlparse import urljoin
+ from urllib2 import URLError
+except Exception:
+ # Python3
+ from urllib.parse import urljoin
+ from urllib.error import URLError
+
+from suds.sudsobject import asdict
+
+__credits__ = ["ALBA Synchrotron"]
+__version__ = "3"
+__category__ = "General"
+
+
+class XalocISPyBClient(ISPyBClient):
+
+ def __init__(self, *args):
+ ISPyBClient.__init__(self, *args)
+ self.logger = logging.getLogger("HWR.XalocISPyBClient")
+
+ def init(self):
+ ISPyBClient.init(self)
+ self.logger.debug("Initializing {0}".format(self.__class__.__name__))
+
+ def ldap_login(self, login_name, psd, ldap_connection):
+ # overwrites standard ldap login is ISPyBClient2.py
+ # to query for homeDirectory
+
+ if ldap_connection is None:
+ ldap_connection = self.ldapConnection
+
+ ok, msg = ldap_connection.login(
+ login_name, psd, fields=[
+ "uid", "homeDirectory"])
+ self.logger.debug("ALBA LDAP login success %s (msg: %s)" % (ok, msg))
+ if ok:
+ vals = ldap_connection.get_field_values()
+ if vals != None:
+ if 'homeDirectory' in vals:
+ home_dir = vals['homeDirectory'][0]
+ self.logger.debug("The homeDirectory for user %s is %s" %
+ (login_name, home_dir))
+ HWR.beamline.session.set_ldap_homedir(home_dir)
+ else:
+ self.logger.error( "ALBA LDAP error, no home directory found for proposal %s" % (login_name) )
+ home_dir = '/tmp'
+ HWR.beamline.session.set_ldap_homedir(home_dir)
+
+ return ok, msg
+
+ def translate(self, code, what):
+ """
+ Given a proposal code, returns the correct code to use in the GUI,
+ or what to send to LDAP, user office database, or the ISPyB database.
+ """
+ self.logger.debug("Translating %s %s" % (code, what))
+ if what == 'ldap':
+ if code == 'mx':
+ return 'u'
+
+ if what == 'ispyb':
+ if code == 'u' or code == 'uind-':
+ return 'mx'
+
+ return code
+
+ def prepare_collect_for_lims(self, mx_collect_dict):
+ # Attention! directory passed by reference. modified in place
+
+ for i in range(4):
+ try:
+ prop = 'xtalSnapshotFullPath%d' % (i + 1)
+ path = mx_collect_dict[prop]
+ ispyb_path = HWR.beamline.session.path_to_ispyb(path)
+ logging.debug("%s = %s " % (prop, ispyb_path))
+ mx_collect_dict[prop] = ispyb_path
+ except BaseException as e:
+ logging.debug("Error when preparing collection for LIMS\n%s" % str(e))
+
+ def prepare_image_for_lims(self, image_dict):
+ for prop in ['jpegThumbnailFileFullPath', 'jpegFileFullPath']:
+ try:
+ path = image_dict[prop]
+ ispyb_path = HWR.beamline.session.path_to_ispyb(path)
+ image_dict[prop] = ispyb_path
+ except BaseException as e:
+ logging.debug("Error when preparing image for LIMS\n%s" % str(e))
+
+ @trace
+ def get_samples(self, proposal_id, session_id):
+ response_samples = None
+
+ if self._tools_ws:
+ try:
+ response_samples = self._tools_ws.service.findSampleInfoLightForProposal(
+ proposal_id, self.beamline_name
+ )
+
+ response_samples = [
+ utf_encode(asdict(sample)) for sample in response_samples
+ ]
+ #logging.getLogger("HWR").debug("%s" % response_samples)
+ # response_samples holds an array of dictionaries. Each dictionary represents a sample.
+ # the basket location in the robot is held in the key containerSampleChangerLocation
+ # the sample location in the basket is held in the key sampleLocation
+ # eg sample_list[0]['containerSampleChangerLocation'] returns '1'
+ # and sample_list[0]['sampleLocation'] returns '1'
+
+ except WebFault as e:
+ logging.getLogger("ispyb_client").exception(str(e))
+ except URLError:
+ logging.getLogger("ispyb_client").exception(_CONNECTION_ERROR_MSG)
+ else:
+ logging.getLogger("ispyb_client").exception(
+ "Error in get_samples: could not connect to server"
+ )
+
+ self.emit("ispyb_sync_successful")
+
+ return response_samples
+
+ def next_sample_by_SC_position(self, input_sample_location ):
+ input_sample_container = input_sample_location[0]
+ input_sample_num = input_sample_location[1]
+ self.logger.debug(
+ "next_sample_by_SC_position: searching for next sample, current location %s" % str(input_sample_location)
+ )
+ input_sample_type = HWR.beamline.sample_changer.basket_types[ input_sample_container ]# spine or unipuck
+
+ sample_dict = self.get_samples(
+ HWR.beamline.session.proposal_id, HWR.beamline.session.session_id
+ )
+
+ next_sample_container = HWR.beamline.sample_changer.number_of_baskets+1 #+1 # more than max number of containers
+ #next_sample_container = 17
+ next_sample_num = 100000
+ suitable_sample_in_input_container = False
+ for sample in sample_dict:
+ if sample['containerSampleChangerLocation'] != 'None' and \
+ HWR.beamline.sample_changer.get_cassette_type( int(sample['containerSampleChangerLocation']) ) == \
+ HWR.beamline.sample_changer.get_cassette_type( input_sample_container ):
+ #if sample['containerSampleChangerLocation'] != 'None':
+ self.logger.debug("next sample container %s" % sample['containerSampleChangerLocation'] )
+ #print("next sample container %s" % sample['containerSampleChangerLocation'] )
+ first_sample_num = 0
+ if int(sample['containerSampleChangerLocation']) == input_sample_container:
+ first_sample_num = input_sample_num
+ self.logger.debug(" sample in same container %s" % sample['containerSampleChangerLocation'] )
+ #print(" sample in same container %s" % sample['containerSampleChangerLocation'] )
+ if int( sample['sampleLocation'] ) > first_sample_num:
+ self.logger.debug(" suitable sample %s in same container %s" % (sample['sampleLocation'], sample['containerSampleChangerLocation'] ) )
+ #print(" suitable sample %s in same container %s" % (sample['sampleLocation'], sample['containerSampleChangerLocation'] ) )
+ suitable_sample_in_input_container = True
+ next_sample_container = input_sample_container
+ if int( sample['sampleLocation'] ) < next_sample_num:
+ next_sample_num = int( sample['sampleLocation'] )
+ if next_sample_num == input_sample_num+1: break
+ elif int(sample['containerSampleChangerLocation']) > input_sample_container and \
+ not suitable_sample_in_input_container:
+ if int(sample['containerSampleChangerLocation']) < next_sample_container:
+ self.logger.debug("found container %s, which is closer to input container %s" % ( sample['containerSampleChangerLocation'], input_sample_container ) )
+ #print("found container %s, which is closer to input container %s" % ( sample['containerSampleChangerLocation'], input_sample_container ) )
+ next_sample_container = int(sample['containerSampleChangerLocation'])
+ next_sample_num = 100000
+ first_sample_num = 0
+ if int( sample['sampleLocation'] ) > first_sample_num and int( sample['sampleLocation'] ) < next_sample_num:
+ self.logger.debug("next sample found container %s, location %s" %
+ ( sample['containerSampleChangerLocation'], sample['sampleLocation'] )
+ )
+ #print("next sample found: container %s, location %s" % ( sample['containerSampleChangerLocation'], sample['sampleLocation'] ) )
+ next_sample_num = int( sample['sampleLocation'] )
+
+# For testing purposes, delete...
+#sample_dict = []
+#for container in range(9):
+ #for sample in range(16):
+ #if container != 2: sample_dict.append( {'containerSampleChangerLocation': 9-container, 'sampleLocation': sample})
+
+ if next_sample_container == HWR.beamline.sample_changer.number_of_baskets+1: return -1,-1
+ return next_sample_container, next_sample_num
+
+def test_hwo(hwo):
+ proposal = 'mx2018002222'
+ pasw = '2222008102'
+
+ info = hwo.login(proposal, pasw)
+ # info = hwo.get_proposal(proposal_code, proposal_number)
+ # info = hwo.get_proposal_by_username("u2020000007")
+ print(info['status'])
+
+ print("Getting associated samples")
+ session_id = 58248
+ proposal_id = 8250
+ samples = hwo.get_samples(proposal_id, session_id)
+ print(samples)
diff --git a/mxcubecore/HardwareObjects/ALBA/XalocImageTracking.py b/mxcubecore/HardwareObjects/ALBA/XalocImageTracking.py
new file mode 100755
index 0000000000..50414ef143
--- /dev/null
+++ b/mxcubecore/HardwareObjects/ALBA/XalocImageTracking.py
@@ -0,0 +1,116 @@
+"""
+[Name] XalocImageTracking
+
+[Description] Hardware object used to control image tracking
+By default ADXV is used
+
+Copy from EMBLImageTracking
+"""
+import os
+import time
+import logging
+import socket
+from mxcubecore.BaseHardwareObjects import Device
+
+
+class XalocImageTracking(Device):
+
+ def __init__(self, *args):
+ Device.__init__(self, *args)
+ self.logger = logging.getLogger("HWR.XalocImageTracking")
+
+ # self.cmd_start = None
+ # self.cmd_stop = None
+ self.cmd_send_image = None
+
+ # self.chan_state = None
+ # self.chan_status = None
+ # self.image_tracking_enabled = None
+
+ def init(self):
+
+ # self.chan_state = self.getChannelObject("State")
+ # self.chan_status = self.getChannelObject("Status")
+ # self.connect(self.chan_state, "update", self.state_changed)
+ #
+ # self.cmd_start = self.getCommandObject('start')
+ # self.cmd_stop = self.getCommandObject('stop')
+ self.cmd_send_image = self.get_command_object('send_image')
+
+ # def enable_image_tracking_changed(self, state):
+ # self.logger.debug('enable_image_tracking_changed: %s' % state)
+ # self.image_tracking_enabled = state
+ # self.emit("imageTrackingEnabledChanged", (self.image_tracking_enabled, ))
+ #
+ # def state_changed(self, state):
+ # self.logger.debug('state_changed: %s' % state)
+ # if self.state != state:
+ # self.state = state
+ # self.emit("stateChanged", (self.state, ))
+ #
+ # def is_tracking_enabled(self):
+ # self.logger.debug('is_tracking enabled')
+ # if self.chan_enable_image_tracking is not None:
+ # return self.chan_enable_image_tracking.get_value()
+ #
+ # def set_image_tracking_state(self, state):
+ # self.logger.debug('set image tracking state: %s' % state)
+ # if self.chan_enable_image_tracking is not None:
+ # self.chan_enable_image_tracking.set_value(state)
+
+ def load_image(self, image_name):
+ self.logger.debug('load_image: %s' % image_name)
+ self.cmd_send_image(image_name)
+
+
+# This was a first version, not based on the Tango DS for the ADXV
+class XalocImageTrackingLocal(Device):
+
+ def __init__(self, *args):
+ Device.__init__(self, *args)
+ self.logger = logging.getLogger("HWR.XalocImageTrackingLocal")
+ self.binary = None
+ self.host = None
+ self.port = None
+ self.autofront = None
+ self.start_adxv_cmd = None
+
+ def init(self):
+ self.binary = self.get_property('executable')
+ self.host = self.get_property('host')
+ self.port = self.get_property('port', '8100')
+ self.autofront = self.get_property('autofront', True)
+
+ if self.binary:
+ _cmd = '{} -socket {}'.format(self.binary, self.port)
+ if self.host:
+ self.start_adxv_cmd = 'ssh {} "{}"'.format(self.host, _cmd)
+ else:
+ self.host = socket.gethostname()
+ self.start_adxv_cmd = _cmd
+
+ def load_image(self, image_name):
+ self._load_image(str(image_name))
+
+ def _load_image(self, image_file_name):
+ """
+ Send the image path associated to this spot to the adxv via socket.
+
+ :param image_file_name: image file associated to the spot.
+ :return: None
+ """
+ def send():
+ self.logger.debug(
+ "Opening socket connection for image: %s" % image_file_name)
+ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ s.connect((self.host, self.port))
+ self.logger.debug("Sending image {}".format(image_file_name))
+ if self.autofront:
+ s.send("raise_window Image\n")
+ s.send("load_image %s\n" % image_file_name)
+ try:
+ send()
+ except Exception as e:
+ os.system(self.start_adxv_cmd)
+ time.sleep(2)
+ send()
diff --git a/mxcubecore/HardwareObjects/ALBA/XalocLN2Shower.py b/mxcubecore/HardwareObjects/ALBA/XalocLN2Shower.py
new file mode 100755
index 0000000000..d1d2cb02d9
--- /dev/null
+++ b/mxcubecore/HardwareObjects/ALBA/XalocLN2Shower.py
@@ -0,0 +1,210 @@
+#
+# Project: 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 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with MXCuBE. If not, see .
+
+"""
+[Name]
+Liquid nitrogen shower hardware object
+
+[Description]
+Specific HwObj for the liquid nitrogen pump installed at XALOC to wash the crystal
+
+[Emitted signals]
+- ln2showerIsPumpingChanged
+- ln2showerFault
+
+TODO: when the dewar is empty, the operation is INVALID and the State is FAULT
+"""
+
+import logging
+import PyTango
+import time
+
+from taurus.core.tango.enums import DevState
+
+from mxcubecore import HardwareRepository as HWR
+from mxcubecore.BaseHardwareObjects import HardwareObject
+
+__credits__ = ["ALBA Synchrotron"]
+__version__ = "3"
+__category__ = "General"
+__author__ = "Roeland Boer"
+
+class XalocLN2Shower(HardwareObject):
+ """
+ Specific liquid nitrogen shower HwObj for XALOC beamline.
+ """
+
+ def __init__(self, name):
+ HardwareObject.__init__(self, name)
+
+ self.logger = logging.getLogger("HWR.XalocLN2Shower")
+ self.userlogger = logging.getLogger("user_level_log")
+
+ self.username = None
+ self.chn_operation_mode = None
+ self.chn_state = None
+ self.operation_mode = None
+ self.state = None
+ self.is_pumping_attr = None
+ self.cmd_ln2shower_wash = None
+ self.cmd_ln2shower_cold = None
+ self.cmd_ln2shower_setflow = None
+ self.cmd_ln2shower_on = None
+ self.cmd_ln2shower_off = None
+ self.cmd_ln2shower_sleep = None
+
+ self.wash_mounted_crystals = None # wash every crystal mounted by robot
+ self.robot_path_is_safe = None
+ self.sample_changer_loading = None
+
+ self.collecting = None
+ self.super_hwobj = None
+
+
+ def init(self):
+ self.logger.debug("Initializing {0}".format(self.__class__.__name__))
+ self.username = self.get_property("username")
+ self.wash_mounted_crystals = self.get_property("wash_mounted_crystals")
+
+ self.chn_operation_mode = self.get_channel_object("operation_mode")
+ self.chn_state = self.get_channel_object("State")
+
+ self.cmd_ln2shower_wash = self.get_command_object("ln2shower_wash")
+ self.cmd_ln2shower_cold = self.get_command_object("ln2shower_cold")
+ self.cmd_ln2shower_setflow = self.get_command_object("ln2shower_setflow")
+ self.cmd_ln2shower_on = self.get_command_object("ln2shower_on")
+ self.cmd_ln2shower_off = self.get_command_object("ln2shower_off")
+ self.cmd_ln2shower_sleep = self.get_command_object("ln2shower_sleep")
+
+ if HWR.beamline.sample_changer is not None:
+ self.robot_path_is_safe = HWR.beamline.sample_changer.path_safe()
+ self.sample_changer_loading = HWR.beamline.sample_changer.cats_running
+
+ if HWR.beamline.detector is not None:
+ if HWR.beamline.detector.get_cam_state() == "RUNNING":
+ self.collecting = True
+ elif HWR.beamline.detector.get_cam_state() == "STANDBY":
+ self.collecting = False
+ else:
+ raise Exception("The detector seems to be in a funny state")
+
+ self.super_hwobj = self.get_object_by_role('beamline-supervisor')
+
+ self.connect(self.chn_operation_mode, "update", self.operation_mode_changed)
+ self.connect(self.chn_state, "update", self.state_changed)
+
+ if HWR.beamline.collect is not None:
+ self.connect(
+ HWR.beamline.collect, "collectStarted", self.collect_started
+ )
+ self.connect(
+ HWR.beamline.collect, "collectOscillationFinished", self.collect_finished
+ )
+ self.connect(
+ HWR.beamline.collect, "collectOscillationFailed", self.collect_finished
+ )
+
+ if HWR.beamline.sample_changer is not None:
+ HWR.beamline.sample_changer.connect("path_safeChanged", self.path_safe_changed)
+ HWR.beamline.sample_changer.connect("loadedSampleChanged", self.loaded_sample_changed)
+
+ def collect_started(self, owner, num_oscillations):
+ #logging.getLogger("user_level_log").info("Collection started in sample_control_brick")
+ self.collecting = True
+
+ def collect_finished(self, owner, state, message, *args):
+ #logging.getLogger("user_level_log").info("Collection finished in sample_control_brick")
+ self.collecting = False
+
+ def path_safe_changed(self, value):
+ self.robot_path_is_safe = value
+ HWR.beamline.diffractometer.wait_device_ready()
+ if value == False:
+ self.sample_changer_loading = True
+ if self.wash_mounted_crystals and HWR.beamline.diffractometer.get_current_phase() == 'Transfer':
+ self.run_ln2shower_wash()
+ else: self.sample_changer_loading = False
+
+ def run_ln2shower_wash(self, washflow = 120):
+ #TODO: move diff to transfer phase first, use XalocMiniDiff set_phase method
+
+ self.logger.debug( "get_current_phase %s" % HWR.beamline.diffractometer.get_current_phase() )
+ self.super_hwobj.wait_ready(timeout = 30)
+ if not self.collecting:
+ if HWR.beamline.diffractometer.get_current_phase() != HWR.beamline.diffractometer.PHASE_TRANSFER:
+ HWR.beamline.diffractometer.set_diff_phase( HWR.beamline.diffractometer.PHASE_TRANSFER, timeout = 20 )
+ if HWR.beamline.diffractometer.get_current_phase() == HWR.beamline.diffractometer.PHASE_TRANSFER:
+ self.cmd_ln2shower_wash(washflow, wait = False)
+ return True
+ else:
+ return False
+ else:
+ self.logger.debug( "Cannot use the shower while collecting!! Wait till the collection is finished" )
+ return False
+
+ return True
+
+ def run_ln2shower_off(self):
+ self.cmd_ln2shower_off(wait = False)
+
+ def operation_mode_changed(self, value):
+ """
+ value can be None!
+ """
+ if value is not None: value = int(value)
+ if self.operation_mode != value:
+ self.operation_mode = value
+ if self.operation_mode in [3]:
+ self.is_pumping_attr = True
+ else:
+ self.is_pumping_attr = False
+ self.emit("ln2showerIsPumpingChanged", self.is_pumping_attr)
+
+ def state_changed(self, value):
+ """
+ value can be DevState.FAULT, DevState.ON
+ """
+ if value is not None:
+ if self.state != value:
+ self.state = value
+ self.emit("stateChanged", self.state)
+ if value in [DevState.FAULT]:
+ self.emit("ln2showerFault", True)
+ else:
+ self.emit("ln2showerFault", False)
+
+ def is_pumping(self):
+ return self.is_pumping_attr
+
+ def loaded_sample_changed(self, sample):
+ """
+ For each getput, the signal is emitted twice: once when the crystal is removed,
+ once when the new crystal is mounted.
+ For a get or a put, only one signal is sent
+ Want only the first signal and turn off the shower.
+
+ TODO: when a put is done, the waiting time should be reduced, because the robot is in and out much faster
+ """
+ time_margin = 2 # waiting time between detecting change of sample and turning off the shower
+ if self.sample_changer_loading:
+ if self.wash_mounted_crystals:
+ time.sleep( time_margin ) # give the CATS time to load the next (in case of getput)
+ self.run_ln2shower_off()
+ self.sample_changer_loading = False
+
diff --git a/mxcubecore/HardwareObjects/ALBA/XalocMachineInfo.py b/mxcubecore/HardwareObjects/ALBA/XalocMachineInfo.py
index 0a2340d5cb..13fefd5703 100644
--- a/mxcubecore/HardwareObjects/ALBA/XalocMachineInfo.py
+++ b/mxcubecore/HardwareObjects/ALBA/XalocMachineInfo.py
@@ -1,185 +1,126 @@
#
# Project: MXCuBE
-# https://github.com/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
+# it under the terms of the GNU 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.
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the`
+# GNU 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 .
+# You should have received a copy of the GNU General Public License
+# along with MXCuBE. If not, see .
"""
[Name]
-ALBAMachineInfo
+XalocMachineInfo
[Description]
Hardware Object is used to get relevant machine information
(machine current, time to next injection, status, etc)
-Based on EMBL HwObj
-[Channels]
-- MachineCurrent
-- TopUpRemaining
-- State
-
-[Commands]
-
-[Emited signals]
+[Emitted signals]
- valuesChanged
-
-[Functions]
-- None
-
-[Included Hardware Objects]
-- None
-
-
-Example Hardware Object XML file :
-==================================
-
- Mach
- mach/ct/gateway
- State
- Current
- TopUpRemaining
-
"""
+from __future__ import print_function
+
import logging
-import time
-from gevent import spawn
-from urllib2 import urlopen
-from datetime import datetime, timedelta
-from mxcubecore import HardwareRepository as HWR
from mxcubecore.BaseHardwareObjects import Equipment
-
-__author__ = "Jordi Andreu"
-__credits__ = ["MXCuBE collaboration"]
-
-__version__ = "2.2."
-__maintainer__ = "Jordi Andreu"
-__email__ = "jandreu[at]cells.es"
-__status__ = "Draft"
+__credits__ = ["ALBA Synchrotron"]
+__version__ = "2.3"
+__category__ = "General"
class XalocMachineInfo(Equipment):
- """
- Descript. : Displays actual information about the machine status.
- """
def __init__(self, name):
Equipment.__init__(self, name)
- """
- Descript. :
- """
- # Parameters values
- self.values_dict = {}
- self.values_dict["mach_current"] = None
- self.values_dict["mach_status"] = ""
- self.values_dict["topup_remaining"] = ""
- # Dictionary for booleans indicating if values are in range
- # self.values_in_range_dict = {}
+ self.logger = logging.getLogger('HWR.MachineInfo')
+ self.values_dict = dict()
+ self.values_dict['mach_current'] = None
+ self.values_dict['mach_status'] = ""
+ self.values_dict['topup_remaining'] = ""
+
self.chan_mach_current = None
self.chan_mach_status = None
self.chan_topup_remaining = None
def init(self):
- """
- Descript. : Inits channels from xml configuration.
- """
+ self.logger.debug("Initializing {0}".format(self.__class__.__name__))
try:
- self.chan_mach_current = self.get_channel_object("MachCurrent")
+ self.chan_mach_current = self.get_channel_object('MachCurrent')
if self.chan_mach_current is not None:
self.chan_mach_current.connect_signal(
- "update", self.mach_current_changed
- )
+ 'update', self.mach_current_changed)
- self.chan_mach_status = self.get_channel_object("MachStatus")
+ self.chan_mach_status = self.get_channel_object('MachStatus')
if self.chan_mach_status is not None:
- self.chan_mach_status.connect_signal("update", self.mach_status_changed)
+ self.chan_mach_status.connect_signal('update', self.mach_status_changed)
- self.chan_topup_remaining = self.get_channel_object("TopUpRemaining")
+ self.chan_topup_remaining = self.get_channel_object('TopUpRemaining')
if self.chan_topup_remaining is not None:
self.chan_topup_remaining.connect_signal(
- "update", self.topup_remaining_changed
- )
+ 'update', self.topup_remaining_changed)
except KeyError:
- logging.getLogger().warning("%s: cannot read machine info", self.name())
+ self.logger.warning('%s: cannot read machine info', self.name())
def mach_current_changed(self, value):
- """
- Descript. : Function called if the machine current is changed
- Arguments : new machine current (float)
- Return : -
- """
- if (
- self.values_dict["mach_current"] is None
- or abs(self.values_dict["mach_current"] - value) > 0.10
- ):
- self.values_dict["mach_current"] = value
- self.re_emit_values()
+ if self.values_dict['mach_current'] is None or\
+ abs(self.values_dict['mach_current'] - value) > 0.10:
+ self.values_dict['mach_current'] = value
+ self.update_values()
+ # self.logger.debug('New machine current value=%smA' % value)
def mach_status_changed(self, status):
- """
- Descript. : Function called if machine status is changed
- Arguments : new machine status (string)
- Return : -
- """
- self.values_dict["mach_status"] = str(status)
- self.re_emit_values()
+ self.values_dict['mach_status'] = str(status).split('.')[-1]
+ self.update_values()
+ # self.logger.debug('New machine status=%s' % status)
def topup_remaining_changed(self, value):
- """
- Descript. : Function called if topup ramaining is changed
- Arguments : new topup remainin (float)
- Return : -
- """
- self.values_dict["topup_remaining"] = value
- self.re_emit_values()
-
- def re_emit_values(self):
- """
- Descript. : Updates storage disc information, detects if intensity
- and storage space is in limits, forms a value list
- and value in range list, both emited by qt as lists
- Arguments : -
- Return : -
- """
-
- values_to_send = []
- values_to_send.append(self.values_dict["mach_current"])
- values_to_send.append(self.values_dict["mach_status"])
- values_to_send.append(self.values_dict["topup_remaining"])
-
- self.emit("valuesChanged", values_to_send)
+ self.values_dict['topup_remaining'] = value
+ self.update_values()
+ # self.logger.debug('New top-up remaining time=%ss' % value)
+
+ def update_values(self):
+ values_to_send = list()
+ values_to_send.append(self.values_dict['mach_current'])
+ values_to_send.append(self.values_dict['mach_status'])
+ values_to_send.append(self.values_dict['topup_remaining'])
+
+ self.emit('valuesChanged', values_to_send)
+ # self.logger.debug("SIGNAL valuesChanged emitted")
def get_mach_current(self):
- return self.chan_mach_current.get_value()
- # return self.values_dict['mach_current']
+ value = None
+ try:
+ value = self.chan_mach_current.get_value()
+ except Exception as e:
+ self.logger.error('Cannot read machine current value.\n%s' % str(e))
+ finally:
+ return value
+
+ def get_current(self):
+ return self.get_mach_current()
- # def get_current_value(self):
- # """
- # Descript. :
- # """
- # return self.values_dict['current']
+ def get_message(self):
+ return 'Machine info status: %s' % str(self.get_mach_status()).split('.')[-1]
def get_mach_status(self):
return self.chan_mach_status.get_value()
- # return self.values_dict['mach_status']
-
def get_topup_remaining(self):
return self.chan_topup_remaining.get_value()
-# return self.values_dict['remaining']
+def test_hwo(hwo):
+ print(hwo.get_message())
+ print("Current = %s" % hwo.get_current())
+ print("Top-Up remaining = %s" % hwo.get_topup_remaining())
diff --git a/mxcubecore/HardwareObjects/ALBA/XalocMiniDiff.py b/mxcubecore/HardwareObjects/ALBA/XalocMiniDiff.py
old mode 100644
new mode 100755
index 650a11e8cf..5c59113927
--- a/mxcubecore/HardwareObjects/ALBA/XalocMiniDiff.py
+++ b/mxcubecore/HardwareObjects/ALBA/XalocMiniDiff.py
@@ -1,267 +1,1316 @@
+#
+# Project: 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 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with MXCuBE. If not, see .
+
+"""
+[Name]
+XalocMiniDiff
+
+[Description]
+Specific HwObj for M2D2 diffractometer @ ALBA
+
+[Emitted signals]
+- pixelsPerMmChanged
+- kappaMotorMoved
+- phiMotorMoved
+- stateChanged
+- zoomMotorPredefinedPositionChanged
+- minidiffStateChanged
+- minidiffPhaseChanged
+"""
+
+from __future__ import print_function
+
import logging
import time
-from mxcubecore.HardwareObjects.GenericDiffractometer import (
- GenericDiffractometer,
-)
-from gevent.event import AsyncResult
import gevent
+import math
+import os
+import tempfile
+from PIL import Image
+import numpy as np
+from mxcubecore import HardwareRepository as HWR
+
+logger = logging.getLogger('HWR')
+
+try:
+ logger.warning("Importing lucid3")
+ import lucid3 as lucid
+except ImportError:
+ try:
+ logger.warning("Could not find lucid3, importing lucid")
+ import lucid
+ except ImportError:
+ logger.warning("Could not find autocentring library, automatic centring is disabled")
+
+import queue_model_objects
+import queue_entry
+
+from mxcubecore.HardwareObjects.GenericDiffractometer import GenericDiffractometer, DiffractometerState
+from taurus.core.tango.enums import DevState
+
+__credits__ = ["ALBA Synchrotron"]
+__version__ = "3"
+__category__ = "General"
+__author__ = "Roeland Boer, Jordi Andreu, Vicente Rey"
class XalocMiniDiff(GenericDiffractometer):
+ """
+ Specific diffractometer HwObj for XALOC beamline.
+ """
+
+ PHASE_TRANSFER = "Transfer"
+ PHASE_CENTRING = "Sample"
+ PHASE_COLLECTION = "Collect"
+ PHASE_BEAM = "Beam"
+ PHASE_UNKNOWN = "Unknown"
+
def __init__(self, *args):
GenericDiffractometer.__init__(self, *args)
+ self.logger = logging.getLogger("HWR.XalocMiniDiff")
+ self.userlogger = logging.getLogger("user_level_log")
+
+ self.chan_phase = None
+ self.chan_state = None
+ self.phi_motor_hwobj = None
+ self.phiz_motor_hwobj = None
+ self.phiy_motor_hwobj = None
+ self.zoom_motor_hwobj = None
+ self.focus_motor_hwobj = None
+ self.sample_x_motor_hwobj = None
+ self.sample_y_motor_hwobj = None
+ self.kappa_motor_hwobj = None
+ self.kappa_phi_motor_hwobj = None
+
+ self.omegaz_reference = None
+ self.omegaz_reference_channel = None
+
+ self.phi_direction = None # direction of the phi rotation angle as defined in centringMath
+ self.phi_centring_direction = None # change centring direction depending on phi value
+ self.saved_zoom_pos = None
+ self.sample_has_been_centred = None
+
+ # Number of images and total angle range used in automatic centering, defined in centring-math.xml
+ self.numCentringImages = None
+ self.centringAngleRange = None
self.centring_hwobj = None
+ self.cmd_go_transfer = None
+ self.cmd_go_sample_view = None
+
+ # For testing
+ self.no_sample = None
+
def init(self):
- self.calibration = self.get_object_by_role("calibration")
- self.centring_hwobj = self.get_object_by_role("centring")
+ self.logger.debug("Initializing {0}".format(self.__class__.__name__))
+
+ self.no_sample = self.get_property('no_sample', False)
+
+ self.centring_hwobj = self.get_object_by_role('centring')
+
+ #if HWR.beamline.centring is None:
if self.centring_hwobj is None:
- logging.getLogger("HWR").debug("EMBLMinidiff: Centring math is not defined")
+ self.logger.debug('XalocMinidiff: Centring math is not defined')
- self.cmd_start_auto_focus = self.get_command_object("startAutoFocus")
+ self.chan_phase = self.get_channel_object("Phase")
+ self.connect(self.chan_phase, "update", self.phase_changed)
+ self.chan_state = self.get_channel_object("State")
+ self.connect(self.chan_state, "update", self.state_changed)
- self.phi_motor_hwobj = self.get_object_by_role("phi")
- self.phiz_motor_hwobj = self.get_object_by_role("phiz")
- self.phiy_motor_hwobj = self.get_object_by_role("phiy")
- self.zoom_motor_hwobj = self.get_object_by_role("zoom")
- self.focus_motor_hwobj = self.get_object_by_role("focus")
- self.sample_x_motor_hwobj = self.get_object_by_role("sampx")
- self.sample_y_motor_hwobj = self.get_object_by_role("sampy")
+ self.cmd_go_transfer = self.get_command_object("go_transfer")
+ self.cmd_go_sample_view = self.get_command_object("go_sample_view")
+
+ self.phi_motor_hwobj = self.get_object_by_role('phi')
+ self.phiz_motor_hwobj = self.get_object_by_role('phiz')
+ self.phiy_motor_hwobj = self.get_object_by_role('phiy')
+ self.zoom_motor_hwobj = self.get_object_by_role('zoom')
+ self.focus_motor_hwobj = self.get_object_by_role('focus')
+ self.sample_x_motor_hwobj = self.get_object_by_role('sampx')
+ self.sample_y_motor_hwobj = self.get_object_by_role('sampy')
+ self.kappa_motor_hwobj = self.get_object_by_role('kappa')
+ self.kappa_phi_motor_hwobj = self.get_object_by_role('kappa_phi')
+
+ self.omegaz_reference_channel = self.get_channel_object("omegazReference")
+
+ #for axis in HWR.beamline.centring.gonioAxes:
+ for axis in self.centring_hwobj.gonioAxes:
+ if axis['motor_name'] == 'phi':
+ self.logger.warning('XalocMinidiff: phi rotation direction is %s' % str(axis['direction']) )
+ self.phi_direction = sum( axis['direction'] )
+ self.phi_centring_direction = 1
+ self.saved_zoom_pos = self.zoom_motor_hwobj.get_value()
+ self.logger.warning('XalocMinidiff: digital zoom position %s' % str(self.saved_zoom_pos) )
+
+ # For automatic centring
+ #self.numCentringImages = HWR.beamline.centring.get_property('numCentringImages')
+ self.numCentringImages = self.centring_hwobj.get_property('numCentringImages')
+ if self.numCentringImages < 2:
+ self.logger.warning('XalocMinidiff: numCentringImages should be at least 2, reset to 2')
+ self.numCentringImages = 2
+ #self.centringAngleRange = HWR.beamline.centring.get_property('centringAngleRange')
+ self.centringAngleRange = self.centring_hwobj.get_property('centringAngleRange')
+ if self.centringAngleRange > 360:
+ self.logger.warning('XalocMinidiff: centringAngleRange should be smaller than 360 degrees, reset to 360 degrees')
+ self.centringAngleRange = 360
+ #self.numAutoCentringCycles = HWR.beamline.centring.get_property('numAutoCentringCycles')
+ self.numAutoCentringCycles = self.centring_hwobj.get_property('numAutoCentringCycles')
+ if self.centringAngleRange < 0:
+ self.logger.warning('XalocMinidiff: numAutoCentringCycles should be at least 1, reset to 1')
+ self.numAutoCentringCycles = 1
if self.phi_motor_hwobj is not None:
self.connect(
- self.phi_motor_hwobj, "stateChanged", self.phi_motor_state_changed
- )
+ self.phi_motor_hwobj,
+ 'stateChanged',
+ self.phi_motor_state_changed)
self.connect(self.phi_motor_hwobj, "valueChanged", self.phi_motor_moved)
+ self.current_motor_positions["phi"] = self.phi_motor_hwobj.get_value()
+ if self.phi_motor_hwobj.get_value() > 0: self.phi_centring_direction = -1
+ else: self.phi_centring_direction = 1
else:
- logging.getLogger("HWR").error("EMBLMiniDiff: Phi motor is not defined")
+ self.logger.error('Phi motor is not defined')
if self.phiz_motor_hwobj is not None:
self.connect(
- self.phiz_motor_hwobj, "stateChanged", self.phiz_motor_state_changed
- )
- self.connect(self.phiz_motor_hwobj, "valueChanged", self.phiz_motor_moved)
+ self.phiz_motor_hwobj,
+ 'stateChanged',
+ self.phiz_motor_state_changed)
+ self.connect(
+ self.phiz_motor_hwobj,
+ 'valueChanged',
+ self.phiz_motor_moved)
+ self.current_motor_positions["phiz"] = self.phiz_motor_hwobj.get_value()
else:
- logging.getLogger("HWR").error("EMBLMiniDiff: Phiz motor is not defined")
+ self.logger.error('Phiz motor is not defined')
if self.phiy_motor_hwobj is not None:
self.connect(
- self.phiy_motor_hwobj, "stateChanged", self.phiy_motor_state_changed
- )
- self.connect(self.phiy_motor_hwobj, "valueChanged", self.phiy_motor_moved)
+ self.phiy_motor_hwobj,
+ 'stateChanged',
+ self.phiy_motor_state_changed)
+ self.connect(
+ self.phiy_motor_hwobj,
+ 'valueChanged',
+ self.phiy_motor_moved)
+ self.current_motor_positions["phiy"] = self.phiy_motor_hwobj.get_value()
else:
- logging.getLogger("HWR").error("EMBLMiniDiff: Phiy motor is not defined")
+ self.logger.error('Phiy motor is not defined')
if self.zoom_motor_hwobj is not None:
self.connect(
- self.zoom_motor_hwobj, "valueChanged", self.zoom_position_changed
- )
+ self.zoom_motor_hwobj,
+ 'valueChanged',
+ self.zoom_position_changed)
self.connect(
self.zoom_motor_hwobj,
- "predefinedPositionChanged",
- self.zoom_motor_predefined_position_changed,
- )
+ 'predefinedPositionChanged',
+ self.zoom_motor_predefined_position_changed)
self.connect(
- self.zoom_motor_hwobj, "stateChanged", self.zoom_motor_state_changed
- )
+ self.zoom_motor_hwobj,
+ 'stateChanged',
+ self.zoom_motor_state_changed)
else:
- logging.getLogger("HWR").error("EMBLMiniDiff: Zoom motor is not defined")
+ self.logger.error('Zoom motor is not defined')
if self.sample_x_motor_hwobj is not None:
self.connect(
self.sample_x_motor_hwobj,
- "stateChanged",
- self.sampleX_motor_state_changed,
- )
+ 'stateChanged',
+ self.sampleX_motor_state_changed)
self.connect(
- self.sample_x_motor_hwobj, "valueChanged", self.sampleX_motor_moved
- )
+ self.sample_x_motor_hwobj,
+ 'valueChanged',
+ self.sampleX_motor_moved)
+ self.current_motor_positions["sampx"] = self.sample_x_motor_hwobj.get_value()
else:
- logging.getLogger("HWR").error("EMBLMiniDiff: Sampx motor is not defined")
+ self.logger.error('Sampx motor is not defined')
if self.sample_y_motor_hwobj is not None:
self.connect(
self.sample_y_motor_hwobj,
- "stateChanged",
- self.sampleY_motor_state_changed,
- )
+ 'stateChanged',
+ self.sampleY_motor_state_changed)
self.connect(
- self.sample_y_motor_hwobj, "valueChanged", self.sampleY_motor_moved
- )
+ self.sample_y_motor_hwobj,
+ 'valueChanged',
+ self.sampleY_motor_moved)
+ self.current_motor_positions["sampy"] = self.sample_y_motor_hwobj.get_value()
else:
- logging.getLogger("HWR").error("EMBLMiniDiff: Sampx motor is not defined")
+ self.logger.error('Sampx motor is not defined')
if self.focus_motor_hwobj is not None:
- self.connect(self.focus_motor_hwobj, "valueChanged", self.focus_motor_moved)
+ self.connect(
+ self.focus_motor_hwobj,
+ 'valueChanged',
+ self.focus_motor_moved)
+
+ if self.kappa_motor_hwobj is not None:
+ self.connect(
+ self.kappa_motor_hwobj,
+ 'stateChanged',
+ self.kappa_motor_state_changed)
+ self.connect(
+ self.kappa_motor_hwobj,
+ "valueChanged",
+ self.kappa_motor_moved)
+ self.current_motor_positions["kappa"] = self.kappa_motor_hwobj.get_value()
+ else:
+ self.logger.error('Kappa motor is not defined')
+
+ if self.kappa_phi_motor_hwobj is not None:
+ self.connect(
+ self.kappa_phi_motor_hwobj,
+ 'stateChanged',
+ self.kappa_phi_motor_state_changed)
+ self.connect(
+ self.kappa_phi_motor_hwobj,
+ "valueChanged",
+ self.kappa_phi_motor_moved)
+ self.current_motor_positions["kappa_phi"] = self.kappa_phi_motor_hwobj.get_value()
+ else:
+ self.logger.error('Kappa-Phi motor is not defined')
GenericDiffractometer.init(self)
- def getCalibrationData(self, offset=None):
- calibx, caliby = self.calibration.getCalibration()
- return 1000.0 / caliby, 1000.0 / caliby
- # return 1000./self.md2.CoaxCamScaleX, 1000./self.md2.CoaxCamScaleY
+ # overwrite default centring motors configuration from GenericDiffractometer
+ # when using sample_centring. Fix phiz position to a reference value.
+ self.omegaz_reference = self.omegaz_reference_channel.get_value()
- def get_pixels_per_mm(self):
- px_x, px_y = self.getCalibrationData()
- return (px_x, px_y)
+ queue_model_objects.CentredPosition.\
+ set_diffractometer_motor_names(
+ "phi", "phiy", "phiz", "sampx", "sampy", "kappa", "kappa_phi")
- def update_pixels_per_mm(self, *args):
+ # TODO: Explicit update would not be necessary, but it is.
+ # Added to make sure pixels_per_mm is initialised
+ self.update_pixels_per_mm()
+
+ #Set the beam_x and beam_y positions so the center point is kept
+ self.current_motor_positions["beam_x"] = (self.beam_position[0] - \
+ self.zoom_centre['x'] )/self.pixels_per_mm_x
+ self.current_motor_positions["beam_y"] = (self.beam_position[1] - \
+ self.zoom_centre['y'] )/self.pixels_per_mm_y
+
+ def state_changed(self, state):
"""
- Descript. :
+ Overwrites method to map Tango ON state to Diffractometer State Ready.
+
+ @state: Taurus state but string for Ready state
+ """
+ if state == DevState.ON:
+ state = DiffractometerState.tostring(DiffractometerState.Ready)
+
+ if state != self.current_state:
+ #self.logger.debug("State changed %s (was: %s)" %
+ #(str(state), self.current_state))
+ self.current_state = state
+ self.emit("minidiffStateChanged", (self.current_state))
+
+ def get_state(self):
+ try:
+ _value = self.chan_state.get_value()
+ #self.logger.debug('get_state: (value={0}, type={1})'.format(_value, type(_value)))
+ except Exception as e:
+ raise RuntimeError('Cannot get diffractometer state:\n%s' % str(e))
+ return _value
+ #return self.chan_state.get_value()
+
+
+ def update_pixels_per_mm(self):
+ """
+ Returns the pixel/mm for x and y. Overrides GenericDiffractometer method.
+ """
+ if self.zoom_motor_hwobj != None:
+ self.pixels_per_mm_x, self.pixels_per_mm_y = self.zoom_motor_hwobj.get_calibration_pixels_per_mm()
+ self.emit('pixelsPerMmChanged', ((self.pixels_per_mm_x, self.pixels_per_mm_y), ))
+
+ def get_pixels_per_mm(self, *args):
+ """
+ Emit signal with current pixel/mm values.
"""
- self.pixels_per_mm_x, self.pixels_per_mm_y = self.getCalibrationData()
- self.emit("pixelsPerMmChanged", ((self.pixels_per_mm_x, self.pixels_per_mm_y),))
+ return self.pixels_per_mm_x, self.pixels_per_mm_y
+
+ # Overwrite from generic diffractometer
+ def update_zoom_calibration(self):
+ """
+ This is used by GenericDiffractometer and basically renamed here to specify the calibraion units
+ """
+ self.update_pixels_per_mm()
def get_centred_point_from_coord(self, x, y, return_by_names=None):
"""
+ Returns a dictionary with motors name and positions centred corresponding to the camera image point with
+ coordinates x and y.
+ It is expected in start_move_to_beam and move_to_beam methods in
+ GenericDiffractometer HwObj,
+ Also needed for the calculation of the motor positions after definition of the mesh grid
+ (Qt4_GraphicsManager, update_grid_motor_positions)
+
+ point x,y is relative to the lower left corner on the camera, this functions returns the motor positions for that point,
+ where the motors that are changed are phiy and phiz.
+
+ @return: dict
"""
- return {"omega": [200, 200]}
- # raise NotImplementedError
+ #self.logger.info('get_centred_point_from_coord x %s and y %s and return_by_names %s' % ( x, y, return_by_names ) )
+ #self.logger.info('get_centred_point_from_coord pixels_per_mm_x %s and pixels_per_mm_y %s' % ( self.pixels_per_mm_x, self.pixels_per_mm_y ) )
+ #self.logger.info('get_centred_point_from_coord beam_position[0] %s and beam_position[1] %s' %
+ #( self.beam_position[0], self.beam_position[1] )
+ #)
+
+ self.update_zoom_calibration()
+
+ loc_centred_point = {}
+ loc_centred_point['phi'] = self.phi_motor_hwobj.get_value()
+ loc_centred_point['kappa'] = self.kappa_motor_hwobj.get_value()
+ loc_centred_point['kappa_phi'] = self.kappa_phi_motor_hwobj.get_value()
+ loc_centred_point['phiy'] = self.phiy_motor_hwobj.get_value() - (
+ ( float( x ) - float( self.beam_position[0] ) ) /
+ float( self.pixels_per_mm_x )
+ )
+
+ # Overwrite phiz, which should remain in the actual position, hopefully the center of rotation
+ omegaz_diff = 0
+ if self.omegaz_reference_channel != None:
+ self.omegaz_reference = self.omegaz_reference_channel.get_value()
+ loc_centred_point['phiz'] = self.omegaz_reference
+ omegaz_diff = self.phiz_motor_hwobj.get_value() - self.omegaz_reference
+ else:
+ loc_centred_point['phiz'] = self.phiz_motor_hwobj.get_value()
+
+ # Calculate the positions of sampx and sampy that correspond to the camera x,y coordinates
+ vertdist = omegaz_diff + ( float( y ) - float ( self.beam_position[1] ) ) / float (self.pixels_per_mm_y )
+ sampxpos = self.sample_x_motor_hwobj.get_value()
+ sampypos = self.sample_y_motor_hwobj.get_value()
+ dx, dy = self.vertical_dist_to_samp_pos (self.phi_motor_hwobj.get_value() , vertdist)
+
+ loc_centred_point['sampx'] = sampxpos + dy
+ loc_centred_point['sampy'] = sampypos + dx
+
+ loc_centred_point = self.add_beam_position_to_centering_motors(loc_centred_point)
+
+ # 20220706 RB: These lines cause the grid to move to the center of camera, do not use!
+ #if return_by_names:
+ #loc_centred_point = self.convert_from_obj_to_name(loc_centred_point)
+
+ self.logger.info('get_centred_point_from_coord loc_centred_point %s ' % ( loc_centred_point ) )
+
+ return loc_centred_point
+
+ def vertical_dist_to_samp_pos(self, phipos, vertdist):
+ """
+ returns the relative displacement of sampx and sampy
+ """
+ d_sampx = 0
+ d_sampy = 0
+
+ #self.logger.debug("phipos %.4f , vertdist %.4f" % ( phipos, vertdist ) )
- def getBeamInfo(self, update_beam_callback):
- calibx, caliby = self.calibration.getCalibration()
+ if self.use_sample_centring:
+ phi_angle = math.radians(self.centring_phi.direction * \
+ phipos )
+ else:
+ phi_angle = math.radians( phipos * self.phi_direction )
- size_x = self.get_channel_object("beamInfoX").get_value() / 1000.0
- size_y = self.get_channel_object("beamInfoY").get_value() / 1000.0
+ #self.logger.debug("phi_angle %.4f" % ( phi_angle ) )
- data = {"size_x": size_x, "size_y": size_y, "shape": "ellipse"}
+ d_sampy = math.cos(phi_angle) * vertdist
+ d_sampx = math.sin(phi_angle) * vertdist
+
+ return d_sampy, d_sampx
- update_beam_callback(data)
+ # RB: Never called?
+ #def getBeamInfo(self, update_beam_callback):
+ #"""
+ #Update beam info (position and shape) ans execute callback.
+ #@update_beam_callback: callback method passed as argument.
+ #"""
+ #size_x = self.getChannelObject("beamInfoX").get_value() / 1000.0
+ #size_y = self.getChannelObject("beamInfoY").get_value() / 1000.0
+
+ #data = {
+ #"size_x": size_x,
+ #"size_y": size_y,
+ #"shape": "ellipse",
+ #}
+
+ #update_beam_callback(data)
+
+ # TODO:Implement dynamically
+ def use_sample_changer(self):
+ """
+ Overrides GenericDiffractometer method.
+ """
+ return True
+
+ # TODO:Implement dynamically
def in_plate_mode(self):
+ """
+ Overrides GenericDiffractometer method.
+ """
return False
+ # overwrite generic diff method to avoid centering when mounting fails
+ def start_centring_method(self, method, sample_info=None, wait=False):
+ """
+ method is either of the centring methods defined in diff HW object:
+ CENTRING_METHOD_MANUAL = "Manual 3-click", CENTRING_METHOD_AUTO = "Computer automatic", CENTRING_METHOD_MOVE_TO_BEAM = "Move to beam"
+ """
+
+ if self.current_centring_method is not None:
+ logging.getLogger("HWR").error(
+ "Diffractometer: using centring method %s"
+ % self.current_centring_method
+ )
+ return
+ curr_time = time.strftime("%Y-%m-%d %H:%M:%S")
+ self.centring_status = {
+ "valid": False,
+ "startTime": curr_time,
+ "angleLimit": None,
+ }
+ self.emit_centring_started(method)
+ self.logger.debug(
+ "Diffractometer: centring method (%s)" % str(self.current_centring_method)
+ )
+
+ try:
+ centring_method = self.centring_methods[method]
+ except KeyError as diag:
+ logging.getLogger("HWR").error(
+ "Diffractometer: unknown centring method (%s)" % str(diag)
+ )
+ self.emit_centring_failed()
+ else:
+ if HWR.beamline.sample_changer.sample_can_be_centered:
+ try:
+ self.prepare_centring()
+ except Exception as e:
+ self.userlogger.error("The diffractometer could not be prepared for centering, warn the lc/floor coordinator")
+ raise Exception(e)
+ try:
+ centring_method(sample_info, wait_result=wait)
+ except Exception:
+ logging.getLogger("HWR").exception(
+ "Diffractometer: problem while centring"
+ )
+ self.emit_centring_failed()
+ else:
+ logging.getLogger("HWR").error(
+ "Diffractometer: there was a problem in loading the sample, centering cancelled"
+ )
+ self.emit_centring_failed()
+
+
def manual_centring(self):
"""
Descript. :
"""
self.centring_hwobj.initCentringProcedure()
-
- # self.head_type = self.chan_head_type.get_value()
-
+ if not self.sample_has_been_centred:
+ self.zoom_motor_hwobj.move_to_position( 1 )
+
for click in range(3):
self.user_clicked_event = gevent.event.AsyncResult()
x, y = self.user_clicked_event.get()
+ #logger.debug("manual_centring : x %s, y %s" % ( str(x), str(y) ) )
self.centring_hwobj.appendCentringDataPoint(
- {
- "X": (x - self.beam_position[0]) / self.pixels_per_mm_x,
- "Y": (y - self.beam_position[1]) / self.pixels_per_mm_y,
- }
- )
-
+ {"X": (x - self.beam_position[0])/ self.pixels_per_mm_x,
+ "Y": (y - self.beam_position[1])/ self.pixels_per_mm_y})
if self.in_plate_mode():
- dynamic_limits = self.phi_motor_hwobj.get_dynamic_limits()
- if click == 0:
- self.phi_motor_hwobj.set_value(dynamic_limits[0])
- elif click == 1:
- self.phi_motor_hwobj.set_value(dynamic_limits[1])
+ pass
+ ##dynamic_limits = self.phi_motor_hwobj.getDynamicLimits()
+ #dynamic_limits = self.get_osc_limits()
+ #if click == 0:
+ #self.motor_hwobj_dict['phi'].set_value(dynamic_limits[0] + 0.5)
+ #elif click == 1:
+ #self.motor_hwobj_dict['phi'].set_value(dynamic_limits[1] - 0.5)
+ #elif click == 2:
+ #self.motor_hwobj_dict['phi'].set_value((dynamic_limits[0] + \
+ #dynamic_limits[1]) / 2.)
else:
if click < 2:
- self.phi_motor_hwobj.set_value_relative(-90)
- # self.omega_reference_add_constraint()
- return self.centring_hwobj.centeredPosition(return_by_name=False)
+ new_pos = self.motor_hwobj_dict['phi'].get_value() + ( self.phi_centring_direction * 90 )
+ self.motor_hwobj_dict['phi'].set_value( new_pos )
+ #self.omega_reference_add_constraint()
+ centred_pos_dict = self.centring_hwobj.centeredPosition(return_by_name=False)
+
+ # Fix the omegaz (phiz) motor position to the known center
+ centred_pos_dict[ self.motor_hwobj_dict['phiz'] ] = self.omegaz_reference
- def phi_motor_moved(self, pos):
+ if not self.sample_has_been_centred:
+ self.zoom_motor_hwobj.move_to_position( self.saved_zoom_pos)
+ self.sample_has_been_centred = True
+
+ #self.logger.debug( "centred_pos_dict %s" % str( centred_pos_dict ) )
+
+ return centred_pos_dict
+
+ def move_to_beam(self, x, y, omega=None):
+ """
+ Descript. : function to create a centring point based on all current motors
+ positions.
+ """
+ logging.getLogger("HWR").debug("move_to_beam x %s y %s" % (x,y) )
+
+ try:
+ pos = self.get_centred_point_from_coord(x, y, return_by_names=False)
+ if omega is not None:
+ pos["phiMotor"] = omega
+ self.move_to_motors_positions(pos)
+ #self.centring_status["motors"] = self.convert_from_obj_to_name( pos )
+ logging.getLogger("HWR").debug("centring_status %s" % self.centring_status)
+ except Exception:
+ logging.getLogger("HWR").exception(
+ "Diffractometer: could not center to beam, aborting"
+ )
+
+ def add_beam_position_to_centering_motors(self, motor_pos):
+ """
+ """
+ logging.getLogger("HWR").debug(
+ "motor_pos %s" % str(motor_pos)
+ )
+ motor_pos["beam_x"] = (
+ self.beam_position[0] - self.zoom_centre["x"]
+ ) / self.pixels_per_mm_y
+ motor_pos["beam_y"] = (
+ self.beam_position[1] - self.zoom_centre["y"]
+ ) / self.pixels_per_mm_x
+ logging.getLogger("HWR").debug(
+ "motors %s" % str(motor_pos)
+ )
+ return motor_pos
+
+ def convert_from_obj_to_name(self, motor_pos):
+ """
+ """
+ motors = {}
+ for motor_role in self.centring_motors_list:
+ motor_obj = self.get_object_by_role(motor_role)
+ try:
+ motors[motor_role] = motor_pos[motor_role]
+ except KeyError:
+ if motor_obj:
+ motors[motor_role] = motor_obj.get_value()
+ motors["beam_x"] = (
+ self.beam_position[0] - self.zoom_centre["x"]
+ ) / self.pixels_per_mm_y
+ motors["beam_y"] = (
+ self.beam_position[1] - self.zoom_centre["y"]
+ ) / self.pixels_per_mm_x
+ return motors
+
+ # Override GenericDiffractometer to add prepare_centring, which sets omega velocity to 60.
+ def start_automatic_centring(self, sample_info=None, loop_only=False, wait_result=None):
+ """
+ Start Automatic centring. Overrides GenericDiffractometer method.
+ Prepares diffractometer for automatic centring.
+ """
+ self.automatic_centring_try_count = 0
+
+ self.logger.debug('automatic_centring_try_count: %d, numAutoCentringCycles: %d' % \
+ (self.automatic_centring_try_count, self.numAutoCentringCycles) )
+
+ #TODO: whould the wait_result argument to start_automatic_centring be set to True?
+ self.emit_progress_message("Automatic centring...")
+
+ #self.logger.debug('Start automatic centring: %s' % self.pixels_per_mm_x)
+ if self.use_sample_centring:
+ if self.numAutoCentringCycles > 1:
+ self.logger.debug( 'Multiple centring not supported when use_sample_centring is set to True' )
+ self.userlogger.info( 'Started 1 cycle of automatic centring' )
+ self.current_centring_procedure = \
+ sample_centring.start_auto(self.camera_hwobj,
+ {"phi": self.centring_phi,
+ "phiy": self.centring_phiy,
+ "sampx": self.centring_sampx,
+ "sampy": self.centring_sampy,
+ "phiz": self.centring_phiz },
+ self.pixels_per_mm_x,
+ self.pixels_per_mm_y,
+ self.beam_position[0],
+ self.beam_position[1],
+ msg_cb = self.emit_progress_message,
+ new_point_cb=lambda point: self.emit("newAutomaticCentringPoint", (point,)))
+ else:
+ #TODO: can this be added to a queue and execute the queue? SampleCentringQueueEntry does not work for this
+ # GPHL uses queue_model_objects.SampleCentring in enqueue_sample_centring
+ self.userlogger.info( 'Started %d cycles of automatic centring' % self.numAutoCentringCycles )
+ for i in range(self.numAutoCentringCycles):
+ self.current_centring_procedure = gevent.spawn( self.automatic_centring, i )
+ self.current_centring_procedure.link(self.centring_done)
+
+ self.sample_has_been_centred = True # used for setting the zoom level
+ self.zoom_motor_hwobj.move_to_position( self.saved_zoom_pos)
+
+ #TODO: make method called finish_centring to reset values?
+
+ def automatic_centring(self, pid):
+ """Automatic centring procedure. Rotates n times and executes
+ centring algorithm. Optimal scan position is detected.
+ """
+
+ #self.logger.info("Cued new automatic centring number %d" % pid+1)
+
+ # wait till it is the turn of this cycle
+ stime = time.time()
+ timeout = 20 * ( pid + 1 )
+ while pid != self.automatic_centring_try_count:
+ gevent.sleep(1)
+ if time.time() - stime > timeout:
+ self.cancel_centring_method()
+
+ self.userlogger.info("Started new automatic centring cycle %d of %d" % ( pid+1, self.numAutoCentringCycles ) )
+
+ if self.phi_motor_hwobj.get_value() > 0: self.phi_centring_direction = -1
+ else: self.phi_centring_direction = 1
+
+ # This cycle now starts
+ if pid == 0:
+ self.zoom_motor_hwobj.move_to_position(1)
+ gevent.sleep(0.2) # wait for zoom update
+ else:
+ self.zoom_motor_hwobj.move_to_position(4)
+ gevent.sleep(0.2) # wait for motors from previous centrings to start moving
+
+ self.wait_device_ready( timeout = 20) # wait for motors from previous centrings to finish
+
+ #self.logger.debug('find_loop output %s' % str(self.find_loop_xaloc()) )
+
+ # check if loop is there, if not, search
+ it = 0
+ maxit = 3
+ x, y, info, surface_score = self.find_loop_xaloc()
+ while ( -1 in [x,y]) and it < maxit:
+ self.logger.debug('-1 in first x,y find_loop output %s, %s' % ( str(x), str(y) ) )
+ if not self.search_pin():
+ self.userlogger.error("Reached minimal position for omegax, sample cannot be found, aborting centring")
+ self.phiy_motor_hwobj.set_value(0, timeout = 5 )
+ self.cancel_centring_method(True)
+ return
+ it += 1
+ gevent.sleep(0.1)
+ x, y, info, surface_score = self.find_loop_xaloc()
+ else:
+ if -1 in [x,y]: self.cancel_centring_method()
+
+ # check if loop is past camera, and the pin is seen. If so, first move loop out
+ it = 0
+ image_edge_margin = 100
+ while x < image_edge_margin and it < maxit:
+ self.logger.debug('x < image_edge_margin, x and y from find_loop %s, %s' % ( str(x), str(y) ) )
+ self.retreat_pin()
+ it += 1
+ gevent.sleep(0.1)
+ x, y, info, surface_score = self.find_loop_xaloc()
+ else:
+ if ( -1 in [x,y] ) or y < image_edge_margin : self.cancel_centring_method()
+
+ surface_score_list = []
+ self.centring_hwobj.initCentringProcedure()
+ self.logger.debug("self.numCentringImages %d, self.centringAngleRange %d" % \
+ (self.numCentringImages, self.centringAngleRange) )
+ for image in range( int( self.numCentringImages ) ):
+ self.logger.debug("self.current_centring_method %s" % self.current_centring_method )
+ if self.current_centring_method == None:
+ self.logger.debug("No centering method selected, cannot continue" )
+ break
+ #self.logger.debug("Harvesting fotos for automatic_centring : x %s, y %s, info %s, surface_score %s" %
+ #( str(x), str(y), str(info), str(surface_score) ) )
+ if x > 0 and y > 0:
+ self.centring_hwobj.appendCentringDataPoint(
+ {"X": (x - self.beam_position[0])/ self.pixels_per_mm_x,
+ "Y": (y - self.beam_position[1])/ self.pixels_per_mm_y})
+ surface_score_list.append(surface_score)
+ # Now rotate and take another point
+ if image < self.numCentringImages - 1: # Last rotation is not necessary
+ #self.userlogger.info( "rotating omega" )
+ new_pos = self.motor_hwobj_dict['phi'].get_value() + ( self.phi_centring_direction * \
+ self.centringAngleRange/ ( self.numCentringImages - 1 ) )
+ self.motor_hwobj_dict['phi'].set_value( new_pos, timeout = 5 )
+ gevent.sleep(0.01)
+ self.wait_device_ready( timeout = 15)
+ x, y, info, surface_score = self.find_loop_xaloc()
+ #self.omega_reference_add_constraint()
+ centred_pos_dict = self.centring_hwobj.centeredPosition(return_by_name=False)
+ self.emit("newAutomaticCentringPoint", centred_pos_dict)
+
+
+ #TODO: add the difference between self.motor_hwobj_dict['phiz'] and self.omegaz_reference to centx & centy
+ vertdist = centred_pos_dict[ self.motor_hwobj_dict['phiz'] ] - self.omegaz_reference
+ # Fix the omegaz (phiz) motor position to the known center
+ #self.logger.debug("Calculated phiz %.4f, difference with reference %.4f" % \
+ # (centred_pos_dict[ self.motor_hwobj_dict[ 'phiz' ] ] , vertdist ) )
+
+ dx = 0
+ dy = 0
+ dx, dy = self.vertical_dist_to_samp_pos (self.phi_motor_hwobj.get_value() , -vertdist)
+ centred_pos_dict[ self.motor_hwobj_dict['phiz'] ] = self.omegaz_reference
+ centred_pos_dict[ self.motor_hwobj_dict['sampx'] ] = centred_pos_dict[ self.motor_hwobj_dict['sampx'] ] + dy
+ centred_pos_dict[ self.motor_hwobj_dict['sampy'] ] = centred_pos_dict[ self.motor_hwobj_dict['sampy'] ] + dx
+
+ #self.logger.debug( "centred_pos_dict %s" % str( centred_pos_dict ) )
+
+ self.automatic_centring_try_count += 1
+
+ return centred_pos_dict
+
+ def retreat_pin(self):
+ self.logger.debug(" moving sample back by half a camera width")
+ hor_mot_hwobj = self.phiy_motor_hwobj
+ half_camera_width_mm = HWR.beamline.sample_view.camera.get_width() / self.pixels_per_mm_x / 2 # half camera width in mm
+ #self.logger.debug( "half camera_width_mm %.4f" % half_camera_width_mm )
+ hor_mot_hwobj.set_value( hor_mot_hwobj.get_value() + half_camera_width_mm, timeout = 6 )
+ gevent.sleep(0.1) # wait for zoom update
+ hor_mot_hwobj.wait_end_of_move( timeout = 10 )
+ hor_mot_hwobj.wait_ready( timeout = 10 )
+ gevent.sleep(0.1) # wait for zoom update
+ self.logger.debug(" Done moving sample back by half a camera width")
+
+ def search_pin(self):
+ spindle_mot_hwobj = self.phi_motor_hwobj
+ hor_mot_hwobj = self.phiy_motor_hwobj
+
+ # Save initial velocity
+ hor_mot_ini_vel = hor_mot_hwobj.get_velocity()
+
+ # get camera width in mm
+ camera_width_mm = HWR.beamline.sample_view.camera.get_width() / self.pixels_per_mm_x # full camera width in mm
+ #self.logger.debug( "camera_width_mm %.4f" % camera_width_mm )
+
+ #TODO:check the limit of the phiy motor and make relative movement smalle if necessary
+ relmovdist = 0
+ if camera_width_mm > math.fabs( hor_mot_hwobj.get_limits()[0] - hor_mot_hwobj.get_value() ):
+ relmovdist = math.fabs( hor_mot_hwobj.get_limits()[0] - hor_mot_hwobj.get_value() ) - 0.002
+ else: relmovdist = camera_width_mm
+ if relmovdist < 0.003: return False #omegax at minimum
+
+ # set horizontal motor velocity so that a full camera with can be scanned with 180 deg rotation of spindle axis
+ time_for_scan = 180 / spindle_mot_hwobj.get_velocity() + 0.01 # in seconds
+ hor_vel = camera_width_mm / time_for_scan
+ #self.logger.debug( "Calculated horizontal velocity %.4f" % hor_vel )
+ if hor_vel < hor_mot_hwobj.get_velocity():
+ if hor_vel < 0.001: hor_vel = 0.001
+ else:
+ hor_mot_hwobj.wait_ready( timeout = 10 )
+ hor_mot_hwobj.set_velocity(hor_vel)
+
+ #self.logger.debug( 'hor mot pos channel info %s' % str( hor_mot_hwobj.position_channel.get_info().minval ) )
+ #self.logger.debug( 'hor mot limits %s' % str( hor_mot_hwobj.get_limits() ) )
+
+ # start the motor positions asynchronously
+ self.logger.debug("Moving omegax relative %s" % relmovdist)
+ hor_mot_hwobj.set_value( hor_mot_hwobj.get_value() - relmovdist )
+ spindle_mot_hwobj.set_value( spindle_mot_hwobj.get_value() + 180 )
+ hor_mot_hwobj.wait_end_of_move( timeout = 10 )
+ spindle_mot_hwobj.wait_end_of_move( timeout = 10 )
+
+ # Keep checking the location of the loop. When found, stop the motor movements
+ stime = time.time()
+ while time.time() - stime < time_for_scan:
+ if not ( -1 in self.find_loop_xaloc()[:1] ):
+ break
+ gevent.sleep(0.1)
+
+ hor_mot_hwobj.stop()
+ spindle_mot_hwobj.stop()
+ gevent.sleep(0.1)
+
+ # reset the velocities
+ hor_mot_hwobj.set_velocity(hor_mot_ini_vel)
+ return True
+
+ def motor_positions_to_screen(self, centred_positions_dict):
+ """
+ Descript. : returns the camera pixels of the point corresponding to the given motor positions
+ """
+ c = centred_positions_dict
+
+ #kappa = self.current_motor_positions["kappa"]
+ #phi = self.current_motor_positions["kappa_phi"]
+
+ kappa = self.motor_hwobj_dict['kappa'].get_value()
+ phi = self.motor_hwobj_dict['kappa_phi'].get_value()
+ #IK TODO remove this director call
+
+ # TODO:implement minikappa_correction_hwobj
+ #if (c['kappa'], c['kappa_phi']) != (kappa, phi) \
+ #and self.minikappa_correction_hwobj is not None:
+ ##c['sampx'], c['sampy'], c['phiy']
+ #c['sampx'], c['sampy'], c['phiy'] = self.minikappa_correction_hwobj.shift(
+ #c['kappa'], c['kappa_phi'], [c['sampx'], c['sampy'], c['phiy']], kappa, phi)
+
+ #TODO: beam_x and beam_y are not part of c? These give difference in beam pos with respect to center
+ #self.logger.debug('motor_positions_to_screen, zoom_centre x %d, y %d' % \
+ #(self.zoom_centre['x'], self.zoom_centre['y']) )
+ #self.logger.debug('motor_positions_to_screen, pixels_per_mm_x %d, y %d' % \
+ #(self.pixels_per_mm_x, self.pixels_per_mm_y) )
+ beam_x = ( self.beam_position[0] - self.zoom_centre['x'] ) / self.pixels_per_mm_x
+ beam_y = ( self.beam_position[1] - self.zoom_centre['y'] ) / self.pixels_per_mm_y
+
+ xy = self.centring_hwobj.centringToScreen(c)
+ #self.logger.debug( 'xy dict %s' % str(xy) )
+ if xy:
+ #self.logger.debug( 'xy[\'X\'] %s xy[\'Y\'] %s' % ( xy['X'], xy['Y'] ) )
+ x = ( xy['X'] + beam_x ) * self.pixels_per_mm_x + \
+ self.zoom_centre['x']
+ y = ( xy['Y'] + beam_y ) * self.pixels_per_mm_y + \
+ self.zoom_centre['y']
+ #self.logger.debug( 'x %4.2f y %4.2f' % ( x, y ) )
+ return x, y
+
+ def centring_done(self, centring_procedure):
+ """
+ Descript. :
+ """
+ try:
+ motor_pos = centring_procedure.get()
+ if isinstance(motor_pos, gevent.GreenletExit):
+ raise Exception( str(motor_pos) )
+ except:
+ logging.exception("Could not complete centring")
+ self.emit_centring_failed()
+ else:
+ self.emit_progress_message("Moving sample to centred position...")
+ self.emit_centring_moving()
+
+ try:
+ # msg = ''
+ # for mot, pos in motor_pos.items():
+ # msg += '%s = %s\n' % (str(mot.name()), pos)
+ self.logger.info("Centring finished")#. Moving motors to:\n%s" % msg)
+ self.move_to_motors_positions(motor_pos, wait=True)
+ except:
+ logging.exception("Could not move to centred position")
+ self.emit_centring_failed()
+ else:
+ #if 3 click centring move -180. well. dont, in principle the calculated
+ # centred positions include omega to initial position
+ pass
+ #if not self.in_plate_mode():
+ # logging.getLogger("HWR").debug("Centring finished. Moving omega back to initial position")
+ # self.motor_hwobj_dict['phi'].set_value(self.motor_hwobj_dict['phi'].get_value() - 180, timeout = 4 )
+ # logging.getLogger("HWR").debug(" Moving omega done")
+
+ #if self.current_centring_method == GenericDiffractometer.CENTRING_METHOD_AUTO:
+ # self.emit("newAutomaticCentringPoint", motor_pos)
+ self.ready_event.set()
+ self.centring_time = time.time()
+ self.update_centring_status(motor_pos)
+ if ( self.current_centring_method == GenericDiffractometer.CENTRING_METHOD_AUTO and \
+ self.automatic_centring_try_count == self.numAutoCentringCycles ) or \
+ self.current_centring_method != GenericDiffractometer.CENTRING_METHOD_AUTO:
+ self.userlogger.info( "Centring finished" )
+ self.emit_centring_successful()
+ self.emit_progress_message("")
+
+ def update_centring_status(self, motor_pos):
+ curr_time = time.strftime("%Y-%m-%d %H:%M:%S")
+ self.centring_status["endTime"] = curr_time
+ self.centring_status["motors"] = self.convert_from_obj_to_name(motor_pos)
+ self.centring_status["method"] = self.current_centring_method
+ self.centring_status["valid"] = True
+
+ def emit_centring_successful(self):
"""
Descript. :
"""
+ method = self.current_centring_method
+ self.emit('centringSuccessful', (method, self.get_centring_status()))
+ self.current_centring_method = None
+ self.current_centring_procedure = None
+
+ def find_loop_xaloc(self):
+ """
+ Description: finds loop using lucid3
+ An example filename can be found at /tmp/mxcube_sample_snapshot.png
+ """
+
+ # the following lines are used because the lucid3 package installed at xaloc
+ # does not allow an array as argument. Lucid3 should be updated to use the code below
+ #self.logger.debug("starting find_loop")
+ #snapshot_filename = os.path.join(tempfile.gettempdir(), "mxcube_sample_snapshot.png")
+ #image_array = HWR.beamline.sample_view.camera.get_snapshot(return_as_array=True)
+ ## Now flip the image and convert to PIL type image
+ #im = Image.fromarray( np.fliplr( image_array ) )
+ #im.save( snapshot_filename )
+ ##self.logger.debug("in find_loop: snapshot_filename is %s" % snapshot_filename)
+ #(info, x, y) = lucid.find_loop( snapshot_filename , IterationClosing=6 )
+ #self.logger.debug('Lucid output: info %s x %s y %s' % ( str(info), str(x), str(y) ) )
+
+
+ #=================================================================================
+
+ #the following lines should be used when lucid3 is updated to the newest version
+ image_array = HWR.beamline.sample_view.camera.get_snapshot(return_as_array=True)
+ #self.logger.debug("image_array: %s" % str(image_array))
+ #self.logger.debug("type( image_array ): %s" % str( type(image_array) ) )
+ if type( image_array ) == str: self.logger.debug("image_array is a string" )
+ image_array = np.fliplr( image_array )
+ (info, x, y) = lucid.find_loop( image_array , IterationClosing=6 )
+ #self.logger.debug('Lucid output: info %s x %s y %s' % ( str(info), str(x), str(y) ) )
+
+ #=================================================================================
+
+ #self.logger.debug("find_loop output : info %s, x %s, y %s" % ( str(info), str(x), str(y) ) )
+ if x > 0 and y > 0:
+ x = 900 - x
+
+ surface_score = 10
+ return x, y, info, surface_score
+
+ def prepare_centring(self):
+ """
+ Prepare beamline for to sample_view phase.
+ """
+
+ self.saved_zoom_pos = self.zoom_motor_hwobj.get_value()
+
+ if self.get_current_phase().upper() != "SAMPLE":
+ self.logger.info("Not in sample view phase. Asking diff to go")
+ self.wait_ready()
+ self.set_diff_phase('Centring') # call diffcentring phase to prepare diff for centring
+ # TODO: workaround to set omega velocity to 60
+ try:
+ self.phi_motor_hwobj.set_velocity(60)
+ except:
+ self.logger.error("Cannot apply workaround for omega velocity")
+ # TODO: dynamic omegaz_reference
+ if self.omegaz_reference_channel != None:
+ if self.use_sample_centring: self.centring_phiz.reference_position = self.omegaz_reference_channel.get_value()
+ self.omegaz_reference = self.omegaz_reference_channel.get_value()
+
+ if self.phi_motor_hwobj.get_value() > 0: self.phi_centring_direction = -1
+ else: self.phi_centring_direction = 1
+
+ return True
+
+ def omega_reference_add_constraint(self):
+ """
+ Descript. : WHAT DOES THIS DO?
+ """
+ if self.omega_reference_par is None or self.beam_position is None:
+ return
+ if self.omega_reference_par["camera_axis"].lower() == "x":
+ on_beam = (self.beam_position[0] - self.zoom_centre['x']) * \
+ self.omega_reference_par["direction"] / self.pixels_per_mm_x + \
+ self.omega_reference_par["position"]
+ else:
+ on_beam = (self.beam_position[1] - self.zoom_centre['y']) * \
+ self.omega_reference_par["direction"] / self.pixels_per_mm_y + \
+ self.omega_reference_par["position"]
+ self.centring_hwobj.appendMotorConstraint(self.omega_reference_motor, on_beam)
+
+ def move_to_motors_positions(self, motors_positions, wait=False):
+ """
+ """
+ self.emit_progress_message("Moving to motors positions...")
+ self.move_to_motors_positions_procedure = gevent.spawn(\
+ self.move_motors, motors_positions)
+ self.move_to_motors_positions_procedure.link(self.move_motors_done)
+ if wait:
+ self.wait_device_not_ready( timeout = 50 )
+ self.wait_device_ready( timeout = 10 )
+
+ def move_motors(self, motor_positions, timeout=15):
+ """
+ Moves diffractometer motors to the requested positions
+
+ :param motors_dict: dictionary with motor names or hwobj
+ and target values.
+ :type motors_dict: dict
+
+ Reimplemented to improve error messaging ()
+ """
+ if not isinstance(motor_positions, dict):
+ motor_positions = motor_positions.as_dict()
+
+ try:
+ self.wait_device_ready( timeout = timeout)
+ except Exception as e:
+ self.userlogger.error( str(e) )
+ raise(e)
+
+ for motor in motor_positions.keys():
+ position = motor_positions[motor]
+ """
+ if isinstance(motor, (str, unicode)):
+ logging.getLogger("HWR").debug(" Moving %s to %s" % (motor, position))
+ else:
+ logging.getLogger("HWR").debug(
+ " Moving %s to %s" % (str(motor.name()), position)
+ )
+ """
+ if isinstance(motor, (str, unicode)):
+ motor_role = motor
+ motor = self.motor_hwobj_dict.get(motor_role)
+ # del motor_positions[motor_role]
+ if None in (motor, position):
+ continue
+ # motor_positions[motor] = position
+ motor.set_value(position)
+ self.wait_device_ready(timeout)
+
+ if self.delay_state_polling is not None and self.delay_state_polling > 0:
+ # delay polling for state in the
+ # case of controller not reporting MOVING inmediately after cmd
+ gevent.sleep(self.delay_state_polling)
+
+ self.wait_device_ready( timeout = timeout)
+
+
+
+ def get_grid_direction(self):
+
+ grid_direction = self.get_property("gridDirection")
+
+ grid_direction = {}
+ self.grid_direction['omega_ref'] = 1
+ self.grid_direction['fast'] = [ 1, 0 ] # Qt4_GraphicsLib.py line 1184/85 MD2
+ self.grid_direction['slow'] = [ 0, -1 ] # Qt4_GraphicsLib.py line 1184/85 MD2
+ self.logger.info('diffr_hwobj grid_direction %s' % self.grid_direction)
+
+ return self.grid_direction
+
+ # TODO: Review override current_state by current_phase
+ def phase_changed(self, phase):
+ """
+ Emit stateChanged signal according to supervisor current phase.
+ """
+ #self.current_phase = phase
+ self.emit('minidiffPhaseChanged', (phase, ))
+
+ def phi_motor_moved(self, pos):
+ """
+ Emit phiMotorMoved signal with position value.
+ """
self.current_motor_positions["phi"] = pos
- self.emit_diffractometer_moved()
self.emit("phiMotorMoved", pos)
- # self.emit('stateChanged', (self.current_motor_states["phi"], ))
def phi_motor_state_changed(self, state):
"""
- Descript. :
+ Emit stateChanged signal with state value.
"""
- self.current_motor_states["phi"] = state
- self.emit("stateChanged", (state,))
+ self.emit('stateChanged', (state, ))
def phiz_motor_moved(self, pos):
"""
- Descript. :
"""
self.current_motor_positions["phiz"] = pos
- if time.time() - self.centring_time > 1.0:
- self.invalidate_centring()
- self.emit_diffractometer_moved()
def phiz_motor_state_changed(self, state):
"""
- Descript. :
+ Emit stateChanged signal with state value.
"""
- self.emit("stateChanged", (state,))
+ self.emit('stateChanged', (state, ))
def phiy_motor_state_changed(self, state):
"""
- Descript. :
+ Emit stateChanged signal with state value.
"""
- self.emit("stateChanged", (state,))
+ self.emit('stateChanged', (state, ))
def phiy_motor_moved(self, pos):
"""
- Descript. :
"""
self.current_motor_positions["phiy"] = pos
- if time.time() - self.centring_time > 1.0:
- self.invalidate_centring()
- self.emit_diffractometer_moved()
def zoom_position_changed(self, value):
+ """
+ Update positions after zoom changed.
+
+ @value: zoom position.
+ """
+ #self.logger.debug("zoom position changed")
self.update_pixels_per_mm()
self.current_motor_positions["zoom"] = value
- self.refresh_omega_reference_position()
def zoom_motor_predefined_position_changed(self, position_name, offset):
"""
- Descript. :
+ Update pixel size and emit signal.
"""
+ #self.logger.debug("zoom predefined position changed")
self.update_pixels_per_mm()
- self.emit("zoomMotorPredefinedPositionChanged", (position_name, offset))
+ self.emit('zoomMotorPredefinedPositionChanged',
+ (position_name, offset, ))
def zoom_motor_state_changed(self, state):
"""
- Descript. :
+ Emit signal for motor zoom changed
+
+ @state: new state value to emit.
"""
- self.emit("stateChanged", (state,))
+ self.emit('stateChanged', (state, ))
def sampleX_motor_moved(self, pos):
"""
- Descript. :
"""
self.current_motor_positions["sampx"] = pos
- if time.time() - self.centring_time > 1.0:
- self.invalidate_centring()
- self.emit_diffractometer_moved()
def sampleX_motor_state_changed(self, state):
"""
- Descript. :
+ Emit stateChanged signal with state value.
"""
self.current_motor_states["sampx"] = state
- self.emit("stateChanged", (state,))
+ self.emit('stateChanged', (state, ))
def sampleY_motor_moved(self, pos):
"""
- Descript. :
"""
self.current_motor_positions["sampy"] = pos
- if time.time() - self.centring_time > 1.0:
- self.invalidate_centring()
- self.emit_diffractometer_moved()
def sampleY_motor_state_changed(self, state):
"""
- Descript. :
+ Emit stateChanged signal with state value.
"""
self.current_motor_states["sampy"] = state
- self.emit("stateChanged", (state,))
+ self.emit('stateChanged', (state, ))
+
+ def kappa_motor_moved(self, pos):
+ """
+ Emit kappaMotorMoved signal with position value.
+ """
+ self.current_motor_positions["kappa"] = pos
+ self.emit("kappaMotorMoved", pos)
+
+ def kappa_motor_state_changed(self, state):
+ """
+ Emit stateChanged signal with state value.
+ """
+ self.current_motor_states["kappa"] = state
+ self.emit('stateChanged', (state, ))
+
+ def kappa_phi_motor_moved(self, pos):
+ """
+ Emit kappa_phiMotorMoved signal with position value.
+ """
+ self.current_motor_positions["kappa_phi"] = pos
+ self.emit("kappa_phiMotorMoved", pos)
+
+ def kappa_phi_motor_state_changed(self, state):
+ """
+ Emit stateChanged signal with state value.
+ """
+ self.current_motor_states["kappa_phi"] = state
+ self.emit('stateChanged', (state, ))
def focus_motor_moved(self, pos):
"""
- Descript. :
"""
self.current_motor_positions["focus"] = pos
def start_auto_focus(self):
- self.cmd_start_auto_focus()
+ pass
+
+ def move_omega(self, pos, velocity=None):
+ """
+ Move omega to absolute position.
+
+ @pos: target position
+ """
+ # turn it on
+ if velocity is not None:
+ self.phi_motor_hwobj.set_velocity(velocity)
+ self.phi_motor_hwobj.set_value(pos)
+ time.sleep(0.2)
+ # it should wait here
+
+ def move_omega_relative(self, relpos):
+ """
+ Move omega to relative position.
+
+ @relpos: target relative position
+ """
+ #TODO:Are all these waiting times really necessary??'
+ self.wait_device_ready()
+ self.phi_motor_hwobj.set_value( self.phi_motor_hwobj.get_value() + relpos, timeout = 10 )
+ time.sleep(0.2)
+ self.wait_device_ready()
+
+ def set_diff_phase(self, phase, timeout=None):
+ """
+ General function to set phase by using supervisor commands.
+ CAUTION: setting the diff phase does not change the position of:
+ - the detector cover
+ - the position of the fast shutter.
+ It is better to use the supervisor phases for safety reasons
+ """
+ if phase.upper() != "TRANSFER" and HWR.beamline.ln2shower.is_pumping():
+ msg = "Cannot change to non transfer phase when the lnshower is pumping, turn off the shower first"
+ self.userlogger.error(msg)
+ raise Exception(msg)
+ if phase.upper() == "TRANSFER":
+ self.go_transfer()
+ #elif phase.upper() == "COLLECT":
+ #self.go_collect()
+ #elif phase.upper() == "BEAMVIEW":
+ #self.go_beam_view()
+ elif phase.upper() == "CENTRING":
+ self.go_sample_view()
+ else:
+ self.logger.warning(
+ "Diffractometer set_phase asked for un-handled phase: %s" % phase
+ )
+ return
+
+ self.logger.debug(
+ "Telling diff to go to phase %s, with timeout %s" % ( phase, timeout )
+ )
+
+ if timeout:
+ time.sleep(1)
+ self.wait_ready( timeout = timeout )
+ time.sleep(1)
+ self.logger.debug(
+ "Diff phase is %s" % ( self.get_current_phase() )
+ )
+
+ # Copied from GenericDiffractometer just to improve error loggin
+ def wait_device_ready(self, timeout=30):
+ """ Waits when diffractometer status is ready:
+
+ :param timeout: timeout in second
+ :type timeout: int
+ """
+ gevent.sleep(1) # wait a bit to see if state does not change inmediately
+ with gevent.Timeout(timeout, Exception("Timeout waiting for Diffracometer ready, check bl13/eh/diff. Is omegax close enough to 0??")):
+ while not self.is_ready():
+ time.sleep(0.01)
+
+ def go_transfer(self):
+ self.cmd_go_transfer()
+
+ def go_sample_view(self):
+ self.cmd_go_sample_view()
+
+ # TODO: move to supervisor
+ def get_current_phase(self):
+ """
+ Descript. : read diff phase
+ """
+ try:
+ _value = self.chan_phase.get_value()
+ #self.logger.debug('get_current_phase: (value={0}, type={1})'.format(_value, type(_value)))
+ except Exception as e:
+ raise RuntimeError('Cannot get diff current phase:\n%s, try to restart the diff DS' % str(e))
+ return _value
+ # return self.chan_phase.get_value()
+
+def test_hwo(hwo):
+ print(hwo.get_phase_list())
diff --git a/mxcubecore/HardwareObjects/ALBA/XalocOfflineProcessing.py b/mxcubecore/HardwareObjects/ALBA/XalocOfflineProcessing.py
new file mode 100755
index 0000000000..8f9c76ef8f
--- /dev/null
+++ b/mxcubecore/HardwareObjects/ALBA/XalocOfflineProcessing.py
@@ -0,0 +1,404 @@
+#
+# Project: 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 .
+
+"""
+[Name]
+XalocOfflineProcessing
+
+[Description]
+Hardware Object used to prepare and start the autoprocessing
+pipelines for ALBA beamlines.
+
+[Emitted signals]
+- None
+
+TODO: the same xml input files can be used for different processing
+TODO: implement small mol processing
+"""
+
+from __future__ import print_function
+
+import os
+import math
+import logging
+
+from mxcubecore.BaseHardwareObjects import HardwareObject
+from XSDataCommon import XSDataBoolean, XSDataFile, XSDataString, XSDataInteger, XSDataDouble
+from XalocXSDataAutoprocv1_0 import XalocXSDataAutoprocInput
+from XalocXSDataControlAutoPROCv1_1 import XSDataInputControlAutoPROC
+from XalocXSDataControlXia2DIALSv1_0 import XalocXSDataInputXia2DIALS
+
+__credits__ = ["ALBA Synchrotron"]
+__version__ = "3"
+__category__ = "General"
+
+
+class XalocOfflineProcessing(HardwareObject):
+ def __init__(self, name):
+ HardwareObject.__init__(self, name)
+ self.logger = logging.getLogger("HWR.XalocOfflineProcessing")
+ self.template_dir = None
+ self.detsamdis_hwobj = None
+ self.chan_beamx = None
+ self.chan_beamy = None
+ self.ednaproc_input_file = None
+ self.autoproc_input_file = None
+ self.cluster = None
+ self.sample_is_small_molecule = False
+
+ def init(self):
+ self.logger.debug("Initializing {0}".format(self.__class__.__name__))
+ self.template_dir = self.get_property("template_dir")
+ self.logger.debug("Autoprocessing template_dir = %s" %
+ self.template_dir)
+ # TODO: include these values in dc_pars or osc_seq dictionaries
+ self.detsamdis_hwobj = self.get_object_by_role("detector_distance")
+ self.chan_beamx = self.get_channel_object('beamx')
+ self.chan_beamy = self.get_channel_object('beamy')
+
+ self.cluster = self.get_object_by_role("cluster")
+
+ def create_input_files(self, dc_pars):
+
+ self.logger.debug("XalocOfflineProcessing create_input_files dc_pars = %s " % dc_pars )
+ xds_dir = dc_pars['xds_dir']
+ mosflm_dir = dc_pars['mosflm_dir']
+ ednaproc_dir = dc_pars['ednaproc_dir']
+ autoproc_dir = dc_pars['autoproc_dir']
+
+ fileinfo = dc_pars['fileinfo']
+ osc_seq = dc_pars['oscillation_sequence'][0]
+
+ prefix = fileinfo['prefix']
+ runno = fileinfo['run_number']
+
+ exp_time = osc_seq['exposure_time']
+
+ # start_angle = osc_seq['start']
+ nb_images = osc_seq['number_of_images']
+ start_img_num = osc_seq['start_image_number']
+ angle_increment = osc_seq['range']
+
+ wavelength = osc_seq.get('wavelength', 0)
+
+ xds_template_name = 'XDS_TEMPLATE.INP'
+ mosflm_template_name = 'mosflm_template.dat'
+
+ xds_template_path = os.path.join(self.template_dir, xds_template_name)
+ mosflm_template_path = os.path.join(self.template_dir, mosflm_template_name)
+
+ xds_file = os.path.join(xds_dir, "XDS.INP")
+ mosflm_file = os.path.join(mosflm_dir, "mosflm.dat")
+
+ # PREPARE VARIABLES
+ detsamdis = self.detsamdis_hwobj.get_value()
+ beamx, beamy = self.chan_beamx.get_value(), self.chan_beamy.get_value()
+
+ mbeamx, mbeamy = beamy * 0.172, beamx * 0.172
+
+ data_range_start_num = start_img_num
+ data_range_finish_num = start_img_num + nb_images - 1
+ background_range_start_num = start_img_num
+ spot_range_start_num = start_img_num
+ minimum_range = 0
+ background_range_finish_num = 0
+ spot_range_finish_num = 0
+
+ if angle_increment != 0:
+ minimum_range = int(round(20 / angle_increment))
+ elif angle_increment == 0:
+ minimum_range = 1
+ if nb_images >= minimum_range:
+ background_range_finish_num = start_img_num + minimum_range - 1
+ if nb_images >= minimum_range:
+ spot_range_finish_num = start_img_num + minimum_range - 1
+ if nb_images < minimum_range:
+ background_range_finish_num = start_img_num + nb_images - 1
+ if nb_images < minimum_range:
+ spot_range_finish_num = start_img_num + nb_images - 1
+
+ test_low_res = 8.
+ largest_vector = 0.172 * ((max(beamx, 2463 - beamx))**2 +
+ (max(beamy, 2527 - beamy))**2)**0.5
+ test_high_res = round(wavelength / (2 * math.sin(0.5 * math.atan(
+ largest_vector / detsamdis))), 2)
+ low_res = 50.
+ high_res = test_high_res
+ data_filename = prefix + '_' + str(runno) + '_????'
+ mdata_filename = prefix + '_' + str(runno) + '_####.cbf'
+ seconds = 5 * exp_time
+
+ if angle_increment < 1 and not angle_increment == 0:
+ seconds = 5 * exp_time / angle_increment
+
+ # DEFINE SG/UNIT CELL
+ spacegroup_number = ''
+ unit_cell_constants = ''
+
+ #datapath_dir = os.path.abspath(xds_file).replace('PROCESS_DATA', 'RAW_DATA')
+ #datapath_dir = os.path.dirname(os.path.dirname(datapath_dir)) + os.path.sep
+ datapath_dir = fileinfo['directory']+ os.path.sep
+
+ # CREATE XDS.INP FILE
+ xds_templ = open(xds_template_path, "r").read()
+
+ xds_templ = xds_templ.replace('###BEAMX###', str(round(beamx, 2)))
+ xds_templ = xds_templ.replace("###BEAMY###", str(round(beamy, 2)))
+ xds_templ = xds_templ.replace("###DETSAMDIS###", str(round(detsamdis, 2)))
+ xds_templ = xds_templ.replace("###ANGLEINCREMENT###", str(angle_increment))
+ xds_templ = xds_templ.replace("###WAVELENGTH###", str(wavelength))
+ xds_templ = xds_templ.replace("###DATARANGESTARTNUM###",
+ str(data_range_start_num))
+ xds_templ = xds_templ.replace("###DATARANGEFINISHNUM###",
+ str(data_range_finish_num))
+ xds_templ = xds_templ.replace("###BACKGROUNDRANGESTART###",
+ str(background_range_start_num))
+ xds_templ = xds_templ.replace("###BACKGROUNDRANGEFINISHNUM###",
+ str(background_range_finish_num))
+ xds_templ = xds_templ.replace("###SPOTRANGESTARTNUM###",
+ str(spot_range_start_num))
+ xds_templ = xds_templ.replace("###SPOTRANGEFINISHNUM###",
+ str(spot_range_finish_num))
+ xds_templ = xds_templ.replace("###TESTLOWRES###", str(test_low_res))
+ xds_templ = xds_templ.replace("###TESTHIGHRES###", str(test_high_res))
+ xds_templ = xds_templ.replace("###LOWRES###", str(low_res))
+ xds_templ = xds_templ.replace("###HIGHRES###", str(high_res))
+ xds_templ = xds_templ.replace("###DIRECTORY###", str(datapath_dir))
+ xds_templ = xds_templ.replace("###FILENAME###", str(data_filename))
+ xds_templ = xds_templ.replace("###SECONDS###", str(int(seconds)))
+ xds_templ = xds_templ.replace("###LYSOZYME_SPACE_GROUP_NUMBER###",
+ str(spacegroup_number))
+ xds_templ = xds_templ.replace("###LYSOZYME_UNIT_CELL_CONSTANTS###",
+ str(unit_cell_constants))
+
+ open(xds_file, "w").write(xds_templ)
+
+ # CREATE MOSFLM.DAT FILE
+ mosflm_templ = open(mosflm_template_path, "r").read()
+
+ mosflm_templ = mosflm_templ.replace("###DETSAMDIS###", str(round(detsamdis, 2)))
+ mosflm_templ = mosflm_templ.replace('###BEAMX###', str(round(mbeamx, 2)))
+ mosflm_templ = mosflm_templ.replace("###BEAMY###", str(round(mbeamy, 2)))
+ mosflm_templ = mosflm_templ.replace("###DIRECTORY###", str(datapath_dir))
+ mosflm_templ = mosflm_templ.replace("###FILENAME###", str(mdata_filename))
+ mosflm_templ = mosflm_templ.replace("###WAVELENGTH###", str(wavelength))
+ mosflm_templ = mosflm_templ.replace("###DATARANGESTARTNUM###",
+ str(data_range_start_num))
+
+ open(mosflm_file, "w").write(mosflm_templ)
+
+ # CREATE EDNAPROC XML FILE
+ collection_id = dc_pars['collection_id']
+ ednaproc_dir = dc_pars['ednaproc_dir']
+
+ ednaproc_input_file = os.path.join(ednaproc_dir, "EDNAprocInput_%d.xml" %
+ collection_id)
+ ednaproc_input = XalocXSDataAutoprocInput()
+
+ input_file = XSDataFile()
+ path = XSDataString()
+ path.setValue(xds_file)
+ input_file.setPath(path)
+
+ ednaproc_input.setInput_file(input_file)
+ ednaproc_input.setData_collection_id(XSDataInteger(collection_id))
+
+ ednaproc_input.setDoAnomAndNonanom(XSDataBoolean(True))
+ ednaproc_input = self.add_user_input_to_xml(ednaproc_input, dc_pars)
+
+ ednaproc_input.exportToFile(ednaproc_input_file)
+ self.ednaproc_input_file = ednaproc_input_file
+
+ # CREATE AUTOPROC XML FILE
+ self.create_autoproc_edna_input_file(dc_pars, data_range_start_num, data_range_finish_num, mdata_filename)
+ self.create_xia2_edna_input_file(dc_pars, data_range_start_num, data_range_finish_num, mdata_filename)
+ self.create_xia2chem_edna_input_file(dc_pars, data_range_start_num, data_range_finish_num, mdata_filename)
+
+ def create_autoproc_edna_input_file(self, dc_pars, fromN, toN, template, ispyb=True):
+
+ # Get data from data collection parameters
+ collection_id = dc_pars['collection_id']
+ images_dir = dc_pars['fileinfo']['directory']
+ template = template
+ first_image_nb = fromN
+ last_image_nb = toN
+ output_dir = dc_pars['autoproc_dir']
+
+ autoproc_input = XSDataInputControlAutoPROC()
+ #autoproc_input = XalocXSDataInputControlAutoPROC()
+ # Do both anom and no anom
+ autoproc_input.setDoAnomAndNonanom(XSDataBoolean(True))
+ # Add specific configuration file by the slurm script
+ try:
+ autoproc_input.setConfigDef(XSDataFile(XSDataString("__configDef")))
+ #self.logger.debug("Setting configDef path" )
+ except Exception as e:
+ self.logger.debug("XalocOfflineProcessing Cant set configDef file for AutoPROC processing" )
+ self.logger.debug("Error %s" % e)
+
+ if ispyb:
+ autoproc_input.setDataCollectionId(XSDataInteger(collection_id))
+ else:
+ autoproc_input.setDirN(XSDataFile(XSDataString(images_dir)))
+ autoproc_input.setFromN(XSDataInteger(first_image_nb))
+ autoproc_input.setToN(XSDataInteger(last_image_nb))
+ autoproc_input.setTemplateN(XSDataString(template))
+
+ # When the user does not give a cell, the cell parameters are set to 0,
+ # the EDNA autoproc plugin does not accept this
+ # TODO: dont add cell parameters unless specified by the user
+ autoproc_input = self.add_user_input_to_xml(autoproc_input, dc_pars)
+ autoproc_input.setDoAnomAndNonanom(XSDataBoolean(True))
+
+ # Export file
+ autoproc_input_filename = os.path.join(output_dir,
+ "AutoPROCInput_%d.xml" % collection_id)
+ autoproc_input.exportToFile(autoproc_input_filename)
+ self.autoproc_input_file = autoproc_input_filename
+
+ def create_xia2_edna_input_file(self, dc_pars, fromN, toN, template, ispyb=True):
+ collection_id = dc_pars['collection_id']
+ images_dir = dc_pars['fileinfo']['directory']
+ template = template
+ first_image_nb = fromN
+ last_image_nb = toN
+ output_dir = dc_pars['xia2_dir']
+ first_image_string = os.path.join(images_dir,template.replace('####',"%04d" % first_image_nb))
+
+ # Create EDNA data model input file
+ xia2_input = XalocXSDataInputXia2DIALS()
+ xia2_input.setDoAnomAndNonanom(XSDataBoolean(True))
+
+ if ispyb:
+ xia2_input.setDiffractionImage(XSDataString(first_image_string))
+ xia2_input.setDataCollectionId(XSDataInteger(collection_id))
+ else:
+ raise NotImplementedError("Cannot process with XIA2 without using ISPyB")
+
+ xia2_input = self.add_user_input_to_xml(xia2_input, dc_pars)
+
+ # Export file
+ xia2_input_filename = os.path.join(output_dir, "XIA2Input_%d.xml" % collection_id)
+ xia2_input.exportToFile(xia2_input_filename)
+ self.xia2_input_file = xia2_input_filename
+
+ def create_xia2chem_edna_input_file(self, dc_pars, fromN, toN, template, ispyb=True):
+ collection_id = dc_pars['collection_id']
+ images_dir = dc_pars['fileinfo']['directory']
+ template = template
+ first_image_nb = fromN
+ last_image_nb = toN
+ output_dir = dc_pars['xia2chem_dir']
+ first_image_string = os.path.join(images_dir,template.replace('####',"%04d" % first_image_nb))
+
+ # Create EDNA data model input file
+ xia2_input = XalocXSDataInputXia2DIALS()
+ xia2_input.setDoAnomAndNonanom(XSDataBoolean(True))
+
+ if ispyb:
+ xia2_input.setDiffractionImage(XSDataString(first_image_string))
+ xia2_input.setDataCollectionId(XSDataInteger(collection_id))
+ else:
+ raise NotImplementedError("Cannot process with XIA2 chem without using ISPyB")
+ #xia2_input = self.add_user_input_to_xml(xia2_input, dc_pars)
+
+ detsamdis = self.detsamdis_hwobj.get_value()
+ osc_seq = dc_pars['oscillation_sequence'][0]
+ wavelength = osc_seq.get('wavelength', 0)
+ beamx, beamy = self.chan_beamx.get_value(), self.chan_beamy.get_value()
+ largest_vector = 0.172 * ((max(beamx, 2463 - beamx))**2 +
+ (max(beamy, 2527 - beamy))**2)**0.5
+
+ max_det_res = round(wavelength / (2 * math.sin(0.5 * math.atan(
+ largest_vector / detsamdis))), 2)
+ max_det_res = dc_pars['resolution']['upper']
+
+ xia2_input.setDetector_max_res( XSDataDouble(max_det_res) )
+ xia2_input.set_small_molecule_3dii( XSDataBoolean(True) )
+
+ # Export file
+ xia2_input_filename = os.path.join(output_dir, "XIA2Input_%d.xml" % collection_id)
+ xia2_input.exportToFile(xia2_input_filename)
+ self.xia2chem_input_file = xia2_input_filename
+
+ def add_user_input_to_xml(self, xsd_autoproc_input, params):
+ #residues_num = float(params.get("residues", 0))
+ # These lines are not compatible with the GP AutoPROC module
+ #if residues_num != 0:
+ #xsd_autoproc_input.setNres(XSDataDouble(residues_num))
+ space_group = params.get("sample_reference").get("spacegroup", "")
+ if not isinstance(space_group, int) and len(space_group) > 0:
+ xsd_autoproc_input.setSpacegroup(XSDataString(space_group))
+ unit_cell = params.get("sample_reference").get("cell", "")
+ #if len(unit_cell) > 0:
+ #xsd_autoproc_input.setUnit_cell(XSDataString(unit_cell))
+ return xsd_autoproc_input
+
+ def trigger_auto_processing(self, dc_pars):
+
+ dc_id = dc_pars['collection_id']
+ self.logger.debug("Collection_id = %s " % dc_id)
+
+ # EDNAProc
+ ednaproc_dir = dc_pars['ednaproc_dir']
+ logging.getLogger('user_level_log').info("Trigger EDNAProc processing")
+ job = self.cluster.create_ednaproc_job(dc_id, self.ednaproc_input_file, ednaproc_dir)
+ ##job.run()
+ self.cluster.run(job)
+ self.logger.debug("EDNAProc input file = %s " % self.ednaproc_input_file)
+ self.logger.debug("Output dir = %s " % ednaproc_dir)
+ logging.getLogger('user_level_log').info("EDNAProc job ID: %s" % job.id)
+
+ # AutoPROC
+ autoproc_dir = dc_pars['autoproc_dir']
+ logging.getLogger('user_level_log').info("Trigger AutoPROC processing")
+ job = self.cluster.create_autoproc_job(dc_id, self.autoproc_input_file, autoproc_dir)
+ self.logger.debug("AutoPROC input file = %s " % self.autoproc_input_file)
+ ##job.run()
+ self.cluster.run(job)
+ self.logger.debug("Output dir = %s " % autoproc_dir)
+ logging.getLogger('user_level_log').info("AutoPROC job ID: %s" % job.id)
+
+ # XIA2
+ xia2_dir = dc_pars['xia2_dir']
+ logging.getLogger('user_level_log').info("Trigger XIA2 processing")
+ job = self.cluster.create_xia2_job(dc_id, self.xia2_input_file, xia2_dir)
+ self.cluster.run(job)
+ self.logger.debug("XIA2 input file = %s " % self.xia2_input_file)
+ self.logger.debug("Output dir = %s " % xia2_dir)
+ logging.getLogger('user_level_log').info("XIA2 job ID: %s" % job.id)
+
+ # XIA2 small molecule
+ xia2chem_dir = dc_pars['xia2chem_dir']
+ logging.getLogger('user_level_log').info("Trigger XIA2 small molecule processing")
+ job = self.cluster.create_xia2_job(dc_id, self.xia2chem_input_file, xia2chem_dir)
+ self.cluster.run(job)
+ self.logger.debug("XIA2 input file = %s " % self.xia2chem_input_file)
+ self.logger.debug("Output dir = %s " % xia2chem_dir)
+ logging.getLogger('user_level_log').info("XIA2 job ID: %s" % job.id)
+
+ def set_sample_type(self, is_small_molecule):
+ is_small_bool = True
+ if is_small_molecule == 0: is_small_bool = False
+
+ logging.getLogger('user_level_log').info("Setting sample is small molecule to %s" % is_small_bool)
+ self.sample_is_small_molecule = is_small_bool
+
+def test_hwo(hwo):
+ pass
diff --git a/mxcubecore/HardwareObjects/ALBA/XalocOnlineProcessing.py b/mxcubecore/HardwareObjects/ALBA/XalocOnlineProcessing.py
new file mode 100755
index 0000000000..eabe9533d5
--- /dev/null
+++ b/mxcubecore/HardwareObjects/ALBA/XalocOnlineProcessing.py
@@ -0,0 +1,641 @@
+#
+# Project: 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 .
+
+import os
+import time
+import gevent
+import logging
+import subprocess
+
+from mxcubecore.HardwareObjects.DozorOnlineProcessing import (
+ DozorOnlineProcessing,
+)
+from mxcubecore.HardwareObjects.abstract.AbstractOnlineProcessing import (
+ AbstractOnlineProcessing,
+)
+
+from XSDataCommon import XSDataBoolean
+from XSDataCommon import XSDataDouble
+from XSDataCommon import XSDataFloat
+from XSDataCommon import XSDataInteger
+from XSDataCommon import XSDataString
+
+import numpy
+
+from scipy import ndimage
+from scipy.interpolate import UnivariateSpline
+
+from mxcubecore import HardwareRepository as HWR
+
+__credits__ = ["ALBA Synchrotron"]
+__licence__ = "LGPLv3+"
+__version__ = "3"
+__category__ = "General"
+
+class XalocOnlineProcessing(DozorOnlineProcessing):
+ def __init__(self, name):
+ DozorOnlineProcessing.__init__(self, name)
+ self.logger = logging.getLogger("HWR.XalocOnlineProcessing")
+ self.pop_object = None # the subprocess.Popen object returned by subprocess.Popen
+ self.testing = None
+
+ def init(self):
+ DozorOnlineProcessing.init(self)
+ self.testing = self.get_property('testing', False)
+
+ def run_processing(self, data_collection):
+ """Starts parallel processing
+
+ :param: data_collection: data collection obj, not used, set in queue_entry
+ :type: data_collection: queue_model_objects.DataCollection
+
+ """
+ #self.data_collection = data_collection
+ #self.logger.debug("data_collection %s" % str(data_collection) )
+ #self.prepare_processing()
+
+ input_filename = self.get_input_filename(self.data_collection)
+ if not input_filename:
+ input_filename = os.path.join(
+ self.params_dict["process_directory"], "dozor_input.xml"
+ )
+
+ self.create_processing_input_file1_1(input_filename)
+
+ # results = {"raw" : self.results_raw,
+ # "aligned": self.results_aligned}
+ # print "emit ! ", results
+ # self.emit("processingStarted", (data_collection, results))
+ # self.emit("processingResultsUpdate", False)
+
+ if not os.path.isfile(self.start_command):
+ msg = (
+ "ParallelProcessing: Start command %s" % self.start_command
+ + "is not executable"
+ )
+ self.logger.error(msg)
+ self.set_processing_status("Failed")
+ else:
+ #TODO: it can be something more complex than a script file
+ line_to_execute = (
+ self.start_command
+ + " "
+ + input_filename
+ #+ " "
+ #+ self.params_dict["process_directory"]
+ )
+
+ line_to_execute = (
+ 'ssh opbl13@ctbl1301 \"'
+ + line_to_execute
+ + '\" '
+ )
+ self.logger.debug("Processing DOZOR with command: %s" % line_to_execute)
+
+ self.started = True
+ self.pop_object = subprocess.Popen(
+ str(line_to_execute),
+ shell=True,
+# stdin=None,
+# stdout=None,
+# stderr=None,
+# close_fds=True,
+ )
+
+ def create_processing_input_file1_1(self, processing_input_filename):
+ """Creates dozor input file base on data collection parameters
+
+ :param processing_input_filename
+ :type : str
+ """
+ from XSDataControlDozorv1_1 import XSDataInputControlDozor
+ from XSDataControlDozorv1_1 import XSDataResultControlDozor
+ from XSDataControlDozorv1_1 import XSDataControlImageDozor
+
+ self.logger.debug('Creating Dozor input file %s' % processing_input_filename )
+
+ input_file = XSDataInputControlDozor()
+ input_file.setTemplate(XSDataString(self.params_dict["template"]))
+ input_file.setFirst_image_number(XSDataInteger(self.params_dict["first_image_num"]))
+ input_file.setLast_image_number(XSDataInteger(self.params_dict["images_num"]))
+ input_file.setFirst_run_number(XSDataInteger(self.params_dict["run_number"]))
+ input_file.setLast_run_number(XSDataInteger(self.params_dict["run_number"]))
+ input_file.setLine_number_of(XSDataInteger(self.params_dict["lines_num"]))
+ input_file.setReversing_rotation(
+ XSDataBoolean(self.params_dict["reversing_rotation"])
+ )
+ pixel_size = HWR.beamline.detector.get_pixel_size()
+ input_file.setPixelMin(XSDataInteger(pixel_size[0]))
+ input_file.setPixelMax(XSDataInteger(pixel_size[1]))
+ #input_file.setPixelMin(XSDataInteger(HWR.beamline.detector.get_pixel_min()))
+ #input_file.setPixelMax(XSDataInteger(HWR.beamline.detector.get_pixel_max()))
+ #input_file.setBeamstopSize(XSDataDouble(self.beamstop_hwobj.get_size()))
+ #input_file.setBeamstopDistance(XSDataDouble(self.beamstop_hwobj.get_distance()))
+ #input_file.setBeamstopDirection(XSDataString(self.beamstop_hwobj.get_direction()))
+
+ input_file.exportToFile(processing_input_filename)
+
+ def create_processing_input_file1_0(self, processing_input_filename):
+ """Creates dozor input file base on data collection parameters using version 1_0
+
+ :param processing_input_filename
+ :type : str
+ """
+ from XalocXSDataControlDozorv1_0 import XSDataInputControlDozor
+ from XalocXSDataControlDozorv1_0 import XSDataResultControlDozor
+ from XalocXSDataControlDozorv1_0 import XSDataControlImageDozor
+
+ self.logger.debug('Creating Dozor input file %s' % processing_input_filename )
+ self.logger.debug('Data collection id %d' % self.params_dict["collection_id"] )
+
+ input_file = XSDataInputControlDozor()
+ input_file.setDataCollectionId(
+ XSDataInteger(
+ self.params_dict["collection_id"]
+ )
+ )
+ input_file.setDoISPyBUpload(
+ XSDataBoolean(True)
+ )
+ input_file.setBatchSize( XSDataInteger(self.params_dict["images_per_line"]) )
+ #input_file.setFirst_image_number(XSDataInteger(self.params_dict["first_image_num"]))
+ #input_file.setLast_image_number(XSDataInteger(self.params_dict["images_num"]))
+ #input_file.setFirst_run_number(XSDataInteger(self.params_dict["run_number"]))
+ #input_file.setLast_run_number(XSDataInteger(self.params_dict["run_number"]))
+ #input_file.setLine_number_of(XSDataInteger(self.params_dict["lines_num"]))
+ #input_file.setReversing_rotation(
+ #XSDataBoolean(self.params_dict["reversing_rotation"])
+ #)
+ ##TODO: the pixel sizes are 0??
+ #pixel_size = HWR.beamline.detector.get_pixel_size()
+ #input_file.setPixelMin(XSDataInteger(pixel_size[0]))
+ #input_file.setPixelMax(XSDataInteger(pixel_size[1]))
+ ##input_file.setPixelMin(XSDataInteger(HWR.beamline.detector.get_pixel_min()))
+ ##input_file.setPixelMax(XSDataInteger(HWR.beamline.detector.get_pixel_max()))
+ ##input_file.setBeamstopSize(XSDataDouble(self.beamstop_hwobj.get_size()))
+ ##input_file.setBeamstopDistance(XSDataDouble(self.beamstop_hwobj.get_distance()))
+ ##input_file.setBeamstopDirection(XSDataString(self.beamstop_hwobj.get_direction()))
+ #input_file.setBeamstopSize( XSDataDouble(1.5) )
+ #input_file.setBeamstopDistance( XSDataDouble(34) )
+ #input_file.setBeamstopDirection( XSDataString("Y") )
+
+ input_file.exportToFile(processing_input_filename)
+
+ def get_input_filename(self, data_collection):
+ # Create dozor dir as in XalocCollect
+ dozor_dir = self._create_proc_files_directory('dozor')
+ input_filename = os.path.join(dozor_dir, "dozor_input.xml")
+ return input_filename
+
+ def stop_processing(self):
+ """Stops processing"""
+ self.started = False
+ self.set_processing_status("Stopped")
+ try:
+ self.pop_object.terminate()
+ except Exception as e:
+ self.logger.error("Cant stop processing: error is \n%s", e)
+
+
+ #def batch_processed2(self, batch):
+ #"""Method called from EDNA via xmlrpc to set results
+
+ #:param batch: list of dictionaries describing processing results
+ #:type batch: lis
+ #"""
+ ## FORCED FOR TESTING
+ ##No longer self.started = True
+
+ #self.logger.debug("Batch arrived %s" % str(self.started))
+ #self.logger.debug("Batch is %s" % batch)
+ #if self.started and (type(batch) in (tuple, list)):
+ #if type(batch[0]) not in (tuple, list):
+ #batch = [batch]
+ #self.logger.debug("Batch, for each image in batch")
+ #for image in batch:
+ #frame_num = int(image[0])
+ #self.logger.debug("Frame number is %s" % frame_num)
+ #self.results_raw["spots_num"][frame_num] = image[1]
+ #self.results_raw["spots_resolution"][frame_num] = 1 / image[3]
+ #self.results_raw["score"][frame_num] = image[2]
+
+ #for score_key in self.results_raw.keys():
+ #if self.params_dict["lines_num"] > 1:
+ #col, row = self.grid.get_col_row_from_image(frame_num)
+ #self.results_aligned[score_key][col][row] =\
+ #self.results_raw[score_key][frame_num]
+ #else:
+ #self.results_aligned[score_key][frame_num] =\
+ #self.results_raw[score_key][frame_num]
+ ## if self.params_dict["lines_num"] <= 1:
+ ## self.smooth()
+
+ ## self.emit("paralleProcessingResults",
+ ## (self.results_aligned,
+ ## self.params_dict,
+ ## False))
+
+ def batch_processed(self, batch):
+ """Method called from EDNA via xmlrpc to set results
+ :param batch: list of dictionaries describing processing results
+ :type batch: lis
+ Reimplmented here for extra logging
+ """
+
+ #self.logger.debug("batch_processed called, batch is %s" % batch)
+ #self.logger.debug("Has process started? %s" % str(self.started))
+
+ if self.started:
+ for image in batch:
+ #self.logger.debug("Loop for each image in batch arrived")
+ #self.logger.debug("image is : %s" % image)
+ self.results_raw["spots_num"][image[0] - 1] = image[1]
+ self.results_raw["spots_resolution"][image[0] - 1] = image[3]
+ self.results_raw["score"][image[0] - 1] = image[2]
+
+ self.align_processing_results(batch[0][0] - 1, batch[-1][0] - 1)
+
+ #self.logger.debug("Emitting signal processingResultsUpdate")
+
+ self.emit("processingResultsUpdate", False)
+
+ # ONLY FOR ALBA!!! Similar function present in the XalocCollect
+ def _create_proc_files_directory(self, proc_name):
+
+ path_template = self.data_collection.acquisitions[
+ 0].path_template
+ proc_dir = path_template.process_directory
+ run_number = path_template.run_number
+ prefix = path_template.get_prefix()
+
+ i = 1
+
+ while True:
+ logging.getLogger('HWR').debug('*** iteration %s' % i)
+ _dirname = "%s_%s_%s_%d" % (
+ proc_name,
+ prefix,
+ run_number,
+ i)
+ _directory = os.path.join(
+ proc_dir,
+ _dirname)
+ if not os.path.exists(_directory):
+ break
+ i += 1
+
+ try:
+ logging.getLogger('HWR').debug(
+ 'Creating proc directory %s: ' % _directory)
+ self._create_directories(_directory)
+ os.system("chmod -R 777 %s" % _directory)
+ except Exception as e:
+ msg = "Could not create directory %s\n%s" % (_directory, str(e))
+ logging.getLogger('HWR').exception(msg)
+ return
+
+ # This is not yet implemented fpor dozor...maybe is not necesary
+
+ # save directory names in current_dc_parameters. They will later be used
+ # by autoprocessing.
+ # key = "%s_dir" % proc_name
+ # self.current_dc_parameters[key] = _directory
+ # logging.getLogger('HWR').debug("dc_pars[%s] = %s" % (key, _directory))
+ return _directory
+
+ # The following methods are copied to improve error logging, the functionality is the same
+ def _create_directories(self, *args):
+ """
+ Descript. :
+ """
+ for directory in args:
+ logging.getLogger('HWR').debug('Creating directory %s: ' % directory)
+ try:
+ os.makedirs(directory)
+ except OSError as e:
+ import errno
+ if e.errno != errno.EEXIST:
+ logging.getLogger('HWR').error(
+ 'Error in making parallel processing directories')
+ raise
+
+ def align_processing_results(self, start_index, end_index):
+ """Realigns all results. Each results (one dimensional numpy array)
+ is converted to 2d numpy array according to diffractometer geometry.
+ Function also extracts 10 (if they exist) best positions
+ """
+ # Each result array is realigned
+
+ self.logger.debug("align_processing_results, start_index %d, end_index %s, self.grid %s" %
+ (start_index, end_index, self.grid))
+ for score_key in self.results_raw.keys():
+ if (
+ self.grid
+ #and self.results_raw[score_key].size == self.params_dict["images_num"]
+ ):
+ for cell_index in range(start_index, end_index + 1):
+ col, row = self.grid.get_col_row_from_image_serial(
+ cell_index + self.params_dict["first_image_num"]
+ )
+ if (
+ col < self.results_aligned[score_key].shape[0]
+ and row < self.results_aligned[score_key].shape[1]
+ ):
+ # to test the xray centering without beam, until "End of lines for test -----
+ if self.testing:
+ self.results_raw[ score_key ][ cell_index ] = \
+ pow( self.results_aligned[score_key].shape[0]/2., 2.001) + \
+ pow( self.results_aligned[score_key].shape[1]/2. , 2.001) - \
+ pow( -2. + col - self.results_aligned[score_key].shape[0]/2., 2.) - \
+ pow( -1. + row - self.results_aligned[score_key].shape[1]/2., 2.) # to test the xray centering without beam
+ if self.results_raw[ score_key ][ cell_index ] < 0 : self.results_raw[ score_key ][ cell_index ] = 0
+ # End of lines for test ----------------------------------------
+ else:
+ self.results_aligned[score_key][col][row] = \
+ self.results_raw[ score_key ][ cell_index ]
+ else:
+ self.results_aligned[score_key] = self.results_raw[score_key]
+ if self.interpolate_results:
+ x_array = numpy.linspace(
+ 0,
+ self.params_dict["images_num"],
+ self.params_dict["images_num"],
+ dtype=int,
+ )
+ spline = UnivariateSpline(
+ x_array, self.results_aligned[score_key], s=10
+ )
+ self.results_aligned["interp_" + score_key] = spline(x_array)
+
+ #self.logger.debug("self.results_aligned %s" % (str(self.results_aligned)) )
+
+ if self.grid:
+ # TODO: this should depend on the user selection of the self._score_type_cbox selection in the brick
+ self.grid.set_score(self.results_raw["score"])
+ (center_x, center_y) = ndimage.measurements.center_of_mass(
+ self.results_aligned["score"]
+ )
+ self.results_aligned["center_mass"] = self.grid.get_motor_pos_from_col_row(
+ center_x, center_y
+ )
+ else:
+ centred_positions = self.data_collection.get_centred_positions()
+ if len(centred_positions) == 2:
+ center_x = ndimage.measurements.center_of_mass(
+ self.results_aligned["score"]
+ )[0]
+ self.results_aligned[
+ "center_mass"
+ ] = HWR.beamline.diffractometer.get_point_from_line(
+ centred_positions[0],
+ centred_positions[1],
+ center_x,
+ self.params_dict["images_num"],
+ )
+ else:
+ self.results_aligned["center_mass"] = centred_positions[0]
+
+ #self.logger.debug("self.results_aligned %s" % (str(self.results_aligned)) )
+
+ # Best positions are extracted
+ best_positions_list = []
+
+ index_arr = (-self.results_raw["score"]).argsort()[:10]
+ if len(index_arr) > 0:
+ for index in index_arr:
+ if self.results_raw["score"][index] > 0:
+ best_position = {}
+ best_position["index"] = index
+ best_position["index_serial"] = (
+ self.params_dict["first_image_num"] + index
+ )
+ best_position["score"] = self.results_raw["score"][index]
+ best_position["spots_num"] = self.results_raw["spots_num"][index]
+ best_position["spots_resolution"] = self.results_raw[
+ "spots_resolution"
+ ][index]
+ best_position["filename"] = os.path.basename(
+ self.params_dict["template"]
+ % (
+ self.params_dict["run_number"],
+ self.params_dict["first_image_num"] + index,
+ )
+ )
+
+ cpos = None
+ if self.grid:
+ col, row = self.grid.get_col_row_from_image_serial(
+ index + self.params_dict["first_image_num"]
+ )
+ col += 0.5
+ row = self.params_dict["steps_y"] - row - 0.5
+ cpos = self.grid.get_motor_pos_from_col_row(col, row)
+ else:
+ col = index
+ row = 0
+ cpos = None
+ # TODO make this nicer
+ # num_images = self.data_collection.acquisitions[0].acquisition_parameters.num_images - 1
+ # (point_one, point_two) = self.data_collection.get_centred_positions()
+ # cpos = HWR.beamline.diffractometer.get_point_from_line(point_one, point_two, index, num_images)
+ best_position["col"] = col
+ best_position["row"] = row
+ best_position["cpos"] = cpos
+ best_positions_list.append(best_position)
+
+ self.results_aligned["best_positions"] = best_positions_list
+
+ self.logger.debug("after best_poitions: self.results_aligned %s" % (str(self.results_aligned)) )
+
+ def store_processing_results(self, status):
+ """
+ Reimplement generation of json file that will fit XALOC preferences
+
+ Note: the location of this file is sent ISpyB in the ISPyBClient module, in the store_workflow methods
+ """
+ AbstractOnlineProcessing.store_processing_results(self, status)
+ # At this point, a html and json file have already been generated. We just want to overwrite the json file
+ try:
+ self.generate_online_processing_json_xaloc()
+ except Exception as e:
+ self.logger.error(
+ "Can not generate json file, error is %s" % ( str(e) )
+ )
+ self.logger.debug( "traceback %s" % traceback.format_exc() )
+
+
+ def generate_online_processing_json_xaloc(self):
+ import json
+ from mxcubecore.HardwareObjects.SimpleHTML import create_json_images
+
+ mesh_scan_results = self.results_aligned
+ params_dict = self.params_dict
+ json_dict = {"items": []}
+
+ osc_range_per_line = params_dict["osc_range"] * (params_dict["images_per_line"] - 1)
+
+ if params_dict["lines_num"] > 1:
+ json_dict["items"].append({"type": "title", "value": "Mesh scan results"})
+ else:
+ json_dict["items"].append({"type": "title", "value": "Line scan results"})
+
+ # Add the table with the grid size
+ table_grid_size = {
+ "type":"table",
+ "title": "Grid size",
+ "orientation": "horizontal"
+ }
+ image = {"title": "plot", "filename": params_dict["cartography_path"]}
+ json_dict["items"].append(create_json_images([image]))
+
+ if params_dict["lines_num"] > 1:
+ table_grid_size["columns"] = [
+ "Grid size",
+ "Scan area",
+ "Horizontal distance between frames",
+ "Vertical distance between frames",
+ "Oscillation middle",
+ "Oscillation range per frame",
+ "Oscillation range per line",
+ ]
+ elif params_dict["lines_num"] == 1:
+ table_grid_size["columns"] = [
+ "Grid size",
+ "Scan area",
+ "Horizontal distance between frames",
+ "Oscillation middle",
+ "Oscillation range per frame",
+ "Oscillation range per line",
+ ]
+
+ data_array = [
+ "%d x %d microns"
+ % (
+ (params_dict["steps_x"] * params_dict["xOffset"] * 1000),
+ (params_dict["steps_y"] * params_dict["yOffset"] * 1000),
+ ),
+ "%d x %d microns"
+ % ((params_dict["dx_mm"] * 1000), (params_dict["dy_mm"] * 1000)),
+ "%d microns" % (params_dict["xOffset"] * 1000),
+ ]
+ if params_dict["lines_num"] > 1:
+ data_array.append(
+ "%d microns" % (params_dict["yOffset"] * 1000),
+ )
+ data_array.extend( [
+ "%.1f" % params_dict["osc_midle"],
+ "%.2f" % params_dict["osc_range"],
+ "%.2f (from %.2f to %2.f)"
+ % (
+ osc_range_per_line,
+ (params_dict["osc_midle"] - osc_range_per_line / 2),
+ (params_dict["osc_midle"] + osc_range_per_line / 2),
+ ),
+ ])
+ table_grid_size["data"] = [data_array]
+ json_dict["items"].append(table_grid_size)
+
+ # Add the table with the best positions
+ table_best_positions= {}
+ positions = mesh_scan_results.get("best_positions", [])
+ if len(positions) > 0:
+ data_array = [[]]
+ # TODO convert following two lines to json equivalent
+ #html_file.write(create_text("All positions", heading=1))
+ #html_file.write("")
+
+ table_best_positions = {
+ "type":"table",
+ "title": "Grid size",
+ "columns": [
+ "Index",
+ "Score",
+ "Number of spots",
+ "Resolution",
+ "File name",
+ "Column",
+ "Row"
+ ],
+ "orientation": "horizontal"
+ }
+ pos = 0
+ for position in positions:
+ data_array[pos] = \
+ [
+ "%d" % position["index"],
+ "%.2f" % position["score"],
+ "%d" % position["spots_num"],
+ "%.1f" % position["spots_resolution"],
+ position["filename"],
+ "%d" % (position["col"] + 1),
+ "%d" % (position["row"] + 1),
+ ]
+ pos+=1
+ table_best_positions["data"] = data_array
+ json_dict["items"].append(table_best_positions)
+
+ self.logger.debug("writing json file %s" % (params_dict["json_file_path"]) )
+ open(params_dict["json_file_path"], "w").write(json.dumps(json_dict, indent=4))
+
+ # def update_map(self):
+ # """Updates plot map
+ #
+ # :return: None
+ # """
+ # gevent.sleep(1)
+ # while self.started:
+ # self.emit("paralleProcessingResults",
+ # (self.results_aligned,
+ # self.params_dict,
+ # False))
+ # if self.params_dict["lines_num"] > 1:
+ # self.grid.set_score(self.results_raw['score'])
+ # gevent.sleep(0.5)
+ #
+ # def set_processing_status(self, status):
+ # """Sets processing status and finalize the processing
+ # Method called from EDNA via xmlrpc
+ #
+ # :param status: processing status (Success, Failed)
+ # :type status: str
+ # """
+ # self.batch_processed(self.chan_dozor_pass.get_value())
+ # GenericParallelProcessing.set_processing_status(self, status)
+ #
+ # def store_processing_results(self, status):
+ # GenericParallelProcessing.store_processing_results(self, status)
+ # self.display_task.kill()
+ #
+ # processing_xml_filename = os.path.join(self.params_dict\
+ # ["directory"], "dozor_result.xml")
+ # dozor_result = XSDataResultControlDozor()
+ # for index in range(self.params_dict["images_num"]):
+ # dozor_image = XSDataControlImageDozor()
+ # dozor_image.setNumber(XSDataInteger(index))
+ # dozor_image.setScore(XSDataDouble(self.results_raw["score"][index]))
+ # dozor_image.setSpots_num_of(XSDataInteger(self.results_raw["spots_num"][index]))
+ # dozor_image.setSpots_resolution(XSDataDouble(self.results_raw["spots_resolution"][index]))
+ # dozor_result.addImageDozor(dozor_image)
+ # dozor_result.exportToFile(processing_xml_filename)
+ # logging.getLogger("HWR").info("Parallel processing: Results saved in %s" % processing_xml_filename)
+
+ def is_running(self):
+ """Returns True if processing is running"""
+ return self.started
+
diff --git a/mxcubecore/HardwareObjects/ALBA/XalocPilatus.py b/mxcubecore/HardwareObjects/ALBA/XalocPilatus.py
new file mode 100755
index 0000000000..939e72a729
--- /dev/null
+++ b/mxcubecore/HardwareObjects/ALBA/XalocPilatus.py
@@ -0,0 +1,557 @@
+#
+# Project: 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 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with MXCuBE. If not, see .
+
+"""
+[Name]
+XalocPilatus
+
+[Description]
+Specific HwObj to interface the Pilatus2 6M detector
+
+[Emitted signals]
+- None
+"""
+
+from __future__ import print_function
+
+import logging
+import time
+
+from datetime import datetime
+from mxcubecore.HardwareObjects.abstract.AbstractDetector import (
+ AbstractDetector,
+)
+#from mxcubecore.BaseHardwareObjects import HardwareObject
+from taurus import Device
+from mxcubecore import HardwareRepository as HWR
+
+__credits__ = ["ALBA"]
+__version__ = "3."
+__category__ = "General"
+
+
+ENERGY_CHANGE_LIMIT=1.2
+
+
+class XalocPilatus(AbstractDetector):
+ """Detector class. Contains all information about detector
+ - states are 'OK', and 'BAD'
+ - status is busy, exposing, ready, etc.
+ - physical property is RH for pilatus, P for rayonix
+ """
+
+ def __init__(self, name):
+ AbstractDetector.__init__(self, name)
+ #HardwareObject.__init__(self, name)
+ self.logger = logging.getLogger("HWR.XalocPilatus")
+ self.cmd_prepare_acq = None
+ self.cmd_start_acq = None
+ self.cmd_abort_acq = None
+ self.cmd_stop_acq = None
+ self.cmd_reset_common_header = None
+ self.cmd_reset_frame_headers = None
+ self.cmd_set_image_header = None
+
+ #self.cmd_set_threshold_gain = None
+
+ self.chan_saving_mode = None
+ self.chan_saving_prefix = None
+ self.chan_saving_directory = None
+ self.chan_saving_format = None
+ self.chan_saving_next_number = None
+ self.chan_saving_header_delimiter = None
+ self.chan_saving_statistics = None
+
+ self.chan_acq_nb_frames = None
+ self.chan_acq_trigger_mode = None
+ self.chan_acq_expo_time = None
+ self.chan_acq_status = None
+ self.chan_acq_status_fault_error = None
+ self.chan_lima_ready = None
+
+ self.latency_time = None
+ self.chan_latency_time = None
+
+ self.chan_energy = None
+ self.chan_threshold = None
+ #self.chan_gain = None
+ self.chan_cam_state = None
+ self.cmd_cam_server = None
+
+ self.chan_beam_x = None
+ self.chan_beam_y = None
+ self.chan_eugap = None
+
+ self.default_distance = None
+ self.default_distance_limits = None
+ self.exp_time_limits = None
+ self.device = None
+ self.start_acq_cam_server = None
+
+ self.headers = {}
+
+ def init(self):
+ AbstractDetector.init(self)
+ self.logger.debug("Initializing {0}".format(self.__class__.__name__))
+
+ self.latency_time = self.get_property("latency_time")
+
+ self.cmd_prepare_acq = self.get_command_object('prepare_acq')
+ self.cmd_start_acq = self.get_command_object('start_acq')
+ self.cmd_abort_acq = self.get_command_object('abort_acq')
+ self.cmd_stop_acq = self.get_command_object('stop_acq')
+ self.cmd_reset = self.get_command_object('reset')
+ self.cmd_reset_common_header = self.get_command_object('reset_common_header')
+ self.cmd_reset_frame_headers = self.get_command_object('reset_frame_headers')
+ self.cmd_set_image_header = self.get_command_object('set_image_header')
+
+ #self.cmd_set_threshold_gain = self.get_command_object('set_threshold_gain')
+
+ self.chan_saving_mode = self.get_channel_object('saving_mode')
+ self.chan_saving_prefix = self.get_channel_object('saving_prefix')
+ self.chan_saving_directory = self.get_channel_object('saving_directory')
+ self.chan_saving_format = self.get_channel_object('saving_format')
+ self.chan_saving_next_number = self.get_channel_object('saving_next_number')
+ self.chan_saving_header_delimiter = self.get_channel_object(
+ 'saving_header_delimiter')
+ self.chan_saving_statistics = self.get_channel_object('saving_statistics')
+
+ self.chan_acq_nb_frames = self.get_channel_object('acq_nb_frames')
+ self.chan_acq_trigger_mode = self.get_channel_object('acq_trigger_mode')
+ self.chan_acq_expo_time = self.get_channel_object('acq_expo_time')
+ self.chan_acq_status = self.get_channel_object('acq_status')
+ self.chan_acq_status_fault_error = self.get_channel_object(
+ 'acq_status_fault_error')
+ self.chan_lima_ready = self.get_channel_object('lima_ready_for_next_acq')
+ self.chan_latency_time = self.get_channel_object('latency_time')
+
+ if self.latency_time == None:
+ self.latency_time = self.chan_latency_time.get_value()
+ else:
+ self.chan_latency_time.set_value( self.latency_time )
+
+ self.chan_energy = self.get_channel_object('energy')
+ self.chan_threshold = self.get_channel_object('threshold')
+ #self.chan_gain = self.get_channel_object('gain')
+ self.chan_cam_state = self.get_channel_object('cam_state')
+ self.cmd_cam_server = self.get_command_object('cmd_cam_server')
+
+ # TODO: set timeout via xml but for command?
+ name = self.get_property("taurusname")
+ self.device = Device(name)
+ self.device.set_timeout_millis(30000)
+
+ exp_time_limits = self.get_property("exposure_limits")
+ self.exp_time_limits = map(float, exp_time_limits.strip().split(","))
+ self.start_acq_cam_server = self.get_property("start_acq_cam_server")
+
+ self.chan_beam_x = self.get_channel_object("beamx")
+ self.chan_beam_y = self.get_channel_object("beamy")
+ self.chan_eugap = self.get_channel_object("eugap")
+
+ def start_acquisition(self):
+ if self.start_acq_cam_server is True:
+ #TODO format the number of digits correctly
+ first_file_name = self.chan_saving_prefix.get_value() + \
+ "%04d" % self.chan_saving_next_number.get_value() + \
+ "." + self.chan_saving_format.get_value().lower()
+ self.cmd_cam_server("ExtTrigger %s" % first_file_name)
+ else:
+ self.cmd_start_acq()
+
+ def stop_acquisition(self):
+ self.logger.debug("Stopping detector and resetting it")
+ if self.start_acq_cam_server is True:
+ self.cmd_cam_server("k")
+ self.wait_not_running()
+ self.chan_energy.set_value( self._get_beamline_energy() )
+ else:
+ #self.cmd_stop_acq()
+ self.cmd_abort_acq()
+ self.wait_not_running()
+ time.sleep(0.1)
+ self.cmd_reset()
+
+ def get_radius(self, distance=None):
+ """Get distance from the beam position to the nearest detector edge.
+ Args:
+ distance (float): Distance [mm]
+ Returns:
+ (float): Detector radius [mm]
+ """
+ try:
+ distance = distance or self._distance_motor_hwobj.get_value()
+ except AttributeError:
+ raise RuntimeError("Cannot calculate radius, distance unknown")
+
+ beam_x, beam_y = self.get_beam_position(distance)
+ pixel_x, pixel_y = self.get_pixel_size()
+ rrx = min(self.get_width() - beam_x, beam_x) * pixel_x
+ rry = min(self.get_height() - beam_y, beam_y) * pixel_y
+ radius = min(rrx, rry)
+
+ return radius
+
+
+ def get_distance(self):
+ """Returns detector distance in mm"""
+ if self._distance_motor_hwobj is not None:
+ return float( self._distance_motor_hwobj.get_value() )
+ else:
+ return self.default_distance
+
+ def move_distance(self, value):
+ if self._distance_motor_hwobj is not None:
+ self._distance_motor_hwobj.move(value)
+
+ def wait_move_distance_done(self):
+ self._distance_motor_hwobj.wait_ready(1000)
+ #self._distance_motor_hwobj.wait_end_of_move(timeout=1000) # wait_end_of_nove does not work!
+
+ def wait_ready(self):
+ self.wait_move_distance_done()
+ self.wait_standby()
+
+ def wait_lima_ready(self):
+ self.wait_move_distance_done()
+ self.wait_lima_ready_for_next_acq()
+
+ def get_distance_limits(self):
+ """Returns detector distance limits"""
+ if self._distance_motor_hwobj is not None:
+ return self._distance_motor_hwobj.get_limits()
+ else:
+ return self.default_distance_limits
+
+ def get_energy(self):
+ return self.chan_energy.get_value()
+
+ def get_threshold(self):
+ return self.chan_threshold.get_value()
+
+ #def get_gain(self):
+ #return self.chan_gain.get_value()
+
+ def get_cam_state(self):
+ return self.chan_cam_state.force_get_value()
+
+ def has_shutterless(self):
+ """Return True if has shutterless mode"""
+ return True
+
+ def get_beam_position(self, distance=None, wavelength=None):
+ """
+ Returns beam center coordinates
+ TODO: update values according to distance, see XALOC modules for the calculation and calibration
+ """
+ beam_x = 0
+ beam_y = 0
+ try:
+ beam_x = self.chan_beam_x.get_value()
+ beam_y = self.chan_beam_y.get_value()
+ except BaseException as e:
+ self.logger.debug("Cannot load beam channels\n%s" % str(e))
+ return beam_x, beam_y
+
+ def get_manufacturer(self):
+ return self.get_property("manufacturer")
+
+ def get_model(self):
+ return self.get_property("model")
+
+ def get_detector_type(self):
+ return self.get_property("type")
+
+ def get_default_exposure_time(self):
+ return self.get_property("default_exposure_time")
+
+ def get_minimum_exposure_time(self):
+ return self.get_property("minimum_exposure_time")
+
+ def get_exposure_time_limits(self):
+ """Returns exposure time limits as list with two floats"""
+ return self.exp_time_limits
+
+ def get_file_suffix(self):
+ return self.get_property("file_suffix")
+
+ def get_pixel_size(self):
+ return self.get_property("px"), self.get_property("py")
+
+ def _get_beamline_energy(self):
+ try:
+ beamline_energy = self.chan_eugap.get_value()
+ except Exception as e:
+ self.logger.debug("Error getting energy\n%s" % str(e))
+ beamline_energy = 12.6
+ self.logger.debug("Setting default energy = %s" % beamline_energy)
+ return beamline_energy
+
+ #def set_gain(self, value):
+ #self.chan_gain.set_value(value)
+
+ def arm(self):
+ """
+ Configure detector electronics.
+ :return:
+ """
+ self.logger.debug("Arming the detector")
+ try:
+ beamline_energy = self._get_beamline_energy()
+ energy = self.get_energy()
+ threshold = self.get_threshold()
+ #threshold_gain = self.get_gain()
+ cam_state = self.get_cam_state()
+
+ self.logger.debug("beamline energy (Eb): %s" % beamline_energy)
+ self.logger.debug("energy_threshold (Eth): %s" % energy)
+ #self.logger.debug("current threshold gain: %s" % threshold_gain)
+
+ if abs(energy - beamline_energy) > ENERGY_CHANGE_LIMIT:
+ self.chan_energy.set_value(beamline_energy)
+ logging.getLogger("user_level_log").info(
+ "Setting detector energy_threshold: %s" % beamline_energy)
+ # wait until detector is configured
+ # Wait for 3 secs to let time for iState to change
+ time.sleep(3)
+ if not self.wait_standby():
+ raise RuntimeError("Detector could not be configured!")
+ else:
+ logging.getLogger("user_level_log").info("Energy difference (Eth - Eb) is below the difference limit %s keV" % ENERGY_CHANGE_LIMIT)
+ logging.getLogger("user_level_log").info("Detector energy threshold will remain unchanged (%s keV)" % energy)
+
+# if round(beamline_energy, 6) < 7.538:
+# beamline_energy = 7.538
+#
+# kev_diff = abs(energy - beamline_energy)
+#
+# if kev_diff > 1.2 or beamline_energy > 10.0:
+# if cam_state == 'STANDBY':
+# if beamline_energy > 10.0:
+# if threshold_gain != 'LOW':
+# self.set_threshold_gain('LOW')
+# self.logger.debug(
+# "Setting threshold_gain to LOW for energy %s > 10keV" % str(round(kev_diff, 4)))
+# else:
+# self.chan_energy_threshold = beamline_energy
+# self.logger.debug(
+# "Setting detector energy_threshold: %s" % beamline_energy)
+# # wait until detector is configured
+# # Wait for 3 secs to let time for change
+# time.sleep(3)
+# if not self.wait_standby():
+# raise RuntimeError("Detector could not be configured!")
+# else:
+# msg = "Cannot set energy threshold, detector not in STANDBY"
+# raise RuntimeError(msg)
+ except Exception as e:
+ self.logger.error("Exception when setting threshold to pilatus: %s" % str(e))
+
+ def get_latency_time(self):
+ if self.latency_time != None:
+ return self.latency_time
+ return self.chan_latency_time.get_value()
+
+ def wait_standby(self, timestep = 0.1, timeout=300):
+ standby = self.get_cam_state()
+ if standby != 'STANDBY':
+ self.logger.debug("Waiting detector to be in STANDBY")
+ t0 = time.time()
+ while standby != 'STANDBY' and standby != 'ERROR':
+ if time.time() - t0 > timeout:
+ self.logger.debug("timeout waiting for Pilatus to be on STANDBY")
+ return False
+ time.sleep(timestep)
+ standby = self.get_cam_state()
+ #self.logger.debug("Detector is %s" % self.get_cam_state())
+ if standby == 'STANDBY': return True
+ return False
+
+ def wait_lima_ready_for_next_acq(self, timeout=300):
+ lima_ready = self.chan_lima_ready.get_value()
+ if lima_ready != True:
+ logging.getLogger("").info("Waiting detector lima to be ready for next image")
+ t0 = time.time()
+ while lima_ready != True and HWR.beamline.collect._collecting and self.get_cam_state() != 'ERROR':
+ if time.time() - t0 > timeout:
+ self.logger.debug("timeout waiting for Pilatus lima to be ready for next image")
+ return False
+ time.sleep(0.1)
+ lima_ready = self.chan_lima_ready.get_value()
+ #self.logger.debug("Detector lima ready for next image is %s" % lima_ready )
+ return True
+
+ def wait_running(self, timestep=0.1, timeout=300):
+ self.logger.debug("Waiting detector to be in RUNNING")
+ t0 = time.time()
+ while self.get_cam_state() != 'RUNNING':
+ if time.time() - t0 > timeout:
+ self.logger.debug("timeout waiting for Pilatus to be inn RUNNING state")
+ return False
+ time.sleep( timestep )
+ #self.logger.debug("Detector is %s" % self.get_cam_state())
+ return True
+
+ def wait_not_running(self, timestep=0.1, timeout=300):
+ self.logger.debug("Waiting detector to stop RUNNING")
+ t0 = time.time()
+ self.logger.debug("wait_not_running: Detector is %s" % self.get_cam_state())
+ while self.get_cam_state() == 'RUNNING':
+ if time.time() - t0 > timeout:
+ self.logger.debug("timeout waiting for Pilatus to stop RUNNING")
+ return False
+ time.sleep( timestep )
+ #self.logger.debug("Detector is %s" % self.get_cam_state())
+ return True
+
+ def prepare_acquisition(self, dcpars):
+
+ self.arm()
+ latency_time = self.get_latency_time()
+
+ osc_seq = dcpars['oscillation_sequence'][0]
+ file_pars = dcpars['fileinfo']
+
+ basedir = file_pars['directory']
+ prefix = "%s_%s_" % (file_pars['prefix'], file_pars['run_number'])
+
+ #TODO: deprecated
+ # first_img_no = osc_seq['start_image_number']
+ nb_frames = osc_seq['number_of_images']
+ exp_time = osc_seq['exposure_time']
+
+ fileformat = "CBF"
+ trig_mode = dcpars['detector_binning_mode'][0]
+
+ self.logger.debug(" Preparing detector for data collection")
+
+ self.logger.debug(" /saving directory: %s" % basedir)
+ self.logger.debug(" /prefix : %s" % prefix)
+ self.logger.debug(" /saving_format : %s" % fileformat)
+ self.logger.debug(" /trigger_mode : %s" % trig_mode)
+ self.logger.debug(" /acq_nb_frames : %s" % nb_frames)
+ self.logger.debug(" /acq_expo_time : %s" %
+ str(exp_time - latency_time))
+ self.logger.debug(" /latency_time : %s" % latency_time)
+
+ self.chan_saving_mode.set_value('AUTO_FRAME')
+ self.chan_saving_directory.set_value(basedir)
+ self.chan_saving_prefix.set_value(prefix)
+ self.chan_saving_format.set_value(fileformat)
+
+ self.chan_acq_trigger_mode.set_value(trig_mode)
+
+ return True
+
+ def set_exposure_time(exp_period):
+ self.chan_acq_expo_time.set_value(exp_period - latency_time)
+
+ def prepare_collection(self, nb_frames, first_img_no, exp_time):
+ self.logger.debug("Preparing collection")
+ self.logger.debug("# images = %s, first image number: %s, exp_time %.4f" %
+ (nb_frames, first_img_no, exp_time)
+ )
+ self.chan_acq_nb_frames.set_value(nb_frames)
+ self.chan_saving_next_number.set_value(first_img_no)
+ self.chan_acq_expo_time.set_value(exp_time)
+ self.cmd_prepare_acq()
+ return True
+
+ def start_collection(self):
+ self.start_acquisition()
+
+ def stop_collection(self):
+ self.stop_acquisition()
+
+ def set_image_headers(self, image_headers, angle_info):
+ """
+ Prepares headers both in lima as well as the camserver
+ TODO: use start_acq_cam_server to set the appropriate header
+ """
+
+ nb_images = image_headers['nb_images']
+ angle_inc = image_headers['Angle_increment']
+ start_angle = image_headers['Start_angle']
+
+ ang_start, ang_inc, spacing = angle_info
+
+ #Set the camserver headings in case lima is not used
+ self.cmd_cam_server("MXsettings Start_angle %s" % image_headers["Start_angle"].split()[0] )
+ self.cmd_cam_server("MXsettings Angle_increment %s" % image_headers["Angle_increment"].split()[0] )
+ self.cmd_cam_server("MXsettings Kappa %s" % image_headers["Kappa"].split()[0] )
+ self.cmd_cam_server("MXsettings Phi %s" % image_headers["Phi"].split()[0] )
+ self.cmd_cam_server("MXsettings Flux %s" % image_headers["Flux"].split()[0] )
+ self.cmd_cam_server("MXsettings Wavelength %s" % image_headers["Wavelength"].split()[0] )
+ self.cmd_cam_server("MXsettings Filter_transmission %s" % image_headers["Filter_transmission"].split()[0] )
+ self.cmd_cam_server("MXsettings Detector_distance %s" % image_headers["Detector_distance"].split()[0] )
+ self.cmd_cam_server("MXsettings Polarization %s" % image_headers["Polarization"].split()[0] )
+ self.cmd_cam_server("MXsettings Detector_2theta %s" % image_headers["Detector_2theta"].split()[0] )
+ self.cmd_cam_server("MXsettings Beam_xy %s" % image_headers["Beam_xy"].split("pixels")[0] )
+ self.cmd_cam_server("MXsettings Detector_Voffset %s" % image_headers["Detector_Voffset"].split()[0] )
+ self.cmd_cam_server("MXsettings Oscillation_axis %s" % image_headers["Oscillation_axis"] )
+
+ startangles_list = list()
+ for i in range(nb_images):
+ startangles_list.append("%0.4f deg." % (ang_start + spacing * i))
+
+ headers = list()
+ for i, sa in enumerate(startangles_list):
+ header = "# Detector: PILATUS3X 6M, S/N 60-0140, XALOC, Alba\n" \
+ "# %s\n" \
+ "# Pixel_size 172e-6 m x 172e-6 m\n" \
+ "# Silicon sensor, thickness 0.001 m\n" % datetime.now().strftime(
+ "%Y-%m-%dT%T.%f")[:-3]
+
+ # Acquisition values (headers dictionary) but overwrites start angle
+ image_headers["Start_angle"] = sa
+ for key, value in image_headers.iteritems():
+ if key == 'nb_images':
+ continue
+ header += "# %s %s\n" % (key, value)
+ headers.append("%d : array_data/header_convention|%s;" % (i, "PILATUS_1.2"))
+ headers.append("%d : array_data/header_contents|%s;" % (i, header))
+
+ #self.logger.debug(" saving header delimiters %s" % ["|", ";", ":"])
+ self.chan_saving_header_delimiter.set_value(["|", ";", ":"])
+ #self.logger.debug(" reset_common_header" )
+ self.cmd_reset_common_header()
+ #self.logger.debug(" reset_frame_headers" )
+ self.cmd_reset_frame_headers()
+ #self.logger.debug(" set_image_header %s" % headers)
+ self.cmd_set_image_header(headers)
+
+ def get_saving_statistics(self):
+ values = self.chan_saving_statistics.get_value()
+ if all(values):
+ saving_speed, compression_speed, compression_ratio, incoming_speed = values
+ comp_ratio = compression_speed / incoming_speed
+ saving_ratio = saving_speed / (incoming_speed / compression_ratio)
+
+ self.logger.debug(" compression ratio = %.4f" % comp_ratio)
+ self.logger.debug(" saving ratio = %.4f" % saving_ratio)
+ self.logger.debug("If comp_ratio < 1, increase the NbProcessingThread")
+ self.logger.debug(
+ "If saving_ratio < 1, increase the SavingMaxConcurrentWritingTask")
+ else:
+ self.logger.debug("No data available to evaluate the Pilatus/Lima performance")
+ self.logger.debug("raw values --> %s" % values)
+
+def test_hwo(hwo):
+ for chan in hwo.getChannels():
+ print("%s = %s" % (chan.userName(), chan.get_value()))
diff --git a/mxcubecore/HardwareObjects/ALBA/XalocQtGraphicsManager.py b/mxcubecore/HardwareObjects/ALBA/XalocQtGraphicsManager.py
new file mode 100644
index 0000000000..685e61a179
--- /dev/null
+++ b/mxcubecore/HardwareObjects/ALBA/XalocQtGraphicsManager.py
@@ -0,0 +1,225 @@
+# Project: 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 .
+
+"""
+Qt4/5/PySide Graphics manager for MxCuBE.
+Hardware object handles QGraphicsView and QGraphicsScene with all
+objects and actions necessary for MXCuBE:
+- Creating/removing/editing/drawing of centring points, collection vectors
+ and 2D grids
+- Display of beam shape, rotatio axis, scales
+- Distance, angle and area measurement tools
+- Video handling, scalling and magnification tools
+
+example xml:
+
+"""
+
+import logging
+
+from mxcubecore.HardwareObjects.QtGraphicsManager import QtGraphicsManager
+from mxcubecore.HardwareObjects import QtGraphicsLib as GraphicsLib
+from mxcubecore import HardwareRepository as HWR
+
+class XalocQtGraphicsManager(QtGraphicsManager):
+ def __init__(self, name):
+ QtGraphicsManager.__init__(self, name)
+ self.userlogger = logging.getLogger("user_level_log")
+
+ def mouse_clicked(self, pos_x, pos_y, left_click=True):
+ """Method when mouse clicked on GraphicsScene
+
+ :param pos_x: screen coordinate X
+ :type pos_x: int
+ :param pos_y: screen coordinate Y
+ :type pos_y: int
+ :param left_click: left button clicked
+ :type left_click: bool
+ :emits: - shapeSelected
+ - pointSelected
+ - infoMsg
+ """
+ if self.in_centring_state:
+ if self.current_centring_method == HWR.beamline.diffractometer.CENTRING_METHOD_MANUAL:
+ self.graphics_centring_lines_item.add_position(pos_x, pos_y)
+ self.diffractometer_hwobj.image_clicked(pos_x, pos_y)
+ else:
+ self.userlogger.error("Click ignored, not in manual centring. ")
+ self.userlogger.error("\tChange centring procedure in the \"Centring\" pulldown close to the ISPyB button if necessary")
+ elif self.wait_grid_drawing_click:
+ self.in_grid_drawing_state = True
+ self.graphics_grid_draw_item.set_draw_mode(True)
+ self.graphics_grid_draw_item.set_start_position(pos_x, pos_y)
+ self.graphics_grid_draw_item.show()
+ elif self.wait_measure_distance_click:
+ self.start_graphics_item(self.graphics_measure_distance_item)
+ self.in_measure_distance_state = True
+ self.wait_measure_distance_click = False
+ elif self.wait_measure_angle_click:
+ self.start_graphics_item(self.graphics_measure_angle_item)
+ self.in_measure_angle_state = True
+ self.wait_measure_angle_click = False
+ elif self.wait_measure_area_click:
+ self.start_graphics_item(self.graphics_measure_area_item)
+ self.in_measure_area_state = True
+ self.wait_measure_area_click = False
+ elif self.wait_beam_define_click:
+ self.start_graphics_item(self.graphics_beam_define_item)
+ self.in_beam_define_state = True
+ self.wait_beam_define_click = False
+ elif self.in_measure_distance_state:
+ self.graphics_measure_distance_item.store_coord(pos_x, pos_y)
+ elif self.in_measure_angle_state:
+ self.graphics_measure_angle_item.store_coord(pos_x, pos_y)
+ elif self.in_measure_area_state:
+ self.graphics_measure_area_item.store_coord()
+ elif self.in_move_beam_mark_state:
+ self.stop_move_beam_mark()
+ elif self.in_beam_define_state:
+ self.stop_beam_define()
+ # self.graphics_beam_define_item.store_coord(pos_x, pos_y)
+ elif self.in_one_click_centering:
+ self.diffractometer_hwobj.start_move_to_beam(pos_x, pos_y)
+ else:
+ self.emit("pointSelected", None)
+ self.emit("infoMsg", "")
+ if left_click:
+ self.graphics_select_tool_item.set_start_position(pos_x, pos_y)
+ self.graphics_select_tool_item.set_end_position(pos_x, pos_y)
+ self.graphics_select_tool_item.show()
+ self.in_select_items_state = True
+ for graphics_item in self.graphics_view.scene().items():
+ graphics_item.setSelected(False)
+ if type(graphics_item) in [
+ GraphicsLib.GraphicsItemPoint,
+ GraphicsLib.GraphicsItemLine,
+ GraphicsLib.GraphicsItemGrid,
+ ]:
+ self.emit("shapeSelected", graphics_item, False)
+ # if isinstance(graphics_item, GraphicsLib.GraphicsItemPoint):
+ # self.emit("pointSelected", graphics_item)
+
+ def mouse_double_clicked(self, pos_x, pos_y):
+ """If in one of the measuring states, then stops measuring.
+ Otherwise moves to screen coordinate
+
+ :param pos_x: screen coordinate X
+ :type pos_x: int
+ :param pos_y: screen coordinate Y
+ :type pos_y: int
+ """
+ if self.in_centring_state:
+ self.userlogger.error("Double click ignored, centring in progress. ")
+ self.userlogger.error("\tWait for the centring procedure to finish")
+ elif self.in_measure_distance_state:
+ self.stop_measure_distance()
+ elif self.in_measure_angle_state:
+ self.stop_measure_angle()
+ elif self.in_measure_area_state:
+ self.stop_measure_area()
+ elif self.in_beam_define_state:
+ self.stop_beam_define()
+ else:
+ self.diffractometer_hwobj.move_to_beam(pos_x, pos_y)
+ self.emit("imageDoubleClicked", pos_x, pos_y)
+
+ def diffractometer_pixels_per_mm_changed(self, pixels_per_mm):
+ """Updates graphics scale when zoom changed
+
+ :param pixels_per_mm: two floats for scaling
+ :type pixels_per_mm: list with two floats
+ """
+
+ if type(pixels_per_mm) in (list, tuple):
+ if pixels_per_mm != self.pixels_per_mm:
+ self.pixels_per_mm = pixels_per_mm
+ for item in self.graphics_view.graphics_scene.items():
+ if isinstance(item, GraphicsLib.GraphicsItem):
+ item.set_pixels_per_mm(self.pixels_per_mm)
+ self.diffractometer_state_changed()
+ self.graphics_view.graphics_scene.update()
+
+
+ # CHECK: accept_centring, reject_centring, cancel_centring, start_one_click_centring, stop_one_click_centring
+ # did not have an emit, but this perhaps is done through emits from the diffractometer??
+ def accept_centring(self):
+ """Accepts centring
+ """
+ self.set_cursor_busy(False)
+ self.diffractometer_hwobj.accept_centring()
+ self.diffractometer_state_changed()
+ self.show_all_items()
+ self.emit("centringInProgress", False)
+
+ def reject_centring(self):
+ """Rejects centring
+ """
+ self.set_cursor_busy(False)
+ self.diffractometer_hwobj.reject_centring()
+ self.show_all_items()
+ self.emit("centringInProgress", False)
+
+ def cancel_centring(self, reject=False):
+ """Cancels centring
+
+ :param reject: reject position
+ :type reject: bool
+ """
+ self.set_cursor_busy(False)
+ self.diffractometer_hwobj.cancel_centring_method(reject=reject)
+ self.show_all_items()
+ self.emit("centringInProgress", False)
+
+ def start_one_click_centring(self):
+ self.set_cursor_busy(True)
+ self.emit("infoMsg", "Click on the screen to create centring points")
+ self.in_one_click_centering = True
+ self.graphics_centring_lines_item.setVisible(True)
+ self.emit("centringInProgress", True)
+
+ def stop_one_click_centring(self):
+ self.set_cursor_busy(False)
+ self.emit("infoMsg", "")
+ self.in_one_click_centering = False
+ self.graphics_centring_lines_item.setVisible(False)
+ self.emit("centringInProgress", False)
+
+ def create_grid(self, spacing=(0, 0)):
+ """Creates grid
+
+ :param spacing: spacing between beams
+ :type spacing: list with two floats (can be negative)
+ """
+ if not self.wait_grid_drawing_click:
+ self.set_cursor_busy(True)
+ self.graphics_grid_draw_item = GraphicsLib.GraphicsItemGrid(
+ self, self.beam_info_dict, spacing, self.pixels_per_mm
+ )
+ self.graphics_grid_draw_item.set_draw_mode(True)
+ self.graphics_grid_draw_item.index = self.grid_count
+ self.grid_count += 1
+ self.graphics_view.graphics_scene.addItem(self.graphics_grid_draw_item)
+ self.wait_grid_drawing_click = True
+ self.emit('gridDrawn')
+
diff --git a/mxcubecore/HardwareObjects/ALBA/XalocQtTangoLimaVideo.py b/mxcubecore/HardwareObjects/ALBA/XalocQtTangoLimaVideo.py
new file mode 100755
index 0000000000..6debe83e98
--- /dev/null
+++ b/mxcubecore/HardwareObjects/ALBA/XalocQtTangoLimaVideo.py
@@ -0,0 +1,162 @@
+#
+# Project: 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 .
+
+"""
+[Name]
+XalocQtTangoLimaVideo
+
+[Description]
+HwObj used to grab images via Tango LImA library or Lima Tango server, based on QtTangoLimaVideo.
+
+[Configuration]
+See example below. To select between "Library" or "Tango" simply
+use and configure the field
(for Library)
+or (for Tango)
+in the XML file.
+
+
+Example Hardware Object XML file :
+==================================
+
+ basler
+ yuv422p
+ 84.89.227.6
+ 0.5
+ 0.01
+ (False, False)
+ 30
+
+"""
+
+__credits__ = ["ALBA"]
+__version__ = "3."
+__category__ = "General"
+
+import sys
+import numpy as np
+
+import logging
+
+from mxcubecore.HardwareObjects.QtTangoLimaVideo import QtTangoLimaVideo
+from mxcubecore.HardwareObjects.abstract.AbstractVideoDevice import (
+ AbstractVideoDevice,
+)
+
+try:
+ import cv2
+except:
+ pass
+
+module_names = ["qt", "PyQt5", "PyQt4"]
+
+if any(mod in sys.modules for mod in module_names):
+ USEQT = True
+ try:
+ from PyQt5.QtGui import QImage, QPixmap
+ except ImportError:
+ from PyQt4.QtGui import QImage, QPixmap
+else:
+ USEQT = False
+ from PIL import Image
+
+class XalocQtTangoLimaVideo(QtTangoLimaVideo):
+ """
+ Descript. :
+ """
+
+ def __init__(self, name):
+ """
+ Descript. :
+ """
+ self.logger = logging.getLogger("HWR")
+ self.logger.debug("XalocQtTangoLimaVideo.__init__()")
+ QtTangoLimaVideo.__init__(self, name)
+ self.align_mode = None
+
+ def init(self):
+ QtTangoLimaVideo.init(self)
+ # TODO: Sometimes, the error Can't set live mode if an acquisition is running appears. The bzoom DS needs to be restarted in that case
+ # check refresh_camera method of the camera / sample_view
+ self.align_mode = False
+
+ def set_cam_encoding(self, cam_encoding):
+ self.logger.debug("XalocQtTangoLimaVideo set_cam_encoding")
+ if cam_encoding == "yuv422p":
+ self.device.video_mode = "YUV422"
+ if cam_encoding == "rgb24":
+ self.device.video_mode = "RGB24"
+ elif cam_encoding == "y8":
+ self.device.video_mode = "Y8"
+ elif cam_encoding.lower() == "bayer_rg16":
+ self.device.video_mode = "BAYER_RG16"
+
+ self.logger.debug(
+ "%s: using %s encoding" %
+ (self.name, cam_encoding)
+ )
+
+ AbstractVideoDevice.set_cam_encoding(self, cam_encoding)
+
+ self.logger.debug(
+ "%s: using %s encoding" %
+ (self.name, cam_encoding)
+ )
+
+
+ def get_new_image(self):
+ """
+ Descript. :
+ """
+ raw_buffer, width, height = self.get_image()
+
+ # self.cam_type is bzoom
+
+ if raw_buffer is not None and raw_buffer.any():
+ if self.cam_type == "basler":
+ raw_buffer = self.decoder(raw_buffer)
+ if self.align_mode:
+ raw_buffer = cv2.applyColorMap(raw_buffer, cv2.COLORMAP_JET)
+
+ qimage = QImage(raw_buffer, width, height,
+ width * 3,
+ QImage.Format_RGB888)
+ else:
+ raw_buffer = self.bgr_2_rgb(raw_buffer)
+ if self.align_mode:
+ raw_buffer = cv2.applyColorMap(cv2.bitwise_not(raw_buffer), cv2.COLORMAP_JET)
+
+ qimage = QImage(raw_buffer, width, height,
+ QImage.Format_RGB888)
+
+ if self.cam_mirror is not None:
+ qimage = qimage.mirrored(self.cam_mirror[0], self.cam_mirror[1])
+
+ if self.scale != 1:
+ dims = self.get_image_dimensions() # should be already scaled
+ qimage = qimage.scaled(QSize(dims[0], dims[1]))
+
+ qpixmap = QPixmap(qimage)
+ self.emit("imageReceived", qpixmap)
+ return qimage.copy()
+
+ def bgr_2_rgb(self, raw_buffer):
+ image = np.fromstring(raw_buffer, dtype=np.uint8)
+ raw_dims = self.get_raw_image_size()
+ image.resize(raw_dims[1], raw_dims[0], 3)
+ return cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
diff --git a/mxcubecore/HardwareObjects/ALBA/XalocResolution.py b/mxcubecore/HardwareObjects/ALBA/XalocResolution.py
new file mode 100644
index 0000000000..51da0c81f1
--- /dev/null
+++ b/mxcubecore/HardwareObjects/ALBA/XalocResolution.py
@@ -0,0 +1,103 @@
+from mxcubecore import HardwareRepository as HWR
+from mxcubecore.HardwareObjects.Resolution import Resolution
+import logging
+import math
+
+from mxcubecore.HardwareObjects.abstract.AbstractMotor import (
+ MotorStates,
+)
+
+class XalocResolution(Resolution):
+
+ unit = "A"
+
+ #def __init__(self, *args, **kwargs):
+ def __init__(self, name):
+ #Resolution.__init__(self, name="XalocResolution")
+ super(XalocResolution, self).__init__(name)
+ self.logger = logging.getLogger("HWR.XalocResolution")
+
+ #self._chnBeamX = None
+ #self._chnBeamY = None
+ self.resedge = None
+
+ def init(self):
+ self.logger.debug("Initializing {0}".format(self.__class__.__name__))
+ #super(XalocResolution, self).init()
+
+ self._hwr_detector = (
+ self.get_object_by_role("detector") or HWR.beamline.detector
+ )
+ self.resedge = self.get_channel_object("resedge_value")
+
+ self.connect(self.resedge, "valueChanged", self.set_value)
+ if HWR.beamline.energy is not None:
+ HWR.beamline.energy.connect("energyChanged", self.update_energy)
+ self.connect(self._hwr_detector.distance, "stateChanged", self.update_state)
+ self.connect(self._hwr_detector.distance, "valueChanged", self.update_distance)
+
+
+ def is_ready(self):
+ return self._hwr_detector.distance.get_state() == MotorStates.READY
+
+
+ #def get_beam_centre(self, dtox=None):
+ #return self._chnBeamX.get_value(), self._chnBeamY.get_value()
+
+ #def get_value_at_corner(self):
+ #if self.rescorner is not None:
+ #return self.rescorner.get_value()
+
+ def get_limits(self):
+ """Return resolution low and high limits.
+ Returns:
+ (tuple): two floats tuple (low limit, high limit).
+ """
+ _low, _high = self._hwr_detector.distance.get_limits()
+
+ self._limits = (
+ self.distance_to_resolution(_low),
+ self.distance_to_resolution(_high),
+ )
+ return self._limits
+
+ def update_energy(self, energy_pos, wavelength_pos):
+ """Update the resolution when energy changed.
+ Args:
+ value(float): Energy [keV]
+ """
+ logging.getLogger("HWR").debug(
+ "Energy changed, updating resolution and limits"
+ )
+
+ self._nominal_value = self.resedge.force_get_value()
+ self.value = self._nominal_value
+ self.get_limits()
+ self.emit("limitsChanged", (self._limits, ))
+ self.emit("valueChanged", (self._nominal_value,))
+
+ def update_state(self, state):
+ pass
+
+ def update_distance(self, value=None):
+ """Update the resolution when distance changed.
+ Args:
+ value (float): Detector distance [mm].
+ """
+ self._nominal_value = self.resedge.force_get_value()
+ self.emit("valueChanged", (self._nominal_value,))
+
+ def get_value(self):
+ """Read the value.
+ Returns:
+ (float): value.
+ """
+ self._nominal_value = self.resedge.force_get_value()
+
+ return self._nominal_value
+
+ def set_value(self, value, timeout = None):
+ distance = self.resolution_to_distance(value)
+ msg = "Move resolution to {} ({} mm)".format(value, distance)
+ logging.getLogger().info(msg)
+ self._hwr_detector.distance.set_value(distance)
diff --git a/mxcubecore/HardwareObjects/ALBA/XalocSardanaMotor.py b/mxcubecore/HardwareObjects/ALBA/XalocSardanaMotor.py
new file mode 100755
index 0000000000..7973950d16
--- /dev/null
+++ b/mxcubecore/HardwareObjects/ALBA/XalocSardanaMotor.py
@@ -0,0 +1,133 @@
+# encoding: utf-8
+#
+# Project: 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 General Lesser Public License
+# along with MXCuBE. If not, see .
+
+from mxcubecore.HardwareObjects.abstract.AbstractMotor import (
+ AbstractMotor,
+ MotorStates,
+)
+from mxcubecore.HardwareObjects.SardanaMotor import SardanaMotor
+from gevent import Timeout
+import time
+
+__copyright__ = """ Copyright © 2010-2020 by the MXCuBE collaboration """
+__license__ = "LGPLv3+"
+__credits__ = ["ALBA"]
+__version__ = "3."
+__category__ = "General"
+
+class XalocSardanaMotor(SardanaMotor):
+
+ def __init__(self, name):
+ AbstractMotor.__init__(self, name)
+ self.stop_command = None
+ self.position_channel = None
+ self.state_channel = None
+ self.taurusname = None
+ self.motor_position = 0.0
+ self.last_position_emitted = 0.0
+ self.threshold_default = 0.0018
+ self.move_threshold_default = 0.0
+ self.polling_default = "events"
+ self.limit_upper = None
+ self.limit_lower = None
+ self.static_limits = (-1e4, 1e4)
+ self.limits = (None, None)
+ #RB: critical bug, NOTINITIALIZED is not a valid MotorStates
+ #self.motor_state = MotorStates.NOTINITIALIZED
+ self.motor_state = MotorStates.INITIALIZING
+
+ def init(self):
+ SardanaMotor.init(self)
+
+ def motor_state_changed(self, state=None):
+ """
+ Descript. : called by the state channels update event
+ checks if the motor is at it's limit,
+ and sets the new device state
+ """
+ motor_state = self.motor_state
+
+ if state is None:
+ state = self.state_channel.get_value()
+
+ state = str(state).strip("DevState.")
+ motor_state = SardanaMotor.state_map[state]
+
+ if motor_state != MotorStates.DISABLED:
+ if self.motor_position >= self.limit_upper:
+ motor_state = MotorStates.HIGHLIMIT
+ elif self.motor_position <= self.limit_lower:
+ motor_state = MotorStates.LOWLIMIT
+
+ #self.set_ready(motor_state > MotorStates.DISABLED)
+
+ if motor_state != self.motor_state:
+ self.motor_state = motor_state
+ self.emit("stateChanged", (motor_state,))
+
+ def get_limits(self):
+ """
+ Descript. : returns motor limits. If no limits channel defined then
+ static_limits is returned
+ """
+ try:
+ # RB: added the following three lines, since the limits were never properly initialized
+ info = self.position_channel.get_info()
+ self.limit_lower = info.minval
+ self.limit_upper = info.maxval
+
+ return (self.limit_lower, self.limit_upper)
+ except Exception:
+ return (None, None)
+
+ def is_ready(self):
+ return self.get_state() == MotorStates.READY
+
+ def wait_ready(self, timeout=None):
+ """Wait timeout seconds till SardanaMotor is ready.
+
+ if timeout is None: wait forever.
+
+ Args:
+ timeout (s):
+
+ Returns:
+ """
+ with Timeout(timeout, RuntimeError("Timeout waiting for SardanaMotor status ready")):
+ while not self.is_ready():
+ time.sleep(0.05)
+
+ def motor_position_changed(self, position=None):
+ """
+ Descript. : called by the position channels update event
+ if the position change exceeds threshold,
+ valueChanged is fired
+ """
+ if position is None:
+ position = self.position_channel.get_value()
+ self.last_position_emitted = position
+ if abs(self.last_position_emitted - position) >= self.threshold:
+ self.motor_position = position
+ self.last_position_emitted = position
+ self.emit("valueChanged", (position,))
+ self.motor_state_changed()
+
+
+
diff --git a/mxcubecore/HardwareObjects/ALBA/XalocSession.py b/mxcubecore/HardwareObjects/ALBA/XalocSession.py
new file mode 100644
index 0000000000..25225ba74c
--- /dev/null
+++ b/mxcubecore/HardwareObjects/ALBA/XalocSession.py
@@ -0,0 +1,175 @@
+#
+# Project: 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 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with MXCuBE. If not, see .
+
+"""
+[Name]
+XalocSession
+
+[Description]
+Specific HwObj to control user configuration.
+
+[Emitted signals]
+- None
+"""
+
+#from __future__ import print_function
+
+import os
+import time
+import logging
+from Session import Session
+import queue_model_objects
+
+__credits__ = ["ALBA"]
+__version__ = "3."
+__category__ = "General"
+
+# RB: refactored version uses PROCESSED_DATA, the previous version uses PROCESS_DATA for the processing dir
+# might cause problems
+#default_processed_data_folder = "PROCESS_DATA"
+
+class XalocSession(Session):
+
+ def __init__(self, *args):
+ Session.__init__(self, *args)
+ self.logger = logging.getLogger("HWR.XalocSession")
+ self.senv = None
+
+ def init(self):
+ Session.init(self)
+ self.logger.debug("Initializing {0}".format(self.__class__.__name__))
+ self.senv = self.get_command_object("senv")
+
+ def get_base_data_directory(self):
+ """
+ Returns the base data directory for Xaloc
+ In Xaloc the base directory already includes the user
+ home directory. So
+ information into account, such as if the current user
+ is inhouse.
+
+ :returns: The base data path.
+ :rtype: str
+ """
+ if self.session_start_date:
+ start_time = self.session_start_date.split(' ')[0].replace('-', '')
+ else:
+ start_time = time.strftime("%Y%m%d")
+
+ if self.base_directory is not None:
+ directory = os.path.join(self.base_directory, start_time)
+ else:
+ directory = '/tmp'
+ return directory
+
+ def get_archive_directory(self, directory=None):
+ if directory is None:
+ _dir = self.get_base_data_directory()
+ else:
+ _dir = directory
+
+ parts = _dir.split(os.path.sep)
+ try:
+ user_dir = parts[5]
+ session_date = parts[6]
+ except:
+ user_dir = parts[0]
+ session_date = parts[1]
+ # remove RAW_DATA from da
+
+
+ try:
+ more = parts[8:]
+ except Exception as e:
+ logging.getLogger('HWR').debug("%s" % str(e))
+ more = []
+
+ archive_dir = os.path.join(
+ self.base_archive_directory,
+ user_dir,
+ session_date,
+ *more)
+ self.logger.debug("XalocSession. returning archive directory: %s" % archive_dir)
+ return archive_dir
+
+ def set_ldap_homedir(self, homedir):
+ self.base_directory = homedir
+ self.base_process_directory = homedir
+
+ queue_model_objects.PathTemplate.set_data_base_path(self.base_directory)
+
+ def get_default_prefix(self, sample_data_node=None, generic_name=False):
+ """
+ Returns the default prefix, using sample data such as the
+ acronym as parts in the prefix.
+
+ :param sample_data_node: The data node to get additional
+ information from, (which will be
+ added to the prefix).
+ :type sample_data_node: Sample
+
+
+ :returns: The default prefix.
+ :rtype: str
+ """
+ proposal = self.get_proposal()
+ prefix = proposal
+
+ if sample_data_node:
+ if sample_data_node.has_lims_data():
+ protein_acronym = sample_data_node.crystals[0].protein_acronym
+ name = sample_data_node.name
+ if protein_acronym:
+ if name:
+ if self.proposal_number.split('-')[-1] in ['2019013247','2018002222']:
+ prefix = "%s" % (name)
+ else:
+ prefix = "%s-%s" % (protein_acronym, name)
+ else:
+ prefix = protein_acronym
+ else:
+ prefix = name or ""
+ else:
+ try:
+ prefix = "B{0}X{1}".format(*sample_data_node.get_name().split(":"))
+ except Exception:
+ prefix = str(sample_data_node.get_name())
+
+ elif generic_name:
+ prefix = "-"
+ #
+ return prefix
+
+ def set_sardana_collect_env(self, MXCollectDir = None, MXCollectPrefix = None, MXRunNumber = None):
+ if MXCollectDir != None:
+ self.senv('MXCollectDir', MXCollectDir, wait=True)
+ if MXCollectPrefix != None:
+ self.senv('MXCollectPrefix', MXCollectPrefix, wait=True)
+ if MXRunNumber != None:
+ self.senv('MXRunNumber', MXRunNumber, wait=True)
+
+
+
+def test_hwo(hwo):
+ print('Base data directory: %s' % hwo.get_base_data_directory())
+ print('Base Image directory: %s' % hwo.get_base_image_directory())
+ print('Image directory: %s' % hwo.get_image_directory())
+ print('Base Process directory: %s' % hwo.get_base_process_directory())
+ print('Process directory: %s' % hwo.get_process_directory())
+ print('Archive directory: %s' % hwo.get_archive_directory())
diff --git a/mxcubecore/HardwareObjects/ALBA/XalocSupervisor.py b/mxcubecore/HardwareObjects/ALBA/XalocSupervisor.py
new file mode 100755
index 0000000000..c0696e3ab3
--- /dev/null
+++ b/mxcubecore/HardwareObjects/ALBA/XalocSupervisor.py
@@ -0,0 +1,233 @@
+#
+# Project: 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 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with MXCuBE. If not, see .
+
+"""
+[Name]
+XalocSupervisor
+
+[Description]
+Specific HwObj to interface the Beamline Supervisor TangoDS
+
+[Emitted signals]
+- stateChanged
+- phaseChanged
+"""
+
+from __future__ import print_function
+
+import logging
+import time
+
+from mxcubecore.BaseHardwareObjects import Device
+from taurus.core.tango.enums import DevState
+from mxcubecore.HardwareObjects import GenericDiffractometer
+
+from mxcubecore import HardwareRepository as HWR
+
+__credits__ = ["ALBA"]
+__version__ = "3."
+__category__ = "General"
+__author__ = "Roeland Boer, Jordi Andreu"
+
+class XalocSupervisor(Device):
+
+ def __init__(self, *args):
+ Device.__init__(self, *args)
+ self.logger = logging.getLogger("HWR.XalocSupervisor")
+ self.user_level_log = logging.getLogger("user_level_log")
+
+ self.cmd_go_collect = None
+ self.cmd_go_sample_view = None
+ self.cmd_go_transfer = None
+ self.cmd_go_beam_view = None
+ self.chan_state = None
+ self.chan_phase = None
+ self.chan_detector_cover = None
+
+ self.current_state = None
+ self.current_phase = None
+ self.detector_cover_opened = None
+
+ self.phase_list = []
+
+ def init(self):
+ self.logger.debug("Initializing {0}".format(self.__class__.__name__))
+ self.cmd_go_collect = self.get_command_object("go_collect")
+ self.cmd_go_sample_view = self.get_command_object("go_sample_view")
+ self.cmd_go_transfer = self.get_command_object("go_transfer")
+ self.cmd_go_beam_view = self.get_command_object("go_beam_view")
+ self.chan_state = self.get_channel_object("state")
+ self.chan_phase = self.get_channel_object("phase")
+ self.chan_detector_cover = self.get_channel_object("detector_cover_open")
+ #self.chan_fast_shutter_collect_position = self.get_channel_object("FastShutCollectPosition")
+
+ try:
+ self.phase_list = eval(self.get_property("phase_list"))
+ except Exception:
+ self.phase_list = [
+ GenericDiffractometer.PHASE_TRANSFER,
+ GenericDiffractometer.PHASE_CENTRING,
+ GenericDiffractometer.PHASE_COLLECTION,
+ GenericDiffractometer.PHASE_BEAM,
+ ]
+
+ self.chan_state.connect_signal("update", self.state_changed)
+ self.chan_phase.connect_signal("update", self.phase_changed)
+ self.chan_detector_cover.connect_signal("update", self.detector_cover_changed)
+
+ self.logger.debug("Supervisor state: {0}".format(self.current_state))
+ self.logger.debug("Supervisor phase: {0}".format(self.current_phase))
+
+ #def isReady(self):
+ #return True
+
+ #def getUserName(self):
+ #return self.username
+
+ def state_changed(self, value):
+ self.current_state = value
+ self.emit('stateChanged', self.current_state)
+
+ def phase_changed(self, value):
+ # TODO: Define supervisor states with enum
+ if value == 'Sample':
+ value = 'Centring'
+ self.current_phase = value
+ self.emit('phaseChanged', self.current_phase)
+
+ def get_current_phase(self):
+ try:
+ _value = self.chan_phase.get_value()
+ #self.logger.debug('get_current_phase: (value={0}, type={1})'.format(_value, type(_value)))
+ except Exception as e:
+ raise RuntimeError('Cannot get supervisor current phase:\n%s' % str(e))
+ return _value
+ # return self.chan_phase.get_value()
+
+ def go_collect(self):
+ return self.cmd_go_collect()
+
+ def go_transfer(self):
+ return self.cmd_go_transfer()
+
+ def go_sample_view(self):
+ return self.cmd_go_sample_view()
+
+ def go_beam_view(self):
+ return self.cmd_go_beam_view()
+
+
+ def get_phase(self):
+ return self.current_phase
+
+ def get_phase_list(self):
+ """
+ Returns list of available phases
+
+ :returns: list with str
+ """
+ return self.phase_list
+
+ def get_state(self):
+ try:
+ _value = self.chan_state.get_value()
+ #self.logger.debug('get_state: (value={0}, type={1})'.format(_value, type(_value)))
+ except Exception as e:
+ raise RuntimeError('Cannot get supervisor state:\n%s' % str(e))
+ return _value
+ #return self.chan_state.get_value()
+
+ def detector_cover_changed(self, value):
+ self.detector_cover_opened = value
+
+ def open_detector_cover(self):
+ self.chan_detector_cover.set_value(True)
+
+ def close_detector_cover(self):
+ self.chan_detector_cover.set_value(False)
+
+ def is_detector_cover_opened(self):
+ return self.chan_detector_cover.get_value()
+
+ def is_fast_shutter_in_collect_position(self):
+ return self.chan_fast_shutter_collect_position.get_value()
+
+ def wait_ready(self, timeout = 30):
+ stime = time.time()
+ while True:
+ if self.current_state == DevState.ON:
+ self.logger.debug("Supervisor is in ON state. Returning")
+ break
+ time.sleep(0.2)
+ if timeout is not None:
+ if time.time() - stime > timeout:
+ raise Exception("Supervisor timed out waiting for ON state")
+
+ def set_phase(self, phase, timeout=None):
+ #TODO: implement timeout. Current API to fulfill the API.
+ """
+ General function to set phase by using supervisor commands.
+ """
+
+ self.logger.debug("Current supervisor phase is %s" % self.current_phase)
+ if phase.upper() == self.current_phase.upper():
+ self.logger.warning("Suprevisor already in phase %s" % phase)
+ return
+
+ if phase.upper() != "TRANSFER" and HWR.beamline.ln2shower.is_pumping():
+ msg = "Cannot change to non transfer phase when the lnshower is pumping, turn off the shower first"
+ self.user_level_log.error(msg)
+ raise Exception(msg)
+
+ if self.current_state != DevState.ON:
+ msg = "Cannot change to phase %s, supervisor is not ready, state is %s" % ( phase, self.current_state )
+ self.user_level_log.error(msg)
+ raise Exception(msg)
+
+ if phase.upper() == "TRANSFER":
+ self.go_transfer()
+ elif phase.upper() == "COLLECT":
+ self.go_collect()
+ elif phase.upper() == "BEAMVIEW":
+ self.go_beam_view()
+ elif phase.upper() == "CENTRING":
+ self.go_sample_view()
+ else:
+ self.logger.warning(
+ "Supervisor set_phase asked for un-handled phase: %s" % phase
+ )
+ return
+
+ self.logger.debug(
+ "Telling supervisor to go to phase %s, with timeout %s" % ( phase, timeout )
+ )
+
+ if timeout:
+ time.sleep(1)
+ self.wait_ready( timeout = timeout )
+ time.sleep(1)
+ self.logger.debug(
+ "Supervisor phase is %s" % ( self.get_phase() )
+ )
+
+def test_hwo(hwo):
+ print("Supervisor control \"%s\"\n" % hwo.getUserName())
+ print("Is Detector Cover open?:", hwo.is_detector_cover_opened())
+ print("Current Phase is:", hwo.get_current_phase())
+ print("Current State is:", hwo.get_state())
diff --git a/mxcubecore/HardwareObjects/ALBA/XalocTransmission.py b/mxcubecore/HardwareObjects/ALBA/XalocTransmission.py
new file mode 100644
index 0000000000..1b91b13b18
--- /dev/null
+++ b/mxcubecore/HardwareObjects/ALBA/XalocTransmission.py
@@ -0,0 +1,153 @@
+#
+# Project: 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 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with MXCuBE. If not, see .
+
+"""
+[Name]
+XalocTransmission
+
+[Description]
+Specific HwObj to setup the beamline transmission
+
+[Emitted signals]
+- valueChanged
+- stateChanged
+"""
+
+#from __future__ import print_function
+
+import logging
+
+from mxcubecore.BaseHardwareObjects import Device, HardwareObjectState
+from mxcubecore import HardwareRepository as HWR
+
+__credits__ = ["ALBA"]
+__version__ = "3"
+__category__ = "General"
+
+
+class XalocTransmission(Device):
+
+ #Taurus 4.1.1 DevState
+ #ALARM = 11
+ #CLOSE = 2
+ #DISABLE = 12
+ #EXTRACT = 5
+ #FAULT = 8
+ #INIT = 9
+ #INSERT = 4
+ #MOVING = 6
+ #OFF = 1
+ #ON = 0
+ #OPEN = 3
+ #RUNNING = 10
+ #STANDBY = 7
+ #UNKNOWN = 13
+
+ # BaseHardwareObjects.HardwareObjectState(enum.Enum):
+ #UNKNOWN = 0
+ #WARNING = 1
+ #BUSY = 2
+ #READY = 3
+ #FAULT = 4
+ #OFF = 5
+
+ Tango2HWO_State = [
+ HardwareObjectState.READY, # 0 DevState.ON
+ HardwareObjectState.OFF, # 1 DevState.OFF
+ HardwareObjectState.READY, # 2 DevState.CLOSE
+ HardwareObjectState.READY, # 3 DevState.OPEN
+ HardwareObjectState.BUSY, # 4 DevState.INSERT
+ HardwareObjectState.BUSY, # 5 DevState.EXTRACT
+ HardwareObjectState.BUSY, # 6 DevState.MOVING
+ HardwareObjectState.READY, # 7 DevState.STANDBY
+ HardwareObjectState.FAULT, # 8 DevState.FAULT
+ HardwareObjectState.BUSY, # 9 DevState.INIT
+ HardwareObjectState.BUSY, # 10 DevState.RUNNING
+ HardwareObjectState.FAULT, # 11 DevState.ALARM
+ HardwareObjectState.OFF, # 12 DevState.DISABLE
+ HardwareObjectState.UNKNOWN # 13 DevState.UNKNOWN
+ ]
+
+ def __init__(self, *args):
+ Device.__init__(self, *args)
+ self.logger = logging.getLogger("HWR.XalocTransmission")
+ self.chan_transmission = None
+ self.chan_state = None
+
+ def init(self):
+ self.logger.debug("Initializing {0}".format(self.__class__.__name__))
+ self.chan_transmission = self.get_channel_object("transmission")
+ self.chan_state = self.get_channel_object("state")
+
+ self.chan_transmission.connect_signal("update", self.update_values)
+ self.chan_state.connect_signal("update", self.state_changed)
+
+ self.update_values()
+
+ if HWR.beamline.energy is not None:
+ HWR.beamline.energy.connect("energyChanged", self.energy_changed )
+
+ def is_ready(self):
+ return True
+
+ def transmission_changed(self, value):
+ self.emit('valueChanged', value)
+
+ def state_changed(self, value):
+ #TODO: translate DevState to Hardware Object states
+
+ self.emit('stateChanged', self.Tango2HWO_State[ value ] )
+
+ #def getAttState(self):
+ #self.state = self.chan_state.get_value()
+ #return self.state
+
+ #def getAttFactor(self):
+ #return self.get_value()
+
+ def get_value(self, force=False):
+ if force:
+ return self.chan_transmission.force_get_value()
+ else:
+ return self.chan_transmission.get_value()
+
+ def get_state(self):
+ return self.chan_state.get_value()
+
+ def set_value(self, value):
+ self.chan_transmission.set_value(value)
+
+ def set_transmission(self, value):
+ self.set_value(value)
+
+ def update_values(self, force=False):
+ value = self.get_value(force)
+ self.transmission_changed( value )
+ state = self.get_state()
+ self.state_changed( state )
+
+ def energy_changed(self, energy_position, wavelength_position):
+ #self.update_values()
+ if HWR.beamline.energy.is_ready():
+ self.logger.debug("Reading transmission after energy change")
+ self.update_values(force = True)
+
+def test_hwo(hwo):
+ print("Transmission is: ", hwo.get_value())
+ print("Transmission state is: ", hwo.getAttState())
diff --git a/mxcubecore/HardwareObjects/ALBA/XalocXSDataAutoprocv1_0.py b/mxcubecore/HardwareObjects/ALBA/XalocXSDataAutoprocv1_0.py
new file mode 100755
index 0000000000..cc8574c20c
--- /dev/null
+++ b/mxcubecore/HardwareObjects/ALBA/XalocXSDataAutoprocv1_0.py
@@ -0,0 +1,101 @@
+#
+# Project: 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 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with MXCuBE. If not, see .
+
+"""
+[Name] XalocXSDataAutoprocInput
+
+[Description]
+Extending XSDataAutoprocInput to allow doAnomNonanom and xia2 with small molecule
+
+[Signals]
+- None
+"""
+
+from XSDataAutoprocv1_0 import XSDataAutoprocInput
+
+class XalocXSDataAutoprocInput(XSDataAutoprocInput):
+
+ def __init__(
+ self,
+ configuration=None,
+ output_file=None,
+ unit_cell=None,
+ spacegroup=None,
+ nres=None,
+ low_resolution_limit=None,
+ detector_max_res=None,
+ data_collection_id=None,
+ cc_half_cutoff=None,
+ r_value_cutoff=None,
+ isig_cutoff=None,
+ completeness_cutoff=None,
+ res_override=None,
+ input_file=None,
+ setDoAnomAndNonanom=None,
+ ):
+ XSDataAutoprocInput.__init__(
+ self,
+ configuration=None,
+ output_file=None,
+ unit_cell=None,
+ spacegroup=None,
+ nres=None,
+ low_resolution_limit=None,
+ detector_max_res=None,
+ data_collection_id=None,
+ cc_half_cutoff=None,
+ r_value_cutoff=None,
+ isig_cutoff=None,
+ completeness_cutoff=None,
+ res_override=None,
+ input_file=None,
+ )
+
+ if setDoAnomAndNonanom is None:
+ self._doAnomAndNonanom = None
+ elif setDoAnomAndNonanom.__class__.__name__ == "XSDataBoolean":
+ self._doAnomAndNonanom = doAnomAndNonanom
+ else:
+ strMessage = "ERROR! XSDataInputControlAutoPROC constructor argument 'doAnomAndNonanom' is not XSDataBoolean but %s" % doAnomAndNonanom.__class__.__name__
+ raise BaseException(strMessage)
+
+ # Methods and properties for the 'doAnomAndNonanom' attribute, recovered from previous mxcube version
+ def getDoAnomAndNonanom(self): return self._doAnomAndNonanom
+ def setDoAnomAndNonanom(self, doAnomAndNonanom):
+ if doAnomAndNonanom is None:
+ self._doAnomAndNonanom = None
+ elif doAnomAndNonanom.__class__.__name__ == "XSDataBoolean":
+ self._doAnomAndNonanom = doAnomAndNonanom
+ else:
+ strMessage = "ERROR! XSDataInputControlAutoPROC.setDoAnomAndNonanom argument is not XSDataBoolean but %s" % doAnomAndNonanom.__class__.__name__
+ raise BaseException(strMessage)
+ def delDoAnomAndNonanom(self): self._doAnomAndNonanom = None
+
+ #def exportChildren(self, outfile, level, name_="XSDataAutoprocInput"):
+ #if self._doAnomAndNonanom is not None:
+ #self.doAnomAndNonanom.export(outfile, level, name_='doAnomAndNonanom')
+ #XSDataAutoprocInput.exportChildren(self, outfile, level, name_)
+
+
+ def exportChildren(self, outfile, level, name_="XSDataAutoprocInput"):
+ XSDataAutoprocInput.exportChildren(self, outfile, level, name_)
+ if self._doAnomAndNonanom is not None:
+ self._doAnomAndNonanom.export(outfile, level, name_='doAnomAndNonanom')
+
+ doAnomAndNonanom = property(getDoAnomAndNonanom, setDoAnomAndNonanom, delDoAnomAndNonanom, "Property for doAnomAndNonanom")
diff --git a/mxcubecore/HardwareObjects/ALBA/XalocXSDataControlAutoPROCv1_0.py b/mxcubecore/HardwareObjects/ALBA/XalocXSDataControlAutoPROCv1_0.py
new file mode 100644
index 0000000000..dd1b43342f
--- /dev/null
+++ b/mxcubecore/HardwareObjects/ALBA/XalocXSDataControlAutoPROCv1_0.py
@@ -0,0 +1,511 @@
+#!/usr/bin/env python
+
+#
+# Generated Mon Feb 5 08:54::10 2018 by EDGenerateDS.
+#
+
+import os, sys
+from xml.dom import minidom
+from xml.dom import Node
+
+
+strEdnaHome = os.environ.get("EDNA_HOME", None)
+
+dictLocation = { \
+ "XSDataCommon": "kernel/datamodel", \
+ "XSDataCommon": "kernel/datamodel", \
+ "XSDataCommon": "kernel/datamodel", \
+ "XSDataCommon": "kernel/datamodel", \
+ "XSDataCommon": "kernel/datamodel", \
+ "XSDataCommon": "kernel/datamodel", \
+}
+
+try:
+ from XSDataCommon import XSDataBoolean
+ from XSDataCommon import XSDataFile
+ from XSDataCommon import XSDataInput
+ from XSDataCommon import XSDataInteger
+ from XSDataCommon import XSDataResult
+ from XSDataCommon import XSDataString
+except ImportError as error:
+ if strEdnaHome is not None:
+ for strXsdName in dictLocation:
+ strXsdModule = strXsdName + ".py"
+ strRootdir = os.path.dirname(os.path.abspath(os.path.join(strEdnaHome, dictLocation[strXsdName])))
+ for strRoot, listDirs, listFiles in os.walk(strRootdir):
+ if strXsdModule in listFiles:
+ sys.path.append(strRoot)
+ else:
+ raise error
+from XSDataCommon import XSDataBoolean
+from XSDataCommon import XSDataFile
+from XSDataCommon import XSDataInput
+from XSDataCommon import XSDataInteger
+from XSDataCommon import XSDataResult
+from XSDataCommon import XSDataString
+
+
+
+
+#
+# Support/utility functions.
+#
+
+# Compabiltity between Python 2 and 3:
+if sys.version.startswith('3'):
+ unicode = str
+ from io import StringIO
+else:
+ from StringIO import StringIO
+
+
+def showIndent(outfile, level):
+ for idx in range(level):
+ outfile.write(unicode(' '))
+
+
+def warnEmptyAttribute(_strName, _strTypeName):
+ pass
+ #if not _strTypeName in ["float", "double", "string", "boolean", "integer"]:
+ # print("Warning! Non-optional attribute %s of type %s is None!" % (_strName, _strTypeName))
+
+class MixedContainer(object):
+ # Constants for category:
+ CategoryNone = 0
+ CategoryText = 1
+ CategorySimple = 2
+ CategoryComplex = 3
+ # Constants for content_type:
+ TypeNone = 0
+ TypeText = 1
+ TypeString = 2
+ TypeInteger = 3
+ TypeFloat = 4
+ TypeDecimal = 5
+ TypeDouble = 6
+ TypeBoolean = 7
+ def __init__(self, category, content_type, name, value):
+ self.category = category
+ self.content_type = content_type
+ self.name = name
+ self.value = value
+ def getCategory(self):
+ return self.category
+ def getContenttype(self, content_type):
+ return self.content_type
+ def getValue(self):
+ return self.value
+ def getName(self):
+ return self.name
+ def export(self, outfile, level, name):
+ if self.category == MixedContainer.CategoryText:
+ outfile.write(self.value)
+ elif self.category == MixedContainer.CategorySimple:
+ self.exportSimple(outfile, level, name)
+ else: # category == MixedContainer.CategoryComplex
+ self.value.export(outfile, level, name)
+ def exportSimple(self, outfile, level, name):
+ if self.content_type == MixedContainer.TypeString:
+ outfile.write(unicode('<%s>%s%s>' % (self.name, self.value, self.name)))
+ elif self.content_type == MixedContainer.TypeInteger or \
+ self.content_type == MixedContainer.TypeBoolean:
+ outfile.write(unicode('<%s>%d%s>' % (self.name, self.value, self.name)))
+ elif self.content_type == MixedContainer.TypeFloat or \
+ self.content_type == MixedContainer.TypeDecimal:
+ outfile.write(unicode('<%s>%f%s>' % (self.name, self.value, self.name)))
+ elif self.content_type == MixedContainer.TypeDouble:
+ outfile.write(unicode('<%s>%g%s>' % (self.name, self.value, self.name)))
+
+#
+# Data representation classes.
+#
+
+
+
+class XalocXSDataInputControlAutoPROC(XSDataInput):
+ def __init__(self, configuration=None, cell=None, symm=None, doAnomAndNonanom=None, processDirectory=None, toN=None, fromN=None, templateN=None, configDef=None, dirN=None, dataCollectionId=None):
+ XSDataInput.__init__(self, configuration)
+ if dataCollectionId is None:
+ self._dataCollectionId = None
+ elif dataCollectionId.__class__.__name__ == "XSDataInteger":
+ self._dataCollectionId = dataCollectionId
+ else:
+ strMessage = "ERROR! XSDataInputControlAutoPROC constructor argument 'dataCollectionId' is not XSDataInteger but %s" % self._dataCollectionId.__class__.__name__
+ raise BaseException(strMessage)
+ if dirN is None:
+ self._dirN = None
+ elif dirN.__class__.__name__ == "XSDataFile":
+ self._dirN = dirN
+ else:
+ strMessage = "ERROR! XSDataInputControlAutoPROC constructor argument 'dirN' is not XSDataFile but %s" % self._dirN.__class__.__name__
+ raise BaseException(strMessage)
+ if configDef is None:
+ self._configDef = None
+ elif configDef.__class__.__name__ == "XSDataFile":
+ self._configDef = configDef
+ else:
+ strMessage = "ERROR! XSDataInputControlAutoPROC constructor argument 'configDef' is not XSDataFile but %s" % self._configDef.__class__.__name__
+ raise BaseException(strMessage)
+ if templateN is None:
+ self._templateN = None
+ elif templateN.__class__.__name__ == "XSDataString":
+ self._templateN = templateN
+ else:
+ strMessage = "ERROR! XSDataInputControlAutoPROC constructor argument 'templateN' is not XSDataString but %s" % self._templateN.__class__.__name__
+ raise BaseException(strMessage)
+ if fromN is None:
+ self._fromN = None
+ elif fromN.__class__.__name__ == "XSDataInteger":
+ self._fromN = fromN
+ else:
+ strMessage = "ERROR! XSDataInputControlAutoPROC constructor argument 'fromN' is not XSDataInteger but %s" % self._fromN.__class__.__name__
+ raise BaseException(strMessage)
+ if toN is None:
+ self._toN = None
+ elif toN.__class__.__name__ == "XSDataInteger":
+ self._toN = toN
+ else:
+ strMessage = "ERROR! XSDataInputControlAutoPROC constructor argument 'toN' is not XSDataInteger but %s" % self._toN.__class__.__name__
+ raise BaseException(strMessage)
+ if processDirectory is None:
+ self._processDirectory = None
+ elif processDirectory.__class__.__name__ == "XSDataFile":
+ self._processDirectory = processDirectory
+ else:
+ strMessage = "ERROR! XSDataInputControlAutoPROC constructor argument 'processDirectory' is not XSDataFile but %s" % self._processDirectory.__class__.__name__
+ raise BaseException(strMessage)
+ if doAnomAndNonanom is None:
+ self._doAnomAndNonanom = None
+ elif doAnomAndNonanom.__class__.__name__ == "XSDataBoolean":
+ self._doAnomAndNonanom = doAnomAndNonanom
+ else:
+ strMessage = "ERROR! XSDataInputControlAutoPROC constructor argument 'doAnomAndNonanom' is not XSDataBoolean but %s" % self._doAnomAndNonanom.__class__.__name__
+ raise BaseException(strMessage)
+ if symm is None:
+ self._symm = None
+ elif symm.__class__.__name__ == "XSDataString":
+ self._symm = symm
+ else:
+ strMessage = "ERROR! XSDataInputControlAutoPROC constructor argument 'symm' is not XSDataString but %s" % self._symm.__class__.__name__
+ raise BaseException(strMessage)
+ if cell is None:
+ self._cell = None
+ elif cell.__class__.__name__ == "XSDataString":
+ self._cell = cell
+ else:
+ strMessage = "ERROR! XSDataInputControlAutoPROC constructor argument 'cell' is not XSDataString but %s" % self._cell.__class__.__name__
+ raise BaseException(strMessage)
+ # Methods and properties for the 'dataCollectionId' attribute
+ def getDataCollectionId(self): return self._dataCollectionId
+ def setDataCollectionId(self, dataCollectionId):
+ if dataCollectionId is None:
+ self._dataCollectionId = None
+ elif dataCollectionId.__class__.__name__ == "XSDataInteger":
+ self._dataCollectionId = dataCollectionId
+ else:
+ strMessage = "ERROR! XSDataInputControlAutoPROC.setDataCollectionId argument is not XSDataInteger but %s" % dataCollectionId.__class__.__name__
+ raise BaseException(strMessage)
+ def delDataCollectionId(self): self._dataCollectionId = None
+ dataCollectionId = property(getDataCollectionId, setDataCollectionId, delDataCollectionId, "Property for dataCollectionId")
+ # Methods and properties for the 'dirN' attribute
+ def getDirN(self): return self._dirN
+ def setDirN(self, dirN):
+ if dirN is None:
+ self._dirN = None
+ elif dirN.__class__.__name__ == "XSDataFile":
+ self._dirN = dirN
+ else:
+ strMessage = "ERROR! XSDataInputControlAutoPROC.setDirN argument is not XSDataFile but %s" % dirN.__class__.__name__
+ raise BaseException(strMessage)
+ def delDirN(self): self._dirN = None
+ dirN = property(getDirN, setDirN, delDirN, "Property for dirN")
+ # Methods and properties for the 'configDef' attribute
+ def getConfigDef(self): return self._configDef
+ def setConfigDef(self, configDef):
+ if configDef is None:
+ self._configDef = None
+ elif configDef.__class__.__name__ == "XSDataFile":
+ self._configDef = configDef
+ else:
+ strMessage = "ERROR! XSDataInputControlAutoPROC.setDirN argument is not XSDataFile but %s" % configDef.__class__.__name__
+ raise BaseException(strMessage)
+ def delConfigDef(self): self._configDef = None
+ configDef = property(getConfigDef, setConfigDef, delConfigDef, "Property for configDef")
+ # Methods and properties for the 'templateN' attribute
+ def getTemplateN(self): return self._templateN
+ def setTemplateN(self, templateN):
+ if templateN is None:
+ self._templateN = None
+ elif templateN.__class__.__name__ == "XSDataString":
+ self._templateN = templateN
+ else:
+ strMessage = "ERROR! XSDataInputControlAutoPROC.setTemplateN argument is not XSDataString but %s" % templateN.__class__.__name__
+ raise BaseException(strMessage)
+ def delTemplateN(self): self._templateN = None
+ templateN = property(getTemplateN, setTemplateN, delTemplateN, "Property for templateN")
+ # Methods and properties for the 'fromN' attribute
+ def getFromN(self): return self._fromN
+ def setFromN(self, fromN):
+ if fromN is None:
+ self._fromN = None
+ elif fromN.__class__.__name__ == "XSDataInteger":
+ self._fromN = fromN
+ else:
+ strMessage = "ERROR! XSDataInputControlAutoPROC.setFromN argument is not XSDataInteger but %s" % fromN.__class__.__name__
+ raise BaseException(strMessage)
+ def delFromN(self): self._fromN = None
+ fromN = property(getFromN, setFromN, delFromN, "Property for fromN")
+ # Methods and properties for the 'toN' attribute
+ def getToN(self): return self._toN
+ def setToN(self, toN):
+ if toN is None:
+ self._toN = None
+ elif toN.__class__.__name__ == "XSDataInteger":
+ self._toN = toN
+ else:
+ strMessage = "ERROR! XSDataInputControlAutoPROC.setToN argument is not XSDataInteger but %s" % toN.__class__.__name__
+ raise BaseException(strMessage)
+ def delToN(self): self._toN = None
+ toN = property(getToN, setToN, delToN, "Property for toN")
+ # Methods and properties for the 'processDirectory' attribute
+ def getProcessDirectory(self): return self._processDirectory
+ def setProcessDirectory(self, processDirectory):
+ if processDirectory is None:
+ self._processDirectory = None
+ elif processDirectory.__class__.__name__ == "XSDataFile":
+ self._processDirectory = processDirectory
+ else:
+ strMessage = "ERROR! XSDataInputControlAutoPROC.setProcessDirectory argument is not XSDataFile but %s" % processDirectory.__class__.__name__
+ raise BaseException(strMessage)
+ def delProcessDirectory(self): self._processDirectory = None
+ processDirectory = property(getProcessDirectory, setProcessDirectory, delProcessDirectory, "Property for processDirectory")
+ # Methods and properties for the 'doAnomAndNonanom' attribute
+ def getDoAnomAndNonanom(self): return self._doAnomAndNonanom
+ def setDoAnomAndNonanom(self, doAnomAndNonanom):
+ if doAnomAndNonanom is None:
+ self._doAnomAndNonanom = None
+ elif doAnomAndNonanom.__class__.__name__ == "XSDataBoolean":
+ self._doAnomAndNonanom = doAnomAndNonanom
+ else:
+ strMessage = "ERROR! XSDataInputControlAutoPROC.setDoAnomAndNonanom argument is not XSDataBoolean but %s" % doAnomAndNonanom.__class__.__name__
+ raise BaseException(strMessage)
+ def delDoAnomAndNonanom(self): self._doAnomAndNonanom = None
+ doAnomAndNonanom = property(getDoAnomAndNonanom, setDoAnomAndNonanom, delDoAnomAndNonanom, "Property for doAnomAndNonanom")
+ # Methods and properties for the 'symm' attribute
+ def getSpacegroup(self): return self._symm
+ def setSpacegroup(self, symm):
+ if symm is None:
+ self._symm = None
+ elif symm.__class__.__name__ == "XSDataString":
+ self._symm = symm
+ else:
+ strMessage = "ERROR! XSDataInputControlAutoPROC.setSymm argument is not XSDataString but %s" % symm.__class__.__name__
+ raise BaseException(strMessage)
+ def delSpacegroup(self): self._symm = None
+ symm = property(getSpacegroup, setSpacegroup, delSpacegroup, "Property for symm")
+ # Methods and properties for the 'cell' attribute
+ def getUnit_cell(self): return self._cell
+ def setUnit_cell(self, cell):
+ if cell is None:
+ self._cell = None
+ elif cell.__class__.__name__ == "XSDataString":
+ self._cell = cell
+ else:
+ strMessage = "ERROR! XSDataInputControlAutoPROC.setCell argument is not XSDataString but %s" % cell.__class__.__name__
+ raise BaseException(strMessage)
+ def delUnit_cell(self): self._cell = None
+ unit_cell = property(getUnit_cell, setUnit_cell, delUnit_cell, "Property for cell")
+ def export(self, outfile, level, name_='XSDataInputControlAutoPROC'):
+ showIndent(outfile, level)
+ outfile.write(unicode('<%s>\n' % name_))
+ self.exportChildren(outfile, level + 1, name_)
+ showIndent(outfile, level)
+ outfile.write(unicode('%s>\n' % name_))
+ def exportChildren(self, outfile, level, name_='XSDataInputControlAutoPROC'):
+ XSDataInput.exportChildren(self, outfile, level, name_)
+ if self._dataCollectionId is not None:
+ self.dataCollectionId.export(outfile, level, name_='dataCollectionId')
+ if self._dirN is not None:
+ self.dirN.export(outfile, level, name_='dirN')
+ if self._configDef is not None:
+ self.configDef.export(outfile, level, name_='configDef')
+ if self._templateN is not None:
+ self.templateN.export(outfile, level, name_='templateN')
+ if self._fromN is not None:
+ self.fromN.export(outfile, level, name_='fromN')
+ if self._toN is not None:
+ self.toN.export(outfile, level, name_='toN')
+ if self._processDirectory is not None:
+ self.processDirectory.export(outfile, level, name_='processDirectory')
+ if self._doAnomAndNonanom is not None:
+ self.doAnomAndNonanom.export(outfile, level, name_='doAnomAndNonanom')
+ if self._symm is not None:
+ self.symm.export(outfile, level, name_='symm')
+ if self._cell is not None:
+ self._cell.export(outfile, level, name_='cell')
+ def build(self, node_):
+ for child_ in node_.childNodes:
+ nodeName_ = child_.nodeName.split(':')[-1]
+ self.buildChildren(child_, nodeName_)
+ def buildChildren(self, child_, nodeName_):
+ if child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'dataCollectionId':
+ obj_ = XSDataInteger()
+ obj_.build(child_)
+ self.setDataCollectionId(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'dirN':
+ obj_ = XSDataFile()
+ obj_.build(child_)
+ self.setDirN(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'configDef':
+ obj_ = XSDataFile()
+ obj_.build(child_)
+ self.setConfigDef(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'templateN':
+ obj_ = XSDataString()
+ obj_.build(child_)
+ self.setTemplateN(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'fromN':
+ obj_ = XSDataInteger()
+ obj_.build(child_)
+ self.setFromN(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'toN':
+ obj_ = XSDataInteger()
+ obj_.build(child_)
+ self.setToN(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'processDirectory':
+ obj_ = XSDataFile()
+ obj_.build(child_)
+ self.setProcessDirectory(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'doAnomAndNonanom':
+ obj_ = XSDataBoolean()
+ obj_.build(child_)
+ self.setDoAnomAndNonanom(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'symm':
+ obj_ = XSDataString()
+ obj_.build(child_)
+ self.setSymm(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'cell':
+ obj_ = XSDataString()
+ obj_.build(child_)
+ self.setCell(obj_)
+ XSDataInput.buildChildren(self, child_, nodeName_)
+ #Method for marshalling an object
+ def marshal( self ):
+ oStreamString = StringIO()
+ oStreamString.write(unicode('\n'))
+ self.export( oStreamString, 0, name_="XSDataInputControlAutoPROC" )
+ oStringXML = oStreamString.getvalue()
+ oStreamString.close()
+ return oStringXML
+ #Only to export the entire XML tree to a file stream on disk
+ def exportToFile( self, _outfileName ):
+ outfile = open( _outfileName, "w" )
+ outfile.write(unicode('\n'))
+ self.export( outfile, 0, name_='XSDataInputControlAutoPROC' )
+ outfile.close()
+ #Deprecated method, replaced by exportToFile
+ def outputFile( self, _outfileName ):
+ print("WARNING: Method outputFile in class XSDataInputControlAutoPROC is deprecated, please use instead exportToFile!")
+ self.exportToFile(_outfileName)
+ #Method for making a copy in a new instance
+ def copy( self ):
+ return XSDataInputControlAutoPROC.parseString(self.marshal())
+ #Static method for parsing a string
+ def parseString( _inString ):
+ doc = minidom.parseString(_inString)
+ rootNode = doc.documentElement
+ rootObj = XSDataInputControlAutoPROC()
+ rootObj.build(rootNode)
+ # Check that all minOccurs are obeyed by marshalling the created object
+ oStreamString = StringIO()
+ rootObj.export( oStreamString, 0, name_="XSDataInputControlAutoPROC" )
+ oStreamString.close()
+ return rootObj
+ parseString = staticmethod( parseString )
+ #Static method for parsing a file
+ def parseFile( _inFilePath ):
+ doc = minidom.parse(_inFilePath)
+ rootNode = doc.documentElement
+ rootObj = XSDataInputControlAutoPROC()
+ rootObj.build(rootNode)
+ return rootObj
+ parseFile = staticmethod( parseFile )
+# end class XSDataInputControlAutoPROC
+
+
+class XSDataResultControlAutoPROC(XSDataResult):
+ def __init__(self, status=None):
+ XSDataResult.__init__(self, status)
+ def export(self, outfile, level, name_='XSDataResultControlAutoPROC'):
+ showIndent(outfile, level)
+ outfile.write(unicode('<%s>\n' % name_))
+ self.exportChildren(outfile, level + 1, name_)
+ showIndent(outfile, level)
+ outfile.write(unicode('%s>\n' % name_))
+ def exportChildren(self, outfile, level, name_='XSDataResultControlAutoPROC'):
+ XSDataResult.exportChildren(self, outfile, level, name_)
+ def build(self, node_):
+ for child_ in node_.childNodes:
+ nodeName_ = child_.nodeName.split(':')[-1]
+ self.buildChildren(child_, nodeName_)
+ def buildChildren(self, child_, nodeName_):
+ pass
+ XSDataResult.buildChildren(self, child_, nodeName_)
+ #Method for marshalling an object
+ def marshal( self ):
+ oStreamString = StringIO()
+ oStreamString.write(unicode('\n'))
+ self.export( oStreamString, 0, name_="XSDataResultControlAutoPROC" )
+ oStringXML = oStreamString.getvalue()
+ oStreamString.close()
+ return oStringXML
+ #Only to export the entire XML tree to a file stream on disk
+ def exportToFile( self, _outfileName ):
+ outfile = open( _outfileName, "w" )
+ outfile.write(unicode('\n'))
+ self.export( outfile, 0, name_='XSDataResultControlAutoPROC' )
+ outfile.close()
+ #Deprecated method, replaced by exportToFile
+ def outputFile( self, _outfileName ):
+ print("WARNING: Method outputFile in class XSDataResultControlAutoPROC is deprecated, please use instead exportToFile!")
+ self.exportToFile(_outfileName)
+ #Method for making a copy in a new instance
+ def copy( self ):
+ return XSDataResultControlAutoPROC.parseString(self.marshal())
+ #Static method for parsing a string
+ def parseString( _inString ):
+ doc = minidom.parseString(_inString)
+ rootNode = doc.documentElement
+ rootObj = XSDataResultControlAutoPROC()
+ rootObj.build(rootNode)
+ # Check that all minOccurs are obeyed by marshalling the created object
+ oStreamString = StringIO()
+ rootObj.export( oStreamString, 0, name_="XSDataResultControlAutoPROC" )
+ oStreamString.close()
+ return rootObj
+ parseString = staticmethod( parseString )
+ #Static method for parsing a file
+ def parseFile( _inFilePath ):
+ doc = minidom.parse(_inFilePath)
+ rootNode = doc.documentElement
+ rootObj = XSDataResultControlAutoPROC()
+ rootObj.build(rootNode)
+ return rootObj
+ parseFile = staticmethod( parseFile )
+# end class XSDataResultControlAutoPROC
+
+
+
+# End of data representation classes.
+
+
diff --git a/mxcubecore/HardwareObjects/ALBA/XalocXSDataControlAutoPROCv1_1.py b/mxcubecore/HardwareObjects/ALBA/XalocXSDataControlAutoPROCv1_1.py
new file mode 100644
index 0000000000..42470b47b3
--- /dev/null
+++ b/mxcubecore/HardwareObjects/ALBA/XalocXSDataControlAutoPROCv1_1.py
@@ -0,0 +1,1044 @@
+#!/usr/bin/env python
+
+#
+# Generated Wed Jul 3 05:01::57 2019 by EDGenerateDS.
+#
+
+import os, sys
+from xml.dom import minidom
+from xml.dom import Node
+
+
+strEdnaHome = os.environ.get("EDNA_HOME", None)
+
+dictLocation = { \
+ "XSDataCommon": "kernel/datamodel", \
+ "XSDataCommon": "kernel/datamodel", \
+ "XSDataCommon": "kernel/datamodel", \
+ "XSDataCommon": "kernel/datamodel", \
+ "XSDataCommon": "kernel/datamodel", \
+ "XSDataCommon": "kernel/datamodel", \
+ "XSDataCommon": "kernel/datamodel", \
+}
+
+try:
+ from XSDataCommon import XSDataBoolean
+ from XSDataCommon import XSDataDouble
+ from XSDataCommon import XSDataFile
+ from XSDataCommon import XSDataInput
+ from XSDataCommon import XSDataInteger
+ from XSDataCommon import XSDataResult
+ from XSDataCommon import XSDataString
+except ImportError as error:
+ if strEdnaHome is not None:
+ for strXsdName in dictLocation:
+ strXsdModule = strXsdName + ".py"
+ strRootdir = os.path.dirname(os.path.abspath(os.path.join(strEdnaHome, dictLocation[strXsdName])))
+ for strRoot, listDirs, listFiles in os.walk(strRootdir):
+ if strXsdModule in listFiles:
+ sys.path.append(strRoot)
+ else:
+ raise error
+from XSDataCommon import XSDataBoolean
+from XSDataCommon import XSDataDouble
+from XSDataCommon import XSDataFile
+from XSDataCommon import XSDataInput
+from XSDataCommon import XSDataInteger
+from XSDataCommon import XSDataResult
+from XSDataCommon import XSDataString
+
+
+
+
+#
+# Support/utility functions.
+#
+
+# Compabiltity between Python 2 and 3:
+if sys.version.startswith('3'):
+ unicode = str
+ from io import StringIO
+else:
+ from StringIO import StringIO
+
+
+def showIndent(outfile, level):
+ for idx in range(level):
+ outfile.write(unicode(' '))
+
+
+def warnEmptyAttribute(_strName, _strTypeName):
+ pass
+ #if not _strTypeName in ["float", "double", "string", "boolean", "integer"]:
+ # print("Warning! Non-optional attribute %s of type %s is None!" % (_strName, _strTypeName))
+
+class MixedContainer(object):
+ # Constants for category:
+ CategoryNone = 0
+ CategoryText = 1
+ CategorySimple = 2
+ CategoryComplex = 3
+ # Constants for content_type:
+ TypeNone = 0
+ TypeText = 1
+ TypeString = 2
+ TypeInteger = 3
+ TypeFloat = 4
+ TypeDecimal = 5
+ TypeDouble = 6
+ TypeBoolean = 7
+ def __init__(self, category, content_type, name, value):
+ self.category = category
+ self.content_type = content_type
+ self.name = name
+ self.value = value
+ def getCategory(self):
+ return self.category
+ def getContenttype(self, content_type):
+ return self.content_type
+ def getValue(self):
+ return self.value
+ def getName(self):
+ return self.name
+ def export(self, outfile, level, name):
+ if self.category == MixedContainer.CategoryText:
+ outfile.write(self.value)
+ elif self.category == MixedContainer.CategorySimple:
+ self.exportSimple(outfile, level, name)
+ else: # category == MixedContainer.CategoryComplex
+ self.value.export(outfile, level, name)
+ def exportSimple(self, outfile, level, name):
+ if self.content_type == MixedContainer.TypeString:
+ outfile.write(unicode('<%s>%s%s>' % (self.name, self.value, self.name)))
+ elif self.content_type == MixedContainer.TypeInteger or \
+ self.content_type == MixedContainer.TypeBoolean:
+ outfile.write(unicode('<%s>%d%s>' % (self.name, self.value, self.name)))
+ elif self.content_type == MixedContainer.TypeFloat or \
+ self.content_type == MixedContainer.TypeDecimal:
+ outfile.write(unicode('<%s>%f%s>' % (self.name, self.value, self.name)))
+ elif self.content_type == MixedContainer.TypeDouble:
+ outfile.write(unicode('<%s>%g%s>' % (self.name, self.value, self.name)))
+
+#
+# Data representation classes.
+#
+
+
+
+class XSDataInputControlAutoPROC(XSDataInput):
+ def __init__(self, configuration=None, highResolutionLimit=None, lowResolutionLimit=None, reprocess=None, cell=None, symm=None, doAnomAndNonanom=None, doAnom=None, processDirectory=None, toN=None, fromN=None, templateN=None, dirN=None, dataCollectionId=None, configDef=None):
+ XSDataInput.__init__(self, configuration)
+ if dataCollectionId is None:
+ self._dataCollectionId = None
+ elif dataCollectionId.__class__.__name__ == "XSDataInteger":
+ self._dataCollectionId = dataCollectionId
+ else:
+ strMessage = "ERROR! XSDataInputControlAutoPROC constructor argument 'dataCollectionId' is not XSDataInteger but %s" % self._dataCollectionId.__class__.__name__
+ raise BaseException(strMessage)
+ if dirN is None:
+ self._dirN = None
+ elif dirN.__class__.__name__ == "XSDataFile":
+ self._dirN = dirN
+ else:
+ strMessage = "ERROR! XSDataInputControlAutoPROC constructor argument 'dirN' is not XSDataFile but %s" % self._dirN.__class__.__name__
+ raise BaseException(strMessage)
+ if templateN is None:
+ self._templateN = None
+ elif templateN.__class__.__name__ == "XSDataString":
+ self._templateN = templateN
+ else:
+ strMessage = "ERROR! XSDataInputControlAutoPROC constructor argument 'templateN' is not XSDataString but %s" % self._templateN.__class__.__name__
+ raise BaseException(strMessage)
+ if fromN is None:
+ self._fromN = None
+ elif fromN.__class__.__name__ == "XSDataInteger":
+ self._fromN = fromN
+ else:
+ strMessage = "ERROR! XSDataInputControlAutoPROC constructor argument 'fromN' is not XSDataInteger but %s" % self._fromN.__class__.__name__
+ raise BaseException(strMessage)
+ if toN is None:
+ self._toN = None
+ elif toN.__class__.__name__ == "XSDataInteger":
+ self._toN = toN
+ else:
+ strMessage = "ERROR! XSDataInputControlAutoPROC constructor argument 'toN' is not XSDataInteger but %s" % self._toN.__class__.__name__
+ raise BaseException(strMessage)
+ if processDirectory is None:
+ self._processDirectory = None
+ elif processDirectory.__class__.__name__ == "XSDataFile":
+ self._processDirectory = processDirectory
+ else:
+ strMessage = "ERROR! XSDataInputControlAutoPROC constructor argument 'processDirectory' is not XSDataFile but %s" % self._processDirectory.__class__.__name__
+ raise BaseException(strMessage)
+ if doAnom is None:
+ self._doAnom = None
+ elif doAnom.__class__.__name__ == "XSDataBoolean":
+ self._doAnom = doAnom
+ else:
+ strMessage = "ERROR! XSDataInputControlAutoPROC constructor argument 'doAnom' is not XSDataBoolean but %s" % self._doAnom.__class__.__name__
+ raise BaseException(strMessage)
+ if doAnomAndNonanom is None:
+ self._doAnomAndNonanom = None
+ elif doAnomAndNonanom.__class__.__name__ == "XSDataBoolean":
+ self._doAnomAndNonanom = doAnomAndNonanom
+ else:
+ strMessage = "ERROR! XSDataInputControlAutoPROC constructor argument 'doAnomAndNonanom' is not XSDataBoolean but %s" % self._doAnomAndNonanom.__class__.__name__
+ raise BaseException(strMessage)
+ if symm is None:
+ self._symm = None
+ elif symm.__class__.__name__ == "XSDataString":
+ self._symm = symm
+ else:
+ strMessage = "ERROR! XSDataInputControlAutoPROC constructor argument 'symm' is not XSDataString but %s" % self._symm.__class__.__name__
+ raise BaseException(strMessage)
+ if cell is None:
+ self._cell = None
+ elif cell.__class__.__name__ == "XSDataString":
+ self._cell = cell
+ else:
+ strMessage = "ERROR! XSDataInputControlAutoPROC constructor argument 'cell' is not XSDataString but %s" % self._cell.__class__.__name__
+ raise BaseException(strMessage)
+ if reprocess is None:
+ self._reprocess = None
+ elif reprocess.__class__.__name__ == "XSDataBoolean":
+ self._reprocess = reprocess
+ else:
+ strMessage = "ERROR! XSDataInputControlAutoPROC constructor argument 'reprocess' is not XSDataBoolean but %s" % self._reprocess.__class__.__name__
+ raise BaseException(strMessage)
+ if lowResolutionLimit is None:
+ self._lowResolutionLimit = None
+ elif lowResolutionLimit.__class__.__name__ == "XSDataDouble":
+ self._lowResolutionLimit = lowResolutionLimit
+ else:
+ strMessage = "ERROR! XSDataInputControlAutoPROC constructor argument 'lowResolutionLimit' is not XSDataDouble but %s" % self._lowResolutionLimit.__class__.__name__
+ raise BaseException(strMessage)
+ if highResolutionLimit is None:
+ self._highResolutionLimit = None
+ elif highResolutionLimit.__class__.__name__ == "XSDataDouble":
+ self._highResolutionLimit = highResolutionLimit
+ else:
+ strMessage = "ERROR! XSDataInputControlAutoPROC constructor argument 'highResolutionLimit' is not XSDataDouble but %s" % self._highResolutionLimit.__class__.__name__
+ raise BaseException(strMessage)
+ if configDef is None:
+ self._configDef = None
+ elif configDef.__class__.__name__ == "XSDataFile":
+ self._configDef = configDef
+ else:
+ strMessage = "ERROR! XSDataInputControlAutoPROC constructor argument 'configDef' is not XSDataFile but %s" % self._configDef.__class__.__name__
+ raise BaseException(strMessage)
+
+ # Methods and properties for the 'dataCollectionId' attribute
+ def getDataCollectionId(self): return self._dataCollectionId
+ def setDataCollectionId(self, dataCollectionId):
+ if dataCollectionId is None:
+ self._dataCollectionId = None
+ elif dataCollectionId.__class__.__name__ == "XSDataInteger":
+ self._dataCollectionId = dataCollectionId
+ else:
+ strMessage = "ERROR! XSDataInputControlAutoPROC.setDataCollectionId argument is not XSDataInteger but %s" % dataCollectionId.__class__.__name__
+ raise BaseException(strMessage)
+ def delDataCollectionId(self): self._dataCollectionId = None
+ dataCollectionId = property(getDataCollectionId, setDataCollectionId, delDataCollectionId, "Property for dataCollectionId")
+ # Methods and properties for the 'dirN' attribute
+ def getDirN(self): return self._dirN
+ def setDirN(self, dirN):
+ if dirN is None:
+ self._dirN = None
+ elif dirN.__class__.__name__ == "XSDataFile":
+ self._dirN = dirN
+ else:
+ strMessage = "ERROR! XSDataInputControlAutoPROC.setDirN argument is not XSDataFile but %s" % dirN.__class__.__name__
+ raise BaseException(strMessage)
+ def delDirN(self): self._dirN = None
+ dirN = property(getDirN, setDirN, delDirN, "Property for dirN")
+ # Methods and properties for the 'templateN' attribute
+ def getTemplateN(self): return self._templateN
+ def setTemplateN(self, templateN):
+ if templateN is None:
+ self._templateN = None
+ elif templateN.__class__.__name__ == "XSDataString":
+ self._templateN = templateN
+ else:
+ strMessage = "ERROR! XSDataInputControlAutoPROC.setTemplateN argument is not XSDataString but %s" % templateN.__class__.__name__
+ raise BaseException(strMessage)
+ def delTemplateN(self): self._templateN = None
+ templateN = property(getTemplateN, setTemplateN, delTemplateN, "Property for templateN")
+ # Methods and properties for the 'fromN' attribute
+ def getFromN(self): return self._fromN
+ def setFromN(self, fromN):
+ if fromN is None:
+ self._fromN = None
+ elif fromN.__class__.__name__ == "XSDataInteger":
+ self._fromN = fromN
+ else:
+ strMessage = "ERROR! XSDataInputControlAutoPROC.setFromN argument is not XSDataInteger but %s" % fromN.__class__.__name__
+ raise BaseException(strMessage)
+ def delFromN(self): self._fromN = None
+ fromN = property(getFromN, setFromN, delFromN, "Property for fromN")
+ # Methods and properties for the 'toN' attribute
+ def getToN(self): return self._toN
+ def setToN(self, toN):
+ if toN is None:
+ self._toN = None
+ elif toN.__class__.__name__ == "XSDataInteger":
+ self._toN = toN
+ else:
+ strMessage = "ERROR! XSDataInputControlAutoPROC.setToN argument is not XSDataInteger but %s" % toN.__class__.__name__
+ raise BaseException(strMessage)
+ def delToN(self): self._toN = None
+ toN = property(getToN, setToN, delToN, "Property for toN")
+ # Methods and properties for the 'processDirectory' attribute
+ def getProcessDirectory(self): return self._processDirectory
+ def setProcessDirectory(self, processDirectory):
+ if processDirectory is None:
+ self._processDirectory = None
+ elif processDirectory.__class__.__name__ == "XSDataFile":
+ self._processDirectory = processDirectory
+ else:
+ strMessage = "ERROR! XSDataInputControlAutoPROC.setProcessDirectory argument is not XSDataFile but %s" % processDirectory.__class__.__name__
+ raise BaseException(strMessage)
+ def delProcessDirectory(self): self._processDirectory = None
+ processDirectory = property(getProcessDirectory, setProcessDirectory, delProcessDirectory, "Property for processDirectory")
+ # Methods and properties for the 'doAnom' attribute
+ def getDoAnom(self): return self._doAnom
+ def setDoAnom(self, doAnom):
+ if doAnom is None:
+ self._doAnom = None
+ elif doAnom.__class__.__name__ == "XSDataBoolean":
+ self._doAnom = doAnom
+ else:
+ strMessage = "ERROR! XSDataInputControlAutoPROC.setDoAnom argument is not XSDataBoolean but %s" % doAnom.__class__.__name__
+ raise BaseException(strMessage)
+ def delDoAnom(self): self._doAnom = None
+ doAnom = property(getDoAnom, setDoAnom, delDoAnom, "Property for doAnom")
+ # Methods and properties for the 'doAnomAndNonanom' attribute
+ def getDoAnomAndNonanom(self): return self._doAnomAndNonanom
+ def setDoAnomAndNonanom(self, doAnomAndNonanom):
+ if doAnomAndNonanom is None:
+ self._doAnomAndNonanom = None
+ elif doAnomAndNonanom.__class__.__name__ == "XSDataBoolean":
+ self._doAnomAndNonanom = doAnomAndNonanom
+ else:
+ strMessage = "ERROR! XSDataInputControlAutoPROC.setDoAnomAndNonanom argument is not XSDataBoolean but %s" % doAnomAndNonanom.__class__.__name__
+ raise BaseException(strMessage)
+ def delDoAnomAndNonanom(self): self._doAnomAndNonanom = None
+ doAnomAndNonanom = property(getDoAnomAndNonanom, setDoAnomAndNonanom, delDoAnomAndNonanom, "Property for doAnomAndNonanom")
+ # Methods and properties for the 'symm' attribute
+ def getSymm(self): return self._symm
+ def setSymm(self, symm):
+ if symm is None:
+ self._symm = None
+ elif symm.__class__.__name__ == "XSDataString":
+ self._symm = symm
+ else:
+ strMessage = "ERROR! XSDataInputControlAutoPROC.setSymm argument is not XSDataString but %s" % symm.__class__.__name__
+ raise BaseException(strMessage)
+ def delSymm(self): self._symm = None
+ symm = property(getSymm, setSymm, delSymm, "Property for symm")
+ setSpacegroup = setSymm
+ getSpacegroup = getSymm
+ delSpacegroup = delSymm
+ # Methods and properties for the 'configDef' attribute
+ def getConfigDef(self): return self._configDef
+ def setConfigDef(self, configDef):
+ if configDef is None:
+ self._configDef = None
+ elif configDef.__class__.__name__ == "XSDataFile":
+ self._configDef = configDef
+ else:
+ strMessage = "ERROR! XSDataInputControlAutoPROC.setDirN argument is not XSDataFile but %s" % configDef.__class__.__name__
+ raise BaseException(strMessage)
+ def delConfigDef(self): self._configDef = None
+ configDef = property(getConfigDef, setConfigDef, delConfigDef, "Property for configDef")
+ # Methods and properties for the 'cell' attribute
+ def getCell(self): return self._cell
+ def setCell(self, cell):
+ if cell is None:
+ self._cell = None
+ elif cell.__class__.__name__ == "XSDataString":
+ self._cell = cell
+ else:
+ strMessage = "ERROR! XSDataInputControlAutoPROC.setCell argument is not XSDataString but %s" % cell.__class__.__name__
+ raise BaseException(strMessage)
+ def delCell(self): self._cell = None
+ cell = property(getCell, setCell, delCell, "Property for cell")
+ # Methods and properties for the 'reprocess' attribute
+ def getReprocess(self): return self._reprocess
+ def setReprocess(self, reprocess):
+ if reprocess is None:
+ self._reprocess = None
+ elif reprocess.__class__.__name__ == "XSDataBoolean":
+ self._reprocess = reprocess
+ else:
+ strMessage = "ERROR! XSDataInputControlAutoPROC.setReprocess argument is not XSDataBoolean but %s" % reprocess.__class__.__name__
+ raise BaseException(strMessage)
+ def delReprocess(self): self._reprocess = None
+ reprocess = property(getReprocess, setReprocess, delReprocess, "Property for reprocess")
+ # Methods and properties for the 'lowResolutionLimit' attribute
+ def getLowResolutionLimit(self): return self._lowResolutionLimit
+ def setLowResolutionLimit(self, lowResolutionLimit):
+ if lowResolutionLimit is None:
+ self._lowResolutionLimit = None
+ elif lowResolutionLimit.__class__.__name__ == "XSDataDouble":
+ self._lowResolutionLimit = lowResolutionLimit
+ else:
+ strMessage = "ERROR! XSDataInputControlAutoPROC.setLowResolutionLimit argument is not XSDataDouble but %s" % lowResolutionLimit.__class__.__name__
+ raise BaseException(strMessage)
+ def delLowResolutionLimit(self): self._lowResolutionLimit = None
+ lowResolutionLimit = property(getLowResolutionLimit, setLowResolutionLimit, delLowResolutionLimit, "Property for lowResolutionLimit")
+ # Methods and properties for the 'highResolutionLimit' attribute
+ def getHighResolutionLimit(self): return self._highResolutionLimit
+ def setHighResolutionLimit(self, highResolutionLimit):
+ if highResolutionLimit is None:
+ self._highResolutionLimit = None
+ elif highResolutionLimit.__class__.__name__ == "XSDataDouble":
+ self._highResolutionLimit = highResolutionLimit
+ else:
+ strMessage = "ERROR! XSDataInputControlAutoPROC.setHighResolutionLimit argument is not XSDataDouble but %s" % highResolutionLimit.__class__.__name__
+ raise BaseException(strMessage)
+ def delHighResolutionLimit(self): self._highResolutionLimit = None
+ highResolutionLimit = property(getHighResolutionLimit, setHighResolutionLimit, delHighResolutionLimit, "Property for highResolutionLimit")
+ def export(self, outfile, level, name_='XSDataInputControlAutoPROC'):
+ showIndent(outfile, level)
+ outfile.write(unicode('<%s>\n' % name_))
+ self.exportChildren(outfile, level + 1, name_)
+ showIndent(outfile, level)
+ outfile.write(unicode('%s>\n' % name_))
+ def exportChildren(self, outfile, level, name_='XSDataInputControlAutoPROC'):
+ XSDataInput.exportChildren(self, outfile, level, name_)
+ if self._dataCollectionId is not None:
+ self.dataCollectionId.export(outfile, level, name_='dataCollectionId')
+ if self._dirN is not None:
+ self.dirN.export(outfile, level, name_='dirN')
+ if self._configDef is not None:
+ self.configDef.export(outfile, level, name_='configDef')
+ if self._templateN is not None:
+ self.templateN.export(outfile, level, name_='templateN')
+ if self._fromN is not None:
+ self.fromN.export(outfile, level, name_='fromN')
+ if self._toN is not None:
+ self.toN.export(outfile, level, name_='toN')
+ if self._processDirectory is not None:
+ self.processDirectory.export(outfile, level, name_='processDirectory')
+ if self._doAnom is not None:
+ self.doAnom.export(outfile, level, name_='doAnom')
+ if self._doAnomAndNonanom is not None:
+ self.doAnomAndNonanom.export(outfile, level, name_='doAnomAndNonanom')
+ if self._symm is not None:
+ self.symm.export(outfile, level, name_='symm')
+ if self._cell is not None:
+ self.cell.export(outfile, level, name_='cell')
+ if self._reprocess is not None:
+ self.reprocess.export(outfile, level, name_='reprocess')
+ if self._lowResolutionLimit is not None:
+ self.lowResolutionLimit.export(outfile, level, name_='lowResolutionLimit')
+ if self._highResolutionLimit is not None:
+ self.highResolutionLimit.export(outfile, level, name_='highResolutionLimit')
+ def build(self, node_):
+ for child_ in node_.childNodes:
+ nodeName_ = child_.nodeName.split(':')[-1]
+ self.buildChildren(child_, nodeName_)
+ def buildChildren(self, child_, nodeName_):
+ if child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'dataCollectionId':
+ obj_ = XSDataInteger()
+ obj_.build(child_)
+ self.setDataCollectionId(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'dirN':
+ obj_ = XSDataFile()
+ obj_.build(child_)
+ self.setDirN(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'configDef':
+ obj_ = XSDataFile()
+ obj_.build(child_)
+ self.setConfigDef(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'templateN':
+ obj_ = XSDataString()
+ obj_.build(child_)
+ self.setTemplateN(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'fromN':
+ obj_ = XSDataInteger()
+ obj_.build(child_)
+ self.setFromN(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'toN':
+ obj_ = XSDataInteger()
+ obj_.build(child_)
+ self.setToN(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'processDirectory':
+ obj_ = XSDataFile()
+ obj_.build(child_)
+ self.setProcessDirectory(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'doAnom':
+ obj_ = XSDataBoolean()
+ obj_.build(child_)
+ self.setDoAnom(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'doAnomAndNonanom':
+ obj_ = XSDataBoolean()
+ obj_.build(child_)
+ self.setDoAnomAndNonanom(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'symm':
+ obj_ = XSDataString()
+ obj_.build(child_)
+ self.setSymm(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'cell':
+ obj_ = XSDataString()
+ obj_.build(child_)
+ self.setCell(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'reprocess':
+ obj_ = XSDataBoolean()
+ obj_.build(child_)
+ self.setReprocess(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'lowResolutionLimit':
+ obj_ = XSDataDouble()
+ obj_.build(child_)
+ self.setLowResolutionLimit(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'highResolutionLimit':
+ obj_ = XSDataDouble()
+ obj_.build(child_)
+ self.setHighResolutionLimit(obj_)
+ XSDataInput.buildChildren(self, child_, nodeName_)
+ #Method for marshalling an object
+ def marshal( self ):
+ oStreamString = StringIO()
+ oStreamString.write(unicode('\n'))
+ self.export( oStreamString, 0, name_="XSDataInputControlAutoPROC" )
+ oStringXML = oStreamString.getvalue()
+ oStreamString.close()
+ return oStringXML
+ #Only to export the entire XML tree to a file stream on disk
+ def exportToFile( self, _outfileName ):
+ outfile = open( _outfileName, "w" )
+ outfile.write(unicode('\n'))
+ self.export( outfile, 0, name_='XSDataInputControlAutoPROC' )
+ outfile.close()
+ #Deprecated method, replaced by exportToFile
+ def outputFile( self, _outfileName ):
+ print("WARNING: Method outputFile in class XSDataInputControlAutoPROC is deprecated, please use instead exportToFile!")
+ self.exportToFile(_outfileName)
+ #Method for making a copy in a new instance
+ def copy( self ):
+ return XSDataInputControlAutoPROC.parseString(self.marshal())
+ #Static method for parsing a string
+ def parseString( _inString ):
+ doc = minidom.parseString(_inString)
+ rootNode = doc.documentElement
+ rootObj = XSDataInputControlAutoPROC()
+ rootObj.build(rootNode)
+ # Check that all minOccurs are obeyed by marshalling the created object
+ oStreamString = StringIO()
+ rootObj.export( oStreamString, 0, name_="XSDataInputControlAutoPROC" )
+ oStreamString.close()
+ return rootObj
+ parseString = staticmethod( parseString )
+ #Static method for parsing a file
+ def parseFile( _inFilePath ):
+ doc = minidom.parse(_inFilePath)
+ rootNode = doc.documentElement
+ rootObj = XSDataInputControlAutoPROC()
+ rootObj.build(rootNode)
+ return rootObj
+ parseFile = staticmethod( parseFile )
+# end class XSDataInputControlAutoPROC
+
+
+class XSDataResultControlAutoPROC(XSDataResult):
+ def __init__(self, status=None):
+ XSDataResult.__init__(self, status)
+ def export(self, outfile, level, name_='XSDataResultControlAutoPROC'):
+ showIndent(outfile, level)
+ outfile.write(unicode('<%s>\n' % name_))
+ self.exportChildren(outfile, level + 1, name_)
+ showIndent(outfile, level)
+ outfile.write(unicode('%s>\n' % name_))
+ def exportChildren(self, outfile, level, name_='XSDataResultControlAutoPROC'):
+ XSDataResult.exportChildren(self, outfile, level, name_)
+ def build(self, node_):
+ for child_ in node_.childNodes:
+ nodeName_ = child_.nodeName.split(':')[-1]
+ self.buildChildren(child_, nodeName_)
+ def buildChildren(self, child_, nodeName_):
+ pass
+ XSDataResult.buildChildren(self, child_, nodeName_)
+ #Method for marshalling an object
+ def marshal( self ):
+ oStreamString = StringIO()
+ oStreamString.write(unicode('\n'))
+ self.export( oStreamString, 0, name_="XSDataResultControlAutoPROC" )
+ oStringXML = oStreamString.getvalue()
+ oStreamString.close()
+ return oStringXML
+ #Only to export the entire XML tree to a file stream on disk
+ def exportToFile( self, _outfileName ):
+ outfile = open( _outfileName, "w" )
+ outfile.write(unicode('\n'))
+ self.export( outfile, 0, name_='XSDataResultControlAutoPROC' )
+ outfile.close()
+ #Deprecated method, replaced by exportToFile
+ def outputFile( self, _outfileName ):
+ print("WARNING: Method outputFile in class XSDataResultControlAutoPROC is deprecated, please use instead exportToFile!")
+ self.exportToFile(_outfileName)
+ #Method for making a copy in a new instance
+ def copy( self ):
+ return XSDataResultControlAutoPROC.parseString(self.marshal())
+ #Static method for parsing a string
+ def parseString( _inString ):
+ doc = minidom.parseString(_inString)
+ rootNode = doc.documentElement
+ rootObj = XSDataResultControlAutoPROC()
+ rootObj.build(rootNode)
+ # Check that all minOccurs are obeyed by marshalling the created object
+ oStreamString = StringIO()
+ rootObj.export( oStreamString, 0, name_="XSDataResultControlAutoPROC" )
+ oStreamString.close()
+ return rootObj
+ parseString = staticmethod( parseString )
+ #Static method for parsing a file
+ def parseFile( _inFilePath ):
+ doc = minidom.parse(_inFilePath)
+ rootNode = doc.documentElement
+ rootObj = XSDataResultControlAutoPROC()
+ rootObj.build(rootNode)
+ return rootObj
+ parseFile = staticmethod( parseFile )
+# end class XSDataResultControlAutoPROC
+
+
+class XSDataInputControlDimpleAP(XSDataInput):
+ def __init__(self, configuration=None, resultsDirectory=None, autoProcProgramId=None, pdbDirectory=None, beamline=None, sessionDate=None, proposal=None, imagePrefix=None, pyarchPath=None, mtzFile=None, dataCollectionId=None):
+ XSDataInput.__init__(self, configuration)
+ if dataCollectionId is None:
+ self._dataCollectionId = None
+ elif dataCollectionId.__class__.__name__ == "XSDataInteger":
+ self._dataCollectionId = dataCollectionId
+ else:
+ strMessage = "ERROR! XSDataInputControlDimpleAP constructor argument 'dataCollectionId' is not XSDataInteger but %s" % self._dataCollectionId.__class__.__name__
+ raise BaseException(strMessage)
+ if mtzFile is None:
+ self._mtzFile = None
+ elif mtzFile.__class__.__name__ == "XSDataFile":
+ self._mtzFile = mtzFile
+ else:
+ strMessage = "ERROR! XSDataInputControlDimpleAP constructor argument 'mtzFile' is not XSDataFile but %s" % self._mtzFile.__class__.__name__
+ raise BaseException(strMessage)
+ if pyarchPath is None:
+ self._pyarchPath = None
+ elif pyarchPath.__class__.__name__ == "XSDataFile":
+ self._pyarchPath = pyarchPath
+ else:
+ strMessage = "ERROR! XSDataInputControlDimpleAP constructor argument 'pyarchPath' is not XSDataFile but %s" % self._pyarchPath.__class__.__name__
+ raise BaseException(strMessage)
+ if imagePrefix is None:
+ self._imagePrefix = None
+ elif imagePrefix.__class__.__name__ == "XSDataString":
+ self._imagePrefix = imagePrefix
+ else:
+ strMessage = "ERROR! XSDataInputControlDimpleAP constructor argument 'imagePrefix' is not XSDataString but %s" % self._imagePrefix.__class__.__name__
+ raise BaseException(strMessage)
+ if proposal is None:
+ self._proposal = None
+ elif proposal.__class__.__name__ == "XSDataString":
+ self._proposal = proposal
+ else:
+ strMessage = "ERROR! XSDataInputControlDimpleAP constructor argument 'proposal' is not XSDataString but %s" % self._proposal.__class__.__name__
+ raise BaseException(strMessage)
+ if sessionDate is None:
+ self._sessionDate = None
+ elif sessionDate.__class__.__name__ == "XSDataString":
+ self._sessionDate = sessionDate
+ else:
+ strMessage = "ERROR! XSDataInputControlDimpleAP constructor argument 'sessionDate' is not XSDataString but %s" % self._sessionDate.__class__.__name__
+ raise BaseException(strMessage)
+ if beamline is None:
+ self._beamline = None
+ elif beamline.__class__.__name__ == "XSDataString":
+ self._beamline = beamline
+ else:
+ strMessage = "ERROR! XSDataInputControlDimpleAP constructor argument 'beamline' is not XSDataString but %s" % self._beamline.__class__.__name__
+ raise BaseException(strMessage)
+ if pdbDirectory is None:
+ self._pdbDirectory = None
+ elif pdbDirectory.__class__.__name__ == "XSDataFile":
+ self._pdbDirectory = pdbDirectory
+ else:
+ strMessage = "ERROR! XSDataInputControlDimpleAP constructor argument 'pdbDirectory' is not XSDataFile but %s" % self._pdbDirectory.__class__.__name__
+ raise BaseException(strMessage)
+ if autoProcProgramId is None:
+ self._autoProcProgramId = None
+ elif autoProcProgramId.__class__.__name__ == "XSDataInteger":
+ self._autoProcProgramId = autoProcProgramId
+ else:
+ strMessage = "ERROR! XSDataInputControlDimpleAP constructor argument 'autoProcProgramId' is not XSDataInteger but %s" % self._autoProcProgramId.__class__.__name__
+ raise BaseException(strMessage)
+ if resultsDirectory is None:
+ self._resultsDirectory = None
+ elif resultsDirectory.__class__.__name__ == "XSDataFile":
+ self._resultsDirectory = resultsDirectory
+ else:
+ strMessage = "ERROR! XSDataInputControlDimpleAP constructor argument 'resultsDirectory' is not XSDataFile but %s" % self._resultsDirectory.__class__.__name__
+ raise BaseException(strMessage)
+ # Methods and properties for the 'dataCollectionId' attribute
+ def getDataCollectionId(self): return self._dataCollectionId
+ def setDataCollectionId(self, dataCollectionId):
+ if dataCollectionId is None:
+ self._dataCollectionId = None
+ elif dataCollectionId.__class__.__name__ == "XSDataInteger":
+ self._dataCollectionId = dataCollectionId
+ else:
+ strMessage = "ERROR! XSDataInputControlDimpleAP.setDataCollectionId argument is not XSDataInteger but %s" % dataCollectionId.__class__.__name__
+ raise BaseException(strMessage)
+ def delDataCollectionId(self): self._dataCollectionId = None
+ dataCollectionId = property(getDataCollectionId, setDataCollectionId, delDataCollectionId, "Property for dataCollectionId")
+ # Methods and properties for the 'mtzFile' attribute
+ def getMtzFile(self): return self._mtzFile
+ def setMtzFile(self, mtzFile):
+ if mtzFile is None:
+ self._mtzFile = None
+ elif mtzFile.__class__.__name__ == "XSDataFile":
+ self._mtzFile = mtzFile
+ else:
+ strMessage = "ERROR! XSDataInputControlDimpleAP.setMtzFile argument is not XSDataFile but %s" % mtzFile.__class__.__name__
+ raise BaseException(strMessage)
+ def delMtzFile(self): self._mtzFile = None
+ mtzFile = property(getMtzFile, setMtzFile, delMtzFile, "Property for mtzFile")
+ # Methods and properties for the 'pyarchPath' attribute
+ def getPyarchPath(self): return self._pyarchPath
+ def setPyarchPath(self, pyarchPath):
+ if pyarchPath is None:
+ self._pyarchPath = None
+ elif pyarchPath.__class__.__name__ == "XSDataFile":
+ self._pyarchPath = pyarchPath
+ else:
+ strMessage = "ERROR! XSDataInputControlDimpleAP.setPyarchPath argument is not XSDataFile but %s" % pyarchPath.__class__.__name__
+ raise BaseException(strMessage)
+ def delPyarchPath(self): self._pyarchPath = None
+ pyarchPath = property(getPyarchPath, setPyarchPath, delPyarchPath, "Property for pyarchPath")
+ # Methods and properties for the 'imagePrefix' attribute
+ def getImagePrefix(self): return self._imagePrefix
+ def setImagePrefix(self, imagePrefix):
+ if imagePrefix is None:
+ self._imagePrefix = None
+ elif imagePrefix.__class__.__name__ == "XSDataString":
+ self._imagePrefix = imagePrefix
+ else:
+ strMessage = "ERROR! XSDataInputControlDimpleAP.setImagePrefix argument is not XSDataString but %s" % imagePrefix.__class__.__name__
+ raise BaseException(strMessage)
+ def delImagePrefix(self): self._imagePrefix = None
+ imagePrefix = property(getImagePrefix, setImagePrefix, delImagePrefix, "Property for imagePrefix")
+ # Methods and properties for the 'proposal' attribute
+ def getProposal(self): return self._proposal
+ def setProposal(self, proposal):
+ if proposal is None:
+ self._proposal = None
+ elif proposal.__class__.__name__ == "XSDataString":
+ self._proposal = proposal
+ else:
+ strMessage = "ERROR! XSDataInputControlDimpleAP.setProposal argument is not XSDataString but %s" % proposal.__class__.__name__
+ raise BaseException(strMessage)
+ def delProposal(self): self._proposal = None
+ proposal = property(getProposal, setProposal, delProposal, "Property for proposal")
+ # Methods and properties for the 'sessionDate' attribute
+ def getSessionDate(self): return self._sessionDate
+ def setSessionDate(self, sessionDate):
+ if sessionDate is None:
+ self._sessionDate = None
+ elif sessionDate.__class__.__name__ == "XSDataString":
+ self._sessionDate = sessionDate
+ else:
+ strMessage = "ERROR! XSDataInputControlDimpleAP.setSessionDate argument is not XSDataString but %s" % sessionDate.__class__.__name__
+ raise BaseException(strMessage)
+ def delSessionDate(self): self._sessionDate = None
+ sessionDate = property(getSessionDate, setSessionDate, delSessionDate, "Property for sessionDate")
+ # Methods and properties for the 'beamline' attribute
+ def getBeamline(self): return self._beamline
+ def setBeamline(self, beamline):
+ if beamline is None:
+ self._beamline = None
+ elif beamline.__class__.__name__ == "XSDataString":
+ self._beamline = beamline
+ else:
+ strMessage = "ERROR! XSDataInputControlDimpleAP.setBeamline argument is not XSDataString but %s" % beamline.__class__.__name__
+ raise BaseException(strMessage)
+ def delBeamline(self): self._beamline = None
+ beamline = property(getBeamline, setBeamline, delBeamline, "Property for beamline")
+ # Methods and properties for the 'pdbDirectory' attribute
+ def getPdbDirectory(self): return self._pdbDirectory
+ def setPdbDirectory(self, pdbDirectory):
+ if pdbDirectory is None:
+ self._pdbDirectory = None
+ elif pdbDirectory.__class__.__name__ == "XSDataFile":
+ self._pdbDirectory = pdbDirectory
+ else:
+ strMessage = "ERROR! XSDataInputControlDimpleAP.setPdbDirectory argument is not XSDataFile but %s" % pdbDirectory.__class__.__name__
+ raise BaseException(strMessage)
+ def delPdbDirectory(self): self._pdbDirectory = None
+ pdbDirectory = property(getPdbDirectory, setPdbDirectory, delPdbDirectory, "Property for pdbDirectory")
+ # Methods and properties for the 'autoProcProgramId' attribute
+ def getAutoProcProgramId(self): return self._autoProcProgramId
+ def setAutoProcProgramId(self, autoProcProgramId):
+ if autoProcProgramId is None:
+ self._autoProcProgramId = None
+ elif autoProcProgramId.__class__.__name__ == "XSDataInteger":
+ self._autoProcProgramId = autoProcProgramId
+ else:
+ strMessage = "ERROR! XSDataInputControlDimpleAP.setAutoProcProgramId argument is not XSDataInteger but %s" % autoProcProgramId.__class__.__name__
+ raise BaseException(strMessage)
+ def delAutoProcProgramId(self): self._autoProcProgramId = None
+ autoProcProgramId = property(getAutoProcProgramId, setAutoProcProgramId, delAutoProcProgramId, "Property for autoProcProgramId")
+ # Methods and properties for the 'resultsDirectory' attribute
+ def getResultsDirectory(self): return self._resultsDirectory
+ def setResultsDirectory(self, resultsDirectory):
+ if resultsDirectory is None:
+ self._resultsDirectory = None
+ elif resultsDirectory.__class__.__name__ == "XSDataFile":
+ self._resultsDirectory = resultsDirectory
+ else:
+ strMessage = "ERROR! XSDataInputControlDimpleAP.setResultsDirectory argument is not XSDataFile but %s" % resultsDirectory.__class__.__name__
+ raise BaseException(strMessage)
+ def delResultsDirectory(self): self._resultsDirectory = None
+ resultsDirectory = property(getResultsDirectory, setResultsDirectory, delResultsDirectory, "Property for resultsDirectory")
+ def export(self, outfile, level, name_='XSDataInputControlDimpleAP'):
+ showIndent(outfile, level)
+ outfile.write(unicode('<%s>\n' % name_))
+ self.exportChildren(outfile, level + 1, name_)
+ showIndent(outfile, level)
+ outfile.write(unicode('%s>\n' % name_))
+ def exportChildren(self, outfile, level, name_='XSDataInputControlDimpleAP'):
+ XSDataInput.exportChildren(self, outfile, level, name_)
+ if self._dataCollectionId is not None:
+ self.dataCollectionId.export(outfile, level, name_='dataCollectionId')
+ else:
+ warnEmptyAttribute("dataCollectionId", "XSDataInteger")
+ if self._mtzFile is not None:
+ self.mtzFile.export(outfile, level, name_='mtzFile')
+ else:
+ warnEmptyAttribute("mtzFile", "XSDataFile")
+ if self._pyarchPath is not None:
+ self.pyarchPath.export(outfile, level, name_='pyarchPath')
+ else:
+ warnEmptyAttribute("pyarchPath", "XSDataFile")
+ if self._imagePrefix is not None:
+ self.imagePrefix.export(outfile, level, name_='imagePrefix')
+ else:
+ warnEmptyAttribute("imagePrefix", "XSDataString")
+ if self._proposal is not None:
+ self.proposal.export(outfile, level, name_='proposal')
+ else:
+ warnEmptyAttribute("proposal", "XSDataString")
+ if self._sessionDate is not None:
+ self.sessionDate.export(outfile, level, name_='sessionDate')
+ else:
+ warnEmptyAttribute("sessionDate", "XSDataString")
+ if self._beamline is not None:
+ self.beamline.export(outfile, level, name_='beamline')
+ else:
+ warnEmptyAttribute("beamline", "XSDataString")
+ if self._pdbDirectory is not None:
+ self.pdbDirectory.export(outfile, level, name_='pdbDirectory')
+ if self._autoProcProgramId is not None:
+ self.autoProcProgramId.export(outfile, level, name_='autoProcProgramId')
+ if self._resultsDirectory is not None:
+ self.resultsDirectory.export(outfile, level, name_='resultsDirectory')
+ def build(self, node_):
+ for child_ in node_.childNodes:
+ nodeName_ = child_.nodeName.split(':')[-1]
+ self.buildChildren(child_, nodeName_)
+ def buildChildren(self, child_, nodeName_):
+ if child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'dataCollectionId':
+ obj_ = XSDataInteger()
+ obj_.build(child_)
+ self.setDataCollectionId(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'mtzFile':
+ obj_ = XSDataFile()
+ obj_.build(child_)
+ self.setMtzFile(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'pyarchPath':
+ obj_ = XSDataFile()
+ obj_.build(child_)
+ self.setPyarchPath(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'imagePrefix':
+ obj_ = XSDataString()
+ obj_.build(child_)
+ self.setImagePrefix(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'proposal':
+ obj_ = XSDataString()
+ obj_.build(child_)
+ self.setProposal(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'sessionDate':
+ obj_ = XSDataString()
+ obj_.build(child_)
+ self.setSessionDate(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'beamline':
+ obj_ = XSDataString()
+ obj_.build(child_)
+ self.setBeamline(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'pdbDirectory':
+ obj_ = XSDataFile()
+ obj_.build(child_)
+ self.setPdbDirectory(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'autoProcProgramId':
+ obj_ = XSDataInteger()
+ obj_.build(child_)
+ self.setAutoProcProgramId(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'resultsDirectory':
+ obj_ = XSDataFile()
+ obj_.build(child_)
+ self.setResultsDirectory(obj_)
+ XSDataInput.buildChildren(self, child_, nodeName_)
+ #Method for marshalling an object
+ def marshal( self ):
+ oStreamString = StringIO()
+ oStreamString.write(unicode('\n'))
+ self.export( oStreamString, 0, name_="XSDataInputControlDimpleAP" )
+ oStringXML = oStreamString.getvalue()
+ oStreamString.close()
+ return oStringXML
+ #Only to export the entire XML tree to a file stream on disk
+ def exportToFile( self, _outfileName ):
+ outfile = open( _outfileName, "w" )
+ outfile.write(unicode('\n'))
+ self.export( outfile, 0, name_='XSDataInputControlDimpleAP' )
+ outfile.close()
+ #Deprecated method, replaced by exportToFile
+ def outputFile( self, _outfileName ):
+ print("WARNING: Method outputFile in class XSDataInputControlDimpleAP is deprecated, please use instead exportToFile!")
+ self.exportToFile(_outfileName)
+ #Method for making a copy in a new instance
+ def copy( self ):
+ return XSDataInputControlDimpleAP.parseString(self.marshal())
+ #Static method for parsing a string
+ def parseString( _inString ):
+ doc = minidom.parseString(_inString)
+ rootNode = doc.documentElement
+ rootObj = XSDataInputControlDimpleAP()
+ rootObj.build(rootNode)
+ # Check that all minOccurs are obeyed by marshalling the created object
+ oStreamString = StringIO()
+ rootObj.export( oStreamString, 0, name_="XSDataInputControlDimpleAP" )
+ oStreamString.close()
+ return rootObj
+ parseString = staticmethod( parseString )
+ #Static method for parsing a file
+ def parseFile( _inFilePath ):
+ doc = minidom.parse(_inFilePath)
+ rootNode = doc.documentElement
+ rootObj = XSDataInputControlDimpleAP()
+ rootObj.build(rootNode)
+ return rootObj
+ parseFile = staticmethod( parseFile )
+# end class XSDataInputControlDimpleAP
+
+
+class XSDataResultControlDimpleAP(XSDataResult):
+ def __init__(self, status=None, dimpleExecutedSuccessfully=None):
+ XSDataResult.__init__(self, status)
+ if dimpleExecutedSuccessfully is None:
+ self._dimpleExecutedSuccessfully = None
+ elif dimpleExecutedSuccessfully.__class__.__name__ == "XSDataBoolean":
+ self._dimpleExecutedSuccessfully = dimpleExecutedSuccessfully
+ else:
+ strMessage = "ERROR! XSDataResultControlDimpleAP constructor argument 'dimpleExecutedSuccessfully' is not XSDataBoolean but %s" % self._dimpleExecutedSuccessfully.__class__.__name__
+ raise BaseException(strMessage)
+ # Methods and properties for the 'dimpleExecutedSuccessfully' attribute
+ def getDimpleExecutedSuccessfully(self): return self._dimpleExecutedSuccessfully
+ def setDimpleExecutedSuccessfully(self, dimpleExecutedSuccessfully):
+ if dimpleExecutedSuccessfully is None:
+ self._dimpleExecutedSuccessfully = None
+ elif dimpleExecutedSuccessfully.__class__.__name__ == "XSDataBoolean":
+ self._dimpleExecutedSuccessfully = dimpleExecutedSuccessfully
+ else:
+ strMessage = "ERROR! XSDataResultControlDimpleAP.setDimpleExecutedSuccessfully argument is not XSDataBoolean but %s" % dimpleExecutedSuccessfully.__class__.__name__
+ raise BaseException(strMessage)
+ def delDimpleExecutedSuccessfully(self): self._dimpleExecutedSuccessfully = None
+ dimpleExecutedSuccessfully = property(getDimpleExecutedSuccessfully, setDimpleExecutedSuccessfully, delDimpleExecutedSuccessfully, "Property for dimpleExecutedSuccessfully")
+ def export(self, outfile, level, name_='XSDataResultControlDimpleAP'):
+ showIndent(outfile, level)
+ outfile.write(unicode('<%s>\n' % name_))
+ self.exportChildren(outfile, level + 1, name_)
+ showIndent(outfile, level)
+ outfile.write(unicode('%s>\n' % name_))
+ def exportChildren(self, outfile, level, name_='XSDataResultControlDimpleAP'):
+ XSDataResult.exportChildren(self, outfile, level, name_)
+ if self._dimpleExecutedSuccessfully is not None:
+ self.dimpleExecutedSuccessfully.export(outfile, level, name_='dimpleExecutedSuccessfully')
+ else:
+ warnEmptyAttribute("dimpleExecutedSuccessfully", "XSDataBoolean")
+ def build(self, node_):
+ for child_ in node_.childNodes:
+ nodeName_ = child_.nodeName.split(':')[-1]
+ self.buildChildren(child_, nodeName_)
+ def buildChildren(self, child_, nodeName_):
+ if child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'dimpleExecutedSuccessfully':
+ obj_ = XSDataBoolean()
+ obj_.build(child_)
+ self.setDimpleExecutedSuccessfully(obj_)
+ XSDataResult.buildChildren(self, child_, nodeName_)
+ #Method for marshalling an object
+ def marshal( self ):
+ oStreamString = StringIO()
+ oStreamString.write(unicode('\n'))
+ self.export( oStreamString, 0, name_="XSDataResultControlDimpleAP" )
+ oStringXML = oStreamString.getvalue()
+ oStreamString.close()
+ return oStringXML
+ #Only to export the entire XML tree to a file stream on disk
+ def exportToFile( self, _outfileName ):
+ outfile = open( _outfileName, "w" )
+ outfile.write(unicode('\n'))
+ self.export( outfile, 0, name_='XSDataResultControlDimpleAP' )
+ outfile.close()
+ #Deprecated method, replaced by exportToFile
+ def outputFile( self, _outfileName ):
+ print("WARNING: Method outputFile in class XSDataResultControlDimpleAP is deprecated, please use instead exportToFile!")
+ self.exportToFile(_outfileName)
+ #Method for making a copy in a new instance
+ def copy( self ):
+ return XSDataResultControlDimpleAP.parseString(self.marshal())
+ #Static method for parsing a string
+ def parseString( _inString ):
+ doc = minidom.parseString(_inString)
+ rootNode = doc.documentElement
+ rootObj = XSDataResultControlDimpleAP()
+ rootObj.build(rootNode)
+ # Check that all minOccurs are obeyed by marshalling the created object
+ oStreamString = StringIO()
+ rootObj.export( oStreamString, 0, name_="XSDataResultControlDimpleAP" )
+ oStreamString.close()
+ return rootObj
+ parseString = staticmethod( parseString )
+ #Static method for parsing a file
+ def parseFile( _inFilePath ):
+ doc = minidom.parse(_inFilePath)
+ rootNode = doc.documentElement
+ rootObj = XSDataResultControlDimpleAP()
+ rootObj.build(rootNode)
+ return rootObj
+ parseFile = staticmethod( parseFile )
+# end class XSDataResultControlDimpleAP
+
+# End of data representation classes.
+
+
diff --git a/mxcubecore/HardwareObjects/ALBA/XalocXSDataControlDozorv1_0.py b/mxcubecore/HardwareObjects/ALBA/XalocXSDataControlDozorv1_0.py
new file mode 100644
index 0000000000..209475004a
--- /dev/null
+++ b/mxcubecore/HardwareObjects/ALBA/XalocXSDataControlDozorv1_0.py
@@ -0,0 +1,1741 @@
+#!/usr/bin/env python
+
+#
+# Generated Thu Jan 12 03:59::59 2017 by EDGenerateDS.
+#
+
+import os, sys
+from xml.dom import minidom
+from xml.dom import Node
+
+
+strEdnaHome = os.environ.get("EDNA_HOME", None)
+
+dictLocation = { \
+ "XSDataCommon": "kernel/datamodel", \
+ "XSDataCommon": "kernel/datamodel", \
+ "XSDataCommon": "kernel/datamodel", \
+ "XSDataCommon": "kernel/datamodel", \
+ "XSDataCommon": "kernel/datamodel", \
+ "XSDataCommon": "kernel/datamodel", \
+ "XSDataCommon": "kernel/datamodel", \
+ "XSDataCommon": "kernel/datamodel", \
+}
+
+try:
+ from XSDataCommon import XSDataBoolean
+ from XSDataCommon import XSDataDouble
+ from XSDataCommon import XSDataFile
+ from XSDataCommon import XSDataInput
+ from XSDataCommon import XSDataInteger
+ from XSDataCommon import XSDataResult
+ from XSDataCommon import XSDataString
+ from XSDataCommon import XSDataAngle
+except ImportError as error:
+ if strEdnaHome is not None:
+ for strXsdName in dictLocation:
+ strXsdModule = strXsdName + ".py"
+ strRootdir = os.path.dirname(os.path.abspath(os.path.join(strEdnaHome, dictLocation[strXsdName])))
+ for strRoot, listDirs, listFiles in os.walk(strRootdir):
+ if strXsdModule in listFiles:
+ sys.path.append(strRoot)
+ else:
+ raise error
+from XSDataCommon import XSDataBoolean
+from XSDataCommon import XSDataDouble
+from XSDataCommon import XSDataFile
+from XSDataCommon import XSDataInput
+from XSDataCommon import XSDataInteger
+from XSDataCommon import XSDataResult
+from XSDataCommon import XSDataString
+from XSDataCommon import XSDataAngle
+
+
+
+
+#
+# Support/utility functions.
+#
+
+# Compabiltity between Python 2 and 3:
+if sys.version.startswith('3'):
+ unicode = str
+ from io import StringIO
+else:
+ from StringIO import StringIO
+
+
+def showIndent(outfile, level):
+ for idx in range(level):
+ outfile.write(unicode(' '))
+
+
+def warnEmptyAttribute(_strName, _strTypeName):
+ pass
+ #if not _strTypeName in ["float", "double", "string", "boolean", "integer"]:
+ # print("Warning! Non-optional attribute %s of type %s is None!" % (_strName, _strTypeName))
+
+class MixedContainer(object):
+ # Constants for category:
+ CategoryNone = 0
+ CategoryText = 1
+ CategorySimple = 2
+ CategoryComplex = 3
+ # Constants for content_type:
+ TypeNone = 0
+ TypeText = 1
+ TypeString = 2
+ TypeInteger = 3
+ TypeFloat = 4
+ TypeDecimal = 5
+ TypeDouble = 6
+ TypeBoolean = 7
+ def __init__(self, category, content_type, name, value):
+ self.category = category
+ self.content_type = content_type
+ self.name = name
+ self.value = value
+ def getCategory(self):
+ return self.category
+ def getContenttype(self, content_type):
+ return self.content_type
+ def getValue(self):
+ return self.value
+ def getName(self):
+ return self.name
+ def export(self, outfile, level, name):
+ if self.category == MixedContainer.CategoryText:
+ outfile.write(self.value)
+ elif self.category == MixedContainer.CategorySimple:
+ self.exportSimple(outfile, level, name)
+ else: # category == MixedContainer.CategoryComplex
+ self.value.export(outfile, level, name)
+ def exportSimple(self, outfile, level, name):
+ if self.content_type == MixedContainer.TypeString:
+ outfile.write(unicode('<%s>%s%s>' % (self.name, self.value, self.name)))
+ elif self.content_type == MixedContainer.TypeInteger or \
+ self.content_type == MixedContainer.TypeBoolean:
+ outfile.write(unicode('<%s>%d%s>' % (self.name, self.value, self.name)))
+ elif self.content_type == MixedContainer.TypeFloat or \
+ self.content_type == MixedContainer.TypeDecimal:
+ outfile.write(unicode('<%s>%f%s>' % (self.name, self.value, self.name)))
+ elif self.content_type == MixedContainer.TypeDouble:
+ outfile.write(unicode('<%s>%g%s>' % (self.name, self.value, self.name)))
+
+#
+# Data representation classes.
+#
+
+
+
+class XSDataControlImageDozor(object):
+ def __init__(self, angle=None, spotFile=None, visibleResolution=None, spotScore=None, mainScore=None, powderWilsonRfactor=None, powderWilsonCorrelation=None, powderWilsonResolution=None, powderWilsonBfactor=None, powderWilsonScale=None, spotsResolution=None, spotsIntAver=None, spotsNumOf=None, image=None, number=None):
+ if number is None:
+ self._number = None
+ elif number.__class__.__name__ == "XSDataInteger":
+ self._number = number
+ else:
+ strMessage = "ERROR! XSDataControlImageDozor constructor argument 'number' is not XSDataInteger but %s" % self._number.__class__.__name__
+ raise BaseException(strMessage)
+ if image is None:
+ self._image = None
+ elif image.__class__.__name__ == "XSDataFile":
+ self._image = image
+ else:
+ strMessage = "ERROR! XSDataControlImageDozor constructor argument 'image' is not XSDataFile but %s" % self._image.__class__.__name__
+ raise BaseException(strMessage)
+ if spotsNumOf is None:
+ self._spotsNumOf = None
+ elif spotsNumOf.__class__.__name__ == "XSDataInteger":
+ self._spotsNumOf = spotsNumOf
+ else:
+ strMessage = "ERROR! XSDataControlImageDozor constructor argument 'spotsNumOf' is not XSDataInteger but %s" % self._spotsNumOf.__class__.__name__
+ raise BaseException(strMessage)
+ if spotsIntAver is None:
+ self._spotsIntAver = None
+ elif spotsIntAver.__class__.__name__ == "XSDataDouble":
+ self._spotsIntAver = spotsIntAver
+ else:
+ strMessage = "ERROR! XSDataControlImageDozor constructor argument 'spotsIntAver' is not XSDataDouble but %s" % self._spotsIntAver.__class__.__name__
+ raise BaseException(strMessage)
+ if spotsResolution is None:
+ self._spotsResolution = None
+ elif spotsResolution.__class__.__name__ == "XSDataDouble":
+ self._spotsResolution = spotsResolution
+ else:
+ strMessage = "ERROR! XSDataControlImageDozor constructor argument 'spotsResolution' is not XSDataDouble but %s" % self._spotsResolution.__class__.__name__
+ raise BaseException(strMessage)
+ if powderWilsonScale is None:
+ self._powderWilsonScale = None
+ elif powderWilsonScale.__class__.__name__ == "XSDataDouble":
+ self._powderWilsonScale = powderWilsonScale
+ else:
+ strMessage = "ERROR! XSDataControlImageDozor constructor argument 'powderWilsonScale' is not XSDataDouble but %s" % self._powderWilsonScale.__class__.__name__
+ raise BaseException(strMessage)
+ if powderWilsonBfactor is None:
+ self._powderWilsonBfactor = None
+ elif powderWilsonBfactor.__class__.__name__ == "XSDataDouble":
+ self._powderWilsonBfactor = powderWilsonBfactor
+ else:
+ strMessage = "ERROR! XSDataControlImageDozor constructor argument 'powderWilsonBfactor' is not XSDataDouble but %s" % self._powderWilsonBfactor.__class__.__name__
+ raise BaseException(strMessage)
+ if powderWilsonResolution is None:
+ self._powderWilsonResolution = None
+ elif powderWilsonResolution.__class__.__name__ == "XSDataDouble":
+ self._powderWilsonResolution = powderWilsonResolution
+ else:
+ strMessage = "ERROR! XSDataControlImageDozor constructor argument 'powderWilsonResolution' is not XSDataDouble but %s" % self._powderWilsonResolution.__class__.__name__
+ raise BaseException(strMessage)
+ if powderWilsonCorrelation is None:
+ self._powderWilsonCorrelation = None
+ elif powderWilsonCorrelation.__class__.__name__ == "XSDataDouble":
+ self._powderWilsonCorrelation = powderWilsonCorrelation
+ else:
+ strMessage = "ERROR! XSDataControlImageDozor constructor argument 'powderWilsonCorrelation' is not XSDataDouble but %s" % self._powderWilsonCorrelation.__class__.__name__
+ raise BaseException(strMessage)
+ if powderWilsonRfactor is None:
+ self._powderWilsonRfactor = None
+ elif powderWilsonRfactor.__class__.__name__ == "XSDataDouble":
+ self._powderWilsonRfactor = powderWilsonRfactor
+ else:
+ strMessage = "ERROR! XSDataControlImageDozor constructor argument 'powderWilsonRfactor' is not XSDataDouble but %s" % self._powderWilsonRfactor.__class__.__name__
+ raise BaseException(strMessage)
+ if mainScore is None:
+ self._mainScore = None
+ elif mainScore.__class__.__name__ == "XSDataDouble":
+ self._mainScore = mainScore
+ else:
+ strMessage = "ERROR! XSDataControlImageDozor constructor argument 'mainScore' is not XSDataDouble but %s" % self._mainScore.__class__.__name__
+ raise BaseException(strMessage)
+ if spotScore is None:
+ self._spotScore = None
+ elif spotScore.__class__.__name__ == "XSDataDouble":
+ self._spotScore = spotScore
+ else:
+ strMessage = "ERROR! XSDataControlImageDozor constructor argument 'spotScore' is not XSDataDouble but %s" % self._spotScore.__class__.__name__
+ raise BaseException(strMessage)
+ if visibleResolution is None:
+ self._visibleResolution = None
+ elif visibleResolution.__class__.__name__ == "XSDataDouble":
+ self._visibleResolution = visibleResolution
+ else:
+ strMessage = "ERROR! XSDataControlImageDozor constructor argument 'visibleResolution' is not XSDataDouble but %s" % self._visibleResolution.__class__.__name__
+ raise BaseException(strMessage)
+ if spotFile is None:
+ self._spotFile = None
+ elif spotFile.__class__.__name__ == "XSDataFile":
+ self._spotFile = spotFile
+ else:
+ strMessage = "ERROR! XSDataControlImageDozor constructor argument 'spotFile' is not XSDataFile but %s" % self._spotFile.__class__.__name__
+ raise BaseException(strMessage)
+ if angle is None:
+ self._angle = None
+ elif angle.__class__.__name__ == "XSDataAngle":
+ self._angle = angle
+ else:
+ strMessage = "ERROR! XSDataControlImageDozor constructor argument 'angle' is not XSDataAngle but %s" % self._angle.__class__.__name__
+ raise BaseException(strMessage)
+ # Methods and properties for the 'number' attribute
+ def getNumber(self): return self._number
+ def setNumber(self, number):
+ if number is None:
+ self._number = None
+ elif number.__class__.__name__ == "XSDataInteger":
+ self._number = number
+ else:
+ strMessage = "ERROR! XSDataControlImageDozor.setNumber argument is not XSDataInteger but %s" % number.__class__.__name__
+ raise BaseException(strMessage)
+ def delNumber(self): self._number = None
+ number = property(getNumber, setNumber, delNumber, "Property for number")
+ # Methods and properties for the 'image' attribute
+ def getImage(self): return self._image
+ def setImage(self, image):
+ if image is None:
+ self._image = None
+ elif image.__class__.__name__ == "XSDataFile":
+ self._image = image
+ else:
+ strMessage = "ERROR! XSDataControlImageDozor.setImage argument is not XSDataFile but %s" % image.__class__.__name__
+ raise BaseException(strMessage)
+ def delImage(self): self._image = None
+ image = property(getImage, setImage, delImage, "Property for image")
+ # Methods and properties for the 'spotsNumOf' attribute
+ def getSpotsNumOf(self): return self._spotsNumOf
+ def setSpotsNumOf(self, spotsNumOf):
+ if spotsNumOf is None:
+ self._spotsNumOf = None
+ elif spotsNumOf.__class__.__name__ == "XSDataInteger":
+ self._spotsNumOf = spotsNumOf
+ else:
+ strMessage = "ERROR! XSDataControlImageDozor.setSpotsNumOf argument is not XSDataInteger but %s" % spotsNumOf.__class__.__name__
+ raise BaseException(strMessage)
+ def delSpotsNumOf(self): self._spotsNumOf = None
+ spotsNumOf = property(getSpotsNumOf, setSpotsNumOf, delSpotsNumOf, "Property for spotsNumOf")
+ # Methods and properties for the 'spotsIntAver' attribute
+ def getSpotsIntAver(self): return self._spotsIntAver
+ def setSpotsIntAver(self, spotsIntAver):
+ if spotsIntAver is None:
+ self._spotsIntAver = None
+ elif spotsIntAver.__class__.__name__ == "XSDataDouble":
+ self._spotsIntAver = spotsIntAver
+ else:
+ strMessage = "ERROR! XSDataControlImageDozor.setSpotsIntAver argument is not XSDataDouble but %s" % spotsIntAver.__class__.__name__
+ raise BaseException(strMessage)
+ def delSpotsIntAver(self): self._spotsIntAver = None
+ spotsIntAver = property(getSpotsIntAver, setSpotsIntAver, delSpotsIntAver, "Property for spotsIntAver")
+ # Methods and properties for the 'spotsResolution' attribute
+ def getSpotsResolution(self): return self._spotsResolution
+ def setSpotsResolution(self, spotsResolution):
+ if spotsResolution is None:
+ self._spotsResolution = None
+ elif spotsResolution.__class__.__name__ == "XSDataDouble":
+ self._spotsResolution = spotsResolution
+ else:
+ strMessage = "ERROR! XSDataControlImageDozor.setSpotsResolution argument is not XSDataDouble but %s" % spotsResolution.__class__.__name__
+ raise BaseException(strMessage)
+ def delSpotsResolution(self): self._spotsResolution = None
+ spotsResolution = property(getSpotsResolution, setSpotsResolution, delSpotsResolution, "Property for spotsResolution")
+ # Methods and properties for the 'powderWilsonScale' attribute
+ def getPowderWilsonScale(self): return self._powderWilsonScale
+ def setPowderWilsonScale(self, powderWilsonScale):
+ if powderWilsonScale is None:
+ self._powderWilsonScale = None
+ elif powderWilsonScale.__class__.__name__ == "XSDataDouble":
+ self._powderWilsonScale = powderWilsonScale
+ else:
+ strMessage = "ERROR! XSDataControlImageDozor.setPowderWilsonScale argument is not XSDataDouble but %s" % powderWilsonScale.__class__.__name__
+ raise BaseException(strMessage)
+ def delPowderWilsonScale(self): self._powderWilsonScale = None
+ powderWilsonScale = property(getPowderWilsonScale, setPowderWilsonScale, delPowderWilsonScale, "Property for powderWilsonScale")
+ # Methods and properties for the 'powderWilsonBfactor' attribute
+ def getPowderWilsonBfactor(self): return self._powderWilsonBfactor
+ def setPowderWilsonBfactor(self, powderWilsonBfactor):
+ if powderWilsonBfactor is None:
+ self._powderWilsonBfactor = None
+ elif powderWilsonBfactor.__class__.__name__ == "XSDataDouble":
+ self._powderWilsonBfactor = powderWilsonBfactor
+ else:
+ strMessage = "ERROR! XSDataControlImageDozor.setPowderWilsonBfactor argument is not XSDataDouble but %s" % powderWilsonBfactor.__class__.__name__
+ raise BaseException(strMessage)
+ def delPowderWilsonBfactor(self): self._powderWilsonBfactor = None
+ powderWilsonBfactor = property(getPowderWilsonBfactor, setPowderWilsonBfactor, delPowderWilsonBfactor, "Property for powderWilsonBfactor")
+ # Methods and properties for the 'powderWilsonResolution' attribute
+ def getPowderWilsonResolution(self): return self._powderWilsonResolution
+ def setPowderWilsonResolution(self, powderWilsonResolution):
+ if powderWilsonResolution is None:
+ self._powderWilsonResolution = None
+ elif powderWilsonResolution.__class__.__name__ == "XSDataDouble":
+ self._powderWilsonResolution = powderWilsonResolution
+ else:
+ strMessage = "ERROR! XSDataControlImageDozor.setPowderWilsonResolution argument is not XSDataDouble but %s" % powderWilsonResolution.__class__.__name__
+ raise BaseException(strMessage)
+ def delPowderWilsonResolution(self): self._powderWilsonResolution = None
+ powderWilsonResolution = property(getPowderWilsonResolution, setPowderWilsonResolution, delPowderWilsonResolution, "Property for powderWilsonResolution")
+ # Methods and properties for the 'powderWilsonCorrelation' attribute
+ def getPowderWilsonCorrelation(self): return self._powderWilsonCorrelation
+ def setPowderWilsonCorrelation(self, powderWilsonCorrelation):
+ if powderWilsonCorrelation is None:
+ self._powderWilsonCorrelation = None
+ elif powderWilsonCorrelation.__class__.__name__ == "XSDataDouble":
+ self._powderWilsonCorrelation = powderWilsonCorrelation
+ else:
+ strMessage = "ERROR! XSDataControlImageDozor.setPowderWilsonCorrelation argument is not XSDataDouble but %s" % powderWilsonCorrelation.__class__.__name__
+ raise BaseException(strMessage)
+ def delPowderWilsonCorrelation(self): self._powderWilsonCorrelation = None
+ powderWilsonCorrelation = property(getPowderWilsonCorrelation, setPowderWilsonCorrelation, delPowderWilsonCorrelation, "Property for powderWilsonCorrelation")
+ # Methods and properties for the 'powderWilsonRfactor' attribute
+ def getPowderWilsonRfactor(self): return self._powderWilsonRfactor
+ def setPowderWilsonRfactor(self, powderWilsonRfactor):
+ if powderWilsonRfactor is None:
+ self._powderWilsonRfactor = None
+ elif powderWilsonRfactor.__class__.__name__ == "XSDataDouble":
+ self._powderWilsonRfactor = powderWilsonRfactor
+ else:
+ strMessage = "ERROR! XSDataControlImageDozor.setPowderWilsonRfactor argument is not XSDataDouble but %s" % powderWilsonRfactor.__class__.__name__
+ raise BaseException(strMessage)
+ def delPowderWilsonRfactor(self): self._powderWilsonRfactor = None
+ powderWilsonRfactor = property(getPowderWilsonRfactor, setPowderWilsonRfactor, delPowderWilsonRfactor, "Property for powderWilsonRfactor")
+ # Methods and properties for the 'mainScore' attribute
+ def getMainScore(self): return self._mainScore
+ def setMainScore(self, mainScore):
+ if mainScore is None:
+ self._mainScore = None
+ elif mainScore.__class__.__name__ == "XSDataDouble":
+ self._mainScore = mainScore
+ else:
+ strMessage = "ERROR! XSDataControlImageDozor.setMainScore argument is not XSDataDouble but %s" % mainScore.__class__.__name__
+ raise BaseException(strMessage)
+ def delMainScore(self): self._mainScore = None
+ mainScore = property(getMainScore, setMainScore, delMainScore, "Property for mainScore")
+ # Methods and properties for the 'spotScore' attribute
+ def getSpotScore(self): return self._spotScore
+ def setSpotScore(self, spotScore):
+ if spotScore is None:
+ self._spotScore = None
+ elif spotScore.__class__.__name__ == "XSDataDouble":
+ self._spotScore = spotScore
+ else:
+ strMessage = "ERROR! XSDataControlImageDozor.setSpotScore argument is not XSDataDouble but %s" % spotScore.__class__.__name__
+ raise BaseException(strMessage)
+ def delSpotScore(self): self._spotScore = None
+ spotScore = property(getSpotScore, setSpotScore, delSpotScore, "Property for spotScore")
+ # Methods and properties for the 'visibleResolution' attribute
+ def getVisibleResolution(self): return self._visibleResolution
+ def setVisibleResolution(self, visibleResolution):
+ if visibleResolution is None:
+ self._visibleResolution = None
+ elif visibleResolution.__class__.__name__ == "XSDataDouble":
+ self._visibleResolution = visibleResolution
+ else:
+ strMessage = "ERROR! XSDataControlImageDozor.setVisibleResolution argument is not XSDataDouble but %s" % visibleResolution.__class__.__name__
+ raise BaseException(strMessage)
+ def delVisibleResolution(self): self._visibleResolution = None
+ visibleResolution = property(getVisibleResolution, setVisibleResolution, delVisibleResolution, "Property for visibleResolution")
+ # Methods and properties for the 'spotFile' attribute
+ def getSpotFile(self): return self._spotFile
+ def setSpotFile(self, spotFile):
+ if spotFile is None:
+ self._spotFile = None
+ elif spotFile.__class__.__name__ == "XSDataFile":
+ self._spotFile = spotFile
+ else:
+ strMessage = "ERROR! XSDataControlImageDozor.setSpotFile argument is not XSDataFile but %s" % spotFile.__class__.__name__
+ raise BaseException(strMessage)
+ def delSpotFile(self): self._spotFile = None
+ spotFile = property(getSpotFile, setSpotFile, delSpotFile, "Property for spotFile")
+ # Methods and properties for the 'angle' attribute
+ def getAngle(self): return self._angle
+ def setAngle(self, angle):
+ if angle is None:
+ self._angle = None
+ elif angle.__class__.__name__ == "XSDataAngle":
+ self._angle = angle
+ else:
+ strMessage = "ERROR! XSDataControlImageDozor.setAngle argument is not XSDataAngle but %s" % angle.__class__.__name__
+ raise BaseException(strMessage)
+ def delAngle(self): self._angle = None
+ angle = property(getAngle, setAngle, delAngle, "Property for angle")
+ def export(self, outfile, level, name_='XSDataControlImageDozor'):
+ showIndent(outfile, level)
+ outfile.write(unicode('<%s>\n' % name_))
+ self.exportChildren(outfile, level + 1, name_)
+ showIndent(outfile, level)
+ outfile.write(unicode('%s>\n' % name_))
+ def exportChildren(self, outfile, level, name_='XSDataControlImageDozor'):
+ pass
+ if self._number is not None:
+ self.number.export(outfile, level, name_='number')
+ else:
+ warnEmptyAttribute("number", "XSDataInteger")
+ if self._image is not None:
+ self.image.export(outfile, level, name_='image')
+ else:
+ warnEmptyAttribute("image", "XSDataFile")
+ if self._spotsNumOf is not None:
+ self.spotsNumOf.export(outfile, level, name_='spotsNumOf')
+ else:
+ warnEmptyAttribute("spotsNumOf", "XSDataInteger")
+ if self._spotsIntAver is not None:
+ self.spotsIntAver.export(outfile, level, name_='spotsIntAver')
+ else:
+ warnEmptyAttribute("spotsIntAver", "XSDataDouble")
+ if self._spotsResolution is not None:
+ self.spotsResolution.export(outfile, level, name_='spotsResolution')
+ if self._powderWilsonScale is not None:
+ self.powderWilsonScale.export(outfile, level, name_='powderWilsonScale')
+ if self._powderWilsonBfactor is not None:
+ self.powderWilsonBfactor.export(outfile, level, name_='powderWilsonBfactor')
+ if self._powderWilsonResolution is not None:
+ self.powderWilsonResolution.export(outfile, level, name_='powderWilsonResolution')
+ if self._powderWilsonCorrelation is not None:
+ self.powderWilsonCorrelation.export(outfile, level, name_='powderWilsonCorrelation')
+ if self._powderWilsonRfactor is not None:
+ self.powderWilsonRfactor.export(outfile, level, name_='powderWilsonRfactor')
+ if self._mainScore is not None:
+ self.mainScore.export(outfile, level, name_='mainScore')
+ if self._spotScore is not None:
+ self.spotScore.export(outfile, level, name_='spotScore')
+ if self._visibleResolution is not None:
+ self.visibleResolution.export(outfile, level, name_='visibleResolution')
+ if self._spotFile is not None:
+ self.spotFile.export(outfile, level, name_='spotFile')
+ if self._angle is not None:
+ self.angle.export(outfile, level, name_='angle')
+ def build(self, node_):
+ for child_ in node_.childNodes:
+ nodeName_ = child_.nodeName.split(':')[-1]
+ self.buildChildren(child_, nodeName_)
+ def buildChildren(self, child_, nodeName_):
+ if child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'number':
+ obj_ = XSDataInteger()
+ obj_.build(child_)
+ self.setNumber(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'image':
+ obj_ = XSDataFile()
+ obj_.build(child_)
+ self.setImage(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'spotsNumOf':
+ obj_ = XSDataInteger()
+ obj_.build(child_)
+ self.setSpotsNumOf(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'spotsIntAver':
+ obj_ = XSDataDouble()
+ obj_.build(child_)
+ self.setSpotsIntAver(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'spotsResolution':
+ obj_ = XSDataDouble()
+ obj_.build(child_)
+ self.setSpotsResolution(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'powderWilsonScale':
+ obj_ = XSDataDouble()
+ obj_.build(child_)
+ self.setPowderWilsonScale(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'powderWilsonBfactor':
+ obj_ = XSDataDouble()
+ obj_.build(child_)
+ self.setPowderWilsonBfactor(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'powderWilsonResolution':
+ obj_ = XSDataDouble()
+ obj_.build(child_)
+ self.setPowderWilsonResolution(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'powderWilsonCorrelation':
+ obj_ = XSDataDouble()
+ obj_.build(child_)
+ self.setPowderWilsonCorrelation(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'powderWilsonRfactor':
+ obj_ = XSDataDouble()
+ obj_.build(child_)
+ self.setPowderWilsonRfactor(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'mainScore':
+ obj_ = XSDataDouble()
+ obj_.build(child_)
+ self.setMainScore(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'spotScore':
+ obj_ = XSDataDouble()
+ obj_.build(child_)
+ self.setSpotScore(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'visibleResolution':
+ obj_ = XSDataDouble()
+ obj_.build(child_)
+ self.setVisibleResolution(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'spotFile':
+ obj_ = XSDataFile()
+ obj_.build(child_)
+ self.setSpotFile(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'angle':
+ obj_ = XSDataAngle()
+ obj_.build(child_)
+ self.setAngle(obj_)
+ #Method for marshalling an object
+ def marshal( self ):
+ oStreamString = StringIO()
+ oStreamString.write(unicode('\n'))
+ self.export( oStreamString, 0, name_="XSDataControlImageDozor" )
+ oStringXML = oStreamString.getvalue()
+ oStreamString.close()
+ return oStringXML
+ #Only to export the entire XML tree to a file stream on disk
+ def exportToFile( self, _outfileName ):
+ outfile = open( _outfileName, "w" )
+ outfile.write(unicode('\n'))
+ self.export( outfile, 0, name_='XSDataControlImageDozor' )
+ outfile.close()
+ #Deprecated method, replaced by exportToFile
+ def outputFile( self, _outfileName ):
+ print("WARNING: Method outputFile in class XSDataControlImageDozor is deprecated, please use instead exportToFile!")
+ self.exportToFile(_outfileName)
+ #Method for making a copy in a new instance
+ def copy( self ):
+ return XSDataControlImageDozor.parseString(self.marshal())
+ #Static method for parsing a string
+ def parseString( _inString ):
+ doc = minidom.parseString(_inString)
+ rootNode = doc.documentElement
+ rootObj = XSDataControlImageDozor()
+ rootObj.build(rootNode)
+ # Check that all minOccurs are obeyed by marshalling the created object
+ oStreamString = StringIO()
+ rootObj.export( oStreamString, 0, name_="XSDataControlImageDozor" )
+ oStreamString.close()
+ return rootObj
+ parseString = staticmethod( parseString )
+ #Static method for parsing a file
+ def parseFile( _inFilePath ):
+ doc = minidom.parse(_inFilePath)
+ rootNode = doc.documentElement
+ rootObj = XSDataControlImageDozor()
+ rootObj.build(rootNode)
+ return rootObj
+ parseFile = staticmethod( parseFile )
+# end class XSDataControlImageDozor
+
+
+class XSDataDozorInput(XSDataInput):
+ def __init__(self, configuration=None, nameTemplateImage=None, numberImages=None, firstImageNumber=None, startingAngle=None, imageStep=None,
+ oscillationRange=None, orgy=None, orgx=None, fractionPolarization=None, wavelength=None, detectorDistance=None, spotSize=None, exposureTime=None, detectorType=None,
+ ):
+ XSDataInput.__init__(self, configuration)
+ if detectorType is None:
+ self._detectorType = None
+ elif detectorType.__class__.__name__ == "XSDataString":
+ self._detectorType = detectorType
+ else:
+ strMessage = "ERROR! XSDataDozorInput constructor argument 'detectorType' is not XSDataString but %s" % self._detectorType.__class__.__name__
+ raise BaseException(strMessage)
+ if exposureTime is None:
+ self._exposureTime = None
+ elif exposureTime.__class__.__name__ == "XSDataDouble":
+ self._exposureTime = exposureTime
+ else:
+ strMessage = "ERROR! XSDataDozorInput constructor argument 'exposureTime' is not XSDataDouble but %s" % self._exposureTime.__class__.__name__
+ raise BaseException(strMessage)
+ if spotSize is None:
+ self._spotSize = None
+ elif spotSize.__class__.__name__ == "XSDataInteger":
+ self._spotSize = spotSize
+ else:
+ strMessage = "ERROR! XSDataDozorInput constructor argument 'spotSize' is not XSDataInteger but %s" % self._spotSize.__class__.__name__
+ raise BaseException(strMessage)
+ if detectorDistance is None:
+ self._detectorDistance = None
+ elif detectorDistance.__class__.__name__ == "XSDataDouble":
+ self._detectorDistance = detectorDistance
+ else:
+ strMessage = "ERROR! XSDataDozorInput constructor argument 'detectorDistance' is not XSDataDouble but %s" % self._detectorDistance.__class__.__name__
+ raise BaseException(strMessage)
+ if wavelength is None:
+ self._wavelength = None
+ elif wavelength.__class__.__name__ == "XSDataDouble":
+ self._wavelength = wavelength
+ else:
+ strMessage = "ERROR! XSDataDozorInput constructor argument 'wavelength' is not XSDataDouble but %s" % self._wavelength.__class__.__name__
+ raise BaseException(strMessage)
+ if fractionPolarization is None:
+ self._fractionPolarization = None
+ elif fractionPolarization.__class__.__name__ == "XSDataDouble":
+ self._fractionPolarization = fractionPolarization
+ else:
+ strMessage = "ERROR! XSDataDozorInput constructor argument 'fractionPolarization' is not XSDataDouble but %s" % self._fractionPolarization.__class__.__name__
+ raise BaseException(strMessage)
+ if orgx is None:
+ self._orgx = None
+ elif orgx.__class__.__name__ == "XSDataDouble":
+ self._orgx = orgx
+ else:
+ strMessage = "ERROR! XSDataDozorInput constructor argument 'orgx' is not XSDataDouble but %s" % self._orgx.__class__.__name__
+ raise BaseException(strMessage)
+ if orgy is None:
+ self._orgy = None
+ elif orgy.__class__.__name__ == "XSDataDouble":
+ self._orgy = orgy
+ else:
+ strMessage = "ERROR! XSDataDozorInput constructor argument 'orgy' is not XSDataDouble but %s" % self._orgy.__class__.__name__
+ raise BaseException(strMessage)
+ if oscillationRange is None:
+ self._oscillationRange = None
+ elif oscillationRange.__class__.__name__ == "XSDataDouble":
+ self._oscillationRange = oscillationRange
+ else:
+ strMessage = "ERROR! XSDataDozorInput constructor argument 'oscillationRange' is not XSDataDouble but %s" % self._oscillationRange.__class__.__name__
+ raise BaseException(strMessage)
+ if imageStep is None:
+ self._imageStep = None
+ elif imageStep.__class__.__name__ == "XSDataDouble":
+ self._imageStep = imageStep
+ else:
+ strMessage = "ERROR! XSDataDozorInput constructor argument 'imageStep' is not XSDataDouble but %s" % self._imageStep.__class__.__name__
+ raise BaseException(strMessage)
+ if startingAngle is None:
+ self._startingAngle = None
+ elif startingAngle.__class__.__name__ == "XSDataDouble":
+ self._startingAngle = startingAngle
+ else:
+ strMessage = "ERROR! XSDataDozorInput constructor argument 'startingAngle' is not XSDataDouble but %s" % self._startingAngle.__class__.__name__
+ raise BaseException(strMessage)
+ if firstImageNumber is None:
+ self._firstImageNumber = None
+ elif firstImageNumber.__class__.__name__ == "XSDataInteger":
+ self._firstImageNumber = firstImageNumber
+ else:
+ strMessage = "ERROR! XSDataDozorInput constructor argument 'firstImageNumber' is not XSDataInteger but %s" % self._firstImageNumber.__class__.__name__
+ raise BaseException(strMessage)
+ if numberImages is None:
+ self._numberImages = None
+ elif numberImages.__class__.__name__ == "XSDataInteger":
+ self._numberImages = numberImages
+ else:
+ strMessage = "ERROR! XSDataDozorInput constructor argument 'numberImages' is not XSDataInteger but %s" % self._numberImages.__class__.__name__
+ raise BaseException(strMessage)
+ if nameTemplateImage is None:
+ self._nameTemplateImage = None
+ elif nameTemplateImage.__class__.__name__ == "XSDataString":
+ self._nameTemplateImage = nameTemplateImage
+ else:
+ strMessage = "ERROR! XSDataDozorInput constructor argument 'nameTemplateImage' is not XSDataString but %s" % self._nameTemplateImage.__class__.__name__
+ raise BaseException(strMessage)
+ # Methods and properties for the 'detectorType' attribute
+ def getDetectorType(self): return self._detectorType
+ def setDetectorType(self, detectorType):
+ if detectorType is None:
+ self._detectorType = None
+ elif detectorType.__class__.__name__ == "XSDataString":
+ self._detectorType = detectorType
+ else:
+ strMessage = "ERROR! XSDataDozorInput.setDetectorType argument is not XSDataString but %s" % detectorType.__class__.__name__
+ raise BaseException(strMessage)
+ def delDetectorType(self): self._detectorType = None
+ detectorType = property(getDetectorType, setDetectorType, delDetectorType, "Property for detectorType")
+ # Methods and properties for the 'exposureTime' attribute
+ def getExposureTime(self): return self._exposureTime
+ def setExposureTime(self, exposureTime):
+ if exposureTime is None:
+ self._exposureTime = None
+ elif exposureTime.__class__.__name__ == "XSDataDouble":
+ self._exposureTime = exposureTime
+ else:
+ strMessage = "ERROR! XSDataDozorInput.setExposureTime argument is not XSDataDouble but %s" % exposureTime.__class__.__name__
+ raise BaseException(strMessage)
+ def delExposureTime(self): self._exposureTime = None
+ exposureTime = property(getExposureTime, setExposureTime, delExposureTime, "Property for exposureTime")
+ # Methods and properties for the 'spotSize' attribute
+ def getSpotSize(self): return self._spotSize
+ def setSpotSize(self, spotSize):
+ if spotSize is None:
+ self._spotSize = None
+ elif spotSize.__class__.__name__ == "XSDataInteger":
+ self._spotSize = spotSize
+ else:
+ strMessage = "ERROR! XSDataDozorInput.setSpotSize argument is not XSDataInteger but %s" % spotSize.__class__.__name__
+ raise BaseException(strMessage)
+ def delSpotSize(self): self._spotSize = None
+ spotSize = property(getSpotSize, setSpotSize, delSpotSize, "Property for spotSize")
+ # Methods and properties for the 'detectorDistance' attribute
+ def getDetectorDistance(self): return self._detectorDistance
+ def setDetectorDistance(self, detectorDistance):
+ if detectorDistance is None:
+ self._detectorDistance = None
+ elif detectorDistance.__class__.__name__ == "XSDataDouble":
+ self._detectorDistance = detectorDistance
+ else:
+ strMessage = "ERROR! XSDataDozorInput.setDetectorDistance argument is not XSDataDouble but %s" % detectorDistance.__class__.__name__
+ raise BaseException(strMessage)
+ def delDetectorDistance(self): self._detectorDistance = None
+ detectorDistance = property(getDetectorDistance, setDetectorDistance, delDetectorDistance, "Property for detectorDistance")
+ # Methods and properties for the 'wavelength' attribute
+ def getWavelength(self): return self._wavelength
+ def setWavelength(self, wavelength):
+ if wavelength is None:
+ self._wavelength = None
+ elif wavelength.__class__.__name__ == "XSDataDouble":
+ self._wavelength = wavelength
+ else:
+ strMessage = "ERROR! XSDataDozorInput.setWavelength argument is not XSDataDouble but %s" % wavelength.__class__.__name__
+ raise BaseException(strMessage)
+ def delWavelength(self): self._wavelength = None
+ wavelength = property(getWavelength, setWavelength, delWavelength, "Property for wavelength")
+ # Methods and properties for the 'fractionPolarization' attribute
+ def getFractionPolarization(self): return self._fractionPolarization
+ def setFractionPolarization(self, fractionPolarization):
+ if fractionPolarization is None:
+ self._fractionPolarization = None
+ elif fractionPolarization.__class__.__name__ == "XSDataDouble":
+ self._fractionPolarization = fractionPolarization
+ else:
+ strMessage = "ERROR! XSDataDozorInput.setFractionPolarization argument is not XSDataDouble but %s" % fractionPolarization.__class__.__name__
+ raise BaseException(strMessage)
+ def delFractionPolarization(self): self._fractionPolarization = None
+ fractionPolarization = property(getFractionPolarization, setFractionPolarization, delFractionPolarization, "Property for fractionPolarization")
+ # Methods and properties for the 'orgx' attribute
+ def getOrgx(self): return self._orgx
+ def setOrgx(self, orgx):
+ if orgx is None:
+ self._orgx = None
+ elif orgx.__class__.__name__ == "XSDataDouble":
+ self._orgx = orgx
+ else:
+ strMessage = "ERROR! XSDataDozorInput.setOrgx argument is not XSDataDouble but %s" % orgx.__class__.__name__
+ raise BaseException(strMessage)
+ def delOrgx(self): self._orgx = None
+ orgx = property(getOrgx, setOrgx, delOrgx, "Property for orgx")
+ # Methods and properties for the 'orgy' attribute
+ def getOrgy(self): return self._orgy
+ def setOrgy(self, orgy):
+ if orgy is None:
+ self._orgy = None
+ elif orgy.__class__.__name__ == "XSDataDouble":
+ self._orgy = orgy
+ else:
+ strMessage = "ERROR! XSDataDozorInput.setOrgy argument is not XSDataDouble but %s" % orgy.__class__.__name__
+ raise BaseException(strMessage)
+ def delOrgy(self): self._orgy = None
+ orgy = property(getOrgy, setOrgy, delOrgy, "Property for orgy")
+ # Methods and properties for the 'oscillationRange' attribute
+ def getOscillationRange(self): return self._oscillationRange
+ def setOscillationRange(self, oscillationRange):
+ if oscillationRange is None:
+ self._oscillationRange = None
+ elif oscillationRange.__class__.__name__ == "XSDataDouble":
+ self._oscillationRange = oscillationRange
+ else:
+ strMessage = "ERROR! XSDataDozorInput.setOscillationRange argument is not XSDataDouble but %s" % oscillationRange.__class__.__name__
+ raise BaseException(strMessage)
+ def delOscillationRange(self): self._oscillationRange = None
+ oscillationRange = property(getOscillationRange, setOscillationRange, delOscillationRange, "Property for oscillationRange")
+ # Methods and properties for the 'imageStep' attribute
+ def getImageStep(self): return self._imageStep
+ def setImageStep(self, imageStep):
+ if imageStep is None:
+ self._imageStep = None
+ elif imageStep.__class__.__name__ == "XSDataDouble":
+ self._imageStep = imageStep
+ else:
+ strMessage = "ERROR! XSDataDozorInput.setImageStep argument is not XSDataDouble but %s" % imageStep.__class__.__name__
+ raise BaseException(strMessage)
+ def delImageStep(self): self._imageStep = None
+ imageStep = property(getImageStep, setImageStep, delImageStep, "Property for imageStep")
+ # Methods and properties for the 'startingAngle' attribute
+ def getStartingAngle(self): return self._startingAngle
+ def setStartingAngle(self, startingAngle):
+ if startingAngle is None:
+ self._startingAngle = None
+ elif startingAngle.__class__.__name__ == "XSDataDouble":
+ self._startingAngle = startingAngle
+ else:
+ strMessage = "ERROR! XSDataDozorInput.setStartingAngle argument is not XSDataDouble but %s" % startingAngle.__class__.__name__
+ raise BaseException(strMessage)
+ def delStartingAngle(self): self._startingAngle = None
+ startingAngle = property(getStartingAngle, setStartingAngle, delStartingAngle, "Property for startingAngle")
+ # Methods and properties for the 'firstImageNumber' attribute
+ def getFirstImageNumber(self): return self._firstImageNumber
+ def setFirstImageNumber(self, firstImageNumber):
+ if firstImageNumber is None:
+ self._firstImageNumber = None
+ elif firstImageNumber.__class__.__name__ == "XSDataInteger":
+ self._firstImageNumber = firstImageNumber
+ else:
+ strMessage = "ERROR! XSDataDozorInput.setFirstImageNumber argument is not XSDataInteger but %s" % firstImageNumber.__class__.__name__
+ raise BaseException(strMessage)
+ def delFirstImageNumber(self): self._firstImageNumber = None
+ firstImageNumber = property(getFirstImageNumber, setFirstImageNumber, delFirstImageNumber, "Property for firstImageNumber")
+ # Methods and properties for the 'numberImages' attribute
+ def getNumberImages(self): return self._numberImages
+ def setNumberImages(self, numberImages):
+ if numberImages is None:
+ self._numberImages = None
+ elif numberImages.__class__.__name__ == "XSDataInteger":
+ self._numberImages = numberImages
+ else:
+ strMessage = "ERROR! XSDataDozorInput.setNumberImages argument is not XSDataInteger but %s" % numberImages.__class__.__name__
+ raise BaseException(strMessage)
+ def delNumberImages(self): self._numberImages = None
+ numberImages = property(getNumberImages, setNumberImages, delNumberImages, "Property for numberImages")
+ # Methods and properties for the 'nameTemplateImage' attribute
+ def getNameTemplateImage(self): return self._nameTemplateImage
+ def setNameTemplateImage(self, nameTemplateImage):
+ if nameTemplateImage is None:
+ self._nameTemplateImage = None
+ elif nameTemplateImage.__class__.__name__ == "XSDataString":
+ self._nameTemplateImage = nameTemplateImage
+ else:
+ strMessage = "ERROR! XSDataDozorInput.setNameTemplateImage argument is not XSDataString but %s" % nameTemplateImage.__class__.__name__
+ raise BaseException(strMessage)
+ def delNameTemplateImage(self): self._nameTemplateImage = None
+ nameTemplateImage = property(getNameTemplateImage, setNameTemplateImage, delNameTemplateImage, "Property for nameTemplateImage")
+
+ def export(self, outfile, level, name_='XSDataDozorInput'):
+ showIndent(outfile, level)
+ outfile.write(unicode('<%s>\n' % name_))
+ self.exportChildren(outfile, level + 1, name_)
+ showIndent(outfile, level)
+ outfile.write(unicode('%s>\n' % name_))
+ def exportChildren(self, outfile, level, name_='XSDataDozorInput'):
+ XSDataInput.exportChildren(self, outfile, level, name_)
+ if self._detectorType is not None:
+ self.detectorType.export(outfile, level, name_='detectorType')
+ else:
+ warnEmptyAttribute("detectorType", "XSDataString")
+ if self._exposureTime is not None:
+ self.exposureTime.export(outfile, level, name_='exposureTime')
+ else:
+ warnEmptyAttribute("exposureTime", "XSDataDouble")
+ if self._spotSize is not None:
+ self.spotSize.export(outfile, level, name_='spotSize')
+ else:
+ warnEmptyAttribute("spotSize", "XSDataInteger")
+ if self._detectorDistance is not None:
+ self.detectorDistance.export(outfile, level, name_='detectorDistance')
+ else:
+ warnEmptyAttribute("detectorDistance", "XSDataDouble")
+ if self._wavelength is not None:
+ self.wavelength.export(outfile, level, name_='wavelength')
+ else:
+ warnEmptyAttribute("wavelength", "XSDataDouble")
+ if self._fractionPolarization is not None:
+ self.fractionPolarization.export(outfile, level, name_='fractionPolarization')
+ if self._orgx is not None:
+ self.orgx.export(outfile, level, name_='orgx')
+ else:
+ warnEmptyAttribute("orgx", "XSDataDouble")
+ if self._orgy is not None:
+ self.orgy.export(outfile, level, name_='orgy')
+ else:
+ warnEmptyAttribute("orgy", "XSDataDouble")
+ if self._oscillationRange is not None:
+ self.oscillationRange.export(outfile, level, name_='oscillationRange')
+ else:
+ warnEmptyAttribute("oscillationRange", "XSDataDouble")
+ if self._imageStep is not None:
+ self.imageStep.export(outfile, level, name_='imageStep')
+ if self._startingAngle is not None:
+ self.startingAngle.export(outfile, level, name_='startingAngle')
+ if self._firstImageNumber is not None:
+ self.firstImageNumber.export(outfile, level, name_='firstImageNumber')
+ else:
+ warnEmptyAttribute("firstImageNumber", "XSDataInteger")
+ if self._numberImages is not None:
+ self.numberImages.export(outfile, level, name_='numberImages')
+ else:
+ warnEmptyAttribute("numberImages", "XSDataInteger")
+ if self._nameTemplateImage is not None:
+ self.nameTemplateImage.export(outfile, level, name_='nameTemplateImage')
+ else:
+ warnEmptyAttribute("nameTemplateImage", "XSDataString")
+
+ def build(self, node_):
+ for child_ in node_.childNodes:
+ nodeName_ = child_.nodeName.split(':')[-1]
+ self.buildChildren(child_, nodeName_)
+ def buildChildren(self, child_, nodeName_):
+ if child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'detectorType':
+ obj_ = XSDataString()
+ obj_.build(child_)
+ self.setDetectorType(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'exposureTime':
+ obj_ = XSDataDouble()
+ obj_.build(child_)
+ self.setExposureTime(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'spotSize':
+ obj_ = XSDataInteger()
+ obj_.build(child_)
+ self.setSpotSize(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'detectorDistance':
+ obj_ = XSDataDouble()
+ obj_.build(child_)
+ self.setDetectorDistance(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'wavelength':
+ obj_ = XSDataDouble()
+ obj_.build(child_)
+ self.setWavelength(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'fractionPolarization':
+ obj_ = XSDataDouble()
+ obj_.build(child_)
+ self.setFractionPolarization(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'orgx':
+ obj_ = XSDataDouble()
+ obj_.build(child_)
+ self.setOrgx(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'orgy':
+ obj_ = XSDataDouble()
+ obj_.build(child_)
+ self.setOrgy(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'oscillationRange':
+ obj_ = XSDataDouble()
+ obj_.build(child_)
+ self.setOscillationRange(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'imageStep':
+ obj_ = XSDataDouble()
+ obj_.build(child_)
+ self.setImageStep(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'startingAngle':
+ obj_ = XSDataDouble()
+ obj_.build(child_)
+ self.setStartingAngle(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'firstImageNumber':
+ obj_ = XSDataInteger()
+ obj_.build(child_)
+ self.setFirstImageNumber(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'numberImages':
+ obj_ = XSDataInteger()
+ obj_.build(child_)
+ self.setNumberImages(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'nameTemplateImage':
+ obj_ = XSDataString()
+ obj_.build(child_)
+ self.setNameTemplateImage(obj_)
+ XSDataInput.buildChildren(self, child_, nodeName_)
+ #Method for marshalling an object
+ def marshal( self ):
+ oStreamString = StringIO()
+ oStreamString.write(unicode('\n'))
+ self.export( oStreamString, 0, name_="XSDataDozorInput" )
+ oStringXML = oStreamString.getvalue()
+ oStreamString.close()
+ return oStringXML
+ #Only to export the entire XML tree to a file stream on disk
+ def exportToFile( self, _outfileName ):
+ outfile = open( _outfileName, "w" )
+ outfile.write(unicode('\n'))
+ self.export( outfile, 0, name_='XSDataDozorInput' )
+ outfile.close()
+ #Deprecated method, replaced by exportToFile
+ def outputFile( self, _outfileName ):
+ print("WARNING: Method outputFile in class XSDataDozorInput is deprecated, please use instead exportToFile!")
+ self.exportToFile(_outfileName)
+ #Method for making a copy in a new instance
+ def copy( self ):
+ return XSDataDozorInput.parseString(self.marshal())
+ #Static method for parsing a string
+ def parseString( _inString ):
+ doc = minidom.parseString(_inString)
+ rootNode = doc.documentElement
+ rootObj = XSDataDozorInput()
+ rootObj.build(rootNode)
+ # Check that all minOccurs are obeyed by marshalling the created object
+ oStreamString = StringIO()
+ rootObj.export( oStreamString, 0, name_="XSDataDozorInput" )
+ oStreamString.close()
+ return rootObj
+ parseString = staticmethod( parseString )
+ #Static method for parsing a file
+ def parseFile( _inFilePath ):
+ doc = minidom.parse(_inFilePath)
+ rootNode = doc.documentElement
+ rootObj = XSDataDozorInput()
+ rootObj.build(rootNode)
+ return rootObj
+ parseFile = staticmethod( parseFile )
+# end class XSDataDozorInput
+
+
+class XSDataInputControlDozor(XSDataInput):
+ def __init__(self, configuration=None, keepCbfTmpDirectory=None, radiationDamage=None, wedgeNumber=None,
+ hdf5BatchSize=None, batchSize=None, endNo=None, startNo=None, template=None, directory=None, image=None, processDirectory=None, dataCollectionId=None,
+ doISPyBUpload=None
+ ):
+ XSDataInput.__init__(self, configuration)
+ if dataCollectionId is None:
+ self._dataCollectionId = None
+ elif dataCollectionId.__class__.__name__ == "XSDataInteger":
+ self._dataCollectionId = dataCollectionId
+ else:
+ strMessage = "ERROR! XSDataInputControlDozor constructor argument 'dataCollectionId' is not XSDataInteger but %s" % self._dataCollectionId.__class__.__name__
+ raise BaseException(strMessage)
+ if processDirectory is None:
+ self._processDirectory = None
+ elif processDirectory.__class__.__name__ == "XSDataFile":
+ self._processDirectory = processDirectory
+ else:
+ strMessage = "ERROR! XSDataInputControlDozor constructor argument 'processDirectory' is not XSDataFile but %s" % self._processDirectory.__class__.__name__
+ raise BaseException(strMessage)
+ if image is None:
+ self._image = []
+ elif image.__class__.__name__ == "list":
+ self._image = image
+ else:
+ strMessage = "ERROR! XSDataInputControlDozor constructor argument 'image' is not list but %s" % self._image.__class__.__name__
+ raise BaseException(strMessage)
+ if directory is None:
+ self._directory = None
+ elif directory.__class__.__name__ == "XSDataFile":
+ self._directory = directory
+ else:
+ strMessage = "ERROR! XSDataInputControlDozor constructor argument 'directory' is not XSDataFile but %s" % self._directory.__class__.__name__
+ raise BaseException(strMessage)
+ if template is None:
+ self._template = None
+ elif template.__class__.__name__ == "XSDataString":
+ self._template = template
+ else:
+ strMessage = "ERROR! XSDataInputControlDozor constructor argument 'template' is not XSDataString but %s" % self._template.__class__.__name__
+ raise BaseException(strMessage)
+ if startNo is None:
+ self._startNo = None
+ elif startNo.__class__.__name__ == "XSDataInteger":
+ self._startNo = startNo
+ else:
+ strMessage = "ERROR! XSDataInputControlDozor constructor argument 'startNo' is not XSDataInteger but %s" % self._startNo.__class__.__name__
+ raise BaseException(strMessage)
+ if endNo is None:
+ self._endNo = None
+ elif endNo.__class__.__name__ == "XSDataInteger":
+ self._endNo = endNo
+ else:
+ strMessage = "ERROR! XSDataInputControlDozor constructor argument 'endNo' is not XSDataInteger but %s" % self._endNo.__class__.__name__
+ raise BaseException(strMessage)
+ if batchSize is None:
+ self._batchSize = None
+ elif batchSize.__class__.__name__ == "XSDataInteger":
+ self._batchSize = batchSize
+ else:
+ strMessage = "ERROR! XSDataInputControlDozor constructor argument 'batchSize' is not XSDataInteger but %s" % self._batchSize.__class__.__name__
+ raise BaseException(strMessage)
+ if hdf5BatchSize is None:
+ self._hdf5BatchSize = None
+ elif hdf5BatchSize.__class__.__name__ == "XSDataInteger":
+ self._hdf5BatchSize = hdf5BatchSize
+ else:
+ strMessage = "ERROR! XSDataInputControlDozor constructor argument 'hdf5BatchSize' is not XSDataInteger but %s" % self._hdf5BatchSize.__class__.__name__
+ raise BaseException(strMessage)
+ if wedgeNumber is None:
+ self._wedgeNumber = None
+ elif wedgeNumber.__class__.__name__ == "XSDataInteger":
+ self._wedgeNumber = wedgeNumber
+ else:
+ strMessage = "ERROR! XSDataInputControlDozor constructor argument 'wedgeNumber' is not XSDataInteger but %s" % self._wedgeNumber.__class__.__name__
+ raise BaseException(strMessage)
+ if radiationDamage is None:
+ self._radiationDamage = None
+ elif radiationDamage.__class__.__name__ == "XSDataBoolean":
+ self._radiationDamage = radiationDamage
+ else:
+ strMessage = "ERROR! XSDataInputControlDozor constructor argument 'radiationDamage' is not XSDataBoolean but %s" % self._radiationDamage.__class__.__name__
+ raise BaseException(strMessage)
+ if keepCbfTmpDirectory is None:
+ self._keepCbfTmpDirectory = None
+ elif keepCbfTmpDirectory.__class__.__name__ == "XSDataBoolean":
+ self._keepCbfTmpDirectory = keepCbfTmpDirectory
+ else:
+ strMessage = "ERROR! XSDataInputControlDozor constructor argument 'keepCbfTmpDirectory' is not XSDataBoolean but %s" % self._keepCbfTmpDirectory.__class__.__name__
+ raise BaseException(strMessage)
+ if doISPyBUpload is None:
+ self._doISPyBUpload = None
+ elif doISPyBUpload.__class__.__name__ == "XSDataBoolean":
+ self._doISPyBUpload = doISPyBUpload
+ else:
+ strMessage = (
+ "ERROR! XSDataControlImageDozor constructor argument 'doISPyBUpload' is not XSDataBoolean but %s"
+ % self._doISPyBUpload.__class__.__name__
+ )
+ raise Exception(strMessage)
+ # Methods and properties for the 'dataCollectionId' attribute
+ def getDataCollectionId(self): return self._dataCollectionId
+ def setDataCollectionId(self, dataCollectionId):
+ if dataCollectionId is None:
+ self._dataCollectionId = None
+ elif dataCollectionId.__class__.__name__ == "XSDataInteger":
+ self._dataCollectionId = dataCollectionId
+ else:
+ strMessage = "ERROR! XSDataInputControlDozor.setDataCollectionId argument is not XSDataInteger but %s" % dataCollectionId.__class__.__name__
+ raise BaseException(strMessage)
+ def delDataCollectionId(self): self._dataCollectionId = None
+ dataCollectionId = property(getDataCollectionId, setDataCollectionId, delDataCollectionId, "Property for dataCollectionId")
+ # Methods and properties for the 'processDirectory' attribute
+ def getProcessDirectory(self): return self._processDirectory
+ def setProcessDirectory(self, processDirectory):
+ if processDirectory is None:
+ self._processDirectory = None
+ elif processDirectory.__class__.__name__ == "XSDataFile":
+ self._processDirectory = processDirectory
+ else:
+ strMessage = "ERROR! XSDataInputControlDozor.setProcessDirectory argument is not XSDataFile but %s" % processDirectory.__class__.__name__
+ raise BaseException(strMessage)
+ def delProcessDirectory(self): self._processDirectory = None
+ processDirectory = property(getProcessDirectory, setProcessDirectory, delProcessDirectory, "Property for processDirectory")
+ # Methods and properties for the 'image' attribute
+ def getImage(self): return self._image
+ def setImage(self, image):
+ if image is None:
+ self._image = []
+ elif image.__class__.__name__ == "list":
+ self._image = image
+ else:
+ strMessage = "ERROR! XSDataInputControlDozor.setImage argument is not list but %s" % image.__class__.__name__
+ raise BaseException(strMessage)
+ def delImage(self): self._image = None
+ image = property(getImage, setImage, delImage, "Property for image")
+ def addImage(self, value):
+ if value is None:
+ strMessage = "ERROR! XSDataInputControlDozor.addImage argument is None"
+ raise BaseException(strMessage)
+ elif value.__class__.__name__ == "XSDataFile":
+ self._image.append(value)
+ else:
+ strMessage = "ERROR! XSDataInputControlDozor.addImage argument is not XSDataFile but %s" % value.__class__.__name__
+ raise BaseException(strMessage)
+ def insertImage(self, index, value):
+ if index is None:
+ strMessage = "ERROR! XSDataInputControlDozor.insertImage argument 'index' is None"
+ raise BaseException(strMessage)
+ if value is None:
+ strMessage = "ERROR! XSDataInputControlDozor.insertImage argument 'value' is None"
+ raise BaseException(strMessage)
+ elif value.__class__.__name__ == "XSDataFile":
+ self._image[index] = value
+ else:
+ strMessage = "ERROR! XSDataInputControlDozor.addImage argument is not XSDataFile but %s" % value.__class__.__name__
+ raise BaseException(strMessage)
+ # Methods and properties for the 'directory' attribute
+ def getDirectory(self): return self._directory
+ def setDirectory(self, directory):
+ if directory is None:
+ self._directory = None
+ elif directory.__class__.__name__ == "XSDataFile":
+ self._directory = directory
+ else:
+ strMessage = "ERROR! XSDataInputControlDozor.setDirectory argument is not XSDataFile but %s" % directory.__class__.__name__
+ raise BaseException(strMessage)
+ def delDirectory(self): self._directory = None
+ directory = property(getDirectory, setDirectory, delDirectory, "Property for directory")
+ # Methods and properties for the 'template' attribute
+ def getTemplate(self): return self._template
+ def setTemplate(self, template):
+ if template is None:
+ self._template = None
+ elif template.__class__.__name__ == "XSDataString":
+ self._template = template
+ else:
+ strMessage = "ERROR! XSDataInputControlDozor.setTemplate argument is not XSDataString but %s" % template.__class__.__name__
+ raise BaseException(strMessage)
+ def delTemplate(self): self._template = None
+ template = property(getTemplate, setTemplate, delTemplate, "Property for template")
+ # Methods and properties for the 'startNo' attribute
+ def getStartNo(self): return self._startNo
+ def setStartNo(self, startNo):
+ if startNo is None:
+ self._startNo = None
+ elif startNo.__class__.__name__ == "XSDataInteger":
+ self._startNo = startNo
+ else:
+ strMessage = "ERROR! XSDataInputControlDozor.setStartNo argument is not XSDataInteger but %s" % startNo.__class__.__name__
+ raise BaseException(strMessage)
+ def delStartNo(self): self._startNo = None
+ startNo = property(getStartNo, setStartNo, delStartNo, "Property for startNo")
+ # Methods and properties for the 'endNo' attribute
+ def getEndNo(self): return self._endNo
+ def setEndNo(self, endNo):
+ if endNo is None:
+ self._endNo = None
+ elif endNo.__class__.__name__ == "XSDataInteger":
+ self._endNo = endNo
+ else:
+ strMessage = "ERROR! XSDataInputControlDozor.setEndNo argument is not XSDataInteger but %s" % endNo.__class__.__name__
+ raise BaseException(strMessage)
+ def delEndNo(self): self._endNo = None
+ endNo = property(getEndNo, setEndNo, delEndNo, "Property for endNo")
+ # Methods and properties for the 'batchSize' attribute
+ def getBatchSize(self): return self._batchSize
+ def setBatchSize(self, batchSize):
+ if batchSize is None:
+ self._batchSize = None
+ elif batchSize.__class__.__name__ == "XSDataInteger":
+ self._batchSize = batchSize
+ else:
+ strMessage = "ERROR! XSDataInputControlDozor.setBatchSize argument is not XSDataInteger but %s" % batchSize.__class__.__name__
+ raise BaseException(strMessage)
+ def delBatchSize(self): self._batchSize = None
+ batchSize = property(getBatchSize, setBatchSize, delBatchSize, "Property for batchSize")
+ # Methods and properties for the 'hdf5BatchSize' attribute
+ def getHdf5BatchSize(self): return self._hdf5BatchSize
+ def setHdf5BatchSize(self, hdf5BatchSize):
+ if hdf5BatchSize is None:
+ self._hdf5BatchSize = None
+ elif hdf5BatchSize.__class__.__name__ == "XSDataInteger":
+ self._hdf5BatchSize = hdf5BatchSize
+ else:
+ strMessage = "ERROR! XSDataInputControlDozor.setHdf5BatchSize argument is not XSDataInteger but %s" % hdf5BatchSize.__class__.__name__
+ raise BaseException(strMessage)
+ def delHdf5BatchSize(self): self._hdf5BatchSize = None
+ hdf5BatchSize = property(getHdf5BatchSize, setHdf5BatchSize, delHdf5BatchSize, "Property for hdf5BatchSize")
+ # Methods and properties for the 'wedgeNumber' attribute
+ def getWedgeNumber(self): return self._wedgeNumber
+ def setWedgeNumber(self, wedgeNumber):
+ if wedgeNumber is None:
+ self._wedgeNumber = None
+ elif wedgeNumber.__class__.__name__ == "XSDataInteger":
+ self._wedgeNumber = wedgeNumber
+ else:
+ strMessage = "ERROR! XSDataInputControlDozor.setWedgeNumber argument is not XSDataInteger but %s" % wedgeNumber.__class__.__name__
+ raise BaseException(strMessage)
+ def delWedgeNumber(self): self._wedgeNumber = None
+ wedgeNumber = property(getWedgeNumber, setWedgeNumber, delWedgeNumber, "Property for wedgeNumber")
+ # Methods and properties for the 'radiationDamage' attribute
+ def getRadiationDamage(self): return self._radiationDamage
+ def setRadiationDamage(self, radiationDamage):
+ if radiationDamage is None:
+ self._radiationDamage = None
+ elif radiationDamage.__class__.__name__ == "XSDataBoolean":
+ self._radiationDamage = radiationDamage
+ else:
+ strMessage = "ERROR! XSDataInputControlDozor.setRadiationDamage argument is not XSDataBoolean but %s" % radiationDamage.__class__.__name__
+ raise BaseException(strMessage)
+ def delRadiationDamage(self): self._radiationDamage = None
+ radiationDamage = property(getRadiationDamage, setRadiationDamage, delRadiationDamage, "Property for radiationDamage")
+ # Methods and properties for the 'keepCbfTmpDirectory' attribute
+ def getKeepCbfTmpDirectory(self): return self._keepCbfTmpDirectory
+ def setKeepCbfTmpDirectory(self, keepCbfTmpDirectory):
+ if keepCbfTmpDirectory is None:
+ self._keepCbfTmpDirectory = None
+ elif keepCbfTmpDirectory.__class__.__name__ == "XSDataBoolean":
+ self._keepCbfTmpDirectory = keepCbfTmpDirectory
+ else:
+ strMessage = "ERROR! XSDataInputControlDozor.setKeepCbfTmpDirectory argument is not XSDataBoolean but %s" % keepCbfTmpDirectory.__class__.__name__
+ raise BaseException(strMessage)
+ def delKeepCbfTmpDirectory(self): self._keepCbfTmpDirectory = None
+ keepCbfTmpDirectory = property(getKeepCbfTmpDirectory, setKeepCbfTmpDirectory, delKeepCbfTmpDirectory, "Property for keepCbfTmpDirectory")
+ # Methods and properties for the 'doISPyBUpload' attribute
+ def getDoISPyBUpload(self):
+ return self._doISPyBUpload
+
+ def setDoISPyBUpload(self, doISPyBUpload):
+ if doISPyBUpload is None:
+ self._doISPyBUpload = None
+ elif doISPyBUpload.__class__.__name__ == "XSDataBoolean":
+ self._doISPyBUpload = doISPyBUpload
+ else:
+ strMessage = (
+ "ERROR! XSDataInputControlDozor.setDoISPyBUpload argument is not XSDataBoolean but %s"
+ % doISPyBUpload.__class__.__name__
+ )
+ raise Exception(strMessage)
+ def delDoISPyBUpload(self):
+ self._doISPyBUpload = None
+ doISPyBUpload = property(
+ getDoISPyBUpload,
+ setDoISPyBUpload,
+ delDoISPyBUpload,
+ "Property for doISPyBUpload",
+ )
+
+ def export(self, outfile, level, name_='XSDataInputControlDozor'):
+ showIndent(outfile, level)
+ outfile.write(unicode('<%s>\n' % name_))
+ self.exportChildren(outfile, level + 1, name_)
+ showIndent(outfile, level)
+ outfile.write(unicode('%s>\n' % name_))
+ def exportChildren(self, outfile, level, name_='XSDataInputControlDozor'):
+ XSDataInput.exportChildren(self, outfile, level, name_)
+ if self._dataCollectionId is not None:
+ self.dataCollectionId.export(outfile, level, name_='dataCollectionId')
+ if self._processDirectory is not None:
+ self.processDirectory.export(outfile, level, name_='processDirectory')
+ for image_ in self.getImage():
+ image_.export(outfile, level, name_='image')
+ if self._directory is not None:
+ self.directory.export(outfile, level, name_='directory')
+ if self._template is not None:
+ self.template.export(outfile, level, name_='template')
+ if self._startNo is not None:
+ self.startNo.export(outfile, level, name_='startNo')
+ if self._endNo is not None:
+ self.endNo.export(outfile, level, name_='endNo')
+ if self._batchSize is not None:
+ self.batchSize.export(outfile, level, name_='batchSize')
+ if self._hdf5BatchSize is not None:
+ self.hdf5BatchSize.export(outfile, level, name_='hdf5BatchSize')
+ if self._wedgeNumber is not None:
+ self.wedgeNumber.export(outfile, level, name_='wedgeNumber')
+ if self._radiationDamage is not None:
+ self.radiationDamage.export(outfile, level, name_='radiationDamage')
+ if self._keepCbfTmpDirectory is not None:
+ self.keepCbfTmpDirectory.export(outfile, level, name_='keepCbfTmpDirectory')
+ if self._doISPyBUpload is not None:
+ self.doISPyBUpload.export(outfile, level, name_="doISPyBUpload")
+ def build(self, node_):
+ for child_ in node_.childNodes:
+ nodeName_ = child_.nodeName.split(':')[-1]
+ self.buildChildren(child_, nodeName_)
+ def buildChildren(self, child_, nodeName_):
+ if child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'dataCollectionId':
+ obj_ = XSDataInteger()
+ obj_.build(child_)
+ self.setDataCollectionId(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'processDirectory':
+ obj_ = XSDataFile()
+ obj_.build(child_)
+ self.setProcessDirectory(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'image':
+ obj_ = XSDataFile()
+ obj_.build(child_)
+ self.image.append(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'directory':
+ obj_ = XSDataFile()
+ obj_.build(child_)
+ self.setDirectory(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'template':
+ obj_ = XSDataString()
+ obj_.build(child_)
+ self.setTemplate(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'startNo':
+ obj_ = XSDataInteger()
+ obj_.build(child_)
+ self.setStartNo(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'endNo':
+ obj_ = XSDataInteger()
+ obj_.build(child_)
+ self.setEndNo(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'batchSize':
+ obj_ = XSDataInteger()
+ obj_.build(child_)
+ self.setBatchSize(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'hdf5BatchSize':
+ obj_ = XSDataInteger()
+ obj_.build(child_)
+ self.setHdf5BatchSize(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'wedgeNumber':
+ obj_ = XSDataInteger()
+ obj_.build(child_)
+ self.setWedgeNumber(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'radiationDamage':
+ obj_ = XSDataBoolean()
+ obj_.build(child_)
+ self.setRadiationDamage(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'keepCbfTmpDirectory':
+ obj_ = XSDataBoolean()
+ obj_.build(child_)
+ self.setKeepCbfTmpDirectory(obj_)
+ elif (
+ child_.nodeType == Node.ELEMENT_NODE
+ and nodeName_ == "doISPyBUpload"
+ ):
+ obj_ = XSDataBoolean()
+ obj_.build(child_)
+ self.setScore(obj_)
+ XSDataInput.buildChildren(self, child_, nodeName_)
+ #Method for marshalling an object
+ def marshal( self ):
+ oStreamString = StringIO()
+ oStreamString.write(unicode('\n'))
+ self.export( oStreamString, 0, name_="XSDataInputControlDozor" )
+ oStringXML = oStreamString.getvalue()
+ oStreamString.close()
+ return oStringXML
+ #Only to export the entire XML tree to a file stream on disk
+ def exportToFile( self, _outfileName ):
+ outfile = open( _outfileName, "w" )
+ outfile.write(unicode('\n'))
+ self.export( outfile, 0, name_='XSDataInputControlDozor' )
+ outfile.close()
+ #Deprecated method, replaced by exportToFile
+ def outputFile( self, _outfileName ):
+ print("WARNING: Method outputFile in class XSDataInputControlDozor is deprecated, please use instead exportToFile!")
+ self.exportToFile(_outfileName)
+ #Method for making a copy in a new instance
+ def copy( self ):
+ return XSDataInputControlDozor.parseString(self.marshal())
+ #Static method for parsing a string
+ def parseString( _inString ):
+ doc = minidom.parseString(_inString)
+ rootNode = doc.documentElement
+ rootObj = XSDataInputControlDozor()
+ rootObj.build(rootNode)
+ # Check that all minOccurs are obeyed by marshalling the created object
+ oStreamString = StringIO()
+ rootObj.export( oStreamString, 0, name_="XSDataInputControlDozor" )
+ oStreamString.close()
+ return rootObj
+ parseString = staticmethod( parseString )
+ #Static method for parsing a file
+ def parseFile( _inFilePath ):
+ doc = minidom.parse(_inFilePath)
+ rootNode = doc.documentElement
+ rootObj = XSDataInputControlDozor()
+ rootObj.build(rootNode)
+ return rootObj
+ parseFile = staticmethod( parseFile )
+# end class XSDataInputControlDozor
+
+
+class XSDataResultControlDozor(XSDataResult):
+ def __init__(self, status=None, pngPlots=None, pathToCbfDirectory=None, dozorPlot=None, halfDoseTime=None, inputDozor=None, imageDozor=None):
+ XSDataResult.__init__(self, status)
+ if imageDozor is None:
+ self._imageDozor = []
+ elif imageDozor.__class__.__name__ == "list":
+ self._imageDozor = imageDozor
+ else:
+ strMessage = "ERROR! XSDataResultControlDozor constructor argument 'imageDozor' is not list but %s" % self._imageDozor.__class__.__name__
+ raise BaseException(strMessage)
+ if inputDozor is None:
+ self._inputDozor = None
+ elif inputDozor.__class__.__name__ == "XSDataDozorInput":
+ self._inputDozor = inputDozor
+ else:
+ strMessage = "ERROR! XSDataResultControlDozor constructor argument 'inputDozor' is not XSDataDozorInput but %s" % self._inputDozor.__class__.__name__
+ raise BaseException(strMessage)
+ if halfDoseTime is None:
+ self._halfDoseTime = None
+ elif halfDoseTime.__class__.__name__ == "XSDataDouble":
+ self._halfDoseTime = halfDoseTime
+ else:
+ strMessage = "ERROR! XSDataResultControlDozor constructor argument 'halfDoseTime' is not XSDataDouble but %s" % self._halfDoseTime.__class__.__name__
+ raise BaseException(strMessage)
+ if dozorPlot is None:
+ self._dozorPlot = None
+ elif dozorPlot.__class__.__name__ == "XSDataFile":
+ self._dozorPlot = dozorPlot
+ else:
+ strMessage = "ERROR! XSDataResultControlDozor constructor argument 'dozorPlot' is not XSDataFile but %s" % self._dozorPlot.__class__.__name__
+ raise BaseException(strMessage)
+ if pathToCbfDirectory is None:
+ self._pathToCbfDirectory = None
+ elif pathToCbfDirectory.__class__.__name__ == "XSDataFile":
+ self._pathToCbfDirectory = pathToCbfDirectory
+ else:
+ strMessage = "ERROR! XSDataResultControlDozor constructor argument 'pathToCbfDirectory' is not XSDataFile but %s" % self._pathToCbfDirectory.__class__.__name__
+ raise BaseException(strMessage)
+ if pngPlots is None:
+ self._pngPlots = []
+ elif pngPlots.__class__.__name__ == "list":
+ self._pngPlots = pngPlots
+ else:
+ strMessage = "ERROR! XSDataResultControlDozor constructor argument 'pngPlots' is not list but %s" % self._pngPlots.__class__.__name__
+ raise BaseException(strMessage)
+ # Methods and properties for the 'imageDozor' attribute
+ def getImageDozor(self): return self._imageDozor
+ def setImageDozor(self, imageDozor):
+ if imageDozor is None:
+ self._imageDozor = []
+ elif imageDozor.__class__.__name__ == "list":
+ self._imageDozor = imageDozor
+ else:
+ strMessage = "ERROR! XSDataResultControlDozor.setImageDozor argument is not list but %s" % imageDozor.__class__.__name__
+ raise BaseException(strMessage)
+ def delImageDozor(self): self._imageDozor = None
+ imageDozor = property(getImageDozor, setImageDozor, delImageDozor, "Property for imageDozor")
+ def addImageDozor(self, value):
+ if value is None:
+ strMessage = "ERROR! XSDataResultControlDozor.addImageDozor argument is None"
+ raise BaseException(strMessage)
+ elif value.__class__.__name__ == "XSDataControlImageDozor":
+ self._imageDozor.append(value)
+ else:
+ strMessage = "ERROR! XSDataResultControlDozor.addImageDozor argument is not XSDataControlImageDozor but %s" % value.__class__.__name__
+ raise BaseException(strMessage)
+ def insertImageDozor(self, index, value):
+ if index is None:
+ strMessage = "ERROR! XSDataResultControlDozor.insertImageDozor argument 'index' is None"
+ raise BaseException(strMessage)
+ if value is None:
+ strMessage = "ERROR! XSDataResultControlDozor.insertImageDozor argument 'value' is None"
+ raise BaseException(strMessage)
+ elif value.__class__.__name__ == "XSDataControlImageDozor":
+ self._imageDozor[index] = value
+ else:
+ strMessage = "ERROR! XSDataResultControlDozor.addImageDozor argument is not XSDataControlImageDozor but %s" % value.__class__.__name__
+ raise BaseException(strMessage)
+ # Methods and properties for the 'inputDozor' attribute
+ def getInputDozor(self): return self._inputDozor
+ def setInputDozor(self, inputDozor):
+ if inputDozor is None:
+ self._inputDozor = None
+ elif inputDozor.__class__.__name__ == "XSDataDozorInput":
+ self._inputDozor = inputDozor
+ else:
+ strMessage = "ERROR! XSDataResultControlDozor.setInputDozor argument is not XSDataDozorInput but %s" % inputDozor.__class__.__name__
+ raise BaseException(strMessage)
+ def delInputDozor(self): self._inputDozor = None
+ inputDozor = property(getInputDozor, setInputDozor, delInputDozor, "Property for inputDozor")
+ # Methods and properties for the 'halfDoseTime' attribute
+ def getHalfDoseTime(self): return self._halfDoseTime
+ def setHalfDoseTime(self, halfDoseTime):
+ if halfDoseTime is None:
+ self._halfDoseTime = None
+ elif halfDoseTime.__class__.__name__ == "XSDataDouble":
+ self._halfDoseTime = halfDoseTime
+ else:
+ strMessage = "ERROR! XSDataResultControlDozor.setHalfDoseTime argument is not XSDataDouble but %s" % halfDoseTime.__class__.__name__
+ raise BaseException(strMessage)
+ def delHalfDoseTime(self): self._halfDoseTime = None
+ halfDoseTime = property(getHalfDoseTime, setHalfDoseTime, delHalfDoseTime, "Property for halfDoseTime")
+ # Methods and properties for the 'dozorPlot' attribute
+ def getDozorPlot(self): return self._dozorPlot
+ def setDozorPlot(self, dozorPlot):
+ if dozorPlot is None:
+ self._dozorPlot = None
+ elif dozorPlot.__class__.__name__ == "XSDataFile":
+ self._dozorPlot = dozorPlot
+ else:
+ strMessage = "ERROR! XSDataResultControlDozor.setDozorPlot argument is not XSDataFile but %s" % dozorPlot.__class__.__name__
+ raise BaseException(strMessage)
+ def delDozorPlot(self): self._dozorPlot = None
+ dozorPlot = property(getDozorPlot, setDozorPlot, delDozorPlot, "Property for dozorPlot")
+ # Methods and properties for the 'pathToCbfDirectory' attribute
+ def getPathToCbfDirectory(self): return self._pathToCbfDirectory
+ def setPathToCbfDirectory(self, pathToCbfDirectory):
+ if pathToCbfDirectory is None:
+ self._pathToCbfDirectory = None
+ elif pathToCbfDirectory.__class__.__name__ == "XSDataFile":
+ self._pathToCbfDirectory = pathToCbfDirectory
+ else:
+ strMessage = "ERROR! XSDataResultControlDozor.setPathToCbfDirectory argument is not XSDataFile but %s" % pathToCbfDirectory.__class__.__name__
+ raise BaseException(strMessage)
+ def delPathToCbfDirectory(self): self._pathToCbfDirectory = None
+ pathToCbfDirectory = property(getPathToCbfDirectory, setPathToCbfDirectory, delPathToCbfDirectory, "Property for pathToCbfDirectory")
+ # Methods and properties for the 'pngPlots' attribute
+ def getPngPlots(self): return self._pngPlots
+ def setPngPlots(self, pngPlots):
+ if pngPlots is None:
+ self._pngPlots = []
+ elif pngPlots.__class__.__name__ == "list":
+ self._pngPlots = pngPlots
+ else:
+ strMessage = "ERROR! XSDataResultControlDozor.setPngPlots argument is not list but %s" % pngPlots.__class__.__name__
+ raise BaseException(strMessage)
+ def delPngPlots(self): self._pngPlots = None
+ pngPlots = property(getPngPlots, setPngPlots, delPngPlots, "Property for pngPlots")
+ def addPngPlots(self, value):
+ if value is None:
+ strMessage = "ERROR! XSDataResultControlDozor.addPngPlots argument is None"
+ raise BaseException(strMessage)
+ elif value.__class__.__name__ == "XSDataFile":
+ self._pngPlots.append(value)
+ else:
+ strMessage = "ERROR! XSDataResultControlDozor.addPngPlots argument is not XSDataFile but %s" % value.__class__.__name__
+ raise BaseException(strMessage)
+ def insertPngPlots(self, index, value):
+ if index is None:
+ strMessage = "ERROR! XSDataResultControlDozor.insertPngPlots argument 'index' is None"
+ raise BaseException(strMessage)
+ if value is None:
+ strMessage = "ERROR! XSDataResultControlDozor.insertPngPlots argument 'value' is None"
+ raise BaseException(strMessage)
+ elif value.__class__.__name__ == "XSDataFile":
+ self._pngPlots[index] = value
+ else:
+ strMessage = "ERROR! XSDataResultControlDozor.addPngPlots argument is not XSDataFile but %s" % value.__class__.__name__
+ raise BaseException(strMessage)
+ def export(self, outfile, level, name_='XSDataResultControlDozor'):
+ showIndent(outfile, level)
+ outfile.write(unicode('<%s>\n' % name_))
+ self.exportChildren(outfile, level + 1, name_)
+ showIndent(outfile, level)
+ outfile.write(unicode('%s>\n' % name_))
+ def exportChildren(self, outfile, level, name_='XSDataResultControlDozor'):
+ XSDataResult.exportChildren(self, outfile, level, name_)
+ for imageDozor_ in self.getImageDozor():
+ imageDozor_.export(outfile, level, name_='imageDozor')
+ if self._inputDozor is not None:
+ self.inputDozor.export(outfile, level, name_='inputDozor')
+ if self._halfDoseTime is not None:
+ self.halfDoseTime.export(outfile, level, name_='halfDoseTime')
+ if self._dozorPlot is not None:
+ self.dozorPlot.export(outfile, level, name_='dozorPlot')
+ if self._pathToCbfDirectory is not None:
+ self.pathToCbfDirectory.export(outfile, level, name_='pathToCbfDirectory')
+ for pngPlots_ in self.getPngPlots():
+ pngPlots_.export(outfile, level, name_='pngPlots')
+ def build(self, node_):
+ for child_ in node_.childNodes:
+ nodeName_ = child_.nodeName.split(':')[-1]
+ self.buildChildren(child_, nodeName_)
+ def buildChildren(self, child_, nodeName_):
+ if child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'imageDozor':
+ obj_ = XSDataControlImageDozor()
+ obj_.build(child_)
+ self.imageDozor.append(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'inputDozor':
+ obj_ = XSDataDozorInput()
+ obj_.build(child_)
+ self.setInputDozor(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'halfDoseTime':
+ obj_ = XSDataDouble()
+ obj_.build(child_)
+ self.setHalfDoseTime(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'dozorPlot':
+ obj_ = XSDataFile()
+ obj_.build(child_)
+ self.setDozorPlot(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'pathToCbfDirectory':
+ obj_ = XSDataFile()
+ obj_.build(child_)
+ self.setPathToCbfDirectory(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'pngPlots':
+ obj_ = XSDataFile()
+ obj_.build(child_)
+ self.pngPlots.append(obj_)
+ XSDataResult.buildChildren(self, child_, nodeName_)
+ #Method for marshalling an object
+ def marshal( self ):
+ oStreamString = StringIO()
+ oStreamString.write(unicode('\n'))
+ self.export( oStreamString, 0, name_="XSDataResultControlDozor" )
+ oStringXML = oStreamString.getvalue()
+ oStreamString.close()
+ return oStringXML
+ #Only to export the entire XML tree to a file stream on disk
+ def exportToFile( self, _outfileName ):
+ outfile = open( _outfileName, "w" )
+ outfile.write(unicode('\n'))
+ self.export( outfile, 0, name_='XSDataResultControlDozor' )
+ outfile.close()
+ #Deprecated method, replaced by exportToFile
+ def outputFile( self, _outfileName ):
+ print("WARNING: Method outputFile in class XSDataResultControlDozor is deprecated, please use instead exportToFile!")
+ self.exportToFile(_outfileName)
+ #Method for making a copy in a new instance
+ def copy( self ):
+ return XSDataResultControlDozor.parseString(self.marshal())
+ #Static method for parsing a string
+ def parseString( _inString ):
+ doc = minidom.parseString(_inString)
+ rootNode = doc.documentElement
+ rootObj = XSDataResultControlDozor()
+ rootObj.build(rootNode)
+ # Check that all minOccurs are obeyed by marshalling the created object
+ oStreamString = StringIO()
+ rootObj.export( oStreamString, 0, name_="XSDataResultControlDozor" )
+ oStreamString.close()
+ return rootObj
+ parseString = staticmethod( parseString )
+ #Static method for parsing a file
+ def parseFile( _inFilePath ):
+ doc = minidom.parse(_inFilePath)
+ rootNode = doc.documentElement
+ rootObj = XSDataResultControlDozor()
+ rootObj.build(rootNode)
+ return rootObj
+ parseFile = staticmethod( parseFile )
+# end class XSDataResultControlDozor
+
+
+
+# End of data representation classes.
+
+
diff --git a/mxcubecore/HardwareObjects/ALBA/XalocXSDataControlXia2DIALSv1_0.py b/mxcubecore/HardwareObjects/ALBA/XalocXSDataControlXia2DIALSv1_0.py
new file mode 100644
index 0000000000..15b6da131d
--- /dev/null
+++ b/mxcubecore/HardwareObjects/ALBA/XalocXSDataControlXia2DIALSv1_0.py
@@ -0,0 +1,599 @@
+#!/usr/bin/env python
+
+#
+# Generated Mon Feb 5 08:54::10 2018 by EDGenerateDS.
+#
+
+import os, sys
+from xml.dom import minidom
+from xml.dom import Node
+
+
+strEdnaHome = os.environ.get("EDNA_HOME", None)
+
+dictLocation = { \
+ "XSDataCommon": "kernel/datamodel", \
+ "XSDataCommon": "kernel/datamodel", \
+ "XSDataCommon": "kernel/datamodel", \
+ "XSDataCommon": "kernel/datamodel", \
+ "XSDataCommon": "kernel/datamodel", \
+ "XSDataCommon": "kernel/datamodel", \
+}
+
+try:
+ from XSDataCommon import XSDataBoolean
+ from XSDataCommon import XSDataFile
+ from XSDataCommon import XSDataInput
+ from XSDataCommon import XSDataInteger
+ from XSDataCommon import XSDataResult
+ from XSDataCommon import XSDataString
+except ImportError as error:
+ if strEdnaHome is not None:
+ for strXsdName in dictLocation:
+ strXsdModule = strXsdName + ".py"
+ strRootdir = os.path.dirname(os.path.abspath(os.path.join(strEdnaHome, dictLocation[strXsdName])))
+ for strRoot, listDirs, listFiles in os.walk(strRootdir):
+ if strXsdModule in listFiles:
+ sys.path.append(strRoot)
+ else:
+ raise error
+from XSDataCommon import XSDataBoolean
+from XSDataCommon import XSDataFile
+from XSDataCommon import XSDataInput
+from XSDataCommon import XSDataInteger
+from XSDataCommon import XSDataResult
+from XSDataCommon import XSDataString
+
+
+
+
+#
+# Support/utility functions.
+#
+
+# Compabiltity between Python 2 and 3:
+if sys.version.startswith('3'):
+ unicode = str
+ from io import StringIO
+else:
+ from StringIO import StringIO
+
+
+def showIndent(outfile, level):
+ for idx in range(level):
+ outfile.write(unicode(' '))
+
+
+def warnEmptyAttribute(_strName, _strTypeName):
+ pass
+ #if not _strTypeName in ["float", "double", "string", "boolean", "integer"]:
+ # print("Warning! Non-optional attribute %s of type %s is None!" % (_strName, _strTypeName))
+
+class MixedContainer(object):
+ # Constants for category:
+ CategoryNone = 0
+ CategoryText = 1
+ CategorySimple = 2
+ CategoryComplex = 3
+ # Constants for content_type:
+ TypeNone = 0
+ TypeText = 1
+ TypeString = 2
+ TypeInteger = 3
+ TypeFloat = 4
+ TypeDecimal = 5
+ TypeDouble = 6
+ TypeBoolean = 7
+ def __init__(self, category, content_type, name, value):
+ self.category = category
+ self.content_type = content_type
+ self.name = name
+ self.value = value
+ def getCategory(self):
+ return self.category
+ def getContenttype(self, content_type):
+ return self.content_type
+ def getValue(self):
+ return self.value
+ def getName(self):
+ return self.name
+ def export(self, outfile, level, name):
+ if self.category == MixedContainer.CategoryText:
+ outfile.write(self.value)
+ elif self.category == MixedContainer.CategorySimple:
+ self.exportSimple(outfile, level, name)
+ else: # category == MixedContainer.CategoryComplex
+ self.value.export(outfile, level, name)
+ def exportSimple(self, outfile, level, name):
+ if self.content_type == MixedContainer.TypeString:
+ outfile.write(unicode('<%s>%s%s>' % (self.name, self.value, self.name)))
+ elif self.content_type == MixedContainer.TypeInteger or \
+ self.content_type == MixedContainer.TypeBoolean:
+ outfile.write(unicode('<%s>%d%s>' % (self.name, self.value, self.name)))
+ elif self.content_type == MixedContainer.TypeFloat or \
+ self.content_type == MixedContainer.TypeDecimal:
+ outfile.write(unicode('<%s>%f%s>' % (self.name, self.value, self.name)))
+ elif self.content_type == MixedContainer.TypeDouble:
+ outfile.write(unicode('<%s>%g%s>' % (self.name, self.value, self.name)))
+
+#
+# Data representation classes.
+#
+
+
+
+class XalocXSDataInputXia2DIALS(XSDataInput):
+ def __init__(self,
+ configuration=None,
+ cell=None,
+ symm=None,
+ doAnomAndNonanom=None,
+ processDirectory=None,
+ toN=None,
+ fromN=None,
+ templateN=None,
+ dirN=None,
+ dataCollectionId=None,
+ diffractionImage = None,
+ small_molecule_3dii = None,
+ detector_max_res=None
+ ):
+ XSDataInput.__init__(self, configuration)
+ if dataCollectionId is None:
+ self._dataCollectionId = None
+ elif dataCollectionId.__class__.__name__ == "XSDataInteger":
+ self._dataCollectionId = dataCollectionId
+ else:
+ strMessage = "ERROR! XalocXSDataInputXia2DIALS constructor argument 'dataCollectionId' is not XSDataInteger but %s" % self._dataCollectionId.__class__.__name__
+ raise BaseException(strMessage)
+ if diffractionImage is None:
+ self._diffractionImage = None
+ elif diffractionImage.__class__.__name__ == "XSDataBoolean":
+ self._diffractionImage = diffractionImage
+ else:
+ strMessage = "ERROR! XSDataInputControlAutoPROC constructor argument 'diffractionImage' is not XSDataBoolean but %s" % diffractionImage.__class__.__name__
+ raise BaseException(strMessage)
+ if dirN is None:
+ self._dirN = None
+ elif dirN.__class__.__name__ == "XSDataFile":
+ self._dirN = dirN
+ else:
+ strMessage = "ERROR! XalocXSDataInputXia2DIALS constructor argument 'dirN' is not XSDataFile but %s" % self._dirN.__class__.__name__
+ raise BaseException(strMessage)
+ if templateN is None:
+ self._templateN = None
+ elif templateN.__class__.__name__ == "XSDataString":
+ self._templateN = templateN
+ else:
+ strMessage = "ERROR! XalocXSDataInputXia2DIALS constructor argument 'templateN' is not XSDataString but %s" % self._templateN.__class__.__name__
+ raise BaseException(strMessage)
+ if fromN is None:
+ self._fromN = None
+ elif fromN.__class__.__name__ == "XSDataInteger":
+ self._fromN = fromN
+ else:
+ strMessage = "ERROR! XalocXSDataInputXia2DIALS constructor argument 'fromN' is not XSDataInteger but %s" % self._fromN.__class__.__name__
+ raise BaseException(strMessage)
+ if toN is None:
+ self._toN = None
+ elif toN.__class__.__name__ == "XSDataInteger":
+ self._toN = toN
+ else:
+ strMessage = "ERROR! XalocXSDataInputXia2DIALS constructor argument 'toN' is not XSDataInteger but %s" % self._toN.__class__.__name__
+ raise BaseException(strMessage)
+ if processDirectory is None:
+ self._processDirectory = None
+ elif processDirectory.__class__.__name__ == "XSDataFile":
+ self._processDirectory = processDirectory
+ else:
+ strMessage = "ERROR! XalocXSDataInputXia2DIALS constructor argument 'processDirectory' is not XSDataFile but %s" % self._processDirectory.__class__.__name__
+ raise BaseException(strMessage)
+ if doAnomAndNonanom is None:
+ self._doAnomAndNonanom = None
+ elif doAnomAndNonanom.__class__.__name__ == "XSDataBoolean":
+ self._doAnomAndNonanom = doAnomAndNonanom
+ else:
+ strMessage = "ERROR! XalocXSDataInputXia2DIALS constructor argument 'doAnomAndNonanom' is not XSDataBoolean but %s" % self._doAnomAndNonanom.__class__.__name__
+ raise BaseException(strMessage)
+ if symm is None:
+ self._symm = None
+ elif symm.__class__.__name__ == "XSDataString":
+ self._symm = symm
+ else:
+ strMessage = "ERROR! XalocXSDataInputXia2DIALS constructor argument 'symm' is not XSDataString but %s" % self._symm.__class__.__name__
+ raise BaseException(strMessage)
+ if cell is None:
+ self._cell = None
+ elif cell.__class__.__name__ == "XSDataString":
+ self._cell = cell
+ else:
+ strMessage = "ERROR! XalocXSDataInputXia2DIALS constructor argument 'cell' is not XSDataString but %s" % self._cell.__class__.__name__
+ raise BaseException(strMessage)
+ if small_molecule_3dii is None:
+ self._small_molecule_3dii = None
+ elif small_molecule_3dii.__class__.__name__ == "XSDataBoolean":
+ self._small_molecule_3dii = small_molecule_3dii
+ else:
+ strMessage = "ERROR! XSDataInputControlAutoPROC constructor argument 'small_molecule_3dii' is not XSDataBoolean but %s" % small_molecule_3dii.__class__.__name__
+ raise BaseException(strMessage)
+ if detector_max_res is None:
+ self._detector_max_res = None
+ elif detector_max_res.__class__.__name__ == "XSDataDouble":
+ self._detector_max_res = detector_max_res
+ else:
+ strMessage = (
+ "ERROR! XSDataAutoprocInput constructor argument 'detector_max_res' is not XSDataDouble but %s"
+ % self._detector_max_res.__class__.__name__
+ )
+ raise Exception(strMessage)
+
+
+ # Methods and properties for the 'small_molecule_3dii' attribute, used for xia2 small molecule processing
+ def get_small_molecule_3dii(self): return self._small_molecule_3dii
+ def set_small_molecule_3dii(self, small_molecule_3dii):
+ if small_molecule_3dii is None:
+ self._small_molecule_3dii = None
+ elif small_molecule_3dii.__class__.__name__ == "XSDataBoolean":
+ self._small_molecule_3dii = small_molecule_3dii
+ else:
+ strMessage = "ERROR! XSDataInputControlAutoPROC.set_small_molecule_3dii argument is not XSDataBoolean but %s" % small_molecule_3dii.__class__.__name__
+ raise BaseException(strMessage)
+ def del_small_molecule_3dii(self): self._small_molecule_3dii = None
+
+ # Methods and properties for the 'dataCollectionId' attribute
+ def getDataCollectionId(self): return self._dataCollectionId
+ def setDataCollectionId(self, dataCollectionId):
+ if dataCollectionId is None:
+ self._dataCollectionId = None
+ elif dataCollectionId.__class__.__name__ == "XSDataInteger":
+ self._dataCollectionId = dataCollectionId
+ else:
+ strMessage = "ERROR! XalocXSDataInputXia2DIALS.setDataCollectionId argument is not XSDataInteger but %s" % dataCollectionId.__class__.__name__
+ raise BaseException(strMessage)
+ def delDataCollectionId(self): self._dataCollectionId = None
+ dataCollectionId = property(getDataCollectionId, setDataCollectionId, delDataCollectionId, "Property for dataCollectionId")
+ # Methods and properties for the 'image' attribute
+ def getDiffractionImage(self): return self._diffractionImage
+ def setDiffractionImage(self, image):
+ if image is None:
+ self._diffractionImage = None
+ elif image.__class__.__name__ == "XSDataString":
+ self._diffractionImage = image
+ else:
+ strMessage = "ERROR! XalocXSDataInputXia2DIALS.setDiffractionImage argument is not XSDataString but %s" % image.__class__.__name__
+ raise BaseException(strMessage)
+ def delDiffractionImage(self): self._diffractionImage = None
+ diffractionImage = property(getDiffractionImage, setDiffractionImage, delDiffractionImage, "Property for diffractionImage")
+ # Methods and properties for the 'dirN' attribute
+ def getDirN(self): return self._dirN
+ def setDirN(self, dirN):
+ if dirN is None:
+ self._dirN = None
+ elif dirN.__class__.__name__ == "XSDataFile":
+ self._dirN = dirN
+ else:
+ strMessage = "ERROR! XalocXSDataInputXia2DIALS.setDirN argument is not XSDataFile but %s" % dirN.__class__.__name__
+ raise BaseException(strMessage)
+ def delDirN(self): self._dirN = None
+ dirN = property(getDirN, setDirN, delDirN, "Property for dirN")
+ # Methods and properties for the 'templateN' attribute
+ def getTemplateN(self): return self._templateN
+ def setTemplateN(self, templateN):
+ if templateN is None:
+ self._templateN = None
+ elif templateN.__class__.__name__ == "XSDataString":
+ self._templateN = templateN
+ else:
+ strMessage = "ERROR! XalocXSDataInputXia2DIALS.setTemplateN argument is not XSDataString but %s" % templateN.__class__.__name__
+ raise BaseException(strMessage)
+ def delTemplateN(self): self._templateN = None
+ templateN = property(getTemplateN, setTemplateN, delTemplateN, "Property for templateN")
+ # Methods and properties for the 'fromN' attribute
+ def getFromN(self): return self._fromN
+ def setFromN(self, fromN):
+ if fromN is None:
+ self._fromN = None
+ elif fromN.__class__.__name__ == "XSDataInteger":
+ self._fromN = fromN
+ else:
+ strMessage = "ERROR! XalocXSDataInputXia2DIALS.setFromN argument is not XSDataInteger but %s" % fromN.__class__.__name__
+ raise BaseException(strMessage)
+ def delFromN(self): self._fromN = None
+ fromN = property(getFromN, setFromN, delFromN, "Property for fromN")
+ # Methods and properties for the 'toN' attribute
+ def getToN(self): return self._toN
+ def setToN(self, toN):
+ if toN is None:
+ self._toN = None
+ elif toN.__class__.__name__ == "XSDataInteger":
+ self._toN = toN
+ else:
+ strMessage = "ERROR! XalocXSDataInputXia2DIALS.setToN argument is not XSDataInteger but %s" % toN.__class__.__name__
+ raise BaseException(strMessage)
+ def delToN(self): self._toN = None
+ toN = property(getToN, setToN, delToN, "Property for toN")
+ # Methods and properties for the 'processDirectory' attribute
+ def getProcessDirectory(self): return self._processDirectory
+ def setProcessDirectory(self, processDirectory):
+ if processDirectory is None:
+ self._processDirectory = None
+ elif processDirectory.__class__.__name__ == "XSDataFile":
+ self._processDirectory = processDirectory
+ else:
+ strMessage = "ERROR! XalocXSDataInputXia2DIALS.setProcessDirectory argument is not XSDataFile but %s" % processDirectory.__class__.__name__
+ raise BaseException(strMessage)
+ def delProcessDirectory(self): self._processDirectory = None
+ processDirectory = property(getProcessDirectory, setProcessDirectory, delProcessDirectory, "Property for processDirectory")
+ # Methods and properties for the 'doAnomAndNonanom' attribute
+ def getDoAnomAndNonanom(self): return self._doAnomAndNonanom
+ def setDoAnomAndNonanom(self, doAnomAndNonanom):
+ if doAnomAndNonanom is None:
+ self._doAnomAndNonanom = None
+ elif doAnomAndNonanom.__class__.__name__ == "XSDataBoolean":
+ self._doAnomAndNonanom = doAnomAndNonanom
+ else:
+ strMessage = "ERROR! XalocXSDataInputXia2DIALS.setDoAnomAndNonanom argument is not XSDataBoolean but %s" % doAnomAndNonanom.__class__.__name__
+ raise BaseException(strMessage)
+ def delDoAnomAndNonanom(self): self._doAnomAndNonanom = None
+ doAnomAndNonanom = property(getDoAnomAndNonanom, setDoAnomAndNonanom, delDoAnomAndNonanom, "Property for doAnomAndNonanom")
+ # Methods and properties for the 'symm' attribute
+ def getSpacegroup(self): return self._symm
+ def setSpacegroup(self, symm):
+ if symm is None:
+ self._symm = None
+ elif symm.__class__.__name__ == "XSDataString":
+ self._symm = symm
+ else:
+ strMessage = "ERROR! XalocXSDataInputXia2DIALS.setSymm argument is not XSDataString but %s" % symm.__class__.__name__
+ raise BaseException(strMessage)
+ def delSpacegroup(self): self._symm = None
+ symm = property(getSpacegroup, setSpacegroup, delSpacegroup, "Property for symm")
+ # Methods and properties for the 'cell' attribute
+ def getUnit_cell(self): return self._cell
+ def setUnit_cell(self, cell):
+ if cell is None:
+ self._cell = None
+ elif cell.__class__.__name__ == "XSDataString":
+ self._cell = cell
+ else:
+ strMessage = "ERROR! XalocXSDataInputXia2DIALS.setCell argument is not XSDataString but %s" % cell.__class__.__name__
+ raise BaseException(strMessage)
+ def delUnit_cell(self): self._cell = None
+ unit_cell = property(getUnit_cell, setUnit_cell, delUnit_cell, "Property for cell")
+ # Methods and properties for the 'detector_max_res' attribute
+
+ def getDetector_max_res(self):
+ return self._detector_max_res
+
+ def setDetector_max_res(self, detector_max_res):
+ if detector_max_res is None:
+ self._detector_max_res = None
+ elif detector_max_res.__class__.__name__ == "XSDataDouble":
+ self._detector_max_res = detector_max_res
+ else:
+ strMessage = (
+ "ERROR! XSDataAutoprocInput.setDetector_max_res argument is not XSDataDouble but %s"
+ % detector_max_res.__class__.__name__
+ )
+ raise Exception(strMessage)
+
+ def delDetector_max_res(self):
+ self._detector_max_res = None
+
+ detector_max_res = property(
+ getDetector_max_res,
+ setDetector_max_res,
+ delDetector_max_res,
+ "Property for detector_max_res",
+ )
+
+ def export(self, outfile, level, name_='XSDataInputXIA2'):
+ showIndent(outfile, level)
+ outfile.write(unicode('<%s>\n' % name_))
+ self.exportChildren(outfile, level + 1, name_)
+ showIndent(outfile, level)
+ outfile.write(unicode('%s>\n' % name_))
+ def exportChildren(self, outfile, level, name_='XSDataInputXIA2'):
+ XSDataInput.exportChildren(self, outfile, level, name_)
+ if self._dataCollectionId is not None:
+ self.dataCollectionId.export(outfile, level, name_='dataCollectionId')
+ #self.dataCollectionId.export(outfile, level, name_='data_collection_id')
+ if self._dirN is not None:
+ self.dirN.export(outfile, level, name_='dirN')
+ if self._templateN is not None:
+ self.templateN.export(outfile, level, name_='templateN')
+ if self._fromN is not None:
+ self.fromN.export(outfile, level, name_='startFrame')
+ if self._toN is not None:
+ self.toN.export(outfile, level, name_='endFrame')
+ if self._processDirectory is not None:
+ self.processDirectory.export(outfile, level, name_='processDirectory')
+ if self._doAnomAndNonanom is not None:
+ self.doAnomAndNonanom.export(outfile, level, name_='doAnomAndNonanom')
+ if self._symm is not None:
+ self.symm.export(outfile, level, name_='spaceGroup')
+ if self._cell is not None:
+ self._cell.export(outfile, level, name_='cell')
+ if self._small_molecule_3dii is not None:
+ self._small_molecule_3dii.export(outfile, level, name_='smallMolecule3dii')
+ #TODO: implement this properly using children
+ if self._diffractionImage is not None:
+ showIndent(outfile, level)
+ outfile.write(unicode('\n'))
+ self._diffractionImage.export(outfile, level+1, name_='path')
+ showIndent(outfile, level)
+ outfile.write(unicode('\n'))
+ if self._detector_max_res is not None:
+ self._detector_max_res.export(outfile, level, name_="d_min")
+ def build(self, node_):
+ for child_ in node_.childNodes:
+ nodeName_ = child_.nodeName.split(':')[-1]
+ self.buildChildren(child_, nodeName_)
+ def buildChildren(self, child_, nodeName_):
+ if child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'dataCollectionId':
+ obj_ = XSDataInteger()
+ obj_.build(child_)
+ self.setDataCollectionId(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'dirN':
+ obj_ = XSDataFile()
+ obj_.build(child_)
+ self.setDirN(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'configDef':
+ obj_ = XSDataFile()
+ obj_.build(child_)
+ self.setConfigDef(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'templateN':
+ obj_ = XSDataString()
+ obj_.build(child_)
+ self.setTemplateN(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'fromN':
+ obj_ = XSDataInteger()
+ obj_.build(child_)
+ self.setFromN(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'toN':
+ obj_ = XSDataInteger()
+ obj_.build(child_)
+ self.setToN(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'processDirectory':
+ obj_ = XSDataFile()
+ obj_.build(child_)
+ self.setProcessDirectory(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'doAnomAndNonanom':
+ obj_ = XSDataBoolean()
+ obj_.build(child_)
+ self.setDoAnomAndNonanom(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'symm':
+ obj_ = XSDataString()
+ obj_.build(child_)
+ self.setSymm(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'cell':
+ obj_ = XSDataString()
+ obj_.build(child_)
+ self.setCell(obj_)
+ elif child_.nodeType == Node.ELEMENT_NODE and \
+ nodeName_ == 'detector_max_res':
+ obj_ = XSDataDouble()
+ obj_.build(child_)
+ self.setDetector_max_res(obj_)
+
+ XSDataInput.buildChildren(self, child_, nodeName_)
+ #Method for marshalling an object
+ def marshal( self ):
+ oStreamString = StringIO()
+ oStreamString.write(unicode('\n'))
+ self.export( oStreamString, 0, name_="XSDataInputXIA2" )
+ oStringXML = oStreamString.getvalue()
+ oStreamString.close()
+ return oStringXML
+ #Only to export the entire XML tree to a file stream on disk
+ def exportToFile( self, _outfileName ):
+ outfile = open( _outfileName, "w" )
+ outfile.write(unicode('\n'))
+ self.export( outfile, 0, name_='XSDataInputXIA2' )
+ outfile.close()
+ #Deprecated method, replaced by exportToFile
+ def outputFile( self, _outfileName ):
+ print("WARNING: Method outputFile in class XalocXSDataInputXia2DIALS is deprecated, please use instead exportToFile!")
+ self.exportToFile(_outfileName)
+ #Method for making a copy in a new instance
+ def copy( self ):
+ return XalocXSDataInputXia2DIALS.parseString(self.marshal())
+ #Static method for parsing a string
+ def parseString( _inString ):
+ doc = minidom.parseString(_inString)
+ rootNode = doc.documentElement
+ rootObj = XalocXSDataInputXia2DIALS()
+ rootObj.build(rootNode)
+ # Check that all minOccurs are obeyed by marshalling the created object
+ oStreamString = StringIO()
+ rootObj.export( oStreamString, 0, name_="XSDataInputXIA2" )
+ oStreamString.close()
+ return rootObj
+ parseString = staticmethod( parseString )
+ #Static method for parsing a file
+ def parseFile( _inFilePath ):
+ doc = minidom.parse(_inFilePath)
+ rootNode = doc.documentElement
+ rootObj = XalocXSDataInputXia2DIALS()
+ rootObj.build(rootNode)
+ return rootObj
+ parseFile = staticmethod( parseFile )
+# end class XalocXSDataInputXia2DIALS
+
+
+class XSDataResultControlAutoPROC(XSDataResult):
+ def __init__(self, status=None):
+ XSDataResult.__init__(self, status)
+ def export(self, outfile, level, name_='XSDataResultControlAutoPROC'):
+ showIndent(outfile, level)
+ outfile.write(unicode('<%s>\n' % name_))
+ self.exportChildren(outfile, level + 1, name_)
+ showIndent(outfile, level)
+ outfile.write(unicode('%s>\n' % name_))
+ def exportChildren(self, outfile, level, name_='XSDataResultControlAutoPROC'):
+ XSDataResult.exportChildren(self, outfile, level, name_)
+ def build(self, node_):
+ for child_ in node_.childNodes:
+ nodeName_ = child_.nodeName.split(':')[-1]
+ self.buildChildren(child_, nodeName_)
+ def buildChildren(self, child_, nodeName_):
+ pass
+ XSDataResult.buildChildren(self, child_, nodeName_)
+ #Method for marshalling an object
+ def marshal( self ):
+ oStreamString = StringIO()
+ oStreamString.write(unicode('\n'))
+ self.export( oStreamString, 0, name_="XSDataResultControlAutoPROC" )
+ oStringXML = oStreamString.getvalue()
+ oStreamString.close()
+ return oStringXML
+ #Only to export the entire XML tree to a file stream on disk
+ def exportToFile( self, _outfileName ):
+ outfile = open( _outfileName, "w" )
+ outfile.write(unicode('\n'))
+ self.export( outfile, 0, name_='XSDataResultControlAutoPROC' )
+ outfile.close()
+ #Deprecated method, replaced by exportToFile
+ def outputFile( self, _outfileName ):
+ print("WARNING: Method outputFile in class XSDataResultControlAutoPROC is deprecated, please use instead exportToFile!")
+ self.exportToFile(_outfileName)
+ #Method for making a copy in a new instance
+ def copy( self ):
+ return XSDataResultControlAutoPROC.parseString(self.marshal())
+ #Static method for parsing a string
+ def parseString( _inString ):
+ doc = minidom.parseString(_inString)
+ rootNode = doc.documentElement
+ rootObj = XSDataResultControlAutoPROC()
+ rootObj.build(rootNode)
+ # Check that all minOccurs are obeyed by marshalling the created object
+ oStreamString = StringIO()
+ rootObj.export( oStreamString, 0, name_="XSDataResultControlAutoPROC" )
+ oStreamString.close()
+ return rootObj
+ parseString = staticmethod( parseString )
+ #Static method for parsing a file
+ def parseFile( _inFilePath ):
+ doc = minidom.parse(_inFilePath)
+ rootNode = doc.documentElement
+ rootObj = XSDataResultControlAutoPROC()
+ rootObj.build(rootNode)
+ return rootObj
+ parseFile = staticmethod( parseFile )
+# end class XSDataResultControlAutoPROC
+
+
+
+# End of data representation classes.
+
+
diff --git a/mxcubecore/HardwareObjects/BeamInfo.py b/mxcubecore/HardwareObjects/BeamInfo.py
index c4f3bb94a6..725bcf5bf9 100644
--- a/mxcubecore/HardwareObjects/BeamInfo.py
+++ b/mxcubecore/HardwareObjects/BeamInfo.py
@@ -22,9 +22,10 @@
import logging
from mxcubecore.BaseHardwareObjects import Equipment
from mxcubecore import HardwareRepository as HWR
+from mxcubecore.HardwareObjects.abstract.AbstractBeam import AbstractBeam
-class BeamInfo(Equipment):
+class BeamInfo(AbstractBeam):
"""
Description:
"""
@@ -33,7 +34,7 @@ def __init__(self, *args):
"""
Descrip. :
"""
- Equipment.__init__(self, *args)
+ AbstractBeam.__init__(self, *args)
self.aperture_hwobj = None
self.beam_definer = None
@@ -53,6 +54,7 @@ def init(self):
"""
Descript. :
"""
+ AbstractBeam.init(self)
self.beam_size_slits = [9999, 9999]
self.beam_size_aperture = [9999, 9999]
self.beam_size_definer = [9999, 9999]
@@ -205,11 +207,13 @@ def evaluate_beam_info(self):
Return : dictionary,{size_x:0.1, size_y:0.1, shape:"rectangular"}
"""
size_x = min(
+ self.beam_info_dict["size_x"],
self.beam_size_aperture[0],
self.beam_size_slits[0],
self.beam_size_definer[0],
)
size_y = min(
+ self.beam_info_dict["size_y"],
self.beam_size_aperture[1],
self.beam_size_slits[1],
self.beam_size_definer[1],
diff --git a/mxcubecore/HardwareObjects/Beamline.py b/mxcubecore/HardwareObjects/Beamline.py
index b3c173835d..4e6e8c07a9 100644
--- a/mxcubecore/HardwareObjects/Beamline.py
+++ b/mxcubecore/HardwareObjects/Beamline.py
@@ -198,6 +198,17 @@ def flux(self):
__content_roles.append("flux")
+ @property
+ def digital_zoom(self):
+ """Flux Hardware object
+
+ Returns:
+ Optional[AbstractActuator]:
+ """
+ return self._objects.get("digital_zoom")
+
+ __content_roles.append("digital_zoom")
+
@property
def beam(self):
"""Beam Hardware object
@@ -554,6 +565,29 @@ def image_tracking(self):
__content_roles.append("image_tracking")
+ @property
+ def supervisor(self):
+ """Imaging tracking object
+
+ Returns:
+ Optional[HardwareObject]:
+ """
+ return self._objects.get("supervisor")
+
+ __content_roles.append("supervisor")
+
+ @property
+ def ln2shower(self):
+ """Imaging tracking object
+
+ Returns:
+ Optional[HardwareObject]:
+ """
+ return self._objects.get("ln2shower")
+
+ __content_roles.append("ln2shower")
+
+
# Procedures
@property
diff --git a/mxcubecore/HardwareObjects/Cats90.py b/mxcubecore/HardwareObjects/Cats90.py
index 5587098aa6..4160c24220 100644
--- a/mxcubecore/HardwareObjects/Cats90.py
+++ b/mxcubecore/HardwareObjects/Cats90.py
@@ -184,8 +184,14 @@ def init(self):
# add support for CATS dewars with variable number of lids
# Create channels from XML
-
- self.cats_device = PyTango.DeviceProxy(self.get_property("tangoname"))
+ try:
+ cats_name = self.get_property("tangoname")
+ except AttributeError as e:
+ logging.getLogger("HWR").debug(
+ "cats device not under tangoname, trying taurusname"
+ )
+ cats_name = self.get_property("taurusname")
+ self.cats_device = PyTango.DeviceProxy( self.get_property("taurusname") )
no_of_lids = self.get_property("no_of_lids")
if no_of_lids is None:
@@ -418,8 +424,11 @@ def init(self):
try:
self.basket_types = self.cats_device.read_attribute("CassetteType").value
self.number_of_baskets = len(self.basket_types)
- except PyTango.DevFailed:
- pass
+ except PyTango.DevFailed as e:
+ logging.getLogger("HWR").warning(
+ "Device failed with error %s" % (e)
+ )
+ #pass
# find number of baskets and number of samples per basket
if self.number_of_baskets is not None:
@@ -588,7 +597,7 @@ def _init_sc_contents(self):
datamatrix = None
present = scanned = loaded = _has_been_loaded = False
sample._set_info(present, datamatrix, scanned)
- sample._set_loaded(loaded, has_been_loaded)
+ sample._set_loaded(loaded, _has_been_loaded)
sample._set_holder_length(spl[4])
logging.getLogger("HWR").warning("Cats90: initializing contents done")
@@ -643,7 +652,7 @@ def _do_update_info(self):
:rtype: None
"""
logging.info(
- "doUpdateInfo should not be called for cats. only for update timer type of SC"
+ "do_update_info should not be called for cats. only for update timer type of SC"
)
return
@@ -658,6 +667,7 @@ def _do_change_mode(self, mode):
:returns: None
:rtype: None
"""
+ pass
def _directly_update_selected_component(self, basket_no, sample_no):
basket = None
@@ -861,7 +871,7 @@ def _do_load(self, sample=None, shifts=None):
else:
if self.cats_sample_on_diffr() == 1:
logging.getLogger("HWR").warning(
- " ==========CATS=== trying to load sample, but sample detected on diffr. aborting"
+ " ==========CATS=== trying to load sample, but there is an unknown sample detected on diffr. aborting"
)
self._update_state() # remove software flags like Loading.
elif self.cats_sample_on_diffr() == -1:
@@ -967,9 +977,9 @@ def cats_state_changed(self, value):
while value in [PyTango.DevState.ALARM, PyTango.DevState.ON]:
time.sleep(0.1)
trials += 1
- logging.getLogger("HWR").warning(
- "SAMPLE CHANGER could be in transient state. trying again"
- )
+ #logging.getLogger("HWR").warning(
+ #"SAMPLE CHANGER could be in transient state. trying again"
+ #)
value = self._chnState.get_value()
if trials > 4:
break
@@ -1010,7 +1020,7 @@ def cats_basket_presence_changed(self, value):
if presence != self.basket_presence:
logging.getLogger("HWR").warning(
- "Basket presence changed. Updating contents"
+ "cats_basket_presence_changed Basket presence changed. Updating contents"
)
self.basket_presence = presence
self._update_cats_contents()
@@ -1206,10 +1216,10 @@ def _decide_state(self, dev_state, powered, lids_closed, has_loaded, on_diff):
elif has_loaded ^ on_diff:
# go to Unknown state if a sample is detected on the gonio but not registered in the internal database
# or registered but not on the gonio anymore
- logging.getLogger("HWR").warning(
- "SAMPLE CHANGER Unknown 2 (hasLoaded: %s / detected: %s)"
- % (self.has_loaded_sample(), self._chnSampleIsDetected.get_value())
- )
+ #logging.getLogger("HWR").warning(
+ #"SAMPLE CHANGER Unknown 2 (hasLoaded: %s / detected: %s)"
+ #% (self.has_loaded_sample(), self._chnSampleIsDetected.get_value())
+ #)
_state = SampleChangerState.Unknown
# elif not lids_closed:
# _state = SampleChangerState.Charging
@@ -1376,14 +1386,22 @@ def _update_loaded_sample(self, sample_num=None, lid=None):
old_sample = self.get_loaded_sample()
+ old_address = None
+ if old_sample != None:
+ old_address = old_sample.get_address()
+ new_address = None
+ if new_sample != None:
+ new_address = new_sample.get_address()
logging.getLogger("HWR").debug(
"----- Cats90 -----. Sample has changed. Dealing with it - new_sample = %s / old_sample = %s"
- % (new_sample, old_sample)
+ % ( old_address, new_address )
)
if old_sample != new_sample:
# remove 'loaded' flag from old sample but keep all other information
+ #TODO: send a signal to be captured by the tree_brick so that the tree can be updated with the new sample info
+
if old_sample is not None:
# there was a sample on the gonio
loaded = False
@@ -1398,7 +1416,7 @@ def _update_loaded_sample(self, sample_num=None, lid=None):
if (
(old_sample is None)
or (new_sample is None)
- or (old_sample.get_address() != new_loaded.get_address())
+ or (old_sample.get_address() != new_sample.get_address())
):
self._trigger_loaded_sample_changed_event(new_sample)
self._trigger_info_changed_event()
@@ -1444,7 +1462,7 @@ def _do_update_cats_contents(self):
def _update_cats_contents(self):
logging.getLogger("HWR").warning(
- "Updating contents %s" % str(self.basket_presence)
+ "_update_cats_contents Updating contents %s" % str(self.basket_presence)
)
for basket_index in range(self.number_of_baskets):
# get saved presence information from object's internal bookkeeping
@@ -1485,7 +1503,7 @@ def _update_cats_contents(self):
# forget about any loaded state in newly mounted or removed basket)
loaded = _has_been_loaded = False
- sample._set_loaded(loaded, has_been_loaded)
+ sample._set_loaded(loaded, _has_been_loaded)
self._trigger_contents_updated_event()
self._update_loaded_sample()
diff --git a/mxcubecore/HardwareObjects/CatsMaint.py b/mxcubecore/HardwareObjects/CatsMaint.py
index 8439ec3869..02e93f41e8 100644
--- a/mxcubecore/HardwareObjects/CatsMaint.py
+++ b/mxcubecore/HardwareObjects/CatsMaint.py
@@ -487,7 +487,8 @@ def _do_set_on_diff(self, sample):
# calculate CATS specific lid/sample number
lid = (int(sample_tmp[0]) - 1) / 3 + 1
puc_pos = ((int(sample_tmp[0]) - 1) % 3) * 10 + int(sample_tmp[1])
- argin = [str(lid), str(puc_pos), "0"]
+ basket_types = self.cats_device.read_attribute("CassetteType").value
+ argin = [str(lid), str(puc_pos), str( basket_types[ sample_tmp[0]-1 ] ) ]
logging.getLogger().info("to SetOnDiff %s", argin)
self._execute_server_task(self._cmdSetOnDiff, argin)
@@ -525,7 +526,6 @@ def _do_power_state(self, state=False):
else:
self._cmdPowerOff()
- self.do_state_action("power", state)
def _do_enable_regulation(self):
"""
diff --git a/mxcubecore/HardwareObjects/EDNACharacterisation.py b/mxcubecore/HardwareObjects/EDNACharacterisation.py
index f806cb83c1..aea0e284e5 100644
--- a/mxcubecore/HardwareObjects/EDNACharacterisation.py
+++ b/mxcubecore/HardwareObjects/EDNACharacterisation.py
@@ -229,7 +229,7 @@ def input_from_params(self, data_collection, char_params):
for img_num in range(int(acquisition_parameters.num_images)):
image_file = XSDataFile()
path = XSDataString()
- path.set_value(path_str % (img_num + 1))
+ path.setValue(path_str % (img_num + 1))
image_file.setPath(path)
data_set.addImageFile(image_file)
diff --git a/mxcubecore/HardwareObjects/GphlWorkflow.py b/mxcubecore/HardwareObjects/GphlWorkflow.py
index 58ec04a0ba..287292c4ef 100644
--- a/mxcubecore/HardwareObjects/GphlWorkflow.py
+++ b/mxcubecore/HardwareObjects/GphlWorkflow.py
@@ -43,7 +43,7 @@
from mxcubecore.dispatcher import dispatcher
from mxcubecore.utils import conversion
-from mxcubecore.BaseHardwareObjects import HardwareObjectYaml
+from mxcubecore.BaseHardwareObjects import HardwareObject
from mxcubecore.HardwareObjects import queue_model_objects
from mxcubecore.HardwareObjects import queue_model_enumerables
from mxcubecore.HardwareObjects.queue_entry import QUEUE_ENTRY_STATUS
@@ -75,7 +75,7 @@
)
-class GphlWorkflow(HardwareObjectYaml):
+class GphlWorkflow(HardwareObject, object):
"""Global Phasing workflow runner.
"""
@@ -84,13 +84,16 @@ class GphlWorkflow(HardwareObjectYaml):
def __init__(self, name):
super(GphlWorkflow, self).__init__(name)
+ # HO that handles connection to GPhL workflow runner
+ self._workflow_connection = None
+
# Needed to allow methods to put new actions on the queue
# And as a place to get hold of other objects
self._queue_entry = None
# Configuration data - set when queried
- self.workflows = {}
- self.settings = {}
+ #self.workflows = {}
+ #self.settings = {}
# Current data collection task group. Different for characterisation and collection
self._data_collection_group = None
@@ -99,7 +102,7 @@ def __init__(self, name):
self._return_parameters = None
# Queue to read messages from GphlConnection
- self._workflow_queue = None
+ #self._workflow_queue = None
# Message - processing function map
self._processor_functions = {}
@@ -119,12 +122,27 @@ def __init__(self, name):
# Configurable file paths
self.file_paths = {}
+ # Dose budget pulldown labels and default
+ self.dose_budgets = OrderedDict()
+ self.default_dose_budget_label = None
+
+
def _init(self):
super(GphlWorkflow, self)._init()
def init(self):
super(GphlWorkflow, self).init()
+ # Get dose budget data
+ default_dose_budget_label = None
+ xx0 = next(self.get_objects("dose_budgets"))
+ for pulldown_item in xx0.get_objects("pulldown_item"):
+ dd0 = pulldown_item.get_properties()
+ self.dose_budgets[dd0["label"]] = float(dd0["value"])
+ if default_dose_budget_label is None or dd0.get("is_default"):
+ default_dose_budget_label = dd0["label"]
+ self.default_dose_budget_label = default_dose_budget_label
+
# Set up processing functions map
self._processor_functions = {
"String": self.echo_info_string,
@@ -141,7 +159,14 @@ def init(self):
"WorkflowCompleted": self.workflow_completed,
"WorkflowFailed": self.workflow_failed,
}
+
+ self.update_state(self.STATES.READY)
+ def setup_workflow_object(self):
+ """Necessary as this set-up cannot be done at init,
+ when the hwobj are still incomplete. Must be called externally
+ TODO This still necessary?"""
+
# Set standard configurable file paths
file_paths = self.file_paths
ss0 = HWR.beamline.gphl_connection.software_paths["gphl_beamline_config"]
@@ -165,39 +190,37 @@ def init(self):
(instrument_data["det_org_x"], instrument_data["det_org_y"])
)
- # Adapt configuration data - must be done after file_paths setting
- if HWR.beamline.gphl_connection.ssh_options:
- # We are running workflow through ssh - set beamline url
- beamline_hook ="py4j:%s:" % socket.gethostname()
- else:
- beamline_hook = "py4j::"
-
- # Consolidate workflow options
- for title, workflow in self.workflows.items():
- workflow["wfname"] = title
- wftype = workflow["wftype"]
-
- opt0 = workflow.get("options", {})
- opt0["beamline"] = beamline_hook
- default_strategy_name = None
- for strategy in workflow["strategies"]:
- strategy["wftype"] = wftype
- if default_strategy_name is None:
- default_strategy_name = workflow["strategy_name"] = (
- strategy["title"]
- )
- dd0 = opt0.copy()
- dd0.update(strategy.get("options", {}))
- strategy["options"] = dd0
- if workflow["wftype"] == "transcal":
- relative_file_path = strategy["options"].get("file")
- if relative_file_path is not None:
- # Special case - this option must be modified before use
- strategy["options"]["file"] = os.path.join(
- self.file_paths["gphl_beamline_config"], relative_file_path
- )
-
- self.update_state(self.STATES.READY)
+ ## Adapt configuration data - must be done after file_paths setting
+ #if HWR.beamline.gphl_connection.ssh_options:
+ ## We are running workflow through ssh - set beamline url
+ #beamline_hook ="py4j:%s:" % socket.gethostname()
+ #else:
+ #beamline_hook = "py4j::"
+
+ ## Consolidate workflow options
+ #for title, workflow in self.workflows.items():
+ #workflow["wfname"] = title
+ #wftype = workflow["wftype"]
+
+ #opt0 = workflow.get("options", {})
+ #opt0["beamline"] = beamline_hook
+ #default_strategy_name = None
+ #for strategy in workflow["strategies"]:
+ #strategy["wftype"] = wftype
+ #if default_strategy_name is None:
+ #default_strategy_name = workflow["strategy_name"] = (
+ #strategy["title"]
+ #)
+ #dd0 = opt0.copy()
+ #dd0.update(strategy.get("options", {}))
+ #strategy["options"] = dd0
+ #if workflow["wftype"] == "transcal":
+ #relative_file_path = strategy["options"].get("file")
+ #if relative_file_path is not None:
+ ## Special case - this option must be modified before use
+ #strategy["options"]["file"] = os.path.join(
+ #self.file_paths["gphl_beamline_config"], relative_file_path
+ #)
def shutdown(self):
"""Shut down workflow and connection. Triggered on program quit."""
@@ -208,7 +231,96 @@ def shutdown(self):
def get_available_workflows(self):
"""Get list of workflow description dictionaries."""
- return copy.deepcopy(self.workflows)
+ result = OrderedDict()
+ if self.has_object("workflow_properties"):
+ properties = self["workflow_properties"].get_properties().copy()
+ else:
+ properties = {}
+ if self.has_object("invocation_properties"):
+ invocation_properties = (
+ self["invocation_properties"].get_properties().copy()
+ )
+ else:
+ invocation_properties = {}
+
+ if self.has_object("all_workflow_options"):
+ all_workflow_options = self["all_workflow_options"].get_properties().copy()
+ if "beamline" in all_workflow_options:
+ pass
+ elif HWR.beamline.gphl_connection.has_object("ssh_options"):
+ # We are running workflow through ssh - set beamline url
+ all_workflow_options["beamline"] = "py4j:%s:" % socket.gethostname()
+ else:
+ all_workflow_options["beamline"] = "py4j::"
+ else:
+ all_workflow_options = {}
+
+ acq_workflow_options = all_workflow_options.copy()
+ acq_workflow_options.update(self["acq_workflow_options"].get_properties())
+ # Add options for target directories:
+ process_root = HWR.beamline.session.get_base_process_directory()
+ acq_workflow_options["appdir"] = process_root
+
+ mx_workflow_options = acq_workflow_options.copy()
+ mx_workflow_options.update(self["mx_workflow_options"].get_properties())
+
+ for wf_node in self["workflows"]:
+ name = wf_node.name()
+ strategy_type = wf_node.get_property("strategy_type")
+ wf_dict = {
+ "name": name,
+ "strategy_type": strategy_type,
+ "application": wf_node.get_property("application"),
+ "documentation": wf_node.get_property(
+ "documentation", default_value=""
+ ),
+ "interleaveOrder": wf_node.get_property(
+ "interleave_order", default_value=""
+ ),
+ }
+ result[name] = wf_dict
+
+ if strategy_type.startswith("transcal"):
+ wf_dict["options"] = dd0 = all_workflow_options.copy()
+ if wf_node.has_object("options"):
+ dd0.update(wf_node["options"].get_properties())
+ relative_file_path = dd0.get("file")
+ if relative_file_path is not None:
+ # Special case - this option must be modified before use
+ dd0["file"] = os.path.join(
+ self.file_paths["gphl_beamline_config"], relative_file_path
+ )
+
+ elif strategy_type.startswith("diffractcal"):
+ wf_dict["options"] = dd0 = acq_workflow_options.copy()
+ if wf_node.has_object("options"):
+ dd0.update(wf_node["options"].get_properties())
+
+ else:
+ wf_dict["options"] = dd0 = mx_workflow_options.copy()
+ if wf_node.has_object("options"):
+ dd0.update(wf_node["options"].get_properties())
+ if wf_node.has_object("beam_energies"):
+ wf_dict["beam_energies"] = dd0 = OrderedDict()
+ for wavelength in wf_node["beam_energies"]:
+ dd0[wavelength.get_property("role")] = wavelength.get_property(
+ "value"
+ )
+
+ wf_dict["properties"] = dd0 = properties.copy()
+ if wf_node.has_object("properties"):
+ dd0.update(wf_node["properties"].get_properties())
+ # Program-specific properties
+ devmode = dd0.get("co.gphl.wf.devMode")
+ if devmode and devmode[0] not in "fFnN":
+ # We are in developer mode. Add parameters
+ dd0["co.gphl.wf.stratcal.opt.--strategy_type"] = strategy_type
+
+ wf_dict["invocation_properties"] = dd0 = invocation_properties.copy()
+ if wf_node.has_object("invocation_properties"):
+ dd0.update(wf_node["invocation_properties"].get_properties())
+ #
+ return result
def query_pre_strategy_params(self, data_model, choose_lattice=None):
"""
@@ -226,76 +338,54 @@ def query_pre_collection_params(self, data_model):
def pre_execute(self, queue_entry):
- if self.is_ready():
- self.update_state(self.STATES.BUSY)
- else:
- raise RuntimeError(
- "Cannot execute workflow - GphlWorkflow HardwareObject is not ready"
- )
self._queue_entry = queue_entry
- data_model = queue_entry.get_data_model()
- self._workflow_queue = gevent.queue.Queue()
- HWR.beamline.gphl_connection.open_connection()
- if data_model.automation_mode:
- if data_model.get_workflow_parameters()["wftype"] == "acquisition":
- params = data_model.auto_char_params
- else:
- params = data_model.auto_acq_params
- else:
- # SIGNAL TO GET Pre-strategy parameters here
- # NB set defaults from data_model
- # NB consider whether to override on None
- params = self.query_pre_strategy_params(data_model)
- data_model.set_pre_strategy_params(**params)
- if data_model.detector_setting is None:
- resolution = HWR.beamline.resolution.get_value()
- distance = HWR.beamline.detector.distance.get_value()
- orgxy = HWR.beamline.detector.get_beam_position()
- data_model.detector_setting = GphlMessages.BcsDetectorSetting(
- resolution, orgxy=orgxy, Distance=distance
- )
- else:
- # Set detector distance and resolution
- distance = data_model.detector_setting.axisSettings["Distance"]
- HWR.beamline.detector.distance.set_value(distance, timeout=30)
- def execute(self):
+ if self.get_state() == self.STATES.OFF:
+ HWR.beamline.gphl_connection.open_connection()
+ self.update_state(self.STATES.READY)
- if HWR.beamline.gphl_connection is None:
- raise RuntimeError(
- "Cannot execute workflow - GphlWorkflowConnection not found"
- )
+ def execute(self):
- # Fork off workflow server process
- HWR.beamline.gphl_connection.start_workflow(
- self._workflow_queue, self._queue_entry.get_data_model()
- )
+ try:
+ self.update_state(self.STATES.BUSY)
- while True:
- if self._workflow_queue is None:
- # We can only get that value if we have already done post_execute
- # but the mechanics of aborting means we conme back
- # Stop further processing here
- raise QueueAbortedException("Aborting...", self)
-
- tt0 = self._workflow_queue.get()
- if tt0 is StopIteration:
- logging.getLogger("HWR").debug("GPhL queue StopIteration")
- break
-
- message_type, payload, correlation_id, result_list = tt0
- func = self._processor_functions.get(message_type)
- if func is None:
- logging.getLogger("HWR").error(
- "GPhL message %s not recognised by MXCuBE. Terminating...",
- message_type,
+ workflow_queue = gevent._threading.Queue()
+ # Fork off workflow server process
+ if HWR.beamline.gphl_connection is not None:
+ HWR.beamline.gphl_connection.start_workflow(
+ workflow_queue, self._queue_entry.get_data_model()
)
- break
- elif message_type != "String":
- logging.getLogger("HWR").info("GPhL queue processing %s", message_type)
- response = func(payload, correlation_id)
- if result_list is not None:
- result_list.append((response, correlation_id))
+
+ while True:
+ while workflow_queue.empty():
+ time.sleep(0.1)
+
+ tt0 = workflow_queue.get_nowait()
+ if tt0 is StopIteration:
+ break
+
+ message_type, payload, correlation_id, result_list = tt0
+ func = self._processor_functions.get(message_type)
+ if func is None:
+ logging.getLogger("HWR").error(
+ "GPhL message %s not recognised by MXCuBE. Terminating...",
+ message_type,
+ )
+ break
+ else:
+ logging.getLogger("HWR").info(
+ "GPhL queue processing %s", message_type
+ )
+ response = func(payload, correlation_id)
+ if result_list is not None:
+ result_list.append((response, correlation_id))
+
+ except Exception:
+ self.workflow_end()
+ logging.getLogger("HWR").error(
+ "Uncaught error during GPhL workflow execution", exc_info=True
+ )
+ raise
def post_execute(self):
"""
diff --git a/mxcubecore/HardwareObjects/GphlWorkflowConnection.py b/mxcubecore/HardwareObjects/GphlWorkflowConnection.py
index 90402db06a..dc838d35df 100644
--- a/mxcubecore/HardwareObjects/GphlWorkflowConnection.py
+++ b/mxcubecore/HardwareObjects/GphlWorkflowConnection.py
@@ -36,7 +36,7 @@
from mxcubecore.utils import conversion
from mxcubecore.HardwareObjects.Gphl import GphlMessages
-from mxcubecore.BaseHardwareObjects import HardwareObjectYaml
+from mxcubecore.BaseHardwareObjects import HardwareObject
from mxcubecore import HardwareRepository as HWR
# NB this is patching the original socket module in to avoid the
@@ -67,7 +67,7 @@
__author__ = "Rasmus H Fogh"
-class GphlWorkflowConnection(HardwareObjectYaml):
+class GphlWorkflowConnection(HardwareObject, object):
"""
This HO acts as a gateway to the Global Phasing workflow engine.
"""
@@ -95,6 +95,10 @@ def __init__(self, name):
self.connection_parameters = {}
self.software_paths = {}
self.software_properties = {}
+
+ # Properties for GPhL invocation
+ self.java_properties = {}
+
def _init(self):
super(GphlWorkflowConnection, self)._init()
@@ -109,27 +113,45 @@ def init(self):
self.connection_parameters["python_address"] = socket.gethostname()
# Adapt paths and properties to use directory_locations
- locations = self.directory_locations
- paths = self.software_paths
- properties = self.software_properties
+ #locations = self.directory_locations
+ #paths = self.software_paths
+ #properties = self.software_properties
+
+ if self.has_object("connection_parameters"):
+ self._connection_parameters.update(
+ self["connection_parameters"].get_properties()
+ )
+ if self.has_object("ssh_options"):
+ # We are running through ssh - so we need python_address
+ # If not, we stick to default, which is localhost (127.0.0.1)
+ self._connection_parameters["python_address"] = socket.gethostname()
- for tag, val in paths.items():
+ locations = next(self.get_objects("directory_locations")).get_properties()
+ paths = self.software_paths
+ props = self.java_properties
+ dd0 = next(self.get_objects("software_paths")).get_properties()
+
+ #for tag, val in paths.items():
+ for tag, val in dd0.items():
val2 = val.format(**locations)
if not os.path.isabs(val2):
val2 = HWR.get_hardware_repository().find_in_repository(val)
if val2 is None:
raise ValueError("File path %s not recognised" % val)
paths[tag] = val2
-
- for tag, val in properties.items():
+ dd0 = next(self.get_objects("software_properties")).get_properties()
+ #for tag, val in properties.items():
+ for tag, val in dd0.items():
val2 = val.format(**locations)
if not os.path.isabs(val2):
val2 = HWR.get_hardware_repository().find_in_repository(val)
if val2 is None:
raise ValueError("File path %s not recognised" % val)
- paths[tag] = properties[tag] = val2
+ #paths[tag] = properties[tag] = val2
+ paths[tag] = props[tag] = val2
- pp0 = properties["co.gphl.wf.bin"] = paths["GPHL_INSTALLATION"]
+ #pp0 = properties["co.gphl.wf.bin"] = paths["GPHL_INSTALLATION"]
+ pp0 = props["co.gphl.wf.bin"] = paths["GPHL_INSTALLATION"]
paths["BDG_home"] = paths.get("co.gphl.wf.bdg_licence_dir") or pp0
self.update_state(self.STATES.OFF)
diff --git a/mxcubecore/HardwareObjects/LdapLogin.py b/mxcubecore/HardwareObjects/LdapLogin.py
index cfdc28354b..4ec2c1506d 100644
--- a/mxcubecore/HardwareObjects/LdapLogin.py
+++ b/mxcubecore/HardwareObjects/LdapLogin.py
@@ -139,7 +139,7 @@ def login(self, username, password, retry=True, fields=None):
except ldap.LDAPError as err:
if retry:
self.cleanup(ex=err)
- return self.login(username, password, retry=False)
+ return self.login(username, password, retry=False, fields=fields)
else:
return self.cleanup(ex=err)
diff --git a/mxcubecore/HardwareObjects/QtGraphicsLib.py b/mxcubecore/HardwareObjects/QtGraphicsLib.py
index 6ff1a38752..d38da2f53e 100644
--- a/mxcubecore/HardwareObjects/QtGraphicsLib.py
+++ b/mxcubecore/HardwareObjects/QtGraphicsLib.py
@@ -1005,7 +1005,7 @@ def set_corner_coord(self, corner_coord):
self.__frame_polygon.setPoint(index, coord[0], coord[1])
if self.__overlay_pixmap:
- if min(self.__spacing_pix) < 20:
+ if min(self.__spacing_pix) > 20:
width = abs(corner_coord[0][0] - corner_coord[1][0])
height = abs(corner_coord[0][1] - corner_coord[3][1])
self.__overlay_pixmap.setPixmap(
@@ -1015,6 +1015,7 @@ def set_corner_coord(self, corner_coord):
self.__overlay_pixmap.setOpacity(self.__fill_alpha / 255.0)
self.__overlay_pixmap.setPos(corner_coord[0][0], corner_coord[0][1])
else:
+ #logging.getLogger("HWR").debug("__overlay_pixmap not visible")
self.__overlay_pixmap.setVisible(False)
self.__grid_size_pix[0] = self.__spacing_pix[0] * self.__num_cols
@@ -1039,7 +1040,7 @@ def set_overlay_pixmap(self, filename):
self.__frame_polygon.point(0).x(), self.__frame_polygon.point(0).y()
)
self.__overlay_pixmap.setOpacity(self.__fill_alpha / 255.0)
- self.__overlay_pixmap.setVisible(min(self.__spacing_pix) < 20)
+ self.__overlay_pixmap.setVisible(min(self.__spacing_pix) > 20)
def set_center_coord(self, center_coord):
"""
@@ -1058,6 +1059,7 @@ def set_spacing(self, spacing, adjust_size=False):
:param adjust_size: boolean
:return:
"""
+
self.__spacing_mm[0] = spacing[0]
self.__spacing_mm[1] = spacing[1]
self.__spacing_pix[0] = self.pixels_per_mm[0] * self.__spacing_mm[0]
diff --git a/mxcubecore/HardwareObjects/QtGraphicsManager.py b/mxcubecore/HardwareObjects/QtGraphicsManager.py
index 708928954f..fd3a8f79e8 100644
--- a/mxcubecore/HardwareObjects/QtGraphicsManager.py
+++ b/mxcubecore/HardwareObjects/QtGraphicsManager.py
@@ -2035,7 +2035,7 @@ def select_lines_and_grids(self):
for shape in self.shape_dict.values():
# for shape in self._shapes.get_all_shapes():
if isinstance(shape, GraphicsLib.GraphicsItemLine):
- (start_point, end_point) = shape.get_graphics_points()
+ (start_point, end_point) = shape.get_graphical_points()
if min(
start_point.start_coord[0], end_point.start_coord[0]
) < select_middle_x < max(
diff --git a/mxcubecore/HardwareObjects/QueueManager.py b/mxcubecore/HardwareObjects/QueueManager.py
index 187d77bdb2..80c571345b 100644
--- a/mxcubecore/HardwareObjects/QueueManager.py
+++ b/mxcubecore/HardwareObjects/QueueManager.py
@@ -135,7 +135,10 @@ def __execute_task(self):
qe.handle_exception(ex)
self.stop()
except gevent.GreenletExit:
- pass
+ #pass
+ logging.getLogger("user_level_log").warning(
+ "Queue execution GreenletExit error, " + str(ex)
+ )
if isinstance(ex, base_queue_entry.QueueAbortedException):
logging.getLogger("user_level_log").warning(
@@ -146,6 +149,8 @@ def __execute_task(self):
"Queue execution failed with: " + str(ex)
)
+ logging.getLogger("HWR").info( "traceback %s" % traceback.format_exc() )
+ logging.getLogger("HWR").info( "ex %s" % ex )
raise ex
finally:
self._running = False
diff --git a/mxcubecore/HardwareObjects/SardanaMotor.py b/mxcubecore/HardwareObjects/SardanaMotor.py
index c760e57aeb..620225f96b 100644
--- a/mxcubecore/HardwareObjects/SardanaMotor.py
+++ b/mxcubecore/HardwareObjects/SardanaMotor.py
@@ -59,7 +59,7 @@ def __init__(self, name):
self.limit_lower = None
self.static_limits = (-1e4, 1e4)
self.limits = (None, None)
- self.motor_state = MotorStates.NOTINITIALIZED
+ self.motor_state = MotorStates.INITIALIZING
def init(self):
@@ -175,7 +175,7 @@ def motor_state_changed(self, state=None):
if state is None:
state = self.state_channel.get_value()
- state = str(state)
+ state = str(state).strip("DevState.")
motor_state = SardanaMotor.state_map[state]
if motor_state != MotorStates.DISABLED:
@@ -184,7 +184,6 @@ def motor_state_changed(self, state=None):
elif self.motor_position <= self.limit_lower:
motor_state = MotorStates.LOWLIMIT
- self.set_ready(motor_state > MotorStates.DISABLED)
if motor_state != self.motor_state:
self.motor_state = motor_state
@@ -216,6 +215,9 @@ def get_limits(self):
static_limits is returned
"""
try:
+ info = self.position_channel.get_info()
+ self.limit_lower = info.minval
+ self.limit_upper = info.maxval
return (self.limit_lower, self.limit_upper)
except Exception:
return (None, None)
diff --git a/mxcubecore/HardwareObjects/SimpleHTML.py b/mxcubecore/HardwareObjects/SimpleHTML.py
index 22dcab81f1..6d39834737 100644
--- a/mxcubecore/HardwareObjects/SimpleHTML.py
+++ b/mxcubecore/HardwareObjects/SimpleHTML.py
@@ -131,7 +131,7 @@ def create_json_images(image_list):
return json_item
-def generate_parallel_processing_report(mesh_scan_results, params_dict):
+def generate_online_processing_report(mesh_scan_results, params_dict):
json_dict = {"items": []}
html_file = open(params_dict["html_file_path"], "w")
@@ -144,7 +144,7 @@ def generate_parallel_processing_report(mesh_scan_results, params_dict):
html_file.write(HTML_START % "Line scan results")
json_dict["items"].append({"type": "title", "value": "Line scan results"})
- html_file.write(create_image("parallel_processing_plot.png"))
+ html_file.write(create_image("online_processing_plot.png"))
html_file.write("")
html_file.write(create_text("Scan parameters", heading=1))
osc_range_per_line = params_dict["osc_range"] * (params_dict["images_per_line"] - 1)
diff --git a/mxcubecore/HardwareObjects/XMLRPCServer.py b/mxcubecore/HardwareObjects/XMLRPCServer.py
index 70375f314a..846847c664 100644
--- a/mxcubecore/HardwareObjects/XMLRPCServer.py
+++ b/mxcubecore/HardwareObjects/XMLRPCServer.py
@@ -169,7 +169,7 @@ def open(self):
def anneal(self, time):
cryoshutter_hwobj = self.get_object_by_role("cryoshutter")
try:
- cryoshutter_hwobj.getCommandObject("anneal")(time)
+ cryoshutter_hwobj.get_command_object("anneal")(time)
except Exception as ex:
logging.getLogger("HWR").exception(str(ex))
raise
diff --git a/mxcubecore/HardwareObjects/abstract/AbstractCollect.py b/mxcubecore/HardwareObjects/abstract/AbstractCollect.py
index f13880b8c7..5d33cebb7e 100644
--- a/mxcubecore/HardwareObjects/abstract/AbstractCollect.py
+++ b/mxcubecore/HardwareObjects/abstract/AbstractCollect.py
@@ -171,12 +171,22 @@ def do_collect(self, owner):
"%Y-%m-%d %H:%M:%S"
)
+ log.info("Collection: Storing data collection in LIMS")
+ self.store_data_collection_in_lims()
+
logging.getLogger("HWR").info(
"Collection parameters: %s" % str(self.current_dc_parameters)
)
- log.info("Collection: Storing data collection in LIMS")
- self.store_data_collection_in_lims()
+ if (
+ self.current_dc_parameters['processing_online']
+ and HWR.beamline.online_processing is not None
+ ):
+ HWR.beamline.online_processing.params_dict["collection_id"] = self.current_dc_parameters["collection_id"]
+ self.online_processing_task = gevent.spawn(
+ HWR.beamline.online_processing.run_processing,
+ self.current_dc_parameters
+ )
log.info(
"Collection: Creating directories for raw images and processing files"
@@ -610,7 +620,7 @@ def update_data_collection_in_lims(self):
i += 1
params[
"resolutionAtCorner"
- ] = HWR.beamline.resolution.get_value_at_corner()
+ ] = self.get_value_at_corner()
beam_size_x, beam_size_y = HWR.beamline.beam.get_beam_size()
params["beamSizeAtSampleX"] = beam_size_x
params["beamSizeAtSampleY"] = beam_size_y
@@ -833,6 +843,13 @@ def data_collection_hook(self):
"""
pass
+ @abc.abstractmethod
+ def get_value_at_corner(self):
+ """
+ Descript. :
+ """
+ pass
+
@abc.abstractmethod
def trigger_auto_processing(self, process_event, frame_number):
"""
diff --git a/mxcubecore/HardwareObjects/abstract/AbstractMotor.py b/mxcubecore/HardwareObjects/abstract/AbstractMotor.py
index 1147957769..0f1c21058d 100644
--- a/mxcubecore/HardwareObjects/abstract/AbstractMotor.py
+++ b/mxcubecore/HardwareObjects/abstract/AbstractMotor.py
@@ -40,11 +40,22 @@
class MotorStates(Enum):
"""Motor states definitions."""
- HOME = HardwareObjectState.READY, 5
- LOWLIMIT = HardwareObjectState.READY, 6
- HIGHLIMIT = HardwareObjectState.READY, 7
- MOVING = HardwareObjectState.BUSY, 8
+ INITIALIZING = HardwareObjectState.BUSY, 0
+ ON = HardwareObjectState.READY, 1
+ OFF = HardwareObjectState.OFF, 2
+ READY = HardwareObjectState.READY, 3
+ BUSY = HardwareObjectState.BUSY, 4
+ MOVING = HardwareObjectState.BUSY, 5
+ STANDBY = HardwareObjectState.READY, 6
+ DISABLED = HardwareObjectState.FAULT, 7
+ UNKNOWN= HardwareObjectState.UNKNOWN, 8
+ ALARM = HardwareObjectState.FAULT, 9
+ FAULT = HardwareObjectState.FAULT, 10
+ INVALID = HardwareObjectState.FAULT, 11
+ OFFLINE = HardwareObjectState.OFF, 12
+ LOWLIMIT = HardwareObjectState.READY, 13
+ HIGHLIMIT = HardwareObjectState.READY, 14
class AbstractMotor(AbstractActuator):
"""Abstract motor class"""
diff --git a/mxcubecore/HardwareObjects/abstract/AbstractSampleChanger.py b/mxcubecore/HardwareObjects/abstract/AbstractSampleChanger.py
index 891ac82b77..f11d240889 100644
--- a/mxcubecore/HardwareObjects/abstract/AbstractSampleChanger.py
+++ b/mxcubecore/HardwareObjects/abstract/AbstractSampleChanger.py
@@ -253,10 +253,10 @@ def init(self):
self.update_info()
def _on_timer_1s_exit(self, task):
- logging.warning("Exiting Sample Changer 1s timer task")
+ logging.getLogger("HWR").warning("Exiting Sample Changer 1s timer task")
def _on_timer_update_exit(self, task):
- logging.warning("Exiting Sample Changer update timer task")
+ logging.getLogger("HWR").warning("Exiting Sample Changer update timer task")
@task
def __timer_1s_task(self, *args):
@@ -729,7 +729,7 @@ def _do_reset(self):
def _execute_task(self, task, wait, method, *args):
self.assert_can_execute_task()
- logging.debug("Start " + SampleChangerState.tostring(task))
+ logging.getLogger("HWR").debug("Start " + SampleChangerState.tostring(task))
self.task = task
self.task_error = None
self._set_state(task)
@@ -779,9 +779,9 @@ def _on_task_failed(self, task, exception):
def _on_task_ended(self, task):
try:
e = task.get()
- logging.debug("Task ended. Return value: " + str(e))
+ logging.getLogger("HWR").debug("Task ended. Return value: " + str(e))
except Exception as errmsg:
- logging.error("Error while executing sample changer task: %s", str(errmsg))
+ logging.getLogger("HWR").error("Error while executing sample changer task: %s", str(errmsg))
def _set_state(self, state=None, status=None):
if (state is not None) and (self.state != state):
diff --git a/mxcubecore/HardwareObjects/queue_entry.py b/mxcubecore/HardwareObjects/queue_entry.py
index 77132678be..8874b72cdc 100644
--- a/mxcubecore/HardwareObjects/queue_entry.py
+++ b/mxcubecore/HardwareObjects/queue_entry.py
@@ -742,11 +742,11 @@ def collect_dc(self, dc, list_item):
if (
dc.run_online_processing
- and acq_1.acquisition_parameters.num_images > 4
and HWR.beamline.online_processing is not None
):
+ HWR.beamline.online_processing.data_collection = dc
self.online_processing_task = gevent.spawn(
- HWR.beamline.online_processing.run_processing, dc
+ HWR.beamline.online_processing.prepare_processing
)
empty_cpos = queue_model_objects.CentredPosition()
@@ -1009,44 +1009,51 @@ def start_char(self):
self.edna_result = HWR.beamline.characterisation.characterise(edna_input)
if self.edna_result:
- log.info("Characterisation completed.")
+ if self.edna_result != 'NOT DONE':
+ log.info("Characterisation completed.")
- char.html_report = HWR.beamline.characterisation.get_html_report(
- self.edna_result
- )
-
- try:
- strategy_result = (
- self.edna_result.getCharacterisationResult().getStrategyResult()
+ char.html_report = HWR.beamline.characterisation.get_html_report(
+ self.edna_result
)
- except Exception:
- strategy_result = None
- if strategy_result:
- collection_plan = strategy_result.getCollectionPlan()
- else:
- collection_plan = None
+ try:
+ strategy_result = (
+ self.edna_result.getCharacterisationResult().getStrategyResult()
+ )
+ except Exception:
+ strategy_result = None
- if collection_plan:
- if char.auto_add_diff_plan:
- # default action
- self.handle_diffraction_plan(self.edna_result, None)
+ if strategy_result:
+ collection_plan = strategy_result.getCollectionPlan()
else:
- collections = HWR.beamline.characterisation.dc_from_output(
- self.edna_result, char.reference_image_collection
- )
- char.diffraction_plan.append(collections)
- HWR.beamline.queue_model.emit(
- "diff_plan_available", (char, collections)
- )
+ collection_plan = None
+
+ if collection_plan:
+ if char.auto_add_diff_plan:
+ # default action
+ self.handle_diffraction_plan(self.edna_result, None)
+ else:
+ collections = HWR.beamline.characterisation.dc_from_output(
+ self.edna_result, char.reference_image_collection
+ )
+ char.diffraction_plan.append(collections)
+ HWR.beamline.queue_model.emit(
+ "diff_plan_available", (char, collections)
+ )
- self.get_view().setText(1, "Done")
+ self.get_view().setText(1, "Done")
+ else:
+ self.get_view().setText(1, "No result")
+ self.status = QUEUE_ENTRY_STATUS.WARNING
+ log.warning(
+ "Characterisation completed "
+ + "successfully but without collection plan."
+ )
else:
- self.get_view().setText(1, "No result")
+ self.get_view().setText(1, "Not run")
self.status = QUEUE_ENTRY_STATUS.WARNING
log.warning(
- "Characterisation completed "
- + "successfully but without collection plan."
+ "Characterisation not initiated."
)
else:
self.get_view().setText(1, "Charact. Failed")
diff --git a/mxcubecore/HardwareObjects/queue_model_objects.py b/mxcubecore/HardwareObjects/queue_model_objects.py
index 4e5e3109e0..5c78ae59aa 100644
--- a/mxcubecore/HardwareObjects/queue_model_objects.py
+++ b/mxcubecore/HardwareObjects/queue_model_objects.py
@@ -32,6 +32,11 @@
from mxcubecore import HardwareRepository as HWR
+try:
+ from collections import OrderedDict
+except ImportError:
+ from ordereddict import OrderedDict
+
__copyright__ = """ Copyright © 2010 - 2020 by MXCuBE Collaboration """
__license__ = "LGPLv3+"
@@ -1857,394 +1862,182 @@ def get_path_template(self):
return self.path_template
+
class GphlWorkflow(TaskNode):
- def __init__(self):
+ def __init__(self, workflow_hwobj):
TaskNode.__init__(self)
-
- workflow_hwobj = HWR.beamline.gphl_workflow
-
- # Workflow start attriutes
+ self.workflow_hwobj = workflow_hwobj
self.path_template = PathTemplate()
+ self._name = str()
self._type = str()
- self.shape = str()
- # string. Only active mode currently is 'MASSIF1'
- self.automation_mode = None
- # Automation mode charancterisation parameters. Replace UI queried values
- self.auto_char_params = {}
- # Automation mode acquisition parameters. Replace UI queried values
- self.auto_acq_params = {}
- # Full path of characterisation data directory, if pre-acquired
- # self.characterisation_directory = None
-
- # Pre-strategy attributes
- self.space_group = str()
- self.crystal_system = str()
- self.point_group = None
- self.bravais_lattice = None
- self._cell_parameters = ()
- self.beamstop_setting = None
- self.wavelengths = ()
- self.detector_setting = None
- self.aimed_resolution = None
- self.goniostat_translations = ()
- self.strategy = str()
- self.characterisation_strategy = str()
- self.strategy_options = {}
-
- # Pre-collection attributes
- # Attributes for workflow
- self.exposure_time = 0.0
- self.image_width = 0.0
- self.wedge_width = 0.0
- self.transmission = 0.0
- self.snapshot_count = 2
- # Workflow interleave order (string).
- # Slowest changing first, characters 'g' (Goniostat position);
- # 's' (Scan number), 'b' (Beam wavelength), 'd' (Detector position)
- self.interleave_order = "gs"
-
- # Centring handling and MXCuBE-side flow
- self.recentring_mode = "sweep"
- self.current_rotation_id = None
- self.characterisation_done = False
- # Dose budget handling
- self.maximum_dose_budget = 20.0
- self.dose_budget = None
- self.decay_limit = 25
- self.characterisation_budget_fraction = 0.05
- self.relative_rad_sensitivity = 1.0
- self.dose_consumed = 0.0
- self.strategy_length = 0.0
+ self._characterisation_strategy = str()
+ self._interleave_order = str()
+ self._number = 0
+ self._beam_energies = OrderedDict()
+ self._detector_resolution = None
+ self._space_group = None
+ self._crystal_system = None
+ self._point_group = None
+ self._cell_parameters = None
+ self._snapshot_count = None
+ self._centre_before_sweep = None
+ self._centre_before_scan = None
+
+ self._dose_budget = None
+ self._characterisation_budget_fraction = 1.0
+ self._relative_rad_sensitivity = 1.0
+
+ # HACK - to differentiate between characterisation and acquisition
+ # TODO remove when workflow gives relevant information
+ self.lattice_selected = False
self.set_requires_centring(False)
- self.set_from_dict(workflow_hwobj.settings["defaults"])
+ # Workflow name (string) - == path_template.base_prefix.
+ def get_name(self):
+ return self._name
- def set_from_dict(self, params_dict):
- for dict_item in params_dict.items():
- if hasattr(self, dict_item[0]):
- setattr(self, dict_item[0], dict_item[1])
+ def set_name(self, value):
+ self._name = value
- def set_pre_strategy_params(
- self,
- point_group="",
- bravais_lattice="",
- crystal_system="",
- space_group=None,
- cell_parameters=(),
- resolution=None,
- energies=(),
- relative_rad_sensitivity=None,
- strategy_options=None,
- **unused):
- """"""
-
- from mxcubecore.HardwareObjects.Gphl import GphlMessages
-
- # Order of precedence: space_group, point_group, bravais_lattice.
- if space_group:
- # Space group overrides point group and and bravais latice
- self.space_group = space_group
- self.point_group = None
- self.bravais_lattice = None
- else:
- if point_group:
- # To avoid compatibility problems, reset other parameters
- # NB Crystal system follows from point group
- self.space_group = None
- self.point_group = point_group
- self.bravais_lattice = None
- if bravais_lattice:
- # NB there are compatibility problems here - TODO
- self.bravais_lattice = bravais_lattice
- if cell_parameters:
- self.cell_parameters = cell_parameters
-
- workflow_parameters = self.get_workflow_parameters()
-
- # NB this is an internal dictionary. DO NOT MODIFY
- settings = HWR.beamline.gphl_workflow.settings
- energy_tags = workflow_parameters.get(
- "beam_energy_tags", (settings["default_beam_energy_tag"],)
- )
- interleave_order = workflow_parameters.get("interleave_order")
- if interleave_order:
- self.interleave_order = interleave_order
-
- if energies:
- if len(energy_tags) != len(energies):
- raise ValueError(
- "Strategy should have %s energies, value was %s"
- % (len(energy_tags), energies)
- )
- wavelengths = []
- for iii, role in enumerate(energy_tags):
- wavelengths.append(
- GphlMessages.PhasingWavelength(
- wavelength= HWR.beamline.energy.get_wavelength(energies[iii]),
- role=role
- )
- )
- self.wavelengths = tuple(wavelengths)
- else:
- if len(energy_tags) != 1:
- raise ValueError(
- "Strategy should have %s explicit energies, values missing"
- % len(energy_tags)
- )
+ # Workflow type (string).
+ def get_type(self):
+ return self._type
- wavelength = self.wavelengths[0].wavelength
+ def set_type(self, value):
+ self._type = value
- if self.detector_setting is None:
- resolution = resolution or self.aimed_resolution
- if resolution:
- distance = HWR.beamline.resolution.resolution_to_distance(
- resolution, wavelength
- )
- orgxy = HWR.beamline.detector.get_beam_position(
- distance, wavelength
- )
- self.detector_setting = GphlMessages.BcsDetectorSetting(
- resolution, orgxy=orgxy, Distance=distance
- )
+ # Workflow interleave order (string).
+ # Slowest changing first, characters 'g' (Goniostat position);
+ # 's' (Scan number), 'b' (Beam wavelength), 'd' (Detector position)
+ def get_interleave_order(self):
+ return self._interleave_order
- self.strategy_options = {
- "strategy_type": workflow_parameters["strategy_type"],
- "angular_tolerance": settings["angular_tolerance"],
- "maximum_chi": settings["maximum_chi"],
- "variant": workflow_parameters["variants"][0],
- }
- if strategy_options:
- self.strategy_options.update(strategy_options)
-
- def set_pre_acquisition_params(
- self,
- exposure_time=None,
- image_width=None,
- wedge_width=None,
- transmission=None,
- snapshot_count=None,
- **unused
- ):
- """"""
- if exposure_time:
- self.exposure_time = float(exposure_time)
- if image_width:
- self.image_width = float(image_width)
- if wedge_width:
- self.wedge_width = float(wedge_width)
- if transmission:
- # NBNB TODO transmission must be calculated
- # for chareacterisation and acquisition
- self.transmission = float(transmission)
- if snapshot_count:
- self.snapshot_count = int(snapshot_count)
-
- def init_from_task_data(self, sample_model, params):
- """
- sample_model is required as this may be called before the object is enqueued
- params is a dictionary with structure determined by mxcube3 usage
- - in this function it is used only for PathTemplate data and strategy_name
- """
+ def set_interleave_order(self, value):
+ self._interleave_order = value
- from mxcubecore.HardwareObjects.Gphl import GphlMessages
+ # Starting run number. Unnecessary.
+ # Left in as it is modified by signal when edited.
+ def get_number(self):
+ logging.getLogger().warning(
+ "Attempt to get unused attribute GphlWorkflow.number"
+ )
+ return None
- # NB settings is an internal attribute DO NOT MODIFY
- settings = HWR.beamline.gphl_workflow.settings
- self.auto_char_params = copy.deepcopy(settings.get("auto_char_params", {}))
- self.auto_char_params.update(params.pop("auto_char_params", {}))
- self.auto_acq_params = copy.deepcopy(settings.get("auto_acq_params", {}))
- self.auto_acq_params.update(params.pop("auto_acq_params", {}))
+ def set_number(self, value):
+ logging.getLogger().warning(
+ "Attempt to set unused attribute GphlWorkflow.number"
+ )
- automation_mode = params.get("automation_mode")
- if automation_mode:
- # Set automation defaults and parameters
- self.automation_mode = automation_mode
+ # Detector resolution (determines detector distance).
+ def get_detector_resolution(self):
+ return self._detector_resolution
- # Set path template
- self.path_template.set_from_dict(params)
+ def set_detector_resolution(self, value):
+ self._detector_resolution = value
- if params["prefix"]:
- self.path_template.base_prefix = params["prefix"]
- else:
- self.path_template.base_prefix = HWR.beamline.session.get_default_prefix(
- sample_model
- )
+ # role:value beam_energy dictionary (in keV)
+ def get_beam_energies(self):
+ return self._beam_energies.copy()
- self.path_template.num_files = 0
- self.path_template.precision = "0" + str(
- HWR.beamline.session["file_info"].get_property("precision", 4)
- )
+ def set_beam_energies(self, value):
+ self._beam_energies = OrderedDict(value)
- self.path_template.directory = os.path.join(
- HWR.beamline.session.get_base_image_directory(), params.get("subdir", "")
- )
+ # Space Group.
+ def get_space_group(self):
+ return self._space_group
- self.path_template.process_directory = os.path.join(
- HWR.beamline.session.get_base_process_directory(), params.get("subdir", ""),
- )
+ def set_space_group(self, value):
+ self._space_group = value
- # Set crystal parameters from sample node
- crystal = sample_model.crystals[0]
- tpl = (
- crystal.cell_a, crystal.cell_b, crystal.cell_c,
- crystal.cell_alpha, crystal.cell_beta, crystal.cell_gamma
- )
- if all(tpl):
- self.cell_parameters = tpl
- self.space_group = crystal.space_group
- self.protein_acronym = crystal.protein_acronym
-
- # Set to current wavelength for now - nothing else available
- wavelength = HWR.beamline.energy.get_wavelength()
- role = HWR.beamline.gphl_workflow.settings["default_beam_energy_tag"]
- self.wavelengths = (
- GphlMessages.PhasingWavelength(wavelength=wavelength, role=role),
- )
+ # Characterisation strategy.
+ def get_characterisation_strategy(self):
+ return self._characterisation_strategy
- # First set some parameters from defaults
- default_parameters = HWR.beamline.get_default_acquisition_parameters()
- self.aimed_resolution = default_parameters.resolution
- self.exposure_time = default_parameters.exp_time
- self.image_width = default_parameters.osc_range
-
- # Set parameters from diffraction plan
- diffraction_plan = sample_model.diffraction_plan
- if diffraction_plan:
- # It is not clear if diffraction_plan is a dict or an object,
- # and if so which kind
- if hasattr(diffraction_plan, "radiationSensitivity"):
- radiation_sensitivity = diffraction_plan.radiationSensitivity
- else:
- radiation_sensitivity = diffraction_plan.get("radiationSensitivity")
+ def set_characterisation_strategy(self, value):
+ self._characterisation_strategy = value
- if radiation_sensitivity:
- self.relative_rad_sensitivity = radiation_sensitivity
+ # Crystal system.
+ def get_crystal_system(self):
+ return self._crystal_system
- if hasattr(diffraction_plan, "aimedResolution"):
- resolution = diffraction_plan.aimedResolution
- else:
- resolution = diffraction_plan.get("aimedResolution")
+ def set_crystal_system(self, value):
+ self._crystal_system = value
- if resolution:
- self.aimed_resolution = resolution
+ # Point Group.
+ def get_point_group(self):
+ return self._point_group
- # Swt paramaters from params dict
- self.set_name(self.path_template.base_prefix)
- self.set_type(params["strategy_name"])
- self.shape = params.get("shape", "")
+ def set_point_group(self, value):
+ self._point_group = value
- def get_workflow_parameters(self):
- """Get parameters dictionary for workflow strategy"""
- for wfdict in HWR.beamline.gphl_workflow.get_available_workflows().values():
- for stratdict in wfdict["strategies"]:
- if stratdict["title"] == self.get_type():
- return stratdict
- raise ValueError("No GPhL workflow strategy named %s found" % self.get_type())
-
- # Parameters for start of workflow
- def get_path_template(self):
- return self.path_template
+ # Dose budget (MGy, float).
+ def get_dose_budget(self):
+ return self._dose_budget
- # Strategy type (string); e.g. 'phasing'
- def get_type(self):
- return self._type
+ def set_dose_budget(self, value):
+ self._dose_budget = value
- def set_type(self, value):
- self._type = value
+ # Fraction of dose budget intended for characterisation.
+ def get_characterisation_budget_fraction(self):
+ return self._characterisation_budget_fraction
- # Run name equal to base_prefix
- def get_name(self):
- return self._name
+ def set_characterisation_budget_fraction(self, value):
+ self._characterisation_budget_fraction = value
- def set_name(self, value):
- self._name = value
+ # Radiation sensitivity of crystal, relative to a 'standard crystal'.
+ def get_relative_rad_sensitivity(self):
+ return self._relative_rad_sensitivity
+
+ def set_relative_rad_sensitivity(self, value):
+ self._relative_rad_sensitivity = value
# Cell parameters - sequence of six floats (a,b,c,alpha,beta,gamma)
- @property
- def cell_parameters(self):
+ def get_cell_parameters(self):
return self._cell_parameters
- @cell_parameters.setter
- def cell_parameters(self, value):
- self._cell_parameters = None
+ def set_cell_parameters(self, value):
if value:
if len(value) == 6:
self._cell_parameters = tuple(float(x) for x in value)
else:
- raise ValueError("invalid value for cell_parameters: %s" % str(value))
-
- def calculate_transmission(self):
- """Calculate transmission matching current parameters"""
-
- transmission = None
- strategy_length = self.strategy_length
- energy = HWR.beamline.energy.calculate_energy(self.wavelengths[0].wavelength)
- exposure_time = self.exposure_time
- image_width = self.image_width
-
- flux_density = HWR.beamline.flux.get_average_flux_density(transmission=100.0)
- if flux_density:
- std_dose_rate = (
- HWR.beamline.flux.get_dose_rate_per_photon_per_mmsq(energy)
- * flux_density
- * 1.0e-6 # convert to MGy/s
- )
+ raise ValueError("cell_parameters %s does not have length six" % value)
+ else:
+ self._cell_parameters = None
- if image_width and exposure_time and std_dose_rate:
- experiment_time = exposure_time * strategy_length / image_width
- max_dose = std_dose_rate * experiment_time
- transmission = 100. * self.dose_budget / max_dose
- if not transmission:
- msg = (
- "Transmission could not be calculated from:\n"
- " energy:%s keV, strategy_length:%s deg, exposure_time:%s s, image_width:%s deg, "
- "flux_density:%s photons/mm^2"
- )
- raise ValueError(
- msg % (energy, strategy_length, exposure_time, image_width, flux_density)
- )
- #
- return transmission
+ # Number of snapshots to take at start of data collection.
+ def get_snapshot_count(self):
+ return self._snapshot_count
- def apply_transmission(self):
- """Reset dose_budget to match current transmission"""
- transmission = self.calculate_transmission()
- self.dose_budget = self.dose_budget * self.transmission / transmission
+ def set_snapshot_count(self, value):
+ self._snapshot_count = value
- def apply_dose_budget(self):
- """
- Set dose budget, changing transmission, and (if necessary) also exposure time
- """
- transmission = self.calculate_transmission()
- if transmission > 100.:
- exposure_limits = HWR.beamline.detector.get_exposure_time_limits()
- self.exposure_time = min(
- exposure_limits[1], self.exposure_time * transmission / 100.
- )
- self.transmission = 100
- self.apply_transmission()
- else:
- self.transmission = transmission
+ # (Re)centre before each sweep?.
+ def get_centre_before_sweep(self):
+ return self._centre_before_sweep
- def reset_transmission(self):
- """reset transmission to match current parameters, lowering dose budget if transmission goes over 100,
- reducing dose if transmission goes over 100
+ def set_centre_before_sweep(self, value):
+ self._centre_before_sweep = bool(value)
- NB intended for running in auto mode, or for changing xposure)time etc."""
- transmission = self.calculate_transmission()
- if transmission > 100.:
- self.transmission = 100.
- self.dose_budget = self.dose_budget * 100. / transmission
- else:
- self.transmission = transmission
+ # (Re)centre before each scan?.
+ def get_centre_before_scan(self):
+ return self._centre_before_scan
- def get_default_dose_budget(self):
- """Get resolution-dependent dose budget using configured values"""
- resolution = self.detector_setting.resolution
- result = 2 * resolution * resolution * math.log(100.0 / self.decay_limit)
- #
- return min(result, self.maximum_dose_budget) / self.relative_rad_sensitivity
+ def set_centre_before_scan(self, value):
+ self._centre_before_scan = bool(value)
+
+ def get_path_template(self):
+ return self.path_template
+
+ def get_workflow_parameters(self):
+ result = HWR.beamline.gphl_workflow.get_available_workflows().get(
+ self.get_type()
+ )
+ if result is None:
+ raise RuntimeError(
+ "No parameters for unknown workflow %s" % repr(self.get_type())
+ )
+ return result
class XrayImaging(TaskNode):
def __init__(self, xray_imaging_params, acquisition=None, crystal=None, name=""):
diff --git a/mxcubecore/HardwareRepository.py b/mxcubecore/HardwareRepository.py
index 25bc4b087d..9f67192d6e 100644
--- a/mxcubecore/HardwareRepository.py
+++ b/mxcubecore/HardwareRepository.py
@@ -36,7 +36,9 @@
import importlib
from datetime import datetime
+#RB: no module named ruamel.yaml, conda environment update needed?
from ruamel.yaml import YAML
+#import yaml
from mxcubecore.utils.conversion import string_types, make_table
from mxcubecore.dispatcher import dispatcher
@@ -53,9 +55,11 @@
# If you want to write out copies of the file, use typ="rt" instead
# pure=True uses yaml version 1.2, with fewere gotchas for strange type conversions
+#RB: since YAML doesnt exist, remove this line
yaml = YAML(typ="safe", pure=True)
# The following are not needed for load, but define the default style.
yaml.default_flow_style = False
+#RB: yaml module has no attribute indent, probably needs the ruamel version
yaml.indent(mapping=4, sequence=4, offset=2)
@@ -176,7 +180,9 @@ def load_from_yaml(configuration_file, role, _container=None, _table=None):
(role, class_name, configuration_file, "%.1d" % load_time, msg1)
)
msg0 = "Done loading contents"
+ #RB: critical bug, objects does not have an attibute items
for role1, config_file in _objects.items():
+ #for role1, config_file in _objects:
fname, fext = os.path.splitext(config_file)
if fext == ".yml":
load_from_yaml(
diff --git a/mxcubecore/Poller.py b/mxcubecore/Poller.py
index a8c7401a03..4ccedd15ac 100644
--- a/mxcubecore/Poller.py
+++ b/mxcubecore/Poller.py
@@ -90,14 +90,11 @@ def __init__(
self.error_callback_ref = saferef.safe_ref(error_callback)
self.compare = compare
self.old_res = NotInitializedValue
- self.queue = queue.Queue()
+ self.queue = queue.Queue()#_threading.Queue()
self.delay = 0
self.stop_event = Event()
- if gevent_version < [1, 3, 0]:
- self.async_watcher = getattr(gevent.get_hub().loop, "async")()
- else:
- self.async_watcher = gevent.get_hub().loop.async_()
+ self.async_watcher = gevent.get_hub().loop.async()
def start_delayed(self, delay):
self.delay = delay
@@ -209,6 +206,7 @@ def run(self):
if new_value:
self.old_res = res
self.queue.put(res)
+ self.async_watcher.send()
sleep(self.polling_period / 1000.0)
if error_cb is not None:
diff --git a/mxcubecore/__init__.py b/mxcubecore/__init__.py
index a15f6b3485..257be06aa4 100644
--- a/mxcubecore/__init__.py
+++ b/mxcubecore/__init__.py
@@ -80,7 +80,7 @@ def setLogFile(filename):
#
# log to rotating files
#
- hdlr = RotatingFileHandler(filename, "a", 1048576, 5) # 1 MB by file, 5 files max.
+ hdlr = RotatingFileHandler(filename, "a", 1048576, 15) # 1 MB by file, 5 files max.
hdlr.setFormatter(_hwr_formatter)
setLoggingHandler(hdlr)
diff --git a/mxcubecore/configuration/alba_xaloc13/Qt4_graphics-manager.xml b/mxcubecore/configuration/alba_xaloc13/Qt4_graphics-manager.xml.unused
similarity index 60%
rename from mxcubecore/configuration/alba_xaloc13/Qt4_graphics-manager.xml
rename to mxcubecore/configuration/alba_xaloc13/Qt4_graphics-manager.xml.unused
index 4676f5b052..53bc4ae5f6 100755
--- a/mxcubecore/configuration/alba_xaloc13/Qt4_graphics-manager.xml
+++ b/mxcubecore/configuration/alba_xaloc13/Qt4_graphics-manager.xml.unused
@@ -1,6 +1,7 @@
-
+
-
+
+ (1, 1.5, 2.)
diff --git a/mxcubecore/configuration/alba_xaloc13/Qt4_testvideo.xml b/mxcubecore/configuration/alba_xaloc13/Qt4_testvideo.xml.unused
similarity index 100%
rename from mxcubecore/configuration/alba_xaloc13/Qt4_testvideo.xml
rename to mxcubecore/configuration/alba_xaloc13/Qt4_testvideo.xml.unused
diff --git a/mxcubecore/configuration/alba_xaloc13/backlight.xml b/mxcubecore/configuration/alba_xaloc13/backlight.xml
index fcd5594dd9..9bd0ca754c 100755
--- a/mxcubecore/configuration/alba_xaloc13/backlight.xml
+++ b/mxcubecore/configuration/alba_xaloc13/backlight.xml
@@ -1,8 +1,8 @@
-
+
Back
BackLightIn
Brightness
0
- 9
- 0,30
+ 35
+ 0,35
diff --git a/mxcubecore/configuration/alba_xaloc13/beam-info.xml b/mxcubecore/configuration/alba_xaloc13/beam-info.xml
deleted file mode 100755
index 4212e4d17e..0000000000
--- a/mxcubecore/configuration/alba_xaloc13/beam-info.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-
- bl13/ct/variables
-
- ImageCenterX
- ImageCenterY
- BeamWidth
- BeamHeight
-
- 230.0
- 150.0
-
diff --git a/mxcubecore/configuration/alba_xaloc13/beam.xml b/mxcubecore/configuration/alba_xaloc13/beam.xml
new file mode 100755
index 0000000000..846245bbe4
--- /dev/null
+++ b/mxcubecore/configuration/alba_xaloc13/beam.xml
@@ -0,0 +1,12 @@
+
+ bl13/ct/variables
+
+ ImageCenterX
+ ImageCenterY
+ BeamWidth
+ BeamHeight
+
+ 230.0
+ 150.0
+
+
diff --git a/mxcubecore/configuration/alba_xaloc13/beamline-setup.xml b/mxcubecore/configuration/alba_xaloc13/beamline-setup.xml
deleted file mode 100755
index 4ea03efd3c..0000000000
--- a/mxcubecore/configuration/alba_xaloc13/beamline-setup.xml
+++ /dev/null
@@ -1,112 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ["MeshScan", "XrayCentering"]
-
-
- True
-
-
- True
-
-
-
- DECTRIS
- pilatus
- 6M_F
- 0.172
- 0.172
- yes
- True
-
-
-
-
- 0.3
- 0.0
- 0.1
- 1
- 1
- 1
- 0
- 1
- 1
-
-
-
- 0.040
- 0.0
- 0.1
- 1
- 1
- 1
- 0
- 100
- 1
-
-
-
- -2165,2165
- 0.003,6000
- 1,9999
-
-
-
-
- 0.3
- 0.0
- 1
- 1
- 1
- 1
- 0
- 1
- 1
-
-
-
- 0.040
- 0.0
- 0.5
- 1
- 1
- 1
- 0
- 100
- 1
-
-
diff --git a/mxcubecore/configuration/alba_xaloc13/beamline_config.yml b/mxcubecore/configuration/alba_xaloc13/beamline_config.yml
old mode 100644
new mode 100755
index 6aa1af4bd5..cb7de5bdf8
--- a/mxcubecore/configuration/alba_xaloc13/beamline_config.yml
+++ b/mxcubecore/configuration/alba_xaloc13/beamline_config.yml
@@ -1,5 +1,3 @@
-# FIRST DRAFT of ALAB xaloc13 configuration. TO BE EDITED
-
# The class to initialise, and init parameters
_initialise_class:
class: mxcubecore.HardwareObjects.Beamline.Beamline
@@ -27,89 +25,107 @@ _objects:
# Hardware:
- session: session.xml
- machine_info: mach-info.xml
- - transmission: transmission.xml
- energy: energy.xml
- - beam: beam-info.xml
+ - transmission: transmission.xml
+ #- beam_info: beam-info.xml
+ - beam: beam.xml
- flux: flux.xml
+ - digital_zoom: digital-zoom.xml
+ - sample_view: sample-view.xml
- detector: pilatus.xml
- resolution: resolution.xml
# - hutch_interlock: door-interlock-mockup.xml
-# - safety_shutter: safshut.xml
+# - safety_shutter: safety_shutter.xml
- fast_shutter: fastshut.xml
- sample_changer: cats.xml
+ - sample_changer_maintenance: catsmaint.xml
# NBNB TODO remove plate_manipulater and treat as another smaple changer
# - plate_manipulator: plate-manipulator.xml
+ - ln2shower: ln2shower.xml
- diffractometer: mini-diff.xml
- - graphics: Qt4_graphics-manager.xml
+ - supervisor: supervisor.xml
- lims: dbconnection.xml
- queue_manager: queue.xml
- queue_model: queue-model.xml
# Procedures:
- collect: mxcollect.xml
- - xrf_spectrum: xrf-spectrum-mockup.xml
- - energy_scan: energyscan-mockup.xml
+ #- xrf_spectrum: xrf-spectrum-mockup.xml
+ #- energy_scan: energyscan.xml
# - imaging: xray-imaging.xml # Only in EMBL as of 201907
- gphl_workflow: gphl-workflow.xml
- gphl_connection: gphl-setup.xml
- # - centring: centring.xml
+ - centring: centring-math.xml
# Analysis:
- - offline_processing: auto-processing.xml
- - online_processing: parallel-processing.xml
- - characterisation: data-analysis.xml
+ - image_tracking: image-tracking.xml
+ - offline_processing: offline-processing.xml
+ - online_processing: online-processing.xml
+ - characterisation: characterisation.xml
+ - xml_rpc_server: xml-rpc-server.xml
+ - cryostream: cryostream.xml
# - beam_realign: # Skipped - optional
# Non-object attributes:
advanced_methods:
- MeshScan
- XrayCentering
tunable_wavelength: true
-disable_num_passes: false
+disable_num_passes: true
run_number: 1
default_acquisition_parameters:
default:
# Default values, also used for standard acquisition.
# Values not given in other dictionaries are taken from here
- exp_time: 0.3 # (s) exposure time
+ exp_time: 0.01 # (s) exposure time
osc_start: 0.0 # (degrees) Only used if no current angle found
osc_range: 0.1 # (degrees)
num_passes: 1 # (int)
first_image: 1 # (int)
overlap: 0
- num_images: 1 # (int)
- detector_binning_mode: 1 # (int)
+ num_images: 100 # (int)
+ # detector_binning_mode: 1 # Removed as not in practice used.
inverse_beam: false # (bool)
take_dark_current: true # (bool)
skip_existing_images: true # (bool)
take_snapshots: true # (bool)
+ kappa_phi: 0
helical:
# Defaults for helical scan. Missing values are taken from default
- exp_time: 0.04 # (s) exposure time
- num_images: 100
+ exp_time: 0.01 # (s) exposure time
characterisation:
# Defaults for chareacterisation. Missing values are taken from default
- osc_range: 1.0
+ exp_time: 0.05 # (s) exposure time
+ osc_range: 0.1
- advanced:
+ mesh:
# Defaults for 'advanced' acquisition. Missing values are taken from default
- exp_time: 0.04 # (s) exposure time
- osc_range: 0.5
+ exp_time: 0.02 # (s) exposure time
+ osc_range: 0.0
num_images: 100
+ cell_counting: inverse-zig-zag
+ cell_spacing: vertical,horizontal
+ mesh_center: top-left
+
+ # The next lines cause an error in the beamline code
+ #advanced:
+ # Defaults for 'advanced' acquisition. Missing values are taken from default
+ # exp_time: 0.04 # (s) exposure time
+ # osc_range: 0.01
acquisition_limit_values:
exposure_time: # (s)
- - 0.003
- - 6000.0
+ - 0.01
+ - 1000.0
osc_range: # (degrees)
- - -2165.0
- - 2165.0
+ - -2160.0
+ - 2160.0
number_of_images: # (int)
- 1
- 9999
-# kappa: # (degrees)
-# - 0.0
-# - 180.0
-# kappa_phi: # (degrees)
-# - 0.0
-# - 360.0
+ kappa: # (degrees)
+ - -1.0
+ - 180.0
+ kappa_phi: # (degrees)
+ - -720.0
+ - 720.0
diff --git a/mxcubecore/configuration/alba_xaloc13/blight.xml b/mxcubecore/configuration/alba_xaloc13/blight.xml
deleted file mode 100755
index 01abdd18af..0000000000
--- a/mxcubecore/configuration/alba_xaloc13/blight.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-
- BLightZoom
- ioregister/eh_zoom_tangoior_ctrl/2
- blight
- blight
- Value
- State
- Labels
- 200
- 0.001
-
diff --git a/mxcubecore/configuration/alba_xaloc13/bstopz.xml b/mxcubecore/configuration/alba_xaloc13/bstopz.xml
index 5ef508770b..07600b5ada 100755
--- a/mxcubecore/configuration/alba_xaloc13/bstopz.xml
+++ b/mxcubecore/configuration/alba_xaloc13/bstopz.xml
@@ -1,4 +1,4 @@
-
+
Beam Stop Z
bstopz
bstopz
diff --git a/mxcubecore/configuration/alba_xaloc13/calibration.xml b/mxcubecore/configuration/alba_xaloc13/calibration.xml.unused
similarity index 89%
rename from mxcubecore/configuration/alba_xaloc13/calibration.xml
rename to mxcubecore/configuration/alba_xaloc13/calibration.xml.unused
index d64e4c5da0..d753cdafb2 100755
--- a/mxcubecore/configuration/alba_xaloc13/calibration.xml
+++ b/mxcubecore/configuration/alba_xaloc13/calibration.xml.unused
@@ -1,4 +1,4 @@
-
+
Calibration
bl13/ct/variables
OAV_PIXELSIZE_X
diff --git a/mxcubecore/configuration/alba_xaloc13/cats.xml b/mxcubecore/configuration/alba_xaloc13/cats.xml
index ab2d495d07..5101a4e7f2 100755
--- a/mxcubecore/configuration/alba_xaloc13/cats.xml
+++ b/mxcubecore/configuration/alba_xaloc13/cats.xml
@@ -1,38 +1,89 @@
-
+
- Cats
- bl13/eh/cats
+ CATS
+ bl13/eh/cats
3
-
-
False
5
True
- MountingPosition
- GoTransferPhase
- GoSampleViewPhase
- CurrentPhase
- Abort
- State
- DetDistance
+ State
+ Status
+ Powered
+ PathRunning
+ Path
+ RecoveryNeeded
+ PathSafe
+ NumSampleOnDiff
+ LidSampleOnDiff
+ Barcode
+ di_PRI_SOM
+ di_AllLidsClosed
+ Tool
+ CassettePresence
+ di_Cassette1Presence
+ di_Cassette2Presence
+ di_Cassette3Presence
+ di_Cassette4Presence
+ di_Cassette5Presence
+ di_Cassette6Presence
+ di_Cassette7Presence
+ di_Cassette8Presence
+ di_Cassette9Presence
+
+ di_CollisonSensorOK
+ do_PRO5_IDL
+ do_PRO6_RAH
+ do_PRO7_RI1
+ do_PRO8_RI2
+ CurrentNumberOfSoaking
+ LidSampleOnTool
+ NumSampleOnTool
- di_PRI4_SOM
- PathSafe
+ put
+ get
+ getput
+ abort
+ powerOn
+ powerOff
+ put_bcrd
+ getput_bcrd
+ barcode
- put_HT
- get_HT
- getput_HT
+ put_HT
+ get_HT
+ getput_HT
+ getpuckpick
+ clear_memory
+ settool
+ settool
+ recoverFailure
+ pick
- put_bcrd
- getput_bcrd
+ MountingPosition
+ GoSampleViewPhase
+ GoSampleViewPhase
+ CurrentPhase
+ State
+ AperturePosition
+ DetDistanceSafe
+ Abort
+ DetDistance
+ position
+ position
- barcode
+ GoSampleViewPhase
+ GoTransferPhase
+ GoSampleViewPhase
+ Abort
+ bl13/door/05
+ cats_recover_collision
+
diff --git a/mxcubecore/configuration/alba_xaloc13/catsmaint.xml b/mxcubecore/configuration/alba_xaloc13/catsmaint.xml
index f17574a8e9..0dbef35f48 100755
--- a/mxcubecore/configuration/alba_xaloc13/catsmaint.xml
+++ b/mxcubecore/configuration/alba_xaloc13/catsmaint.xml
@@ -1,23 +1,35 @@
-
- CatsMaint
+
+ CatsMaintenance
bl13/eh/cats
+
-
-
- MountingPosition
-
- Abort
-
+
+ Abort
-
-
- Barcode
do_PRO6_RAH
+
+
+ SampleOnMagnet
+ MountingPosition
diff --git a/mxcubecore/configuration/alba_xaloc13/centring-math.xml b/mxcubecore/configuration/alba_xaloc13/centring-math.xml
new file mode 100755
index 0000000000..8b1d6ebc59
--- /dev/null
+++ b/mxcubecore/configuration/alba_xaloc13/centring-math.xml
@@ -0,0 +1,59 @@
+
+
+
+
+ phiy
+ [1, 0, 0]
+ translation
+ /omegax
+
+
+
+
+ phiz
+ [0, 0, 1]
+ translation
+ /omegaz
+
+
+
+ phi
+ [-1, 0, 0]
+ rotation
+ /omega
+
+
+
+
+ sampx
+
+ [0, 1, 0]
+ translation
+ /centx
+
+
+
+ sampy
+
+ [0, 0, 1]
+ translation
+ /centy
+
+
+
+
+ X
+ [1, 0, 0]
+
+
+ Y
+ [0, 0, -1]
+
+
+
+ 2
+ 3
+ 300
+
diff --git a/mxcubecore/configuration/alba_xaloc13/centx.xml b/mxcubecore/configuration/alba_xaloc13/centx.xml
index af00f00718..7f33513397 100755
--- a/mxcubecore/configuration/alba_xaloc13/centx.xml
+++ b/mxcubecore/configuration/alba_xaloc13/centx.xml
@@ -1,5 +1,6 @@
-
+
Center X
centx
CentX
+ 0.0002
diff --git a/mxcubecore/configuration/alba_xaloc13/centy.xml b/mxcubecore/configuration/alba_xaloc13/centy.xml
index f7807bbe0b..ce7814dc2b 100755
--- a/mxcubecore/configuration/alba_xaloc13/centy.xml
+++ b/mxcubecore/configuration/alba_xaloc13/centy.xml
@@ -1,5 +1,6 @@
-
+
Center Y
centy
CentY
+ 0.0002
diff --git a/mxcubecore/configuration/alba_xaloc13/characterisation.xml b/mxcubecore/configuration/alba_xaloc13/characterisation.xml
new file mode 100755
index 0000000000..ed23fa4581
--- /dev/null
+++ b/mxcubecore/configuration/alba_xaloc13/characterisation.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+ /beamlines/bl13/controls/production/git/bl13_processing/edna-mx/XSDataInput_templates/mxcube/edna_defaults.xml
+
+ False
+ opbl13
+
+
+
+ pcbl1309
+
+
+ /usr/local/sdm/processing_xaloc
+
+
+ /beamlines/bl13/sdm/production/processing_xaloc/edna-mx/strategy/mxcube/edna-mx.strategy.first.ssh
+ /beamlines/bl13/sdm/production/processing_xaloc/edna-mx/strategy/mxcube/run_local_strategy.sh
+
+
+
diff --git a/mxcubecore/configuration/alba_xaloc13/cluster.xml b/mxcubecore/configuration/alba_xaloc13/cluster.xml
new file mode 100755
index 0000000000..5f27f360e1
--- /dev/null
+++ b/mxcubecore/configuration/alba_xaloc13/cluster.xml
@@ -0,0 +1,12 @@
+
+ opbl13
+ claxaloc01
+
+ /beamlines/bl13/sdm/production/processing_xaloc
+
+
+ {'plugin': 'EDPluginControlInterfaceToMXCuBEv1_3', 'script': 'edna-mx/strategy/mxcube/edna-mx.strategy.sl'}
+ {'plugin': 'EDPluginControlEDNAprocv1_0', 'script': 'edna-mx/ednaproc/mxcube/edna-mx.ednaproc.sl'}
+ {'plugin': 'EDPluginControlAutoPROCv1_1', 'script': 'edna-mx/autoproc/mxcube/edna-mx.autoproc.sl', 'configdef': 'edna-mx/autoproc/mxcube/config.def'}
+ {'plugin': 'EDPluginControlXia2DIALSv1_0', 'script': 'edna-mx/xia2dials/mxcube/edna-mx.xia2dials.sl'}
+
diff --git a/mxcubecore/configuration/alba_xaloc13/cryostream.xml b/mxcubecore/configuration/alba_xaloc13/cryostream.xml
new file mode 100644
index 0000000000..a85c1123d1
--- /dev/null
+++ b/mxcubecore/configuration/alba_xaloc13/cryostream.xml
@@ -0,0 +1,8 @@
+
+ Cryostream
+ bl13/eh/oxfcryo
+
+ GasTemp
+ State
+
+
diff --git a/mxcubecore/configuration/alba_xaloc13/cstagex.xml b/mxcubecore/configuration/alba_xaloc13/cstagex.xml
new file mode 100755
index 0000000000..896ab6e895
--- /dev/null
+++ b/mxcubecore/configuration/alba_xaloc13/cstagex.xml
@@ -0,0 +1,8 @@
+
+ StageX
+ cstagex
+ StageX
+ 45
+
+ 0.0001
+
diff --git a/mxcubecore/configuration/alba_xaloc13/cstagey.xml b/mxcubecore/configuration/alba_xaloc13/cstagey.xml
new file mode 100755
index 0000000000..fbe1af0b3d
--- /dev/null
+++ b/mxcubecore/configuration/alba_xaloc13/cstagey.xml
@@ -0,0 +1,8 @@
+
+ StageY
+ cstagey
+ StageY
+ 45
+
+ 0.0001
+
diff --git a/mxcubecore/configuration/alba_xaloc13/cstagez.xml b/mxcubecore/configuration/alba_xaloc13/cstagez.xml
new file mode 100755
index 0000000000..d013eb6af0
--- /dev/null
+++ b/mxcubecore/configuration/alba_xaloc13/cstagez.xml
@@ -0,0 +1,8 @@
+
+ StageZ
+ cstagez
+ StageZ
+ 45
+
+ 0.0001
+
diff --git a/mxcubecore/configuration/alba_xaloc13/dbconnection.xml b/mxcubecore/configuration/alba_xaloc13/dbconnection.xml
index 13f3ce537f..b6a78010c5 100755
--- a/mxcubecore/configuration/alba_xaloc13/dbconnection.xml
+++ b/mxcubecore/configuration/alba_xaloc13/dbconnection.xml
@@ -1,13 +1,14 @@
-
+
proposal
ldap
- https://ispybtest.cells.es/ispyb/ispyb-ws/ispybWS/
+
+ https://ispyb.cells.es/ispyb/ispyb-ws/ispybWS/
- user
- password
+ wservice
+ jS625Kyg*3DA,;:z
ToolsForCollectionWebService
@@ -24,7 +25,7 @@
mxCuBE 1.0 works with the new xml files (ie. cherry picking
commits from master to 1.0 or merging)
-->
- MX-XALOC
+ MX-BL13
mx
diff --git a/mxcubecore/configuration/alba_xaloc13/detector-distance.xml b/mxcubecore/configuration/alba_xaloc13/detector-distance.xml
index 8778b6c0ca..17c2cc444f 100755
--- a/mxcubecore/configuration/alba_xaloc13/detector-distance.xml
+++ b/mxcubecore/configuration/alba_xaloc13/detector-distance.xml
@@ -1,4 +1,4 @@
-
+
Detector Distance
detsamdis
Detector Distance
diff --git a/mxcubecore/configuration/alba_xaloc13/digital-zoom.xml b/mxcubecore/configuration/alba_xaloc13/digital-zoom.xml
new file mode 100755
index 0000000000..8887abdf83
--- /dev/null
+++ b/mxcubecore/configuration/alba_xaloc13/digital-zoom.xml
@@ -0,0 +1,11 @@
+
+ Zoom
+ bl13/eh/bzoomspecific
+ zoom
+
+
+ zoom_index
+ State
+
+
+
diff --git a/mxcubecore/configuration/alba_xaloc13/edna_defaults.xml b/mxcubecore/configuration/alba_xaloc13/edna_defaults.xml
index 5f2bd94ba4..cf70d74fe9 100755
--- a/mxcubecore/configuration/alba_xaloc13/edna_defaults.xml
+++ b/mxcubecore/configuration/alba_xaloc13/edna_defaults.xml
@@ -17,7 +17,7 @@
1.283000e+11
- 0.1
+ 0.05
diff --git a/mxcubecore/configuration/alba_xaloc13/energy.xml b/mxcubecore/configuration/alba_xaloc13/energy.xml
index 2449104923..5cd8f4feb9 100755
--- a/mxcubecore/configuration/alba_xaloc13/energy.xml
+++ b/mxcubecore/configuration/alba_xaloc13/energy.xml
@@ -1,6 +1,7 @@
-
+
Energy
+ True
diff --git a/mxcubecore/configuration/alba_xaloc13/energy_motor.xml b/mxcubecore/configuration/alba_xaloc13/energy_motor.xml
index f40ab7e3ba..f2854759a7 100755
--- a/mxcubecore/configuration/alba_xaloc13/energy_motor.xml
+++ b/mxcubecore/configuration/alba_xaloc13/energy_motor.xml
@@ -1,8 +1,13 @@
-
- Energy
- ealign
- energy
+
+ Energy Motor
+ Ealign
+
+ ealign
+
0.0005
- 45
+
+ 0.0005
+ 0.5
+
diff --git a/mxcubecore/configuration/alba_xaloc13/fastshut.xml b/mxcubecore/configuration/alba_xaloc13/fastshut.xml
index 4da1394c91..d48a3e4497 100755
--- a/mxcubecore/configuration/alba_xaloc13/fastshut.xml
+++ b/mxcubecore/configuration/alba_xaloc13/fastshut.xml
@@ -1,5 +1,8 @@
-
+
Fast Shutter
+
+ 0.005
+
IdleState
Start
Stop
diff --git a/mxcubecore/configuration/alba_xaloc13/flux.xml b/mxcubecore/configuration/alba_xaloc13/flux.xml
index 6895eb068c..1bd98f3174 100644
--- a/mxcubecore/configuration/alba_xaloc13/flux.xml
+++ b/mxcubecore/configuration/alba_xaloc13/flux.xml
@@ -1,2 +1,9 @@
-
+
+ Flux
+ value
+ position
+ fluxlast
+ fluxlastnorm
+
+ 1.5E12
diff --git a/mxcubecore/configuration/alba_xaloc13/frontend.xml b/mxcubecore/configuration/alba_xaloc13/frontend.xml
index e4d5fa3434..ba85ec8bf1 100755
--- a/mxcubecore/configuration/alba_xaloc13/frontend.xml
+++ b/mxcubecore/configuration/alba_xaloc13/frontend.xml
@@ -1,4 +1,4 @@
-
+
Front End
bl13/ct/eps-plc-01
fe_open
diff --git a/mxcubecore/configuration/alba_xaloc13/frontlight.xml b/mxcubecore/configuration/alba_xaloc13/frontlight.xml
index 7388cf0446..67ec725276 100755
--- a/mxcubecore/configuration/alba_xaloc13/frontlight.xml
+++ b/mxcubecore/configuration/alba_xaloc13/frontlight.xml
@@ -1,7 +1,7 @@
-
+
Front
Brightness
State
- 0,30
+ 0,100
2
diff --git a/mxcubecore/configuration/alba_xaloc13/gphl-setup.xml b/mxcubecore/configuration/alba_xaloc13/gphl-setup.xml
index fe8b677332..407a2e20f6 100644
--- a/mxcubecore/configuration/alba_xaloc13/gphl-setup.xml
+++ b/mxcubecore/configuration/alba_xaloc13/gphl-setup.xml
@@ -3,67 +3,117 @@
- replaced-by-GphlWorkflow.file_paths['scripts']
+
+
+
+ /beamlines/bl13/controls/gphl/latest/mxcube_setup/
+ /beamlines/bl13/controls/gphl/latest/gphl_release/latest
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GPHL
+
+ persistence
+
+
+
+
+
+
+
+
+
+
+
+
+
- /users/blissadm/bin/java
+
+ /usr/bin/java
+
+
+
+
+ {GPHL_RELEASE}/autoPROC/bin/linux64
+
+
+
- /users/blissadm/local/gphl/gphl_java_classes/*
+ {GPHL_SETUP}/wfjars/*
+
+
+ gphl_beamline_config
+
+
+ {GPHL_SETUP}test_samples
+
+
+
+
- /users/blissadm/local/gphl/gphl_latest/exe/
-
- /opt/pxsoft/bin/xds_par
-
-
-
-
-
+
+
+ {GPHL_RELEASE}
+
+
+
+ /beamlines/bl13/commissioning/software/xds/XDS-INTEL64_Linux_x86_64/xds_par
+
+
+
-
+ {GPHL_SETUP}/scripts/run_stratcal_wrap.py
-
-
+
+ {GPHL_SETUP}/scripts/simcal
-
+
-
+
- {LOCAL_SCRIPTS}/aP_wf_rotcal
-
-
+
+ {GPHL_SETUP}/scripts/aP_wf_rotcal
-
- GPHL
+
+
-
-
-
-
-
-
-
-
+
diff --git a/mxcubecore/configuration/alba_xaloc13/gphl-workflow.xml b/mxcubecore/configuration/alba_xaloc13/gphl-workflow.xml
new file mode 100644
index 0000000000..ba6bdc2438
--- /dev/null
+++ b/mxcubecore/configuration/alba_xaloc13/gphl-workflow.xml
@@ -0,0 +1,456 @@
+
+
+
+
+
+
+
+
+ 0.1 0.05 0.2
+
+
+
+
+
+
+ current
+
+
+ 15
+
+
+ 5
+
+
+ InitialCharacterisation_6_5
+ InitialCharacterisation_12_3
+ InitialCharacterisation_12_4
+ InitialCharacterisation_12_5
+
+
+
+
+
+
+ 5.0
+
+
+
+ 10.0
+ True
+
+
+
+ 20.0
+
+
+
+
+
+
+ Thaumatin
+
+ P41212
+ 57.847
+ 57.847
+ 150.125
+ 90
+ 90
+ 90
+
+
+ germanate
+ Ia-3d
+ 51.2487
+ 51.2487
+ 51.2487
+ 90
+ 90
+ 90
+
+
+ CubicInsulin
+
+ I213
+ 77.9
+ 77.9
+ 77.9
+ 90
+ 90
+ 90
+
+
+ HEWLysozyme
+
+ P43212
+ 78.54
+ 78.45
+ 37.70
+ 90
+ 90
+ 90
+
+
+ Se-Met_FAE
+
+ P212121
+ 65.381
+ 108.793
+ 113.877
+ 90
+ 90
+ 90
+
+
+
+
+
+
+
+
+
+
+
+
+ persistence
+
+
+
+
+
+
+
+
+
+
+
+
+ gphl_wf_
+
+
+
+
+
+
+ generic
+
+
+
+
+ gphl_data
+
+ ib_interleaved
+
+ interleaved
+
+
+
+
+
+
+
+
+ UTF-8
+
+
+
+
+
+
+ wf
+
+
+
+
+
+
+
+
+ false
+
+
+
+
+ 26.0
+ 1.5e-3
+ 0.2
+
+
+
+
+
+ true
+
+
+ 48
+ 1
+
+
+
+
+
+
+ co.gphl.wf.workflows.WFSimpleCharToProcessing
+ phasing
+
+ Single wavelength data acquisition, strategy for phasing
+ Includes initial characterisation and complete collection
+
+
+
+
+
+ gs
+
+
+
+ Acquisition
+
+ 12.7
+
+
+
+ SAD_
+
+
+
+
+ co.gphl.wf.workflows.WFSimpleCharToProcessing
+ phasing
+
+ Two-wavelength MAD data acquisition.
+ Includes initial characterisation and complete collection
+
+
+
+
+ gsb
+
+
+
+ Peak
+
+ 12.7
+
+
+ Remote
+
+ 12.72
+
+
+
+ MAD2_
+
+
+
+
+ co.gphl.wf.workflows.WFSimpleCharToProcessing
+ phasing
+
+ Three-wavelength MAD data acquisition.
+ Includes initial characterisation and complete collection
+
+
+
+
+ gsb
+
+
+
+ Peak
+
+ 12.7
+
+
+ Rising_Inflection
+
+ 12.69
+
+
+ Falling_Inflection
+
+ 12.71
+
+
+
+ MAD3_
+
+
+
+
+ co.gphl.wf.workflows.WFSimpleCharToProcessing
+ native_short
+
+ Single wavelength data acquisition for native data collection
+ Includes initial characterisation and complete collection.
+ Fast, 1 sweep (2 for triclinic and monoclinic), chiMax = 20deg
+
+
+
+
+
+
+
+
+
+
+ Acquisition
+
+ 12.7
+
+
+
+ Native1_
+
+
+
+
+ co.gphl.wf.workflows.WFSimpleCharToProcessing
+ native_two360
+
+ Single wavelength data acquisition for native data collection
+ Includes initial characterisation and complete collection.
+ Medium, 2 sweeps (3 for triclinic and monoclinic), chiMax = 35deg
+
+
+
+
+
+
+
+
+
+
+ Acquisition
+
+ 12.7
+
+
+
+ Native2_
+
+
+
+
+ co.gphl.wf.workflows.WFSimpleCharToProcessing
+ native_antishadow
+
+ Single wavelength data acquisition for native data collection
+ Includes initial characterisation and complete collection.
+ Strategy for optimal distribution of redundancy,
+ 3-4 sweeps. Uses full kappa range.
+ May default to medium strategy for sixfold and cubic symmetries.
+
+
+
+
+
+
+
+
+
+
+ Acquisition
+
+ 12.7
+
+
+
+ Native3_
+
+
+
+
+ co.gphl.wf.workflows.WFTransCal
+ transcal
+ Translational calibration.
+ Designed for use by beamline personnel.
+ Will produce a series of goniostat positions compatible with
+ the inbuilt collision checker, move the goniostat to each
+ position, and ask for centring.
+
+
+
+ transcal
+
+
+
+
+
+ transcal_2stage.json
+
+
+
+
+
+
+
+
+
+ co.gphl.wf.workflows.WFDiffractCal
+ diffractcal
+ Diffractometer calibration.
+ Designed for use by beamline personnel.
+
+
+
+
+
+
+ gs
+
+ Dcalib2_
+
+ DiffractCal_ex
+
+
+
+ diffractcal
+
+ multiorientation
+
+
+
+
+
+
+
+
+
+ co.gphl.wf.workflows.WFDiffractCal
+ diffractcal
+ Diffractometer calibration.
+ Designed for use by beamline personnel.
+
+
+
+
+
+
+ gs
+
+ Dcalib1_
+
+ DiffractCal
+
+
+
+ diffractcal
+
+ multiorientation
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mxcubecore/configuration/alba_xaloc13/image-tracking.xml b/mxcubecore/configuration/alba_xaloc13/image-tracking.xml
new file mode 100644
index 0000000000..7b98a8db6b
--- /dev/null
+++ b/mxcubecore/configuration/alba_xaloc13/image-tracking.xml
@@ -0,0 +1,14 @@
+
+ bl13/ct/pilatus
+
+
+
+
+
+ send_image
+
+
+
+
+
+
diff --git a/mxcubecore/configuration/alba_xaloc13/instanceconnection.xml b/mxcubecore/configuration/alba_xaloc13/instanceconnection.xml
index af09626ee8..04d78fff4c 100755
--- a/mxcubecore/configuration/alba_xaloc13/instanceconnection.xml
+++ b/mxcubecore/configuration/alba_xaloc13/instanceconnection.xml
@@ -1,4 +1,4 @@
-
+
14001
diff --git a/mxcubecore/configuration/alba_xaloc13/kappa.xml b/mxcubecore/configuration/alba_xaloc13/kappa.xml
index fd3ec4f943..136e81fb00 100755
--- a/mxcubecore/configuration/alba_xaloc13/kappa.xml
+++ b/mxcubecore/configuration/alba_xaloc13/kappa.xml
@@ -1,5 +1,6 @@
-
+
Kappa
kappa
Kappa
+ 0.0005
diff --git a/mxcubecore/configuration/alba_xaloc13/kappaalign.xml b/mxcubecore/configuration/alba_xaloc13/kappaalign.xml
new file mode 100755
index 0000000000..bb1e6da2d4
--- /dev/null
+++ b/mxcubecore/configuration/alba_xaloc13/kappaalign.xml
@@ -0,0 +1,5 @@
+
+ Kappa
+ kappaalign
+ Kappa
+
diff --git a/mxcubecore/configuration/alba_xaloc13/kappaphi.xml b/mxcubecore/configuration/alba_xaloc13/kappaphi.xml
index 17ce54da63..6aeb7f63b4 100755
--- a/mxcubecore/configuration/alba_xaloc13/kappaphi.xml
+++ b/mxcubecore/configuration/alba_xaloc13/kappaphi.xml
@@ -1,5 +1,6 @@
-
+
Kappa Phi
- kappaphi
+ phi
KappaPhi
+ 0.0005
diff --git a/mxcubecore/configuration/alba_xaloc13/kappaphialign.xml b/mxcubecore/configuration/alba_xaloc13/kappaphialign.xml
new file mode 100755
index 0000000000..c86d9643ae
--- /dev/null
+++ b/mxcubecore/configuration/alba_xaloc13/kappaphialign.xml
@@ -0,0 +1,5 @@
+
+ Kappa Phi
+ phialign
+ KappaPhi
+
diff --git a/mxcubecore/configuration/alba_xaloc13/limavideo.xml b/mxcubecore/configuration/alba_xaloc13/limavideo.xml
index f82bb707ab..1570433037 100755
--- a/mxcubecore/configuration/alba_xaloc13/limavideo.xml
+++ b/mxcubecore/configuration/alba_xaloc13/limavideo.xml
@@ -1,20 +1,21 @@
-
-
- basler
- yuv422p
+
+
+ bzoom
+ rgb24
- 84.89.227.72
- bl13/eh/basler_oav
+ bl13/eh/bzoom
- 0.24
+
1
- 0.08
- (False, False)
+
+ (True, False)
30
+
+
900
670
diff --git a/mxcubecore/configuration/alba_xaloc13/ln2shower.xml b/mxcubecore/configuration/alba_xaloc13/ln2shower.xml
new file mode 100755
index 0000000000..87474417db
--- /dev/null
+++ b/mxcubecore/configuration/alba_xaloc13/ln2shower.xml
@@ -0,0 +1,20 @@
+
+ Ln2 Shower
+ bl13/eh/ln2pump
+
+
+
+ operation
+ State
+
+ False
+
+ bl13/door/05
+ ln2shower_wash
+ ln2shower_cold
+ ln2shower_setflow
+ ln2shower_on
+ ln2shower_off
+ ln2shower_sleep
+
+
diff --git a/mxcubecore/configuration/alba_xaloc13/mach-info.xml b/mxcubecore/configuration/alba_xaloc13/mach-info.xml
index 17e91ab5e2..2f7aa4257c 100755
--- a/mxcubecore/configuration/alba_xaloc13/mach-info.xml
+++ b/mxcubecore/configuration/alba_xaloc13/mach-info.xml
@@ -1,7 +1,7 @@
-
- Mach
- mach/ct/gateway
- State
- Current
- TopUpRemaining
+
+ MachineInfo
+ tango://alba03.cells.es:10000/sr/ct/gateway
+ state
+ current
+ topupremaining
diff --git a/mxcubecore/configuration/alba_xaloc13/mini-diff.xml b/mxcubecore/configuration/alba_xaloc13/mini-diff.xml
index 51af0ce18f..383817af7f 100755
--- a/mxcubecore/configuration/alba_xaloc13/mini-diff.xml
+++ b/mxcubecore/configuration/alba_xaloc13/mini-diff.xml
@@ -1,49 +1,41 @@
-
+
bl13/eh/diff
+
+ False
+
-
-
-
-
-
-
+
+
-
-
-
-
-
-
+
- True
+ False
-
+ {"x": 450,"y": 335}
-
-
- {"actuator_name": "phiz", "position":-0.0175, "camera_axis":"y","direction": -1}
{"fast": (1, 0), "slow": (0, -1)}
True
("Transfer", "Centring", "Collect", "BeamView")
- CurrentPhase
-
+ CurrentPhase
State
+ OmegaZReference
+ GoTransferPhase
+ GoSampleViewPhase
State,CurrentPhase
0.2
diff --git a/mxcubecore/configuration/alba_xaloc13/mxcollect.xml b/mxcubecore/configuration/alba_xaloc13/mxcollect.xml
index 7e41980336..fa66a2d723 100755
--- a/mxcubecore/configuration/alba_xaloc13/mxcollect.xml
+++ b/mxcubecore/configuration/alba_xaloc13/mxcollect.xml
@@ -1,12 +1,16 @@
-
+
+ False
+ True
+ /beamlines/bl13/commissioning/latest_user_data_collection
+
-
+
-
+
@@ -19,15 +23,21 @@
-
+
- bl13/door/05
- ni660x_configure_collect
- ni660x_unconfigure_collect
+ bl13/door/01
+ ni660x_configure_collect_multi
+ ni660x_unconfigure_collect_multi
+ meshct
+ ascanct
+
+ set_meas_conf
+ senv
- position
- position
+ position
+ position
+ position
beamx
beamy
diff --git a/mxcubecore/configuration/alba_xaloc13/offline-processing.xml b/mxcubecore/configuration/alba_xaloc13/offline-processing.xml
new file mode 100755
index 0000000000..ccac52d573
--- /dev/null
+++ b/mxcubecore/configuration/alba_xaloc13/offline-processing.xml
@@ -0,0 +1,9 @@
+
+
+ /beamlines/bl13/sdm/production/processing_xaloc/templates
+
+
+ beamx
+ beamy
+
+
diff --git a/mxcubecore/configuration/alba_xaloc13/omega.xml b/mxcubecore/configuration/alba_xaloc13/omega.xml
index 778e57a44e..6e3bdb5edd 100755
--- a/mxcubecore/configuration/alba_xaloc13/omega.xml
+++ b/mxcubecore/configuration/alba_xaloc13/omega.xml
@@ -1,7 +1,8 @@
-
+
Omega
omega
Omega
45
500
+ 0.0001
diff --git a/mxcubecore/configuration/alba_xaloc13/omegax.xml b/mxcubecore/configuration/alba_xaloc13/omegax.xml
index ce16bdbae3..a7134716dc 100755
--- a/mxcubecore/configuration/alba_xaloc13/omegax.xml
+++ b/mxcubecore/configuration/alba_xaloc13/omegax.xml
@@ -1,7 +1,8 @@
-
+
Omega X
omegax
OmegaX
+ 0.0002
+
+ /beamlines/bl13/sdm/production/processing_xaloc/edna-mx/dozor/run_dozor.sh
+ True
+
+
+
+
diff --git a/mxcubecore/configuration/alba_xaloc13/parallel-processing.xml b/mxcubecore/configuration/alba_xaloc13/parallel-processing.xml
deleted file mode 100755
index c8b3deffa7..0000000000
--- a/mxcubecore/configuration/alba_xaloc13/parallel-processing.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
- /pathToProcessingScript
- True
-
diff --git a/mxcubecore/configuration/alba_xaloc13/photonshut.xml b/mxcubecore/configuration/alba_xaloc13/photonshut.xml
index 45992f4876..fa9cbc6ed3 100755
--- a/mxcubecore/configuration/alba_xaloc13/photonshut.xml
+++ b/mxcubecore/configuration/alba_xaloc13/photonshut.xml
@@ -1,6 +1,6 @@
-
+
Photon Shutter
bl13/ct/eps-plc-01
pshu
- Open,Closed
+ Closed,Open
diff --git a/mxcubecore/configuration/alba_xaloc13/pilatus.xml b/mxcubecore/configuration/alba_xaloc13/pilatus.xml
index 6c233892f2..6a1f37cca0 100755
--- a/mxcubecore/configuration/alba_xaloc13/pilatus.xml
+++ b/mxcubecore/configuration/alba_xaloc13/pilatus.xml
@@ -1,27 +1,59 @@
-
-
+
+ PilatusDetector
-
- bl13/eh/pilatuslima
- bl13/eh/pilatusspecific
+
+ bl13/eh/pilatus3xlima
DECTRIS
- 6M_F
- pilatus
+ Pilatus 3X 6M
+ Hybrid photon counting
+
cbf
0.172
0.172
-
- 0.1
- 0.08
- 0.08,1000
-
- 0.003
-
- beamx
- beamy
-
- Position
+ 2463
+ 2527
+
+ 0.01
+ 0.01
+ 0.01,1000
+ 0.00095
+
+ True
+
+ prepareAcq
+ startAcq
+ abortAcq
+ stopAcq
+ reset
+ resetCommonHeader
+ resetFrameHeaders
+ setImageHeader
+
+ saving_mode
+ saving_prefix
+ saving_directory
+ saving_format
+ saving_next_number
+ saving_header_delimiter
+ saving_statistics
+ ready_for_next_acq
+
+ acq_nb_frames
+ acq_trigger_mode
+ acq_expo_time
+ acq_status
+ acq_status_fault_error
+ latency_time
+
+ energy_threshold
+ threshold
+ cam_state
+ SendCamServerCmd
+
+ beamx
+ beamy
+ Position
diff --git a/mxcubecore/configuration/alba_xaloc13/queue.xml b/mxcubecore/configuration/alba_xaloc13/queue.xml
index 9fd8ee2fe0..6aa2debcd0 100755
--- a/mxcubecore/configuration/alba_xaloc13/queue.xml
+++ b/mxcubecore/configuration/alba_xaloc13/queue.xml
@@ -1,3 +1,5 @@
+
diff --git a/mxcubecore/configuration/alba_xaloc13/resolution.xml b/mxcubecore/configuration/alba_xaloc13/resolution.xml
index 72102baa38..dc32a259c9 100755
--- a/mxcubecore/configuration/alba_xaloc13/resolution.xml
+++ b/mxcubecore/configuration/alba_xaloc13/resolution.xml
@@ -1,7 +1,6 @@
-
+
Resolution
rescomp
- Resolution
- 45
-
+ resolution
+ Position
diff --git a/mxcubecore/configuration/alba_xaloc13/sample-view.xml b/mxcubecore/configuration/alba_xaloc13/sample-view.xml
new file mode 100644
index 0000000000..99df64ac7a
--- /dev/null
+++ b/mxcubecore/configuration/alba_xaloc13/sample-view.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+ False
+
+ (1, 1.5, 2.)
+
diff --git a/mxcubecore/configuration/alba_xaloc13/session.xml b/mxcubecore/configuration/alba_xaloc13/session.xml
index 7d2da8a675..709160cc8d 100755
--- a/mxcubecore/configuration/alba_xaloc13/session.xml
+++ b/mxcubecore/configuration/alba_xaloc13/session.xml
@@ -1,27 +1,26 @@
-
+
ALBA
- MX-XALOC
- MX-XALOC
+ BL13 - XALOC
+ BL13 - XALOC
cbf
'04'
-
-
/tmp
-
+ RAW_DATA
/tmp
-
-
-
-
+ PROCESSED_DATA
/beamlines/ispyb/bl13/
+
+ bl13/door/05
+ senv
+
diff --git a/mxcubecore/configuration/alba_xaloc13/slowshut.xml b/mxcubecore/configuration/alba_xaloc13/slowshut.xml
index 4a2ade9600..569c2bdeec 100755
--- a/mxcubecore/configuration/alba_xaloc13/slowshut.xml
+++ b/mxcubecore/configuration/alba_xaloc13/slowshut.xml
@@ -1,4 +1,4 @@
-
+
Slow Shutter
bl13/ct/eps-plc-01
slowshu
diff --git a/mxcubecore/configuration/alba_xaloc13/supervisor.xml b/mxcubecore/configuration/alba_xaloc13/supervisor.xml
index 3a42d65bbe..548f4d186c 100755
--- a/mxcubecore/configuration/alba_xaloc13/supervisor.xml
+++ b/mxcubecore/configuration/alba_xaloc13/supervisor.xml
@@ -1,4 +1,4 @@
-
+
Beamline Supervisor
bl13/eh/supervisor
DetCoverOpen
@@ -9,4 +9,8 @@
GoTransferPhase
GoSampleViewPhase
GoBeamViewPhase
+
+
+ ("Transfer", "Centring", "Collect")
+
diff --git a/mxcubecore/configuration/alba_xaloc13/transmission.xml b/mxcubecore/configuration/alba_xaloc13/transmission.xml
index ceeb452222..41c71451b7 100755
--- a/mxcubecore/configuration/alba_xaloc13/transmission.xml
+++ b/mxcubecore/configuration/alba_xaloc13/transmission.xml
@@ -1,4 +1,4 @@
-
+
Transmission
motor/eh_mbattransmot_ctrl/1
Position
diff --git a/mxcubecore/configuration/alba_xaloc13/wavelength_motor.xml b/mxcubecore/configuration/alba_xaloc13/wavelength_motor.xml
index 270452d1fc..c15ab8197c 100755
--- a/mxcubecore/configuration/alba_xaloc13/wavelength_motor.xml
+++ b/mxcubecore/configuration/alba_xaloc13/wavelength_motor.xml
@@ -1,7 +1,8 @@
-
+
Wavelength
wavelength
wavelength
+ 0.00002
45
diff --git a/mxcubecore/configuration/alba_xaloc13/xml-rpc-server.xml b/mxcubecore/configuration/alba_xaloc13/xml-rpc-server.xml
index 3555534309..5ed34f0f69 100755
--- a/mxcubecore/configuration/alba_xaloc13/xml-rpc-server.xml
+++ b/mxcubecore/configuration/alba_xaloc13/xml-rpc-server.xml
@@ -9,6 +9,7 @@
8000
+ False
@@ -17,7 +18,7 @@
-
-
-
+
+
+
diff --git a/mxcubecore/configuration/alba_xaloc13/zoom-auto-brightness.xml b/mxcubecore/configuration/alba_xaloc13/zoom-auto-brightness.xml
deleted file mode 100755
index 4df2b9f15b..0000000000
--- a/mxcubecore/configuration/alba_xaloc13/zoom-auto-brightness.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-
diff --git a/mxcubecore/configuration/alba_xaloc13/zoom.xml b/mxcubecore/configuration/alba_xaloc13/zoom.xml
deleted file mode 100755
index a4cc3c2e3e..0000000000
--- a/mxcubecore/configuration/alba_xaloc13/zoom.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-
- Zoom
- ioregister/eh_zoom_tangoior_ctrl/1
- zoom
- Zoom
- Value
- State
- Labels
- 200
- 0.001
-