mxcubecore 1.440.0__py3-none-any.whl → 1.449.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mxcubecore/Command/BlueskyHttpServer.py +84 -0
- mxcubecore/CommandContainer.py +14 -0
- mxcubecore/HardwareObjects/Gphl/GphlQueueEntry.py +2 -2
- mxcubecore/HardwareObjects/ICATLIMS.py +16 -2
- mxcubecore/HardwareObjects/LNLS/BlueskyHttpServer.py +23 -0
- mxcubecore/HardwareObjects/LNLS/EPICS/EPICSMotor.py +40 -0
- mxcubecore/HardwareObjects/LNLS/LNLSDiffractometer.py +44 -297
- mxcubecore/HardwareObjects/MicrodiffInOut.py +12 -5
- mxcubecore/HardwareObjects/QtGraphicsManager.py +28 -21
- mxcubecore/HardwareObjects/abstract/AbstractMultiCollect.py +57 -83
- mxcubecore/HardwareObjects/abstract/AbstractNState.py +3 -1
- mxcubecore/HardwareObjects/abstract/AbstractVideoDevice.py +9 -4
- mxcubecore/HardwareObjects/abstract/ISPyBAbstractLims.py +8 -4
- mxcubecore/HardwareObjects/autoprocessing.py +2 -2
- mxcubecore/HardwareObjects/mockup/CollectMockup.py +11 -8
- mxcubecore/HardwareObjects/mockup/ISPyBRestClientMockup.py +10 -6
- mxcubecore/HardwareRepository.py +1 -1
- mxcubecore/protocols_config.py +7 -0
- mxcubecore/queue_entry/base_queue_entry.py +6 -5
- mxcubecore/utils/qt_import.py +0 -10
- {mxcubecore-1.440.0.dist-info → mxcubecore-1.449.0.dist-info}/METADATA +1 -1
- {mxcubecore-1.440.0.dist-info → mxcubecore-1.449.0.dist-info}/RECORD +25 -23
- {mxcubecore-1.440.0.dist-info → mxcubecore-1.449.0.dist-info}/WHEEL +0 -0
- {mxcubecore-1.440.0.dist-info → mxcubecore-1.449.0.dist-info}/licenses/COPYING +0 -0
- {mxcubecore-1.440.0.dist-info → mxcubecore-1.449.0.dist-info}/licenses/COPYING.LESSER +0 -0
|
@@ -39,8 +39,8 @@ example xml:
|
|
|
39
39
|
import logging
|
|
40
40
|
import math
|
|
41
41
|
import os
|
|
42
|
+
import warnings
|
|
42
43
|
from copy import deepcopy
|
|
43
|
-
from datetime import datetime
|
|
44
44
|
|
|
45
45
|
import gevent
|
|
46
46
|
import matplotlib.pyplot as plt
|
|
@@ -324,12 +324,16 @@ class QtGraphicsManager(AbstractSampleView):
|
|
|
324
324
|
# self.set_scrollbars_off(\
|
|
325
325
|
# self.get_property("scrollbars_always_off") is True)
|
|
326
326
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
327
|
+
magnification_tool = self.get_property("magnification_tool")
|
|
328
|
+
if not magnification_tool:
|
|
329
|
+
warnings.warn("GraphicsManager: Magnification tool not defined")
|
|
330
|
+
else:
|
|
331
|
+
if isinstance(magnification_tool, str):
|
|
332
|
+
try:
|
|
333
|
+
magnification_tool = eval(magnification_tool)
|
|
334
|
+
except TypeError:
|
|
335
|
+
self.log.exception("")
|
|
336
|
+
self.graphics_magnification_item.set_properties(magnification_tool)
|
|
333
337
|
|
|
334
338
|
# try:
|
|
335
339
|
# self.set_view_scale(self.get_property("view_scale"))
|
|
@@ -778,20 +782,23 @@ class QtGraphicsManager(AbstractSampleView):
|
|
|
778
782
|
gevent.spawn_later(2, self.save_crystal_image)
|
|
779
783
|
|
|
780
784
|
def save_crystal_image(self):
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
785
|
+
pass
|
|
786
|
+
# This code ios EMBL-specific and broken.
|
|
787
|
+
# Left as comment to mark ned for refactoring
|
|
788
|
+
# try:
|
|
789
|
+
# raw_snapshot = self.get_raw_snapshot()
|
|
790
|
+
# result_image = raw_snapshot.copy(
|
|
791
|
+
# self.beam_position[0]
|
|
792
|
+
# - self.beam_info_dict["size_x"] * self.pixels_per_mm[0] / 2,
|
|
793
|
+
# self.beam_position[1]
|
|
794
|
+
# - self.beam_info_dict["size_y"] * self.pixels_per_mm[1] / 2,
|
|
795
|
+
# self.beam_info_dict["size_x"] * self.pixels_per_mm[0] * 1.5,
|
|
796
|
+
# self.beam_info_dict["size_y"] * self.pixels_per_mm[1] * 1.5,
|
|
797
|
+
# )
|
|
798
|
+
# date_time_str = datetime.now().strftime("%Y_%m_%d_%H_%M_%S")
|
|
799
|
+
# result_image.save("/opt/embl-hh/var/crystal_images/%s.png" % date_time_str)
|
|
800
|
+
# except Exception:
|
|
801
|
+
# self.log.exception("")
|
|
795
802
|
|
|
796
803
|
def diffractometer_centring_failed(self, method, centring_status):
|
|
797
804
|
"""CleanUp method after centring failed
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import abc
|
|
2
2
|
import collections
|
|
3
3
|
import errno
|
|
4
|
-
|
|
5
|
-
# import types
|
|
6
4
|
import logging
|
|
7
5
|
import os
|
|
8
6
|
import socket
|
|
@@ -13,11 +11,7 @@ import autoprocessing
|
|
|
13
11
|
import gevent
|
|
14
12
|
|
|
15
13
|
from mxcubecore import HardwareRepository as HWR
|
|
16
|
-
from mxcubecore.TaskUtils import
|
|
17
|
-
cleanup,
|
|
18
|
-
error_cleanup,
|
|
19
|
-
task,
|
|
20
|
-
)
|
|
14
|
+
from mxcubecore.TaskUtils import cleanup, error_cleanup, task
|
|
21
15
|
|
|
22
16
|
BeamlineControl = collections.namedtuple(
|
|
23
17
|
"BeamlineControl",
|
|
@@ -105,6 +99,9 @@ class AbstractMultiCollect(object):
|
|
|
105
99
|
def data_collection_end_hook(self, data_collect_parameters):
|
|
106
100
|
pass
|
|
107
101
|
|
|
102
|
+
def _bliss_data_collection_hook(self, data_collect_parameters):
|
|
103
|
+
pass
|
|
104
|
+
|
|
108
105
|
@abc.abstractmethod
|
|
109
106
|
@task
|
|
110
107
|
def close_fast_shutter(self):
|
|
@@ -115,21 +112,21 @@ class AbstractMultiCollect(object):
|
|
|
115
112
|
def move_motors(self, motor_position_dict):
|
|
116
113
|
return
|
|
117
114
|
|
|
118
|
-
@abc.abstractmethod
|
|
119
|
-
@task
|
|
120
115
|
def open_safety_shutter(self):
|
|
121
116
|
pass
|
|
122
117
|
|
|
118
|
+
def open_detector_cover(self):
|
|
119
|
+
"""Placeholder for implementing opening of the detector cover"""
|
|
120
|
+
|
|
121
|
+
def close_detector_cover(self):
|
|
122
|
+
"""Placeholder for implementing closing of the detector cover"""
|
|
123
|
+
|
|
123
124
|
def safety_shutter_opened(self):
|
|
124
125
|
return False
|
|
125
126
|
|
|
126
|
-
@abc.abstractmethod
|
|
127
|
-
@task
|
|
128
127
|
def close_safety_shutter(self):
|
|
129
128
|
pass
|
|
130
129
|
|
|
131
|
-
@abc.abstractmethod
|
|
132
|
-
@task
|
|
133
130
|
def prepare_intensity_monitors(self):
|
|
134
131
|
pass
|
|
135
132
|
|
|
@@ -243,39 +240,42 @@ class AbstractMultiCollect(object):
|
|
|
243
240
|
Use fast characterisation
|
|
244
241
|
|
|
245
242
|
Args:
|
|
246
|
-
value
|
|
243
|
+
value: True if to use fast characterisation otherwise False
|
|
247
244
|
"""
|
|
248
|
-
pass
|
|
249
245
|
|
|
250
246
|
@abc.abstractmethod
|
|
251
247
|
@task
|
|
252
248
|
def generate_image_jpeg(self, filename, jpeg_path, jpeg_thumbnail_path):
|
|
253
249
|
pass
|
|
254
250
|
|
|
255
|
-
def get_sample_info_from_parameters(self, parameters):
|
|
256
|
-
"""Returns sample_id, sample_location and sample_code from data
|
|
251
|
+
def get_sample_info_from_parameters(self, parameters: dict):
|
|
252
|
+
"""Returns sample_id, sample_location and sample_code from data
|
|
253
|
+
collection parameters.
|
|
254
|
+
Args:
|
|
255
|
+
parameters: Dictionary with the data collection parameters
|
|
256
|
+
"""
|
|
257
257
|
sample_info = parameters.get("sample_reference")
|
|
258
258
|
try:
|
|
259
|
-
sample_id = int(sample_info
|
|
260
|
-
except
|
|
259
|
+
sample_id = int(sample_info.get("blSampleId"))
|
|
260
|
+
except (AttributeError, TypeError):
|
|
261
261
|
sample_id = None
|
|
262
262
|
|
|
263
263
|
try:
|
|
264
264
|
sample_code = sample_info["code"]
|
|
265
|
-
except
|
|
265
|
+
except KeyError:
|
|
266
266
|
sample_code = None
|
|
267
267
|
|
|
268
268
|
sample_location = None
|
|
269
269
|
|
|
270
270
|
try:
|
|
271
271
|
sample_container_number = int(sample_info["container_reference"])
|
|
272
|
-
except
|
|
273
|
-
|
|
272
|
+
except KeyError:
|
|
273
|
+
pass
|
|
274
274
|
else:
|
|
275
275
|
try:
|
|
276
276
|
vial_number = int(sample_info["sample_location"])
|
|
277
|
-
except
|
|
278
|
-
|
|
277
|
+
except KeyError:
|
|
278
|
+
pass
|
|
279
279
|
else:
|
|
280
280
|
sample_location = (sample_container_number, vial_number)
|
|
281
281
|
|
|
@@ -370,8 +370,6 @@ class AbstractMultiCollect(object):
|
|
|
370
370
|
wedges_to_collect = []
|
|
371
371
|
|
|
372
372
|
for wedge_size in wedge_sizes_list:
|
|
373
|
-
orig_start = start
|
|
374
|
-
|
|
375
373
|
wedges_to_collect.append((start, wedge_size))
|
|
376
374
|
start += wedge_size * osc_range - overlap
|
|
377
375
|
|
|
@@ -395,12 +393,11 @@ class AbstractMultiCollect(object):
|
|
|
395
393
|
self, files_directory, prefix, run_number, process_directory
|
|
396
394
|
):
|
|
397
395
|
"""Return XDS input file directory"""
|
|
398
|
-
pass
|
|
399
396
|
|
|
400
397
|
@abc.abstractmethod
|
|
401
398
|
@task
|
|
402
399
|
def write_input_files(self, collection_id):
|
|
403
|
-
|
|
400
|
+
"""Write the input files place holder."""
|
|
404
401
|
|
|
405
402
|
def execute_collect_without_loop(self, data_collect_parameters):
|
|
406
403
|
return
|
|
@@ -558,7 +555,7 @@ class AbstractMultiCollect(object):
|
|
|
558
555
|
|
|
559
556
|
current_diffractometer_position = self.diffractometer().get_positions()
|
|
560
557
|
|
|
561
|
-
for motor in motors_to_move_before_collect
|
|
558
|
+
for motor in motors_to_move_before_collect:
|
|
562
559
|
if motors_to_move_before_collect[motor] is not None:
|
|
563
560
|
try:
|
|
564
561
|
if current_diffractometer_position[motor] is not None:
|
|
@@ -624,7 +621,6 @@ class AbstractMultiCollect(object):
|
|
|
624
621
|
snapshot_i = 1
|
|
625
622
|
snapshots = []
|
|
626
623
|
for img in centring_info["images"]:
|
|
627
|
-
img_phi_pos = img[0]
|
|
628
624
|
img_data = img[1]
|
|
629
625
|
snapshot_filename = "%s_%s_%s.snapshot.jpeg" % (
|
|
630
626
|
file_parameters["prefix"],
|
|
@@ -680,11 +676,6 @@ class AbstractMultiCollect(object):
|
|
|
680
676
|
sample_id = data_collect_parameters["blSampleId"]
|
|
681
677
|
subwedge_size = oscillation_parameters.get("reference_interval", 1)
|
|
682
678
|
|
|
683
|
-
# if data_collect_parameters["shutterless"]:
|
|
684
|
-
# subwedge_size = 1
|
|
685
|
-
# else:
|
|
686
|
-
# subwedge_size = oscillation_parameters["number_of_images"]
|
|
687
|
-
|
|
688
679
|
wedges_to_collect = self.prepare_wedges_to_collect(
|
|
689
680
|
oscillation_parameters["start"],
|
|
690
681
|
oscillation_parameters["number_of_images"],
|
|
@@ -703,10 +694,9 @@ class AbstractMultiCollect(object):
|
|
|
703
694
|
)
|
|
704
695
|
|
|
705
696
|
start_image_number = oscillation_parameters["start_image_number"]
|
|
706
|
-
last_frame = start_image_number + nframes - 1
|
|
707
697
|
|
|
708
698
|
if data_collect_parameters["skip_images"]:
|
|
709
|
-
for
|
|
699
|
+
for _start, wedge_size in wedges_to_collect[:]:
|
|
710
700
|
filename = image_file_template % start_image_number
|
|
711
701
|
file_location = file_parameters["directory"]
|
|
712
702
|
file_path = os.path.join(file_location, filename)
|
|
@@ -775,9 +765,9 @@ class AbstractMultiCollect(object):
|
|
|
775
765
|
"Setting resolution to %f", resolution
|
|
776
766
|
)
|
|
777
767
|
try:
|
|
778
|
-
|
|
768
|
+
self.open_detector_cover()
|
|
779
769
|
HWR.beamline.resolution.set_value(resolution, timeout=3500)
|
|
780
|
-
except RuntimeError:
|
|
770
|
+
except (AttributeError, RuntimeError):
|
|
781
771
|
logging.getLogger("user_level_log").info(
|
|
782
772
|
"Failed to set resolution to %f", resolution
|
|
783
773
|
)
|
|
@@ -797,9 +787,6 @@ class AbstractMultiCollect(object):
|
|
|
797
787
|
)
|
|
798
788
|
raise
|
|
799
789
|
|
|
800
|
-
# 0: software binned, 1: unbinned, 2:hw binned
|
|
801
|
-
# self.set_detector_mode(data_collect_parameters["detector_mode"])
|
|
802
|
-
|
|
803
790
|
with cleanup(self.data_collection_cleanup):
|
|
804
791
|
# if not self.safety_shutter_opened():
|
|
805
792
|
self.open_safety_shutter()
|
|
@@ -881,7 +868,7 @@ class AbstractMultiCollect(object):
|
|
|
881
868
|
self.write_input_files(self.collection_id, wait=False)
|
|
882
869
|
|
|
883
870
|
# at this point input files should have been written
|
|
884
|
-
#
|
|
871
|
+
# TO DO: agree what parameters will be sent to this function
|
|
885
872
|
if data_collect_parameters.get("processing", False) == "True":
|
|
886
873
|
self.trigger_auto_processing(
|
|
887
874
|
"before",
|
|
@@ -1028,11 +1015,10 @@ class AbstractMultiCollect(object):
|
|
|
1028
1015
|
)
|
|
1029
1016
|
|
|
1030
1017
|
if data_collect_parameters.get("shutterless"):
|
|
1018
|
+
msg = "Timeout waiting for detector trigger, no image taken"
|
|
1031
1019
|
with gevent.Timeout(
|
|
1032
1020
|
self.first_image_timeout,
|
|
1033
|
-
RuntimeError(
|
|
1034
|
-
"Timeout waiting for detector trigger, no image taken"
|
|
1035
|
-
),
|
|
1021
|
+
RuntimeError(msg),
|
|
1036
1022
|
):
|
|
1037
1023
|
if last_image_saved <= 0:
|
|
1038
1024
|
last_image_saved = self.last_image_saved(
|
|
@@ -1065,14 +1051,10 @@ class AbstractMultiCollect(object):
|
|
|
1065
1051
|
_total_time_spent += time.time() - _time_start
|
|
1066
1052
|
_total_exptime += exptime
|
|
1067
1053
|
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
# raise RuntimeError(msg)
|
|
1073
|
-
|
|
1074
|
-
# Bug fix for MD2/3(UP): diffractometer still has things to do even after the last frame is taken (decelerate motors and
|
|
1075
|
-
# possibly download diagnostics) so we cannot trigger the cleanup (that will send an abort on the diffractometer) as soon as
|
|
1054
|
+
# Bug fix for MD2/3(UP): diffractometer still has things to do
|
|
1055
|
+
# even after the last frame is taken (decelerate motors and
|
|
1056
|
+
# possibly download diagnostics) so we cannot trigger the cleanup
|
|
1057
|
+
# (that will send an abort on the diffractometer) as soon as
|
|
1076
1058
|
# the last frame is counted
|
|
1077
1059
|
self.diffractometer().wait_ready(1000)
|
|
1078
1060
|
|
|
@@ -1114,13 +1096,12 @@ class AbstractMultiCollect(object):
|
|
|
1114
1096
|
|
|
1115
1097
|
# now really start collect sequence
|
|
1116
1098
|
self.do_collect(owner, data_collect_parameters)
|
|
1117
|
-
except Exception
|
|
1099
|
+
except Exception:
|
|
1118
1100
|
failed = True
|
|
1119
1101
|
exc_type, exc_value, exc_tb = sys.exc_info()
|
|
1102
|
+
msg = f"Data collection failed: {exc_value}"
|
|
1120
1103
|
logging.exception("Data collection failed")
|
|
1121
|
-
logging.getLogger("user_level_log").info(
|
|
1122
|
-
"Data collection failed %s" % exc_value
|
|
1123
|
-
)
|
|
1104
|
+
logging.getLogger("user_level_log").info(msg)
|
|
1124
1105
|
data_collect_parameters["status"] = (
|
|
1125
1106
|
"Data collection failed!" # Message to be stored in LIMS
|
|
1126
1107
|
)
|
|
@@ -1178,18 +1159,17 @@ class AbstractMultiCollect(object):
|
|
|
1178
1159
|
if failed:
|
|
1179
1160
|
# if one dc fails, stop the whole loop
|
|
1180
1161
|
break
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
)
|
|
1162
|
+
self.emit(
|
|
1163
|
+
"collectOscillationFinished",
|
|
1164
|
+
(
|
|
1165
|
+
owner,
|
|
1166
|
+
True,
|
|
1167
|
+
data_collect_parameters["status"],
|
|
1168
|
+
self.collection_id,
|
|
1169
|
+
osc_id,
|
|
1170
|
+
data_collect_parameters,
|
|
1171
|
+
),
|
|
1172
|
+
)
|
|
1193
1173
|
|
|
1194
1174
|
if self.get_property("close_safety_shutter_if_idle", False):
|
|
1195
1175
|
try:
|
|
@@ -1208,10 +1188,7 @@ class AbstractMultiCollect(object):
|
|
|
1208
1188
|
self.emit("collectReady", (True,))
|
|
1209
1189
|
|
|
1210
1190
|
def collect_without_loop(self, data_collect_parameters_list):
|
|
1211
|
-
in_multicollect = len(data_collect_parameters_list) > 1
|
|
1212
|
-
collections_analyse_params = []
|
|
1213
1191
|
self.emit("collectReady", (False,))
|
|
1214
|
-
# self.emit("collectStarted", (self.owner, 1))
|
|
1215
1192
|
total_frames = 0
|
|
1216
1193
|
total_time_sec = 0
|
|
1217
1194
|
# in principle data_collect_parameters_list always has one element
|
|
@@ -1303,13 +1280,12 @@ class AbstractMultiCollect(object):
|
|
|
1303
1280
|
if isinstance(residues, str):
|
|
1304
1281
|
try:
|
|
1305
1282
|
residues = int(residues)
|
|
1306
|
-
except
|
|
1283
|
+
except ValueError:
|
|
1307
1284
|
residues = 200
|
|
1308
1285
|
|
|
1309
1286
|
# residues = zero should be interpreted as if no value was provided
|
|
1310
1287
|
# use default of 200
|
|
1311
|
-
|
|
1312
|
-
residues = 200
|
|
1288
|
+
residues = residues or 200
|
|
1313
1289
|
|
|
1314
1290
|
processAnalyseParams = {}
|
|
1315
1291
|
processAnalyseParams["EDNA_files_dir"] = EDNA_files_dir
|
|
@@ -1324,15 +1300,13 @@ class AbstractMultiCollect(object):
|
|
|
1324
1300
|
processAnalyseParams["residues"] = residues
|
|
1325
1301
|
processAnalyseParams["spacegroup"] = spacegroup
|
|
1326
1302
|
processAnalyseParams["cell"] = cell
|
|
1327
|
-
except Exception as
|
|
1328
|
-
|
|
1303
|
+
except Exception as err:
|
|
1304
|
+
msg = f"DataCollect:processing: {err}"
|
|
1305
|
+
logging.getLogger().exception(msg)
|
|
1329
1306
|
else:
|
|
1330
|
-
|
|
1331
|
-
|
|
1307
|
+
programs = self.get_property("auto_processing")
|
|
1332
1308
|
try:
|
|
1333
|
-
autoprocessing.start(
|
|
1334
|
-
self["auto_processing"], process_event, processAnalyseParams
|
|
1335
|
-
)
|
|
1309
|
+
autoprocessing.start(programs, process_event, processAnalyseParams)
|
|
1336
1310
|
except Exception:
|
|
1337
1311
|
logging.getLogger().exception("Error starting processing")
|
|
1338
1312
|
|
|
@@ -94,7 +94,9 @@ class AbstractNState(AbstractActuator):
|
|
|
94
94
|
values_dict.update(values)
|
|
95
95
|
self.VALUES = Enum("ValueEnum", values_dict)
|
|
96
96
|
except (ValueError, TypeError):
|
|
97
|
-
self.log.exception(
|
|
97
|
+
self.log.exception(
|
|
98
|
+
"Error initialising values for %s", self.__class__.__name__
|
|
99
|
+
)
|
|
98
100
|
|
|
99
101
|
def value_to_enum(self, value, idx=0):
|
|
100
102
|
"""Transform a value to Enum
|
|
@@ -117,10 +117,15 @@ class AbstractVideoDevice(HardwareObject):
|
|
|
117
117
|
|
|
118
118
|
self.poll_interval = self.get_property("interval", self.default_poll_interval)
|
|
119
119
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
120
|
+
cam_gain = self.get_property("gain")
|
|
121
|
+
if cam_gain is None:
|
|
122
|
+
warnings.warn("VideoDevice gain is not configured")
|
|
123
|
+
else:
|
|
124
|
+
try:
|
|
125
|
+
cam_gain = float(cam_gain)
|
|
126
|
+
except TypeError:
|
|
127
|
+
self.log.exception("")
|
|
128
|
+
self.cam_gain = cam_gain
|
|
124
129
|
|
|
125
130
|
try:
|
|
126
131
|
self.cam_exposure = float(self.get_property("exposure"))
|
|
@@ -53,10 +53,14 @@ class ISPyBAbstractLIMS(AbstractLims):
|
|
|
53
53
|
else:
|
|
54
54
|
self.proxy = {}
|
|
55
55
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
56
|
+
base_result_url = self.get_property("base_result_url")
|
|
57
|
+
if base_result_url and isinstance(base_result_url, str):
|
|
58
|
+
self.base_result_url = base_result_url.strip()
|
|
59
|
+
else:
|
|
60
|
+
warnings.warn(
|
|
61
|
+
"%s.%s missing or misconfigured: %s"
|
|
62
|
+
% (self.__class__.__name__, "base_result_url", base_result_url)
|
|
63
|
+
)
|
|
60
64
|
|
|
61
65
|
self.adapter = self._create_data_adapter()
|
|
62
66
|
self.log.debug("[ISPYB] Proxy address: %s" % self.proxy)
|
|
@@ -43,9 +43,9 @@ def grouped_processing(processEvent, params):
|
|
|
43
43
|
def start(programs, processEvent, paramsDict):
|
|
44
44
|
for program in programs["program"]:
|
|
45
45
|
try:
|
|
46
|
-
allowed_events = program.
|
|
46
|
+
allowed_events = program.get("event").split(" ")
|
|
47
47
|
if processEvent in allowed_events:
|
|
48
|
-
executable = program.
|
|
48
|
+
executable = program.get("executable")
|
|
49
49
|
|
|
50
50
|
if os.path.isfile(executable):
|
|
51
51
|
if processEvent == "end_multicollect":
|
|
@@ -55,7 +55,7 @@ class CollectMockup(AbstractCollect):
|
|
|
55
55
|
"""Main collection hook"""
|
|
56
56
|
self.emit("collectStarted", (None, 1))
|
|
57
57
|
self.emit("fsmConditionChanged", "data_collection_started", True)
|
|
58
|
-
self.
|
|
58
|
+
self.store_image_in_lims_by_frame_num(1)
|
|
59
59
|
number_of_images = self.current_dc_parameters["oscillation_sequence"][0][
|
|
60
60
|
"number_of_images"
|
|
61
61
|
]
|
|
@@ -84,20 +84,20 @@ class CollectMockup(AbstractCollect):
|
|
|
84
84
|
def emit_collection_finished(self):
|
|
85
85
|
"""Collection finished behaviour"""
|
|
86
86
|
if self.current_dc_parameters["experiment_type"] != "Collect - Multiwedge":
|
|
87
|
-
self.
|
|
87
|
+
self.update_data_collection_in_lims()
|
|
88
88
|
|
|
89
89
|
last_frame = self.current_dc_parameters["oscillation_sequence"][0][
|
|
90
90
|
"number_of_images"
|
|
91
91
|
]
|
|
92
92
|
if last_frame > 1:
|
|
93
|
-
self.
|
|
93
|
+
self.store_image_in_lims_by_frame_num(last_frame)
|
|
94
94
|
if (
|
|
95
95
|
self.current_dc_parameters["experiment_type"] in ("OSC", "Helical")
|
|
96
96
|
and self.current_dc_parameters["oscillation_sequence"][0]["overlap"]
|
|
97
97
|
== 0
|
|
98
98
|
and last_frame > 19
|
|
99
99
|
):
|
|
100
|
-
self.trigger_auto_processing("after",
|
|
100
|
+
self.trigger_auto_processing("after", 0)
|
|
101
101
|
|
|
102
102
|
success_msg = "Data collection successful"
|
|
103
103
|
# self.current_dc_parameters["status"] = success_msg
|
|
@@ -120,13 +120,16 @@ class CollectMockup(AbstractCollect):
|
|
|
120
120
|
self._collecting = False
|
|
121
121
|
self.ready_event.set()
|
|
122
122
|
|
|
123
|
-
def
|
|
123
|
+
def store_image_in_lims_by_frame_num(self, frame, motor_position_id=None):
|
|
124
124
|
"""
|
|
125
125
|
Descript. :
|
|
126
126
|
"""
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
127
|
+
return
|
|
128
|
+
# This entire function is a mess and it is not clear what should be called
|
|
129
|
+
# when or how. Disabled till somebody knows how to fix it
|
|
130
|
+
# self.trigger_auto_processing("image", frame)
|
|
131
|
+
# image_id = self._store_image_in_lims(frame)
|
|
132
|
+
# return image_id
|
|
130
133
|
|
|
131
134
|
def trigger_auto_processing(self, process_event, frame_number):
|
|
132
135
|
"""
|
|
@@ -3,6 +3,7 @@ A client for ISPyB Webservices.
|
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
5
|
import logging
|
|
6
|
+
import warnings
|
|
6
7
|
from datetime import datetime
|
|
7
8
|
from urllib.parse import urljoin
|
|
8
9
|
|
|
@@ -11,8 +12,7 @@ from mxcubecore.BaseHardwareObjects import HardwareObject
|
|
|
11
12
|
|
|
12
13
|
_CONNECTION_ERROR_MSG = (
|
|
13
14
|
"Could not connect to ISPyB, please verify that "
|
|
14
|
-
|
|
15
|
-
+ "configuration is correct"
|
|
15
|
+
"the server is running and that your configuration is correct"
|
|
16
16
|
)
|
|
17
17
|
_NO_TOKEN_MSG = "Could not connect to ISPyB, no valid REST token available." # noqa: S105
|
|
18
18
|
|
|
@@ -79,10 +79,14 @@ class ISPyBRestClientMockup(HardwareObject):
|
|
|
79
79
|
self.__rest_password = self.get_property("restPass").strip()
|
|
80
80
|
self.__site = self.get_property("site").strip()
|
|
81
81
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
82
|
+
base_result_url = self.get_property("base_result_url")
|
|
83
|
+
if base_result_url and isinstance(base_result_url, str):
|
|
84
|
+
self.base_result_url = base_result_url.strip()
|
|
85
|
+
else:
|
|
86
|
+
warnings.warn(
|
|
87
|
+
"%s.%s missing or misconfigured: %s"
|
|
88
|
+
% (self.__class__.__name__, "base_result_url", base_result_url)
|
|
89
|
+
)
|
|
86
90
|
|
|
87
91
|
self.__update_rest_token()
|
|
88
92
|
|
mxcubecore/HardwareRepository.py
CHANGED
|
@@ -401,7 +401,7 @@ def init_hardware_repository(
|
|
|
401
401
|
|
|
402
402
|
beamline_config_file = _instance.find_beamline_config_file()
|
|
403
403
|
if beamline_config_file.endswith(".yml"):
|
|
404
|
-
warn(
|
|
404
|
+
warn(
|
|
405
405
|
f"Config file '{beamline_config_file}' have deprecated extension 'yml', "
|
|
406
406
|
"change to 'yaml'."
|
|
407
407
|
)
|
mxcubecore/protocols_config.py
CHANGED
|
@@ -132,12 +132,19 @@ def _setup_sardana_commands(hwobj: HardwareObject, sardana_config: dict):
|
|
|
132
132
|
setup_door(door_name, door_config)
|
|
133
133
|
|
|
134
134
|
|
|
135
|
+
def _setup_bluesky_http_server_command(hwobj: HardwareObject, server: str):
|
|
136
|
+
hwobj.add_command(
|
|
137
|
+
{"type": "bluesky_http_server", "name": "bluesky_http_server"}, server
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
|
|
135
141
|
def _protocol_handles():
|
|
136
142
|
return {
|
|
137
143
|
"tango": _setup_tango_commands_channels,
|
|
138
144
|
"exporter": _setup_exporter_commands_channels,
|
|
139
145
|
"epics": _setup_epics_channels,
|
|
140
146
|
"sardana": _setup_sardana_commands,
|
|
147
|
+
"bluesky_http_server": _setup_bluesky_http_server_command,
|
|
141
148
|
}
|
|
142
149
|
|
|
143
150
|
|
|
@@ -800,11 +800,12 @@ class SampleQueueEntry(BaseQueueEntry):
|
|
|
800
800
|
}
|
|
801
801
|
)
|
|
802
802
|
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
803
|
+
programs = HWR.beamline.collect.get_property("auto_processing")
|
|
804
|
+
if programs:
|
|
805
|
+
try:
|
|
806
|
+
autoprocessing.start(programs, "end_multicollect", params)
|
|
807
|
+
except KeyError:
|
|
808
|
+
logging.getLogger("HWR").exception("")
|
|
808
809
|
|
|
809
810
|
self._set_background_color()
|
|
810
811
|
self._view.setText(1, "")
|
mxcubecore/utils/qt_import.py
CHANGED
|
@@ -242,11 +242,6 @@ if (qt_variant == "PyQt5") or (qt_variant is None and not qt_imported):
|
|
|
242
242
|
except ImportError:
|
|
243
243
|
logging.getLogger("HWR").exception("")
|
|
244
244
|
|
|
245
|
-
try:
|
|
246
|
-
from PyQt5.QtWebKit import QWebPage
|
|
247
|
-
except ImportError:
|
|
248
|
-
logging.getLogger("HWR").exception("")
|
|
249
|
-
|
|
250
245
|
#
|
|
251
246
|
# PyQt4
|
|
252
247
|
#
|
|
@@ -383,11 +378,6 @@ if (qt_variant == "PyQt4") or (qt_variant is None and not qt_imported):
|
|
|
383
378
|
except BaseException:
|
|
384
379
|
logging.getLogger("HWR").exception("")
|
|
385
380
|
|
|
386
|
-
try:
|
|
387
|
-
from PyQt4.QtWebKit import QWebPage
|
|
388
|
-
except ImportError:
|
|
389
|
-
logging.getLogger("HWR").exception("")
|
|
390
|
-
|
|
391
381
|
#
|
|
392
382
|
# PySide
|
|
393
383
|
#
|