Source code for mxcubecore.HardwareObjects.ESRF.ESRFMultiCollect

import logging
import math
import os
import time
from http.client import HTTPConnection
from urllib.parse import urlencode

from mxcubecore import HardwareRepository as HWR
from mxcubecore.BaseHardwareObjects import HardwareObject
from mxcubecore.HardwareObjects.abstract.AbstractMultiCollect import *
from mxcubecore.model.queue_model_objects import PathTemplate
from mxcubecore.utils.conversion import string_types


[docs]class ESRFMultiCollect(AbstractMultiCollect, HardwareObject): def __init__(self, name): AbstractMultiCollect.__init__(self) HardwareObject.__init__(self, name) self._centring_status = None self._metadataClient = None self.__mesh_steps = None self._mesh_range = None @property def _mesh_steps(self): return self.__mesh_steps @_mesh_steps.setter def _mesh_steps(self, steps): self.__mesh_steps = steps self._detector._mesh_steps = steps
[docs] def execute_command(self, command_name, *args, **kwargs): wait = kwargs.get("wait", True) cmd_obj = self.get_command_object(command_name) return cmd_obj(*args, wait=wait)
[docs] def init(self): self._detector = HWR.beamline.detector self.number_of_snapshots = self.get_property("num_snapshots", 4) self.setControlObjects( diffractometer=self.get_object_by_role("diffractometer"), sample_changer=self.get_object_by_role("sample_changer"), lims=self.get_object_by_role("dbserver"), safety_shutter=self.get_object_by_role("safety_shutter"), machine_current=self.get_object_by_role("machine_current"), cryo_stream=self.get_object_by_role("cryo_stream"), energy=self.get_object_by_role("energy"), resolution=self.get_object_by_role("resolution"), detector_distance=self.get_object_by_role("detector_distance"), transmission=self.get_object_by_role("transmission"), undulators=self.get_object_by_role("undulators"), flux=self.get_object_by_role("flux"), detector=self.get_object_by_role("detector"), beam_info=self.get_object_by_role("beam_info"), ) try: undulators = self["undulator"] except KeyError: undulators = [] beam_div_hor, beam_div_ver = HWR.beamline.beam.get_beam_divergence() self.setBeamlineConfiguration( synchrotron_name="ESRF", directory_prefix=self.get_property("directory_prefix"), default_exposure_time=HWR.beamline.detector.get_property( "default_exposure_time" ), minimum_exposure_time=HWR.beamline.detector.get_property( "minimum_exposure_time" ), detector_fileext=HWR.beamline.detector.get_property("file_suffix"), detector_type=HWR.beamline.detector.get_property("type"), detector_manufacturer=HWR.beamline.detector.get_property("manufacturer"), detector_model=HWR.beamline.detector.get_property("model"), detector_binning_mode=HWR.beamline.detector.get_property("binning_mode"), detector_px=HWR.beamline.detector.get_property("px"), detector_py=HWR.beamline.detector.get_property("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"), maximum_phi_speed=self.get_property("maximum_phi_speed"), minimum_phi_oscillation=self.get_property("minimum_phi_oscillation"), input_files_server=self.get_property("input_files_server"), ) # self._detector.init(HWR.beamline.detector, self) self.emit("collectConnected", (True,)) self.emit("collectReady", (True,))
@task def data_collection_end_hook(self, data_collect_parameters): self._detector._emit_status() def prepare_oscillation( self, start, osc_range, exptime, number_of_images, shutterless, first_frame, ): if shutterless: end = start + osc_range * number_of_images exptime = (exptime + self._detector.get_deadtime()) * number_of_images if first_frame: self.do_prepare_oscillation(start, end, exptime) else: if osc_range < 1e-4: # still image end = start else: end = start + osc_range self.do_prepare_oscillation(start, end, exptime) return start, end @task def no_oscillation(self, exptime): self.open_fast_shutter() time.sleep(exptime) self.close_fast_shutter() @task def do_oscillation( self, start, end, exptime, number_of_images, shutterless, first_frame, ): if shutterless: if first_frame: exptime = (exptime + self._detector.get_deadtime()) * number_of_images self.oscillation_task = self.oscil( start, end, exptime, number_of_images, wait=False ) if self.oscillation_task.ready(): self.oscillation_task.get() else: self.oscil(start, end, exptime, number_of_images) @task def oscil(self, start, end, exptime, number_of_images, wait=False): if math.fabs(end - start) < 1e-4: self.open_fast_shutter() time.sleep(exptime) self.close_fast_shutter() else: return self.execute_command("do_oscillation", start, end, exptime, number_of_images) def set_wavelength(self, wavelength): if HWR.beamline.tunable_wavelength: return HWR.beamline.energy.set_wavelength(wavelength) else: return def set_energy(self, energy): if HWR.beamline.tunable_wavelength: return HWR.beamline.energy.set_value(energy) else: return def data_collection_cleanup(self): try: self.close_fast_shutter() self.stop_oscillation() HWR.beamline.detector.stop_acquisition() except Exception: logging.getLogger("HWR").exception("") def queue_finished_cleanup(self): logging.getLogger("user_level_log").info("Queue execution finished") @task def close_fast_shutter(self): self.execute_command("close_fast_shutter") @task def open_fast_shutter(self): self.execute_command("open_fast_shutter") @task def move_motors(self, motor_position_dict): # We do not wnta to modify the input dict motor_positions_copy = motor_position_dict.copy() for motor in motor_positions_copy.keys(): # iteritems(): position = motor_positions_copy[motor] if isinstance(motor, string_types): # find right motor object from motor role in diffractometer obj. motor_role = motor motor = HWR.beamline.diffractometer.get_deviceby_role(motor_role) del motor_positions_copy[motor_role] if motor is None: continue motor_positions_copy[motor] = position logging.getLogger("HWR").info( "Moving motor '%s' to %f", motor.get_motor_mnemonic(), position ) motor.set_value(position) while any([motor.motorIsMoving() for motor in motor_positions_copy]): logging.getLogger("HWR").info("Waiting for end of motors motion") time.sleep(0.02) def open_safety_shutter(self): if HWR.beamline.safety_shutter.get_value().name == "CLOSED": try: logging.getLogger("user_level_log").info("Opening safety shutter") HWR.beamline.safety_shutter.set_value( HWR.beamline.safety_shutter.VALUES.OPEN, timeout=10 ) except Exception: logging.getLogger("HWR").exception("") def safety_shutter_opened(self): state = False try: state = HWR.beamline.safety_shutter.get_value().name == "OPEN" except Exception: logging.getLogger("HWR").exception("") state = True return state @task def close_safety_shutter(self): if HWR.beamline.safety_shutter.get_value().name == "OPEN": try: HWR.beamline.safety_shutter.set_value( HWR.beamline.safety_shutter.VALUES.CLOSED ) except Exception: logging.getLogger("HWR").exception("") @task def prepare_intensity_monitors(self): try: self.execute_command("adjust_gains") except AttributeError: pass def prepare_acquisition( self, take_dark, start, osc_range, exptime, npass, number_of_images, comment="", ): self._detector.prepare_acquisition( take_dark, start, osc_range, exptime, npass, number_of_images, comment, self.mesh, self.mesh_num_lines, ) def set_detector_filenames( self, is_first_frame, frame_number, start, filename, shutterless ): if is_first_frame or not shutterless: return self._detector.set_detector_filenames(frame_number, start, filename) def stop_oscillation(self): HWR.beamline.diffractometer.abort_cmd() def start_acquisition(self, exptime, npass, first_frame, shutterless): if first_frame: return self._detector.start_acquisition() @task def write_image(self, last_frame): if last_frame: res = self._detector.wait_ready() self._detector._emit_status() return res def last_image_saved(self, total_time, exptime, num_images): # check here if fast shutter is open ? if HWR.beamline.detector.status["acq_satus"] == "RUNNING": return int(total_time / exptime) else: return HWR.beamline.detector.last_image_saved() def stop_acquisition(self): return self._detector.stop_acquisition() def reset_detector(self): return self._detector.reset()
[docs] def prepare_input_files( self, files_directory, prefix, run_number, process_directory ): autoprocessing_input_file_dirname = "autoprocessing" autoprocessing_directory = os.path.join( process_directory, autoprocessing_input_file_dirname ) xds_input_file_dirname = "xds_%s_run%s" % (prefix, run_number,) mosflm_input_file_dirname = "mosflm_%s_run%s" % (prefix, run_number) hkl2000_dirname = "hkl2000_%s_run%s" % (prefix, run_number) i = 1 while os.path.exists(autoprocessing_directory): autoprocessing_input_file_dirname = "autoprocessing_%d" % i autoprocessing_directory = os.path.join( process_directory, autoprocessing_input_file_dirname ) xds_input_file_dirname = "xds_%s_run%s_%d" % (prefix, run_number, i) mosflm_input_file_dirname = "mosflm_%s_run%s_%d" % (prefix, run_number, i) hkl2000_dirname = "hkl2000_%s_run%s_%d" % (prefix, run_number, i) i += 1 self.raw_data_input_file_dir = os.path.join( files_directory, "process", xds_input_file_dirname ) self.mosflm_raw_data_input_file_dir = os.path.join( files_directory, "process", mosflm_input_file_dirname ) self.raw_hkl2000_dir = os.path.join(files_directory, "process", hkl2000_dirname) for dir0 in ( self.raw_data_input_file_dir, self.mosflm_raw_data_input_file_dir, self.raw_hkl2000_dir, autoprocessing_directory, ): self.create_directories(dir0) logging.info("Creating processing input file directory: %s", dir0) os.chmod(dir0, 0o777) try: try: os.symlink(files_directory, os.path.join(process_directory, "links")) except os.error as e: if e.errno != errno.EEXIST: raise except Exception: logging.exception("Could not create processing file directory") return autoprocessing_directory, "", ""
@task def write_input_files(self, collection_id): # assumes self.xds_directory and self.mosflm_directory are valid conn = HTTPConnection(self.bl_config.input_files_server) # hkl input files input_file_dir = self.raw_hkl2000_dir file_prefix = "../.." hkl_file_path = os.path.join(input_file_dir, "def.site") conn.request("GET", "/def.site/%d?basedir=%s" % (collection_id, file_prefix)) hkl_file = open(hkl_file_path, "w") r = conn.getresponse() if r.status != 200: logging.error("Could not create hkl input file") else: hkl_file.write(r.read().decode()) hkl_file.close() os.chmod(hkl_file_path, 0o666) for input_file_dir, file_prefix in ( (self.raw_data_input_file_dir, "../.."), (self.xds_directory, "../links"), ): xds_input_file = os.path.join(input_file_dir, "XDS.INP") conn.request("GET", "/xds.inp/%d?basedir=%s" % (collection_id, file_prefix)) xds_file = open(xds_input_file, "w") res = conn.getresponse() if res.status != 200: logging.error("Could not create xds input file") else: xds_file.write(res.read().decode()) xds_file.close() os.chmod(xds_input_file, 0o666) input_file_dir = self.mosflm_raw_data_input_file_dir file_prefix = "../.." mosflm_input_file = os.path.join(input_file_dir, "mosflm.inp") conn.request("GET", "/mosflm.inp/%d?basedir=%s" % (collection_id, file_prefix)) mosflm_file = open(mosflm_input_file, "w") mosflm_file.write(conn.getresponse().read().decode()) mosflm_file.close() os.chmod(mosflm_input_file, 0o666) # also write input file for STAC for stac_om_input_file_name, stac_om_dir in ( ("xds.descr", self.xds_directory), ("mosflm.descr", self.mosflm_raw_data_input_file_dir), ("xds.descr", self.raw_data_input_file_dir), ): stac_om_input_file = os.path.join(stac_om_dir, stac_om_input_file_name) conn.request("GET", "/stac.descr/%d" % collection_id) stac_om_file = open(stac_om_input_file, "w") stac_template = conn.getresponse().read().decode() if stac_om_input_file_name.startswith("xds"): om_type = "xds" if stac_om_dir == self.raw_data_input_file_dir: om_filename = os.path.join(stac_om_dir, "CORRECT.LP") else: om_filename = os.path.join( stac_om_dir, "xds_fastproc", "CORRECT.LP" ) else: om_type = "mosflm" om_filename = os.path.join(stac_om_dir, "bestfile.par") stac_om_file.write( stac_template.format( omfilename=om_filename, omtype=om_type, phi=HWR.beamline.diffractometer.phiMotor.get_value(), sampx=HWR.beamline.diffractometer.sampleXMotor.get_value(), sampy=HWR.beamline.diffractometer.sampleYMotor.get_value(), phiy=HWR.beamline.diffractometer.phiyMotor.get_value(), ) ) stac_om_file.close() os.chmod(stac_om_input_file, 0o666) def get_wavelength(self): return HWR.beamline.energy.get_wavelength() def get_undulators_gaps(self): all_gaps = {"Unknown": None} _gaps = {} try: _gaps = HWR.beamline.undulators except Exception: logging.getLogger("HWR").exception("Could not get undulator gaps") all_gaps.clear() for key in _gaps: if "_Position" in key: nkey = key[:-9] all_gaps[nkey] = _gaps[key] else: all_gaps = _gaps return all_gaps def get_resolution_at_corner(self): return self.execute_command("get_resolution_at_corner") def get_beam_size(self): return ( self.execute_command("get_beam_size_x"), self.execute_command("get_beam_size_y"), ) def get_slit_gaps(self): return ( self.execute_command("get_slit_gap_h"), self.execute_command("get_slit_gap_v"), ) def get_beam_shape(self): return self.execute_command("get_beam_shape") # def get_measured_intensity(self): # try: # val = self.get_channel_object("image_intensity").getValue() # return float(val) # except Exception: # return 0 def get_machine_current(self): if HWR.beamline.machine_info: try: return HWR.beamline.machine_info.get_current() except Exception: return -1 else: return 0 def get_machine_message(self): if HWR.beamline.machine_info: return HWR.beamline.machine_info.get_message() else: return "" def get_machine_fill_mode(self): if HWR.beamline.machine_info: return HWR.beamline.machine_info.get_fill_mode() else: """""" def get_cryo_temperature(self): while True: logging.info("Reading cryostream temperature") try: T = HWR.beamline.cryo_stream.getTemperature() except Exception: time.sleep(0.1) continue else: return T def get_current_energy(self): return HWR.beamline.energy.get_value() def get_beam_centre(self): return ( self.execute_command("get_beam_centre_x"), self.execute_command("get_beam_centre_y"), ) def getBeamlineConfiguration(self, *args): # TODO: change this to stop using a dictionary at the other end return self.bl_config._asdict() def is_connected(self): return True
[docs] def is_ready(self): return True
def sampleChangerHO(self): return HWR.beamline.sample_changer def diffractometer(self): return HWR.beamline.diffractometer def dbServerHO(self): return HWR.beamline.lims def sanityCheck(self, collect_params): return def setBrick(self, brick): return def directoryPrefix(self): return self.bl_config.directory_prefix def store_image_in_lims(self, frame, first_frame, last_frame): if first_frame or last_frame: return True @task def generate_image_jpeg(self, filename, jpeg_path, jpeg_thumbnail_path): directories = filename.split(os.path.sep) try: if directories[1] == "data" and directories[2] == "gz": if directories[3] == "visitor": proposal = directories[4] beamline = directories[5] elif directories[4] == "inhouse": proposal = directories[5] beamline = directories[3] else: proposal = "unknown" beamline = "unknown" elif directories[2] == "visitor": beamline = directories[4] proposal = directories[3] else: beamline = directories[2] proposal = directories[4] except Exception: beamline = "unknown" proposal = "unknown" host, port = self.get_property("bes_jpeg_hostport").split(":") conn = HTTPConnection(host, int(port)) params = urlencode( { "image_path": filename, "jpeg_path": jpeg_path, "jpeg_thumbnail_path": jpeg_thumbnail_path, "initiator": beamline, "externalRef": proposal, "reuseCase": "true", } ) conn.request( "POST", "/BES/bridge/rest/processes/CreateThumbnails/RUN?%s" % params, headers={"Accept": "text/plain"}, ) conn.getresponse() """ getOscillation Description: Returns the parameters (and results) of an oscillation. Type : method Arguments : oscillation_id (int; the oscillation id, the last parameters of the collectOscillationStarted signal) Returns : tuple; (blsampleid,barcode,location,parameters) """ def getOscillation(self, oscillation_id): return self.oscillations_history[oscillation_id - 1] def sampleAcceptCentring(self, accepted, centring_status): self.sample_centring_done(accepted, centring_status) def setCentringStatus(self, centring_status): self._centring_status = centring_status """ getOscillations Description: Returns the history of oscillations for a session Type : method Arguments : session_id (int; the session id, stored in the "sessionId" key in each element of the parameters list in the collect method) Returns : list; list of all oscillation_id for the specified session """ def getOscillations(self, session_id): # TODO return [] def set_helical(self, helical_on): self.get_channel_object("helical").set_value(1 if helical_on else 0) def set_helical_pos(self, helical_oscil_pos): self.get_channel_object("helical_pos").set_value(helical_oscil_pos) def get_archive_directory(self, directory): pt = PathTemplate() pt.directory = directory return pt.get_archive_directory()
[docs] def setMeshScanParameters(self, mesh_steps, mesh_range): """ Descript. : """ self._mesh_steps = mesh_steps self._mesh_range = mesh_range