From ec8eec23d96ff496fdc1e951d990c68751ba4d79 Mon Sep 17 00:00:00 2001 From: Keara Soloway Date: Mon, 16 Oct 2023 13:34:16 -0400 Subject: [PATCH] refactor: improve perfomance of CHAP.utils.scanparsers.FMBSAXSWAXSScanParser.get_detector_data_file --- CHAP/utils/scanparsers.py | 44 +++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/CHAP/utils/scanparsers.py b/CHAP/utils/scanparsers.py index 6396717..767a1e4 100755 --- a/CHAP/utils/scanparsers.py +++ b/CHAP/utils/scanparsers.py @@ -15,9 +15,6 @@ from pyspec.file.spec import FileSpec from pyspec.file.tiff import TiffFile -@cache -def get_filespec(spec_file_name): - return FileSpec(spec_file_name) class ScanParser: """Partial implementation of a class representing a SPEC scan and @@ -62,7 +59,7 @@ def spec_file(self): # NB This FileSpec instance is not stored as a private # attribute because it cannot be pickled (and therefore could # cause problems for parallel code that uses ScanParsers). - return get_filespec(self.spec_file_name) + return FileSpec(self.spec_file_name) @property def scan_path(self): @@ -582,6 +579,27 @@ def get_detector_data_path(self): return os.path.join(self.scan_path, self.scan_title) + +@cache +def list_fmb_saxswaxs_detector_files(detector_data_path, detector_prefix): + """Return a sorted list of all data files for the given detector + in the given directory. This function is cached to improve + performace for carrying our full FAMB SAXS/WAXS data-processing + workflows. + + :param detector_data_path: directory in which to look for detector + data files + :type detector_data_path: str + :param detector_prefix: detector name to list files for + :type detector_prefix: str + :return: list of detector filenames + :rtype: list[str] + """ + return sorted( + [f for f in os.listdir(detector_data_path) + if detector_prefix in f + and not f.endswith('.log')]) + class FMBSAXSWAXSScanParser(FMBLinearScanParser): """Concrete implementation of a class representing a scan taken with the typical SAXS/WAXS setup at FMB. @@ -591,20 +609,8 @@ def get_scan_title(self): return f'{self.scan_name}_{self.scan_number:03d}' def get_detector_data_file(self, detector_prefix, scan_step_index:int): - scan_step = self.get_scan_step(scan_step_index) - file_indices = [f'{scan_step[i]:03d}' - for i in range(len(self.spec_scan_shape)) - if self.spec_scan_shape[i] != 1] - if len(file_indices) == 0: - file_indices = ['000'] - file_name = f'{self.scan_name}_{detector_prefix}_' \ - f'{self.scan_number:03d}_{"_".join(file_indices)}.tiff' - file_name_full = os.path.join(self.detector_data_path, file_name) - if os.path.isfile(file_name_full): - return file_name_full - raise RuntimeError(f'{self.scan_title}: could not find detector image ' - f'file for detector {detector_prefix} scan step ' - f'({scan_step})') + detector_files = list_fmb_saxswaxs_detector_files(self.detector_data_path, detector_prefix) + return os.path.join(self.detector_data_path, detector_files[scan_step_index]) def get_detector_data(self, detector_prefix, scan_step_index:int): image_file = self.get_detector_data_file(detector_prefix, @@ -699,8 +705,6 @@ def get_spec_scan_shape(self): return (mot_npts,) if self.spec_macro in ('tseries', 'loopscan'): return len(np.array(self.spec_scan.data[:,0])) - if self.spec_macro == 'wbsync_ct': - return (1,) raise RuntimeError(f'{self.scan_title}: cannot determine scan shape ' f'for scans of type {self.spec_macro}')