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/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 FileSpec(self.spec_file_name)
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
- par_files = fnmatch_filter(
340
- os.listdir(self.scan_path),
341
- f'{self._par_file_pattern}.par')
342
- if len(par_files) != 1:
343
- raise RuntimeError(f'{self.scan_title}: cannot find the .par '
344
- 'file for this scan directory')
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(os.path.join(self.scan_path, par_files[0])) as par_file:
347
- par_reader = reader(par_file, delimiter=' ')
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 == 'flymesh':
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 == 'flymesh':
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 == 'flymesh':
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 == 'flymesh':
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', 'flyscan', 'ascan'):
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 == 'flymesh':
718
- return (self.spec_args[0], self.spec_args[5])
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 == 'flymesh':
728
- fast_mot_vals = np.linspace(float(self.spec_args[1]),
729
- float(self.spec_args[2]),
730
- int(self.spec_args[3])+1)
731
- slow_mot_vals = np.linspace(float(self.spec_args[6]),
732
- float(self.spec_args[7]),
733
- int(self.spec_args[8])+1)
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 == 'flymesh':
747
- fast_mot_npts = int(self.spec_args[3])+1
748
- slow_mot_npts = int(self.spec_args[8])+1
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 ({scan_step_index})')
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
- def get_detector_num_bins(self, detector_prefix):
1095
- with open(self.get_detector_data_file(detector_prefix)) \
1096
- as detector_file:
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 for '
1107
- f'detector {detector_prefix}')
1208
+ raise RuntimeError(f'{self.scan_title}: could not find num_bins')
1108
1209
 
1109
- def get_detector_data_path(self):
1110
- return self.scan_path
1111
-
1112
- def get_detector_data_file(self, detector_prefix, scan_step_index=0):
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 RuntimeError(
1118
- f'{self.scan_title}: could not find detector image file')
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
- def get_all_detector_data(self, detector_prefix):
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 '@mca1' instead
1295
+ # In example scans, it begins with '@{detector_prefix}'
1296
+ # instead
1126
1297
  data = []
1127
1298
 
1128
- with open(self.get_detector_data_file(detector_prefix)) \
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(detector_prefix)
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 get_detector_data(self, detector_prefix, scan_step_index:int):
1160
- detector_data = self.get_all_detector_data(detector_prefix)
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,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ChessAnalysisPipeline
3
- Version: 0.0.13
3
+ Version: 0.0.14
4
4
  Summary: CHESS analysis pipeline framework
5
5
  Home-page: https://github.com/CHESSComputing/ChessAnalysisPipeline
6
6
  Author: Keara Soloway, Rolf Verberg, Valentin Kuznetsov
@@ -1,23 +1,23 @@
1
1
  CHAP/TaskManager.py,sha256=NEqg2jAq10kbScE18XtzY3liqkIdAtysaR-gMG5tBzs,6803
2
- CHAP/__init__.py,sha256=fgkAhLmrMNcSnOgxfo_WLbanG5pOsqqtWctjRgtk1aw,1073
3
- CHAP/pipeline.py,sha256=nEoMJVn7ckn_hbo_O-B53tN-zo7MRZqcJsSlYWNbxNM,7358
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=VdmCVA7wosGGI6QKJIAPuU1NFBMTCKPh1I1YZCR1qDc,6542
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=xNKfvDLBW3NIKqcjCMH7LAl__I43BKwKFQRGn_Sei0c,1033
10
- CHAP/common/processor.py,sha256=RJu-gGhY--cqmpJUQMaT3HW8MwdnFKk-sdQQ0I2FSsg,29183
11
- CHAP/common/reader.py,sha256=iVlOluctVpfMTKQzI79bwuaXKqAwU6XJ52oZSqKf7-E,13557
12
- CHAP/common/writer.py,sha256=Zk_LnYOwX-UwmlMAEwLbX3rmBooDGNV1O2o-lOxr2iQ,12242
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=YIDojY_bgXS4k4GFOpmzo__yi7IsXl1mCIquTBS5srA,38280
16
- CHAP/edd/__init__.py,sha256=w3qmOjaoeiY69pf0ombi6TPRHcm60_T3sbTms5393pQ,422
17
- CHAP/edd/models.py,sha256=60xqOyClZefLngLFLN2lHM9c0UQKti8ZTylj5h9pJek,35075
18
- CHAP/edd/processor.py,sha256=s2w7qqcn0ajld6QBy3uMg8PzrE-Re0DR7yCt7330qkQ,56335
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=9K_OnSUNcRL_oLDqivXkqbwbxE9HmP1cXf-6vkkPDxI,35095
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=UPmn5rJl1MQe2cifBIOu7yBQO2qMmUtFu-KKw8XBMys,7889
36
- CHAP/tomo/processor.py,sha256=evNtZ3yTPKWDsm-RNxcQm7Pw7ERnwwDZu74QOqVrIAI,153325
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=VEhqAkNqkDpjBQ_kbOfGlNCEwmaPCh8RBc5SxHUy-OM,127878
41
- CHAP/utils/general.py,sha256=E1aKdoIEZCIDJoFGmOqSn0rRRA1rfbpImCmzhhyRGfY,67565
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=zCyad4P6OTytozM-rJjmIKXrOqeotbUHmr8Xc4YhpG8,44881
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.13.dist-info/LICENSE,sha256=GrJL25aZivxje_x-zBbeWASvdmgztxv8kBMhIP4XSMo,1075
50
- ChessAnalysisPipeline-0.0.13.dist-info/METADATA,sha256=KTZzy22v8P2ISFOgRLCXMDc6ytFoR2yayPtficwLHZA,1542
51
- ChessAnalysisPipeline-0.0.13.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
52
- ChessAnalysisPipeline-0.0.13.dist-info/entry_points.txt,sha256=w-KIKdUjmj5GCobrFC4_jexCsFB4yMXYjrsMWrhI6Co,42
53
- ChessAnalysisPipeline-0.0.13.dist-info/top_level.txt,sha256=BKhggOWLb9dD6oQm1RXrkJPnXm-zJxVzQef1iXYtt2k,11
54
- ChessAnalysisPipeline-0.0.13.dist-info/RECORD,,
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,,