ChessAnalysisPipeline 0.0.13__py3-none-any.whl → 0.0.14__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 ChessAnalysisPipeline might be problematic. Click here for more details.
- CHAP/__init__.py +1 -1
- CHAP/common/__init__.py +1 -0
- CHAP/common/models/map.py +95 -70
- CHAP/common/processor.py +653 -54
- CHAP/common/reader.py +9 -8
- CHAP/common/writer.py +20 -6
- CHAP/edd/__init__.py +2 -0
- CHAP/edd/models.py +94 -48
- CHAP/edd/processor.py +625 -169
- CHAP/edd/utils.py +186 -6
- CHAP/pipeline.py +35 -3
- CHAP/runner.py +40 -13
- CHAP/tomo/models.py +8 -0
- CHAP/tomo/processor.py +758 -727
- CHAP/utils/fit.py +98 -45
- CHAP/utils/general.py +177 -54
- CHAP/utils/scanparsers.py +326 -56
- {ChessAnalysisPipeline-0.0.13.dist-info → ChessAnalysisPipeline-0.0.14.dist-info}/METADATA +1 -1
- {ChessAnalysisPipeline-0.0.13.dist-info → ChessAnalysisPipeline-0.0.14.dist-info}/RECORD +23 -23
- {ChessAnalysisPipeline-0.0.13.dist-info → ChessAnalysisPipeline-0.0.14.dist-info}/LICENSE +0 -0
- {ChessAnalysisPipeline-0.0.13.dist-info → ChessAnalysisPipeline-0.0.14.dist-info}/WHEEL +0 -0
- {ChessAnalysisPipeline-0.0.13.dist-info → ChessAnalysisPipeline-0.0.14.dist-info}/entry_points.txt +0 -0
- {ChessAnalysisPipeline-0.0.13.dist-info → ChessAnalysisPipeline-0.0.14.dist-info}/top_level.txt +0 -0
CHAP/utils/scanparsers.py
CHANGED
|
@@ -15,6 +15,9 @@ import numpy as np
|
|
|
15
15
|
from pyspec.file.spec import FileSpec
|
|
16
16
|
from pyspec.file.tiff import TiffFile
|
|
17
17
|
|
|
18
|
+
@cache
|
|
19
|
+
def filespec(spec_file_name):
|
|
20
|
+
return FileSpec(spec_file_name)
|
|
18
21
|
|
|
19
22
|
class ScanParser:
|
|
20
23
|
"""Partial implementation of a class representing a SPEC scan and
|
|
@@ -64,7 +67,7 @@ class ScanParser:
|
|
|
64
67
|
# NB This FileSpec instance is not stored as a private
|
|
65
68
|
# attribute because it cannot be pickled (and therefore could
|
|
66
69
|
# cause problems for parallel code that uses ScanParsers).
|
|
67
|
-
return
|
|
70
|
+
return filespec(self.spec_file_name)
|
|
68
71
|
|
|
69
72
|
@property
|
|
70
73
|
def scan_path(self):
|
|
@@ -323,6 +326,10 @@ class SMBScanParser(ScanParser):
|
|
|
323
326
|
json_files = fnmatch_filter(
|
|
324
327
|
os.listdir(self.scan_path),
|
|
325
328
|
f'{self._par_file_pattern}.json')
|
|
329
|
+
if not json_files:
|
|
330
|
+
json_files = fnmatch_filter(
|
|
331
|
+
os.listdir(self.scan_path),
|
|
332
|
+
f'*.json')
|
|
326
333
|
if len(json_files) != 1:
|
|
327
334
|
raise RuntimeError(f'{self.scan_title}: cannot find the '
|
|
328
335
|
'.json file to decode the .par file')
|
|
@@ -336,15 +343,19 @@ class SMBScanParser(ScanParser):
|
|
|
336
343
|
raise RuntimeError(f'{self.scan_title}: cannot find scan pars '
|
|
337
344
|
'without a "SCAN_N" column in the par file')
|
|
338
345
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
346
|
+
if hasattr(self, '_par_file'):
|
|
347
|
+
par_file = self._par_file
|
|
348
|
+
else:
|
|
349
|
+
par_files = fnmatch_filter(
|
|
350
|
+
os.listdir(self.scan_path),
|
|
351
|
+
f'{self._par_file_pattern}.par')
|
|
352
|
+
if len(par_files) != 1:
|
|
353
|
+
raise RuntimeError(f'{self.scan_title}: cannot find the .par '
|
|
354
|
+
'file for this scan directory')
|
|
355
|
+
par_file = os.path.join(self.scan_path, par_files[0])
|
|
345
356
|
par_dict = None
|
|
346
|
-
with open(
|
|
347
|
-
par_reader = reader(
|
|
357
|
+
with open(par_file) as f:
|
|
358
|
+
par_reader = reader(f, delimiter=' ')
|
|
348
359
|
for row in par_reader:
|
|
349
360
|
if len(row) == len(par_col_names):
|
|
350
361
|
row_scann = int(row[scann_col_idx])
|
|
@@ -531,7 +542,7 @@ class FMBLinearScanParser(LinearScanParser, FMBScanParser):
|
|
|
531
542
|
"""
|
|
532
543
|
|
|
533
544
|
def get_spec_scan_motor_mnes(self):
|
|
534
|
-
if self.spec_macro
|
|
545
|
+
if self.spec_macro in ('flymesh', 'mesh', 'flydmesh', 'dmesh'):
|
|
535
546
|
m1_mne = self.spec_args[0]
|
|
536
547
|
try:
|
|
537
548
|
# Try post-summer-2022 format
|
|
@@ -551,7 +562,7 @@ class FMBLinearScanParser(LinearScanParser, FMBScanParser):
|
|
|
551
562
|
f'for scans of type {self.spec_macro}')
|
|
552
563
|
|
|
553
564
|
def get_spec_scan_motor_vals(self):
|
|
554
|
-
if self.spec_macro
|
|
565
|
+
if self.spec_macro in ('flymesh', 'mesh', 'flydmesh', 'dmesh'):
|
|
555
566
|
m1_start = float(self.spec_args[1])
|
|
556
567
|
m1_end = float(self.spec_args[2])
|
|
557
568
|
m1_npt = int(self.spec_args[3]) + 1
|
|
@@ -584,7 +595,7 @@ class FMBLinearScanParser(LinearScanParser, FMBScanParser):
|
|
|
584
595
|
f'for scans of type {self.spec_macro}')
|
|
585
596
|
|
|
586
597
|
def get_spec_scan_shape(self):
|
|
587
|
-
if self.spec_macro
|
|
598
|
+
if self.spec_macro in ('flymesh', 'mesh', 'flydmesh', 'dmesh'):
|
|
588
599
|
fast_mot_npts = int(self.spec_args[3]) + 1
|
|
589
600
|
try:
|
|
590
601
|
# Try post-summer-2022 format
|
|
@@ -605,7 +616,7 @@ class FMBLinearScanParser(LinearScanParser, FMBScanParser):
|
|
|
605
616
|
f'for scans of type {self.spec_macro}')
|
|
606
617
|
|
|
607
618
|
def get_spec_scan_dwell(self):
|
|
608
|
-
if self.macro
|
|
619
|
+
if self.macro in ('flymesh', 'mesh', 'flydmesh', 'dmesh'):
|
|
609
620
|
try:
|
|
610
621
|
# Try post-summer-2022 format
|
|
611
622
|
dwell = float(self.spec_args[4])
|
|
@@ -704,7 +715,15 @@ class SMBLinearScanParser(LinearScanParser, SMBScanParser):
|
|
|
704
715
|
"""
|
|
705
716
|
|
|
706
717
|
def get_spec_scan_dwell(self):
|
|
707
|
-
if self.spec_macro in ('flymesh', '
|
|
718
|
+
if self.spec_macro in ('flymesh', 'mesh'):
|
|
719
|
+
try:
|
|
720
|
+
# Try post-summer-2022 format
|
|
721
|
+
dwell = float(self.spec_args[4])
|
|
722
|
+
except:
|
|
723
|
+
# Accommodate pre-summer-2022 format
|
|
724
|
+
dwell = float(self.spec_args[8])
|
|
725
|
+
return dwell
|
|
726
|
+
if self.spec_macro in ('flyscan', 'ascan'):
|
|
708
727
|
return float(self.spec_args[4])
|
|
709
728
|
if self.spec_macro == 'tseries':
|
|
710
729
|
return float(self.spec_args[1])
|
|
@@ -714,8 +733,18 @@ class SMBLinearScanParser(LinearScanParser, SMBScanParser):
|
|
|
714
733
|
f'for scans of type {self.spec_macro}')
|
|
715
734
|
|
|
716
735
|
def get_spec_scan_motor_mnes(self):
|
|
717
|
-
if self.spec_macro
|
|
718
|
-
|
|
736
|
+
if self.spec_macro in ('flymesh', 'mesh'):
|
|
737
|
+
m1_mne = self.spec_args[0]
|
|
738
|
+
try:
|
|
739
|
+
# Try post-summer-2022 format
|
|
740
|
+
dwell = float(self.spec_args[4])
|
|
741
|
+
except:
|
|
742
|
+
# Accommodate pre-summer-2022 format
|
|
743
|
+
m2_mne_i = 4
|
|
744
|
+
else:
|
|
745
|
+
m2_mne_i = 5
|
|
746
|
+
m2_mne = self.spec_args[m2_mne_i]
|
|
747
|
+
return (m1_mne, m2_mne)
|
|
719
748
|
if self.spec_macro in ('flyscan', 'ascan'):
|
|
720
749
|
return (self.spec_args[0],)
|
|
721
750
|
if self.spec_macro in ('tseries', 'loopscan'):
|
|
@@ -724,13 +753,27 @@ class SMBLinearScanParser(LinearScanParser, SMBScanParser):
|
|
|
724
753
|
f'for scans of type {self.spec_macro}')
|
|
725
754
|
|
|
726
755
|
def get_spec_scan_motor_vals(self):
|
|
727
|
-
if self.spec_macro
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
756
|
+
if self.spec_macro in ('flymesh', 'mesh'):
|
|
757
|
+
m1_start = float(self.spec_args[1])
|
|
758
|
+
m1_end = float(self.spec_args[2])
|
|
759
|
+
m1_npt = int(self.spec_args[3]) + 1
|
|
760
|
+
try:
|
|
761
|
+
# Try post-summer-2022 format
|
|
762
|
+
dwell = float(self.spec_args[4])
|
|
763
|
+
except:
|
|
764
|
+
# Accommodate pre-summer-2022 format
|
|
765
|
+
m2_start_i = 5
|
|
766
|
+
m2_end_i = 6
|
|
767
|
+
m2_nint_i = 7
|
|
768
|
+
else:
|
|
769
|
+
m2_start_i = 6
|
|
770
|
+
m2_end_i = 7
|
|
771
|
+
m2_nint_i = 8
|
|
772
|
+
m2_start = float(self.spec_args[m2_start_i])
|
|
773
|
+
m2_end = float(self.spec_args[m2_end_i])
|
|
774
|
+
m2_npt = int(self.spec_args[m2_nint_i]) + 1
|
|
775
|
+
fast_mot_vals = np.linspace(m1_start, m1_end, m1_npt)
|
|
776
|
+
slow_mot_vals = np.linspace(m2_start, m2_end, m2_npt)
|
|
734
777
|
return (fast_mot_vals, slow_mot_vals)
|
|
735
778
|
if self.spec_macro in ('flyscan', 'ascan'):
|
|
736
779
|
mot_vals = np.linspace(float(self.spec_args[1]),
|
|
@@ -738,31 +781,31 @@ class SMBLinearScanParser(LinearScanParser, SMBScanParser):
|
|
|
738
781
|
int(self.spec_args[3])+1)
|
|
739
782
|
return (mot_vals,)
|
|
740
783
|
if self.spec_macro in ('tseries', 'loopscan'):
|
|
741
|
-
return self.spec_scan.data[:,0]
|
|
784
|
+
return (self.spec_scan.data[:,0],)
|
|
742
785
|
raise RuntimeError(f'{self.scan_title}: cannot determine scan motors '
|
|
743
786
|
f'for scans of type {self.spec_macro}')
|
|
744
787
|
|
|
745
788
|
def get_spec_scan_shape(self):
|
|
746
|
-
if self.spec_macro
|
|
747
|
-
fast_mot_npts = int(self.spec_args[3])+1
|
|
748
|
-
|
|
789
|
+
if self.spec_macro in ('flymesh', 'mesh'):
|
|
790
|
+
fast_mot_npts = int(self.spec_args[3]) + 1
|
|
791
|
+
try:
|
|
792
|
+
# Try post-summer-2022 format
|
|
793
|
+
dwell = float(self.spec_args[4])
|
|
794
|
+
except:
|
|
795
|
+
# Accommodate pre-summer-2022 format
|
|
796
|
+
m2_nint_i = 7
|
|
797
|
+
else:
|
|
798
|
+
m2_nint_i = 8
|
|
799
|
+
slow_mot_npts = int(self.spec_args[m2_nint_i]) + 1
|
|
749
800
|
return (fast_mot_npts, slow_mot_npts)
|
|
750
801
|
if self.spec_macro in ('flyscan', 'ascan'):
|
|
751
802
|
mot_npts = int(self.spec_args[3])+1
|
|
752
803
|
return (mot_npts,)
|
|
753
804
|
if self.spec_macro in ('tseries', 'loopscan'):
|
|
754
|
-
return len(np.array(self.spec_scan.data[:,0]))
|
|
805
|
+
return (len(np.array(self.spec_scan.data[:,0])),)
|
|
755
806
|
raise RuntimeError(f'{self.scan_title}: cannot determine scan shape '
|
|
756
807
|
f'for scans of type {self.spec_macro}')
|
|
757
808
|
|
|
758
|
-
def get_spec_scan_dwell(self):
|
|
759
|
-
if self.spec_macro == 'flymesh':
|
|
760
|
-
return float(self.spec_args[4])
|
|
761
|
-
if self.spec_macro in ('flyscan', 'ascan'):
|
|
762
|
-
return float(self.spec_args[-1])
|
|
763
|
-
raise RuntimeError(f'{self.scan_title}: cannot determine dwell time '
|
|
764
|
-
f'for scans of type {self.spec_macro}')
|
|
765
|
-
|
|
766
809
|
def get_detector_data_path(self):
|
|
767
810
|
return os.path.join(self.scan_path, str(self.scan_number))
|
|
768
811
|
|
|
@@ -963,12 +1006,14 @@ class SMBRotationScanParser(RotationScanParser, SMBScanParser):
|
|
|
963
1006
|
with the typical tomography setup at SMB.
|
|
964
1007
|
"""
|
|
965
1008
|
|
|
966
|
-
def __init__(self, spec_file_name, scan_number):
|
|
1009
|
+
def __init__(self, spec_file_name, scan_number, par_file=None):
|
|
967
1010
|
self._scan_type = None
|
|
968
1011
|
super().__init__(spec_file_name, scan_number)
|
|
969
1012
|
|
|
970
1013
|
self._katefix = 0 # RV remove when no longer needed
|
|
971
1014
|
self._par_file_pattern = f'id*-*tomo*-{self.scan_name}'
|
|
1015
|
+
if par_file is not None:
|
|
1016
|
+
self._par_file = par_file
|
|
972
1017
|
|
|
973
1018
|
@property
|
|
974
1019
|
def scan_type(self):
|
|
@@ -1038,7 +1083,8 @@ class SMBRotationScanParser(RotationScanParser, SMBScanParser):
|
|
|
1038
1083
|
if os.path.isfile(file_name_full):
|
|
1039
1084
|
return file_name_full
|
|
1040
1085
|
raise RuntimeError(f'{self.scan_title}: could not find detector image '
|
|
1041
|
-
f'file for scan step
|
|
1086
|
+
f'file ({file_name_full}) for scan step '
|
|
1087
|
+
f'({scan_step_index})')
|
|
1042
1088
|
|
|
1043
1089
|
def get_detector_data(self, detector_prefix, scan_step_index=None):
|
|
1044
1090
|
if scan_step_index is None:
|
|
@@ -1090,10 +1136,66 @@ class SMBMCAScanParser(MCAScanParser, SMBLinearScanParser):
|
|
|
1090
1136
|
"""Concrete implementation of a class representing a scan taken
|
|
1091
1137
|
with the typical EDD setup at SMB or FAST.
|
|
1092
1138
|
"""
|
|
1139
|
+
detector_data_formats = ('spec', 'h5')
|
|
1140
|
+
def __init__(self, spec_file_name, scan_number, detector_data_format=None):
|
|
1141
|
+
"""Constructor for SMBMCAScnaParser.
|
|
1142
|
+
|
|
1143
|
+
:param spec_file: Path to scan's SPEC file
|
|
1144
|
+
:type spec_file: str
|
|
1145
|
+
:param scan_number: Number of the SPEC scan
|
|
1146
|
+
:type scan_number: int
|
|
1147
|
+
:param detector_data_format: Format of the MCA data collected,
|
|
1148
|
+
defaults to None
|
|
1149
|
+
:type detector_data_format: Optional[Literal["spec", "h5"]]
|
|
1150
|
+
"""
|
|
1151
|
+
super().__init__(spec_file_name, scan_number)
|
|
1093
1152
|
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1153
|
+
self.detector_data_format = None
|
|
1154
|
+
if detector_data_format is None:
|
|
1155
|
+
self.init_detector_data_format()
|
|
1156
|
+
else:
|
|
1157
|
+
if detector_data_format.lower() in self.detector_data_formats:
|
|
1158
|
+
self.detector_data_format = detector_data_format.lower()
|
|
1159
|
+
else:
|
|
1160
|
+
raise ValueError(
|
|
1161
|
+
'Unrecognized value for detector_data_format: '
|
|
1162
|
+
+ f'{detector_data_format}. Allowed values are: '
|
|
1163
|
+
+ ', '.join(self.detector_data_formats))
|
|
1164
|
+
|
|
1165
|
+
def init_detector_data_format(self):
|
|
1166
|
+
"""Determine and set a value for the instance variable
|
|
1167
|
+
`detector_data_format` based on the presence / absence of
|
|
1168
|
+
detector data files of different formats conventionally
|
|
1169
|
+
associated with this scan. Also set the corresponding
|
|
1170
|
+
appropriate value for `_detector_data_path`.
|
|
1171
|
+
"""
|
|
1172
|
+
try:
|
|
1173
|
+
self._detector_data_path = self.scan_path
|
|
1174
|
+
detector_file = self.get_detector_data_file_spec()
|
|
1175
|
+
except OSError:
|
|
1176
|
+
try:
|
|
1177
|
+
self._detector_data_path = os.path.join(
|
|
1178
|
+
self.scan_path, str(self.scan_number), 'edd')
|
|
1179
|
+
detector_file = self.get_detector_data_file_h5()
|
|
1180
|
+
except OSError:
|
|
1181
|
+
raise RuntimeError(
|
|
1182
|
+
f"{self.scan_title}: Can't determine detector data format")
|
|
1183
|
+
else:
|
|
1184
|
+
self.detector_data_format = 'h5'
|
|
1185
|
+
else:
|
|
1186
|
+
self.detector_data_format = 'spec'
|
|
1187
|
+
|
|
1188
|
+
def get_detector_data_path(self):
|
|
1189
|
+
raise NotImplementedError
|
|
1190
|
+
|
|
1191
|
+
def get_detector_num_bins(self, element_index=0):
|
|
1192
|
+
if self.detector_data_format == 'spec':
|
|
1193
|
+
return self.get_detector_num_bins_spec()
|
|
1194
|
+
elif self.detector_data_format == 'h5':
|
|
1195
|
+
return self.get_detector_num_bins_h5(element_index)
|
|
1196
|
+
|
|
1197
|
+
def get_detector_num_bins_spec(self):
|
|
1198
|
+
with open(self.get_detector_data_file_spec()) as detector_file:
|
|
1097
1199
|
lines = detector_file.readlines()
|
|
1098
1200
|
for line in lines:
|
|
1099
1201
|
if line.startswith('#@CHANN'):
|
|
@@ -1103,33 +1205,101 @@ class SMBMCAScanParser(MCAScanParser, SMBLinearScanParser):
|
|
|
1103
1205
|
return int(number_saved)
|
|
1104
1206
|
except:
|
|
1105
1207
|
continue
|
|
1106
|
-
raise RuntimeError(f'{self.scan_title}: could not find num_bins
|
|
1107
|
-
f'detector {detector_prefix}')
|
|
1208
|
+
raise RuntimeError(f'{self.scan_title}: could not find num_bins')
|
|
1108
1209
|
|
|
1109
|
-
def
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1210
|
+
def get_detector_num_bins_h5(self, element_index):
|
|
1211
|
+
from h5py import File
|
|
1212
|
+
detector_file = self.get_detector_data_file_h5()
|
|
1213
|
+
with File(detector_file) as h5_file:
|
|
1214
|
+
dset_shape = h5_file['/entry/data/data'].shape
|
|
1215
|
+
return dset_shape[-1]
|
|
1216
|
+
|
|
1217
|
+
def get_detector_data_file(self, scan_step_index=0):
|
|
1218
|
+
if self.detector_data_format == 'spec':
|
|
1219
|
+
return self.get_detector_data_file_spec()
|
|
1220
|
+
elif self.detector_data_format == 'h5':
|
|
1221
|
+
return self.get_detector_data_file_h5(
|
|
1222
|
+
scan_step_index=scan_step_index)
|
|
1223
|
+
|
|
1224
|
+
def get_detector_data_file_spec(self):
|
|
1225
|
+
"""Return the filename (full absolute path) to the file
|
|
1226
|
+
containing spec-formatted MCA data for this scan.
|
|
1227
|
+
"""
|
|
1113
1228
|
file_name = f'spec.log.scan{self.scan_number}.mca1.mca'
|
|
1114
1229
|
file_name_full = os.path.join(self.detector_data_path, file_name)
|
|
1115
1230
|
if os.path.isfile(file_name_full):
|
|
1116
1231
|
return file_name_full
|
|
1117
|
-
raise
|
|
1118
|
-
|
|
1232
|
+
raise OSError(
|
|
1233
|
+
'{self.scan_title}: could not find detector image file'
|
|
1234
|
+
)
|
|
1235
|
+
|
|
1236
|
+
def get_detector_data_file_h5(self, scan_step_index=0):
|
|
1237
|
+
"""Return the filename (full absolute path) to the file
|
|
1238
|
+
containing h5-formatted MCA data for this scan.
|
|
1239
|
+
|
|
1240
|
+
:param scan_step_index:
|
|
1241
|
+
"""
|
|
1242
|
+
scan_step = self.get_scan_step(scan_step_index)
|
|
1243
|
+
if len(self.spec_scan_shape) == 1:
|
|
1244
|
+
filename_index = 0
|
|
1245
|
+
elif len(self.spec_scan_shape) == 2:
|
|
1246
|
+
scan_step = self.get_scan_step(scan_step_index)
|
|
1247
|
+
filename_index = scan_step[0]
|
|
1248
|
+
else:
|
|
1249
|
+
raise NotImplementedError(
|
|
1250
|
+
'Cannot find detector file for scans with dimension > 2')
|
|
1251
|
+
file_name = list_smb_mca_detector_files_h5(
|
|
1252
|
+
self.detector_data_path)[filename_index]
|
|
1253
|
+
file_name_full = os.path.join(self.detector_data_path, file_name)
|
|
1254
|
+
if os.path.isfile(file_name_full):
|
|
1255
|
+
return file_name_full
|
|
1256
|
+
raise OSError(
|
|
1257
|
+
'{self.scan_title}: could not find detector image file'
|
|
1258
|
+
)
|
|
1259
|
+
|
|
1260
|
+
|
|
1261
|
+
def get_all_detector_data(self, detector):
|
|
1262
|
+
"""Return a 2D array of all MCA spectra collected in this scan
|
|
1263
|
+
by the detector element indicated with `detector`.
|
|
1119
1264
|
|
|
1120
|
-
|
|
1265
|
+
:param detector: For detector data collected in SPEC format,
|
|
1266
|
+
this is the detector prefix as it appears in the spec MCA
|
|
1267
|
+
data file. For detector data collected in H5 format, this
|
|
1268
|
+
is the index of a particular detector element.
|
|
1269
|
+
:type detector: Union[str, int]
|
|
1270
|
+
:rtype: numpy.ndarray
|
|
1271
|
+
"""
|
|
1272
|
+
if self.detector_data_format == 'spec':
|
|
1273
|
+
return self.get_all_detector_data_spec(detector)
|
|
1274
|
+
elif self.detector_data_format == 'h5':
|
|
1275
|
+
try:
|
|
1276
|
+
element_index = int(detector)
|
|
1277
|
+
except:
|
|
1278
|
+
raise TypeError(f'{detector} is not an integer element index')
|
|
1279
|
+
return self.get_all_detector_data_h5(element_index)
|
|
1280
|
+
|
|
1281
|
+
def get_all_detector_data_spec(self, detector_prefix):
|
|
1282
|
+
"""Return a 2D array of all MCA spectra collected by a
|
|
1283
|
+
detector in the spec MCA file format during the scan.
|
|
1284
|
+
|
|
1285
|
+
:param detector_prefix: Detector name at is appears in the
|
|
1286
|
+
spec MCA file.
|
|
1287
|
+
:type detector_prefix: str
|
|
1288
|
+
:returns: 2D array of MCA spectra
|
|
1289
|
+
:rtype: numpy.ndarray
|
|
1290
|
+
"""
|
|
1121
1291
|
# This should be easy with pyspec, but there are bugs in
|
|
1122
1292
|
# pyspec for MCA data..... or is the 'bug' from a nonstandard
|
|
1123
1293
|
# implementation of some macro on our end? According to spec
|
|
1124
1294
|
# manual and pyspec code, mca data should always begin w/ '@A'
|
|
1125
|
-
# In example scans, it begins with '@
|
|
1295
|
+
# In example scans, it begins with '@{detector_prefix}'
|
|
1296
|
+
# instead
|
|
1126
1297
|
data = []
|
|
1127
1298
|
|
|
1128
|
-
with open(self.
|
|
1129
|
-
as detector_file:
|
|
1299
|
+
with open(self.get_detector_data_file_spec()) as detector_file:
|
|
1130
1300
|
lines = [line.strip("\\\n") for line in detector_file.readlines()]
|
|
1131
1301
|
|
|
1132
|
-
num_bins = self.get_detector_num_bins(
|
|
1302
|
+
num_bins = self.get_detector_num_bins()
|
|
1133
1303
|
|
|
1134
1304
|
counter = 0
|
|
1135
1305
|
for line in lines:
|
|
@@ -1156,6 +1326,106 @@ class SMBMCAScanParser(MCAScanParser, SMBLinearScanParser):
|
|
|
1156
1326
|
|
|
1157
1327
|
return np.array(data)
|
|
1158
1328
|
|
|
1159
|
-
def
|
|
1160
|
-
|
|
1329
|
+
def get_all_detector_data_h5(self, element_index):
|
|
1330
|
+
"""Return a 2D array of all MCA spectra collected by a
|
|
1331
|
+
detector in the h5 file format during the scan.
|
|
1332
|
+
|
|
1333
|
+
:param element_index: The index of a particualr MCA element to
|
|
1334
|
+
return data for.
|
|
1335
|
+
:type element_index: int
|
|
1336
|
+
:returns: 2D array of MCA spectra
|
|
1337
|
+
:rtype: numpy.ndarray
|
|
1338
|
+
"""
|
|
1339
|
+
detector_data = np.empty(
|
|
1340
|
+
(self.spec_scan_npts,
|
|
1341
|
+
self.get_detector_num_bins_h5(element_index)))
|
|
1342
|
+
detector_files = list_smb_mca_detector_files_h5(
|
|
1343
|
+
self.detector_data_path)
|
|
1344
|
+
for i, detector_file in enumerate(detector_files):
|
|
1345
|
+
full_filename = os.path.join(
|
|
1346
|
+
self.detector_data_path, detector_file)
|
|
1347
|
+
element_data = get_all_mca_data_h5(
|
|
1348
|
+
full_filename)[:,element_index,:]
|
|
1349
|
+
i_0 = i * self.spec_scan_shape[0]
|
|
1350
|
+
if len(self.spec_scan_shape) == 2:
|
|
1351
|
+
i_f = i_0 + self.spec_scan_shape[1]
|
|
1352
|
+
else:
|
|
1353
|
+
i_f = self.spec_scan_npts
|
|
1354
|
+
detector_data[i_0:i_f] = element_data
|
|
1355
|
+
return detector_data
|
|
1356
|
+
|
|
1357
|
+
def get_detector_data(self, detector, scan_step_index:int):
|
|
1358
|
+
"""Return a single MCA spectrum for the detector indicated.
|
|
1359
|
+
|
|
1360
|
+
:param detector: If this scan collected MCA data in "spec"
|
|
1361
|
+
format, this is the detector prefix as it appears in the
|
|
1362
|
+
spec MCA data file. If this scan collected data in .h5
|
|
1363
|
+
format, this is the index of the detector element of
|
|
1364
|
+
interest.:type detector: typing.Union[str, int]
|
|
1365
|
+
:param scan_step_index: Index of the scan step to return the
|
|
1366
|
+
spectrum from.
|
|
1367
|
+
:type scan_step_index: int
|
|
1368
|
+
:returns: A single MCA spectrum
|
|
1369
|
+
:rtype: numpy.ndarray
|
|
1370
|
+
"""
|
|
1371
|
+
detector_data = self.get_all_detector_data(detector)
|
|
1161
1372
|
return detector_data[scan_step_index]
|
|
1373
|
+
|
|
1374
|
+
@cache
|
|
1375
|
+
def list_smb_mca_detector_files_h5(detector_data_path):
|
|
1376
|
+
"""Return a sorted list of all *.hdf5 files in a directory
|
|
1377
|
+
|
|
1378
|
+
:param detector_data_path: Directory to return *.hdf5 files from
|
|
1379
|
+
:type detector_data_path: str
|
|
1380
|
+
:returns: Sorted list of detector data filenames
|
|
1381
|
+
:rtype: list[str]
|
|
1382
|
+
"""
|
|
1383
|
+
return sorted(
|
|
1384
|
+
[f for f in os.listdir(detector_data_path) if f.endswith('.hdf5')])
|
|
1385
|
+
|
|
1386
|
+
@cache
|
|
1387
|
+
def get_all_mca_data_h5(filename):
|
|
1388
|
+
"""Return all data from all elements from an MCA data file
|
|
1389
|
+
|
|
1390
|
+
:param filename: Name of the MCA h5 data file
|
|
1391
|
+
:type filename: str
|
|
1392
|
+
:returns: 3D array of MCA spectra where the first axis is scan
|
|
1393
|
+
step, second index is detector element, third index is channel
|
|
1394
|
+
energy.
|
|
1395
|
+
:rtype: numpy.ndarray
|
|
1396
|
+
"""
|
|
1397
|
+
import os
|
|
1398
|
+
|
|
1399
|
+
from h5py import File
|
|
1400
|
+
import numpy as np
|
|
1401
|
+
|
|
1402
|
+
with File(filename) as h5_file:
|
|
1403
|
+
data = h5_file['/entry/data/data'][:]
|
|
1404
|
+
|
|
1405
|
+
# Prior to 2023-12-12, there was an issue where the XPS23 detector
|
|
1406
|
+
# was capturing one or two frames of all 0s at the start of the
|
|
1407
|
+
# dataset in every hdf5 file. In both cases, there is only ONE
|
|
1408
|
+
# extra frame of data relative to the number of frames that should
|
|
1409
|
+
# be there (based on the number of points in the spec scan). If
|
|
1410
|
+
# one frame of all 0s is present: skip it and deliver only the
|
|
1411
|
+
# real data. If two frames of all 0s are present: detector data
|
|
1412
|
+
# will be missing for the LAST step in the scan. Skip the first
|
|
1413
|
+
# two frames of all 0s in the hdf5 dataset, then add a frame of
|
|
1414
|
+
# fake data (all 0-s) to the end of that real data so that the
|
|
1415
|
+
# number of detector data frames matches the number of points in
|
|
1416
|
+
# the spec scan.
|
|
1417
|
+
check_zeros_before = 1702357200
|
|
1418
|
+
file_mtime = os.path.getmtime(filename)
|
|
1419
|
+
if file_mtime <= check_zeros_before:
|
|
1420
|
+
if not np.any(data[0]):
|
|
1421
|
+
# If present, remove first frame of blank data
|
|
1422
|
+
print('Warning: removing blank first frame of detector data')
|
|
1423
|
+
data = data[1:]
|
|
1424
|
+
if not np.any(data[0]):
|
|
1425
|
+
# If present, shift second frame of blank data to the
|
|
1426
|
+
# end
|
|
1427
|
+
print('Warning: shifting second frame of blank detector data '
|
|
1428
|
+
+ 'to the end of the scan')
|
|
1429
|
+
data = np.concatenate((data[1:], np.asarray([data[0]])))
|
|
1430
|
+
|
|
1431
|
+
return data
|
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
CHAP/TaskManager.py,sha256=NEqg2jAq10kbScE18XtzY3liqkIdAtysaR-gMG5tBzs,6803
|
|
2
|
-
CHAP/__init__.py,sha256=
|
|
3
|
-
CHAP/pipeline.py,sha256=
|
|
2
|
+
CHAP/__init__.py,sha256=CjKQO1ao0OkBYJyBjtyt-kNq6PHBVlDPl65EvhyVGnw,1073
|
|
3
|
+
CHAP/pipeline.py,sha256=wyOMT0fuXsVL2sPCRynfIXpTZraI2USxzAyyMz1DkdY,8984
|
|
4
4
|
CHAP/processor.py,sha256=nqg1uK5jvADl35xuR6VIdU5uVGFVt-rzivnaZyOWruA,2639
|
|
5
5
|
CHAP/reader.py,sha256=wGzAl_p5UnR7fC7Cie29S7RZTFFLcdOuhbViNDzH-4s,2534
|
|
6
|
-
CHAP/runner.py,sha256=
|
|
6
|
+
CHAP/runner.py,sha256=yRwK8OgcoDQrGUbHULmFoWXkodbWXQBhHGzqDLJrm-k,7891
|
|
7
7
|
CHAP/server.py,sha256=JAh5a7ZPh_Vx7fm0uI_g2WHLVxLn8s1uwBX8oMJ3G9c,3648
|
|
8
8
|
CHAP/writer.py,sha256=9hed3_51AwSSH3kNisMR6Wq6mLInNGpgktPG5G_s-DM,2589
|
|
9
|
-
CHAP/common/__init__.py,sha256=
|
|
10
|
-
CHAP/common/processor.py,sha256=
|
|
11
|
-
CHAP/common/reader.py,sha256=
|
|
12
|
-
CHAP/common/writer.py,sha256=
|
|
9
|
+
CHAP/common/__init__.py,sha256=MP_8flMD7b-hq5O_x7GfGN9TFx-DnFLwQx3Am6bs5NI,1056
|
|
10
|
+
CHAP/common/processor.py,sha256=orJiphJPQL6ZnM0CKYPgpIH1-G-ZERkMoeRGNStvTV8,55608
|
|
11
|
+
CHAP/common/reader.py,sha256=Ph6St2H-6HB3O8pKbsNSEUe-fWOXn6qch-zCMf1n0D8,13597
|
|
12
|
+
CHAP/common/writer.py,sha256=6LH0FoKHh30ixwM3qTHBoMyki0A0PODY8n7jr1Fo1-0,12654
|
|
13
13
|
CHAP/common/models/__init__.py,sha256=MpmtY6biXgC7AaedznoSqFJJZ54YU8tBPgwzYJIVJ1c,200
|
|
14
14
|
CHAP/common/models/integration.py,sha256=0WM2Q15XFQf-uydMALh3snbpoop-c5N6Pnf_O7ikXW0,27175
|
|
15
|
-
CHAP/common/models/map.py,sha256=
|
|
16
|
-
CHAP/edd/__init__.py,sha256=
|
|
17
|
-
CHAP/edd/models.py,sha256=
|
|
18
|
-
CHAP/edd/processor.py,sha256=
|
|
15
|
+
CHAP/common/models/map.py,sha256=WzJ8Z-TRoQsG83wAQqIEDCJKsGQtf6RNgVRWjfmmiog,39296
|
|
16
|
+
CHAP/edd/__init__.py,sha256=5GfA6Rr8ixps4_qC2V6G_WdDA2eqleykYHz-ZRvRXcs,554
|
|
17
|
+
CHAP/edd/models.py,sha256=2Shnqkemf8xgHGEVzMZtaTF025lMJncRyPDJ9DcHtxo,37229
|
|
18
|
+
CHAP/edd/processor.py,sha256=oKXDGoZCHLCYvO2SbVZBHgmX8anrkm5KmFLyFBRBCd8,78164
|
|
19
19
|
CHAP/edd/reader.py,sha256=O0KeZcqACsZ8ngrliPU6I3u8SeQT0Aq866jCTbruXqc,94
|
|
20
|
-
CHAP/edd/utils.py,sha256=
|
|
20
|
+
CHAP/edd/utils.py,sha256=07hSeBk7hVpHJE9bbJQupaSSul4hjcyK33a9I1PrPHs,42888
|
|
21
21
|
CHAP/edd/writer.py,sha256=Y1CXWMRU87XeeDp4g4-sUgPP2UbCguYZUR_Cg5Ci6l8,94
|
|
22
22
|
CHAP/inference/__init__.py,sha256=GwpEKEMHY1-3AE7HWKBdBz_i7N1sz7xwve6y9tZ7Skk,263
|
|
23
23
|
CHAP/inference/processor.py,sha256=TYYPtZ3YlZS1kgvGr6I_9RvSaR0kn9PKL98A3QwqeDI,2065
|
|
@@ -32,23 +32,23 @@ CHAP/sin2psi/processor.py,sha256=6ytGpsK5u6tyUTzOJqAlcRdaimA4QfXZ6xpwGf2QMFo,97
|
|
|
32
32
|
CHAP/sin2psi/reader.py,sha256=O0KeZcqACsZ8ngrliPU6I3u8SeQT0Aq866jCTbruXqc,94
|
|
33
33
|
CHAP/sin2psi/writer.py,sha256=Y1CXWMRU87XeeDp4g4-sUgPP2UbCguYZUR_Cg5Ci6l8,94
|
|
34
34
|
CHAP/tomo/__init__.py,sha256=7cwm1ufJkDKqrp2OPH_z7tKAOQ0S_RJbNainK0soKNo,328
|
|
35
|
-
CHAP/tomo/models.py,sha256=
|
|
36
|
-
CHAP/tomo/processor.py,sha256=
|
|
35
|
+
CHAP/tomo/models.py,sha256=TTq1QbIK1h2xVpPWXwc41fWaDCavmufcTOK3N-MxGh0,8293
|
|
36
|
+
CHAP/tomo/processor.py,sha256=mF9gCugvsEPsUgwFM_3GuzdpAxouJ7H8lMov73C_HHk,155112
|
|
37
37
|
CHAP/tomo/reader.py,sha256=7nNP_KyIR-ghrrajCR2k5IsJnrLm6BIy-eAXIDXrQe8,123
|
|
38
38
|
CHAP/tomo/writer.py,sha256=J7q_nmsqi_zbgAS-LvAciiBqtYD8hHJ4QmwS2oZAM2Q,123
|
|
39
39
|
CHAP/utils/__init__.py,sha256=3blWv3cFKA4woMNUUI8d1WZFc4izlgMbfUPNAyBDiRs,183
|
|
40
|
-
CHAP/utils/fit.py,sha256=
|
|
41
|
-
CHAP/utils/general.py,sha256=
|
|
40
|
+
CHAP/utils/fit.py,sha256=jF1ZjjFWMXXBqhWHNbHhOnUJgCXTU_jdqD3dKTCtRGk,130694
|
|
41
|
+
CHAP/utils/general.py,sha256=ATVpbfNRp0dRBgioLmAeJcb7mAAWmrVHUYqphE18vCg,72270
|
|
42
42
|
CHAP/utils/material.py,sha256=NnLHAin3PrDxZiG6of8v7vFma0nAeOIRZJuXxSN_xj8,11495
|
|
43
43
|
CHAP/utils/parfile.py,sha256=GxBWG6EVKQnV1I_r_m4nfJrCb0VGAn6tjEfuxVTg-aA,7227
|
|
44
|
-
CHAP/utils/scanparsers.py,sha256=
|
|
44
|
+
CHAP/utils/scanparsers.py,sha256=UUmSDW9l002gi4yW7W9xy2rBJ0n-UgHQOiaK3g-pHzE,55782
|
|
45
45
|
MLaaS/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
46
46
|
MLaaS/ktrain.py,sha256=SPDUOQgjBDSx7sI8vZNXog9orvSyKmzpe6TdGHol9qM,7467
|
|
47
47
|
MLaaS/mnist_img.py,sha256=ppDtlo6yrNQy0oIhFZVOnLvHJrR3ZPZ3PjZTtJY8l0E,2738
|
|
48
48
|
MLaaS/tfaas_client.py,sha256=zpZ201wwcQBW1XkzDakD9Kl_NRSESAUdbnN6k6Ey15A,14889
|
|
49
|
-
ChessAnalysisPipeline-0.0.
|
|
50
|
-
ChessAnalysisPipeline-0.0.
|
|
51
|
-
ChessAnalysisPipeline-0.0.
|
|
52
|
-
ChessAnalysisPipeline-0.0.
|
|
53
|
-
ChessAnalysisPipeline-0.0.
|
|
54
|
-
ChessAnalysisPipeline-0.0.
|
|
49
|
+
ChessAnalysisPipeline-0.0.14.dist-info/LICENSE,sha256=GrJL25aZivxje_x-zBbeWASvdmgztxv8kBMhIP4XSMo,1075
|
|
50
|
+
ChessAnalysisPipeline-0.0.14.dist-info/METADATA,sha256=U9FLhH71SVqIu4TPV7acfJOspAAFiF0G-rZEn7aFh0Y,1542
|
|
51
|
+
ChessAnalysisPipeline-0.0.14.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
|
52
|
+
ChessAnalysisPipeline-0.0.14.dist-info/entry_points.txt,sha256=w-KIKdUjmj5GCobrFC4_jexCsFB4yMXYjrsMWrhI6Co,42
|
|
53
|
+
ChessAnalysisPipeline-0.0.14.dist-info/top_level.txt,sha256=BKhggOWLb9dD6oQm1RXrkJPnXm-zJxVzQef1iXYtt2k,11
|
|
54
|
+
ChessAnalysisPipeline-0.0.14.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
{ChessAnalysisPipeline-0.0.13.dist-info → ChessAnalysisPipeline-0.0.14.dist-info}/entry_points.txt
RENAMED
|
File without changes
|
{ChessAnalysisPipeline-0.0.13.dist-info → ChessAnalysisPipeline-0.0.14.dist-info}/top_level.txt
RENAMED
|
File without changes
|