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.
Files changed (25) hide show
  1. mxcubecore/Command/BlueskyHttpServer.py +84 -0
  2. mxcubecore/CommandContainer.py +14 -0
  3. mxcubecore/HardwareObjects/Gphl/GphlQueueEntry.py +2 -2
  4. mxcubecore/HardwareObjects/ICATLIMS.py +16 -2
  5. mxcubecore/HardwareObjects/LNLS/BlueskyHttpServer.py +23 -0
  6. mxcubecore/HardwareObjects/LNLS/EPICS/EPICSMotor.py +40 -0
  7. mxcubecore/HardwareObjects/LNLS/LNLSDiffractometer.py +44 -297
  8. mxcubecore/HardwareObjects/MicrodiffInOut.py +12 -5
  9. mxcubecore/HardwareObjects/QtGraphicsManager.py +28 -21
  10. mxcubecore/HardwareObjects/abstract/AbstractMultiCollect.py +57 -83
  11. mxcubecore/HardwareObjects/abstract/AbstractNState.py +3 -1
  12. mxcubecore/HardwareObjects/abstract/AbstractVideoDevice.py +9 -4
  13. mxcubecore/HardwareObjects/abstract/ISPyBAbstractLims.py +8 -4
  14. mxcubecore/HardwareObjects/autoprocessing.py +2 -2
  15. mxcubecore/HardwareObjects/mockup/CollectMockup.py +11 -8
  16. mxcubecore/HardwareObjects/mockup/ISPyBRestClientMockup.py +10 -6
  17. mxcubecore/HardwareRepository.py +1 -1
  18. mxcubecore/protocols_config.py +7 -0
  19. mxcubecore/queue_entry/base_queue_entry.py +6 -5
  20. mxcubecore/utils/qt_import.py +0 -10
  21. {mxcubecore-1.440.0.dist-info → mxcubecore-1.449.0.dist-info}/METADATA +1 -1
  22. {mxcubecore-1.440.0.dist-info → mxcubecore-1.449.0.dist-info}/RECORD +25 -23
  23. {mxcubecore-1.440.0.dist-info → mxcubecore-1.449.0.dist-info}/WHEEL +0 -0
  24. {mxcubecore-1.440.0.dist-info → mxcubecore-1.449.0.dist-info}/licenses/COPYING +0 -0
  25. {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
- try:
328
- self.graphics_magnification_item.set_properties(
329
- eval(self.get_property("magnification_tool"))
330
- )
331
- except Exception:
332
- self.log.exception("")
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
- try:
782
- raw_snapshot = self.get_raw_snapshot()
783
- result_image = raw_snapshot.copy(
784
- self.beam_position[0]
785
- - self.beam_info_dict["size_x"] * self.pixels_per_mm[0] / 2,
786
- self.beam_position[1]
787
- - self.beam_info_dict["size_y"] * self.pixels_per_mm[1] / 2,
788
- self.beam_info_dict["size_x"] * self.pixels_per_mm[0] * 1.5,
789
- self.beam_info_dict["size_y"] * self.pixels_per_mm[1] * 1.5,
790
- )
791
- date_time_str = datetime.now().strftime("%Y_%m_%d_%H_%M_%S")
792
- result_image.save("/opt/embl-hh/var/crystal_images/%s.png" % date_time_str)
793
- except Exception:
794
- self.log.exception("")
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 (boolean): True if to use fast characterisation otherwise False
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 collection parameters"""
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["blSampleId"])
260
- except Exception:
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 Exception:
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 Exception:
273
- logging.getLogger("HWR").exception("")
272
+ except KeyError:
273
+ pass
274
274
  else:
275
275
  try:
276
276
  vial_number = int(sample_info["sample_location"])
277
- except Exception:
278
- logging.getLogger("HWR").exception("")
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
- pass
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.keys():
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 start, wedge_size in wedges_to_collect[:]:
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
- HWR.beamline.diffractometer.open_detector_cover()
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
- # TODO agree what parameters will be sent to this function
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
- # if _total_time_spent > (wedge_size * (exptime + 0.005)) * 4:
1069
- # msg = "Data collection failure, detector not responding"
1070
- # logging.getLogger("user_level_log").info(msg)
1071
- # HWR.beamline.detector.recover_from_failure()
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 as ex:
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
- else:
1182
- self.emit(
1183
- "collectOscillationFinished",
1184
- (
1185
- owner,
1186
- True,
1187
- data_collect_parameters["status"],
1188
- self.collection_id,
1189
- osc_id,
1190
- data_collect_parameters,
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 Exception:
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
- if residues == 0:
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 msg:
1328
- logging.getLogger().exception("DataCollect:processing: %r" % str(msg))
1303
+ except Exception as err:
1304
+ msg = f"DataCollect:processing: {err}"
1305
+ logging.getLogger().exception(msg)
1329
1306
  else:
1330
- # logging.info("AUTO PROCESSING: %s, %s, %s, %s, %s, %s, %r, %r", process_event, EDNA_files_dir, anomalous, residues, do_inducedraddam, spacegroup, cell)
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
- try:
121
- self.cam_gain = float(self.get_property("gain"))
122
- except TypeError:
123
- self.log.exception("")
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
- try:
57
- self.base_result_url = self.get_property("base_result_url").strip()
58
- except AttributeError:
59
- self.log.exception("")
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.get_property("event").split(" ")
46
+ allowed_events = program.get("event").split(" ")
47
47
  if processEvent in allowed_events:
48
- executable = program.get_property("executable")
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._store_image_in_lims_by_frame_num(1)
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._update_data_collection_in_lims()
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._store_image_in_lims_by_frame_num(last_frame)
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", self.current_dc_parameters, 0)
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 _store_image_in_lims_by_frame_num(self, frame, motor_position_id=None):
123
+ def store_image_in_lims_by_frame_num(self, frame, motor_position_id=None):
124
124
  """
125
125
  Descript. :
126
126
  """
127
- self.trigger_auto_processing("image", self.current_dc_parameters, frame)
128
- image_id = self._store_image_in_lims(frame)
129
- return image_id
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
- + "the server is running and that your "
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
- try:
83
- self.base_result_url = self.get_property("base_result_url").strip()
84
- except AttributeError:
85
- self.log.exception("")
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
 
@@ -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( # noqa: B028 we don't care about stacklevel for this warning
404
+ warn(
405
405
  f"Config file '{beamline_config_file}' have deprecated extension 'yml', "
406
406
  "change to 'yaml'."
407
407
  )
@@ -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
- try:
804
- programs = HWR.beamline.collect["auto_processing"]
805
- autoprocessing.start(programs, "end_multicollect", params)
806
- except KeyError:
807
- logging.getLogger("HWR").exception("")
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, "")
@@ -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
  #
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mxcubecore
3
- Version: 1.440.0
3
+ Version: 1.449.0
4
4
  Summary: Core libraries for the MXCuBE application
5
5
  License-Expression: LGPL-3.0-or-later
6
6
  License-File: COPYING