mxcubecore 1.384.0__py3-none-any.whl → 1.386.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.

Potentially problematic release.


This version of mxcubecore might be problematic. Click here for more details.

@@ -326,9 +326,9 @@ class ICATLIMS(AbstractLims):
326
326
  )
327
327
  if sample_information is not None:
328
328
  if len(HWR.beamline.session.get_full_path("", "")) > 0:
329
- destination_folder = HWR.beamline.session.get_full_path("", "")[
330
- 0
331
- ]
329
+ destination_folder = (
330
+ HWR.beamline.session.get_base_process_directory()
331
+ )
332
332
  msg = "Download restource: "
333
333
  msg += f"sample_sheet_id={sample_sheet_id} "
334
334
  msg += f"destination_folder={destination_folder}"
@@ -820,21 +820,20 @@ class ICATLIMS(AbstractLims):
820
820
  msg = f"Sample {sample_id} not found"
821
821
  logging.getLogger("HWR").debug(msg)
822
822
 
823
- start_time = datacollection_dict.get("startTime", "")
824
- end_time = datacollection_dict.get("endTime", "")
823
+ start_time = datacollection_dict.get("collection_start_time", "")
824
+ end_time = datetime.now(ZoneInfo("Europe/Paris")).isoformat()
825
825
 
826
- try:
827
- dt_aware = datetime.strptime(start_time, "%Y-%m-%d %H:%M:%S").replace(
828
- tzinfo=ZoneInfo("Europe/Paris")
829
- )
830
- dt_aware_end = datetime.strptime(end_time, "%Y-%m-%d %H:%M:%S").replace(
831
- tzinfo=ZoneInfo("Europe/Paris")
832
- )
826
+ if start_time:
827
+ try:
828
+ dt_aware = datetime.strptime(start_time, "%Y-%m-%d %H:%M:%S").replace(
829
+ tzinfo=ZoneInfo("Europe/Paris")
830
+ )
831
+ start_time = dt_aware.isoformat(timespec="microseconds")
832
+ except (ValueError, TypeError):
833
+ logging.getLogger("HWR").exception("Cannot parse start time")
834
+ else:
835
+ start_time = datetime.now(ZoneInfo("Europe/Paris")).isoformat()
833
836
 
834
- start_time = dt_aware.isoformat(timespec="microseconds")
835
- end_time = dt_aware_end.isoformat(timespec="microseconds")
836
- except TypeError:
837
- logging.getLogger("HWR").exception("Cannot parse start and end time")
838
837
  bsx, bsy, shape, _ = HWR.beamline.beam.get_value()
839
838
  flux_end = datacollection_dict.get("flux_end") or HWR.beamline.flux.get_value()
840
839
 
@@ -887,6 +886,29 @@ class ICATLIMS(AbstractLims):
887
886
 
888
887
  directory = Path(energyscan_dict["scanFileFullPath"]).parent
889
888
 
889
+ start_time = energyscan_dict.get("startTime", "")
890
+ end_time = energyscan_dict.get("endTime", "")
891
+
892
+ if start_time:
893
+ try:
894
+ dt_aware = datetime.strptime(
895
+ start_time, "%Y-%m-%d %H:%M:%S"
896
+ ).replace(tzinfo=ZoneInfo("Europe/Paris"))
897
+ start_time = dt_aware.isoformat(timespec="microseconds")
898
+ metadata.update({"startDate": start_time})
899
+ except (ValueError, TypeError):
900
+ logging.getLogger("HWR").exception("Cannot parse start time")
901
+
902
+ if end_time:
903
+ try:
904
+ dt_aware = datetime.strptime(end_time, "%Y-%m-%d %H:%M:%S").replace(
905
+ tzinfo=ZoneInfo("Europe/Paris")
906
+ )
907
+ end_time = dt_aware.isoformat(timespec="microseconds")
908
+ metadata.update({"endDate": end_time})
909
+ except (ValueError, TypeError):
910
+ logging.getLogger("HWR").exception("Cannot parse start time")
911
+
890
912
  metadata.update(
891
913
  {
892
914
  "scanType": "energy_scan",
@@ -940,6 +962,29 @@ class ICATLIMS(AbstractLims):
940
962
 
941
963
  directory = Path(xfespectrum_dict["filename"]).parent
942
964
 
965
+ start_time = xfespectrum_dict.get("startTime", "")
966
+ end_time = xfespectrum_dict.get("endTime", "")
967
+
968
+ if start_time:
969
+ try:
970
+ dt_aware = datetime.strptime(
971
+ start_time, "%Y-%m-%d %H:%M:%S"
972
+ ).replace(tzinfo=ZoneInfo("Europe/Paris"))
973
+ start_time = dt_aware.isoformat(timespec="microseconds")
974
+ metadata.update({"startDate": start_time})
975
+ except (ValueError, TypeError):
976
+ logging.getLogger("HWR").exception("Cannot parse start time")
977
+
978
+ if end_time:
979
+ try:
980
+ dt_aware = datetime.strptime(end_time, "%Y-%m-%d %H:%M:%S").replace(
981
+ tzinfo=ZoneInfo("Europe/Paris")
982
+ )
983
+ end_time = dt_aware.isoformat(timespec="microseconds")
984
+ metadata.update({"endDate": end_time})
985
+ except (ValueError, TypeError):
986
+ logging.getLogger("HWR").exception("Cannot parse end time")
987
+
943
988
  metadata.update(
944
989
  {
945
990
  "scanType": "xrf",
@@ -1045,7 +1090,7 @@ class ICATLIMS(AbstractLims):
1045
1090
  try:
1046
1091
  token = self.icat_session["sessionId"]
1047
1092
  url = f"{self.url}/catalogue/{token}/files/download?sampleId={sample_id}&resourceId={resource.id}"
1048
- response = requests.get(url, stream=True, timeout=3)
1093
+ response = requests.get(url, stream=True, timeout=30)
1049
1094
  response.raise_for_status()
1050
1095
 
1051
1096
  file_path = resource_folder / resource.filename
@@ -1110,15 +1155,6 @@ class ICATLIMS(AbstractLims):
1110
1155
  proposal = f"{HWR.beamline.session.proposal_code}"
1111
1156
  proposal += f"{HWR.beamline.session.proposal_number}"
1112
1157
 
1113
- try:
1114
- dt_aware = datetime.strptime(
1115
- datacollection_dict.get("collection_start_time"),
1116
- "%Y-%m-%d %H:%M:%S",
1117
- ).replace(tzinfo=ZoneInfo("Europe/Paris"))
1118
- start_time = dt_aware.isoformat(timespec="microseconds")
1119
- except RuntimeError:
1120
- logger.warning("Failed to parse start and end time")
1121
-
1122
1158
  metadata.update(
1123
1159
  {
1124
1160
  "MX_dataCollectionId": datacollection_dict.get("collection_id"),
@@ -1149,7 +1185,6 @@ class ICATLIMS(AbstractLims):
1149
1185
  ),
1150
1186
  "MX_position_id": workflow_params.get("workflow_position_id"),
1151
1187
  "group_by": workflow_params.get("workflow_group_by"),
1152
- "startDate": start_time,
1153
1188
  }
1154
1189
  )
1155
1190
 
@@ -1171,7 +1206,7 @@ class ICATLIMS(AbstractLims):
1171
1206
  )
1172
1207
 
1173
1208
  try:
1174
- metadata["lims"] = HWR.beamline.lims.get_active_lims()
1209
+ metadata["lims"] = HWR.beamline.lims.get_active_lims().name
1175
1210
  except Exception:
1176
1211
  logger.exception("Failed to read get_active_lims.")
1177
1212
 
@@ -312,6 +312,98 @@ class SampleChanger(Container, HardwareObject):
312
312
  """
313
313
  return self.status
314
314
 
315
+ def get_contents_as_dict(self) -> dict:
316
+ """
317
+ Build and return the hierarchical structure of the sample changer contents.
318
+
319
+ Returns:
320
+ dict: A nested dictionary describing the sample changer contents.
321
+ {
322
+ "name": <str>, # root sample changer address
323
+ "room_temperature_mode": <bool> (optional),
324
+ "children": [
325
+ {
326
+ "name": <str>, # element address
327
+ "status": <str>, # "Loaded", "Used", "Present", or ""
328
+ "id": <str>, # element ID
329
+ "selected": <bool>, # whether element is selected
330
+ "children": [ ... ] # nested elements, same structure
331
+ },
332
+ ...
333
+ ]
334
+ }
335
+ """
336
+ contents = {"name": self.get_address()}
337
+
338
+ if hasattr(self, "get_room_temperature_mode"):
339
+ contents["room_temperature_mode"] = self.get_room_temperature_mode()
340
+
341
+ for element in self.get_components():
342
+ if element.is_present():
343
+ self._add_element(contents, element)
344
+
345
+ return contents
346
+
347
+ def _get_status(self, element) -> str:
348
+ """
349
+ Determine the status string for a sample changer element.
350
+
351
+ Args:
352
+ element: The element object to check.
353
+
354
+ Returns:
355
+ str: One of:
356
+ - "Loaded": element is a leaf and currently loaded
357
+ - "Used": element is a leaf and has been loaded before
358
+ - "Present": element is present in the changer
359
+ - "": element is not present
360
+ """
361
+ if element.is_leaf():
362
+ if element.is_loaded():
363
+ return "Loaded"
364
+ if element.has_been_loaded():
365
+ return "Used"
366
+ return ""
367
+ return "Present" if element.is_present() else ""
368
+
369
+ def _get_id(self, element) -> str:
370
+ """
371
+ Get the unique identifier (ID or token) for a sample changer element.
372
+
373
+ Args:
374
+ element: The element to get the ID for.
375
+
376
+ Returns:
377
+ str: The token (if root sample changer and available),
378
+ the element ID (if available), or an empty string.
379
+ """
380
+ if element == self:
381
+ token = element.get_token()
382
+ return token if token else ""
383
+
384
+ return element.get_id() or ""
385
+
386
+ def _add_element(self, parent, element) -> dict:
387
+ """
388
+ Recursively add an element and its children into the contents dictionary.
389
+
390
+ Args:
391
+ parent (dict): The parent dictionary to append the element to.
392
+ element: The element object to add.
393
+ """
394
+ new_element = {
395
+ "name": element.get_address(),
396
+ "status": self._get_status(element),
397
+ "id": self._get_id(element),
398
+ "selected": element.is_selected(),
399
+ }
400
+
401
+ parent.setdefault("children", []).append(new_element)
402
+
403
+ if not element.is_leaf():
404
+ for child in element.get_components():
405
+ self._add_element(new_element, child)
406
+
315
407
  @property
316
408
  def progress_message(self) -> str:
317
409
  """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: mxcubecore
3
- Version: 1.384.0
3
+ Version: 1.386.0
4
4
  Summary: Core libraries for the MXCuBE application
5
5
  License: LGPL-3.0-or-later
6
6
  Keywords: mxcube,mxcube3,mxcubecore
@@ -196,7 +196,7 @@ mxcubecore/HardwareObjects/GrobMotor.py,sha256=l5A9Us_ceLXlhEF6RNwyXQsI56fJiobWh
196
196
  mxcubecore/HardwareObjects/GrobSampleChanger.py,sha256=LMetcL45fWrwP4C8rtENrEDNydelLpJ77SD1JC5C3go,8113
197
197
  mxcubecore/HardwareObjects/Harvester.py,sha256=0TYUXmz-Pmfd7Dhz7ToUGHzJRuJmnga8-4BK4B0KGQA,26524
198
198
  mxcubecore/HardwareObjects/HarvesterMaintenance.py,sha256=8s4yHDEFG-C1WYyW_RlwrFPSpc8o5hGi14aQuFQFrHs,9405
199
- mxcubecore/HardwareObjects/ICATLIMS.py,sha256=irvsn5xLy0CZpheFG_UGUzFO1nIKn5Mz3GVGZt9c2ic,53129
199
+ mxcubecore/HardwareObjects/ICATLIMS.py,sha256=YMlha9sg6U1EWSiKZ1Uy8fbud9XdfYNH9-oHESwPD34,54814
200
200
  mxcubecore/HardwareObjects/ISARAMaint.py,sha256=I8LHXK6wCfzixsxWmmcqWlrdaL3AOX91XmVeAwT7GPk,8959
201
201
  mxcubecore/HardwareObjects/LNLS/EPICSActuator.py,sha256=3dDj6aXyTz03m8osdA6udq_a4bch-KNcUMrXSNvbG5Q,2587
202
202
  mxcubecore/HardwareObjects/LNLS/EPICSMotor.py,sha256=lRTc1t32rJKNTIcnKCECrqo2m9BhlYvLq9NWg4Y0w0Q,3576
@@ -359,7 +359,7 @@ mxcubecore/HardwareObjects/abstract/AbstractNState.py,sha256=JZvD_ZpQu5U8ycaWFii
359
359
  mxcubecore/HardwareObjects/abstract/AbstractOnlineProcessing.py,sha256=vs_fJsDDLwivu1kYHA7RKJXj1aTH5V6G2tEy7MYGw4c,34104
360
360
  mxcubecore/HardwareObjects/abstract/AbstractProcedure.py,sha256=kW2SzN5kYYCeOS2IzpzQ9VAjYAoRU7ZtyDxqrOb8Pbg,7849
361
361
  mxcubecore/HardwareObjects/abstract/AbstractResolution.py,sha256=eLoymf-i637FbwfZwOtTmKOeSqCQjE2OnpSMdl8oIEg,8524
362
- mxcubecore/HardwareObjects/abstract/AbstractSampleChanger.py,sha256=h9j7XF8KrRtVQpthF_424fsEIR2LqsEZLNPrLaQB4TI,26718
362
+ mxcubecore/HardwareObjects/abstract/AbstractSampleChanger.py,sha256=f_D8YSoHPHkVLtGBobKEw79oMDf4rBL1y4Io3bqYnIw,29968
363
363
  mxcubecore/HardwareObjects/abstract/AbstractSampleView.py,sha256=-E9cTMW-gw2vY91OeL2V5wg1icduLeYFOX50vo2_NEA,7774
364
364
  mxcubecore/HardwareObjects/abstract/AbstractShutter.py,sha256=OeHSr3N9x-a9QmGdQEu3usN23TYspJGDnZjAkShqk3w,2798
365
365
  mxcubecore/HardwareObjects/abstract/AbstractSlits.py,sha256=1fymQFlxJ9naOVT9A8THszEkHm7VxQSGJJWPQV0v3Hs,3839
@@ -467,8 +467,8 @@ mxcubecore/utils/conversion.py,sha256=G1bk2Mi2ZwGbZa5pEeiFaKWxhSVXVGqu1L9_SioyUO
467
467
  mxcubecore/utils/qt_import.py,sha256=0lPmqok_oYQZ059kJCq7RWdg490T8YKyRvoZGyWDy4M,14486
468
468
  mxcubecore/utils/tango.py,sha256=vwEVrIrWKEFaeaJUz3xbaC7XWHY8ZeJ-pfcSrTfZPIE,2114
469
469
  mxcubecore/utils/units.py,sha256=Gh7ovTUN00XBMUoyDG5W7akCx1pROL-M6pK2z1ouemg,1361
470
- mxcubecore-1.384.0.dist-info/COPYING,sha256=u-Mc8zCecwyo4YoP8UulmzCiZZ_MmCLROd_NBtOcRj0,35148
471
- mxcubecore-1.384.0.dist-info/COPYING.LESSER,sha256=46mU2C5kSwOnkqkw9XQAJlhBL2JAf1_uCD8lVcXyMRg,7652
472
- mxcubecore-1.384.0.dist-info/METADATA,sha256=66iGNybEYtqpHBGq_qJ5xpvzlYErk-ys5D7XCMh86OY,4259
473
- mxcubecore-1.384.0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
474
- mxcubecore-1.384.0.dist-info/RECORD,,
470
+ mxcubecore-1.386.0.dist-info/COPYING,sha256=u-Mc8zCecwyo4YoP8UulmzCiZZ_MmCLROd_NBtOcRj0,35148
471
+ mxcubecore-1.386.0.dist-info/COPYING.LESSER,sha256=46mU2C5kSwOnkqkw9XQAJlhBL2JAf1_uCD8lVcXyMRg,7652
472
+ mxcubecore-1.386.0.dist-info/METADATA,sha256=oh50leeNzHaCAdv4fg8O96k0ewFL-ijez3eQW0QsbLw,4259
473
+ mxcubecore-1.386.0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
474
+ mxcubecore-1.386.0.dist-info/RECORD,,