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.
- mxcubecore/HardwareObjects/ICATLIMS.py +63 -28
- mxcubecore/HardwareObjects/abstract/AbstractSampleChanger.py +92 -0
- {mxcubecore-1.384.0.dist-info → mxcubecore-1.386.0.dist-info}/METADATA +1 -1
- {mxcubecore-1.384.0.dist-info → mxcubecore-1.386.0.dist-info}/RECORD +7 -7
- {mxcubecore-1.384.0.dist-info → mxcubecore-1.386.0.dist-info}/COPYING +0 -0
- {mxcubecore-1.384.0.dist-info → mxcubecore-1.386.0.dist-info}/COPYING.LESSER +0 -0
- {mxcubecore-1.384.0.dist-info → mxcubecore-1.386.0.dist-info}/WHEEL +0 -0
|
@@ -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 =
|
|
330
|
-
|
|
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("
|
|
824
|
-
end_time =
|
|
823
|
+
start_time = datacollection_dict.get("collection_start_time", "")
|
|
824
|
+
end_time = datetime.now(ZoneInfo("Europe/Paris")).isoformat()
|
|
825
825
|
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
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=
|
|
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
|
"""
|
|
@@ -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=
|
|
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=
|
|
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.
|
|
471
|
-
mxcubecore-1.
|
|
472
|
-
mxcubecore-1.
|
|
473
|
-
mxcubecore-1.
|
|
474
|
-
mxcubecore-1.
|
|
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,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|