Mercurial > repos > rv43 > tomo
comparison detector.py @ 63:98a83f03d91b draft
"planemo upload for repository https://github.com/rolfverberg/galaxytools commit a9ebbfca439737ae17ddcb0df84408155f964877"
| author | rv43 |
|---|---|
| date | Thu, 18 Aug 2022 14:36:46 +0000 |
| parents | 26f99fdd8d61 |
| children | 15288e9746e0 |
comparison
equal
deleted
inserted
replaced
| 62:e544e5d110eb | 63:98a83f03d91b |
|---|---|
| 2 import os | 2 import os |
| 3 import yaml | 3 import yaml |
| 4 from functools import cache | 4 from functools import cache |
| 5 from copy import deepcopy | 5 from copy import deepcopy |
| 6 | 6 |
| 7 #from .general import * | 7 from .general import * |
| 8 from general import illegal_value, is_int, is_num, input_yesno | |
| 9 | 8 |
| 10 #from hexrd.instrument import HEDMInstrument, PlanarDetector | 9 #from hexrd.instrument import HEDMInstrument, PlanarDetector |
| 11 | 10 |
| 12 class DetectorConfig: | 11 class DetectorConfig: |
| 13 def __init__(self, config_source): | 12 def __init__(self, config_source): |
| 13 | |
| 14 self._config_source = config_source | 14 self._config_source = config_source |
| 15 | 15 |
| 16 if isinstance(self._config_source, str): | 16 if isinstance(self._config_source, ((str, bytes, os.PathLike, int))): |
| 17 self._config_file = self._config_source | 17 self._config_file = self._config_source |
| 18 self._config = self._load_config_file() | 18 self._config = self._load_config_file() |
| 19 elif isinstance(self._config_source, dict): | 19 elif isinstance(self._config_source, dict): |
| 20 self._config_file = None | 20 self._config_file = None |
| 21 self._config = self._config_source | 21 self._config = self._config_source |
| 24 self._config = False | 24 self._config = False |
| 25 | 25 |
| 26 self._valid = self._validate() | 26 self._valid = self._validate() |
| 27 | 27 |
| 28 if not self.valid: | 28 if not self.valid: |
| 29 logging.error(f'Cannot create a valid instance of {self.__class__.__name__} '+ | 29 logging.error(f'Cannot create a valid instance of {self.__class__.__name__} from {self._config_source}') |
| 30 f'from {self._config_source}') | |
| 31 | 30 |
| 32 def __repr__(self): | 31 def __repr__(self): |
| 33 return(f'{self.__class__.__name__}({self._config_source.__repr__()})') | 32 return(f'{self.__class__.__name__}({self._config_source.__repr__()})') |
| 34 def __str__(self): | 33 def __str__(self): |
| 35 return(f'{self.__class__.__name__} generated from {self._config_source}') | 34 return(f'{self.__class__.__name__} generated from {self._config_source}') |
| 36 | 35 |
| 37 @property | 36 @property |
| 38 def config_file(self): | 37 def config_file(self): |
| 39 return(self._config_file) | 38 return(self._config_file) |
| 40 | |
| 41 @property | 39 @property |
| 42 def config(self): | 40 def config(self): |
| 43 return(deepcopy(self._config)) | 41 return(deepcopy(self._config)) |
| 44 | |
| 45 @property | 42 @property |
| 46 def valid(self): | 43 def valid(self): |
| 47 return(self._valid) | 44 return(self._valid) |
| 48 | 45 |
| 49 def load_config_file(self): | 46 def load_config_file(self): |
| 50 raise(NotImplementedError) | 47 raise(NotImplementedError) |
| 51 | |
| 52 def validate(self): | 48 def validate(self): |
| 53 raise(NotImplementedError) | 49 raise(NotImplementedError) |
| 54 | 50 |
| 55 def _load_config_file(self): | 51 def _load_config_file(self): |
| 56 return(self.load_config_file()) | 52 if not os.path.isfile(self.config_file): |
| 57 | 53 logging.error(f'{self.config_file} is not a file.') |
| 54 return(False) | |
| 55 else: | |
| 56 return(self.load_config_file()) | |
| 58 def _validate(self): | 57 def _validate(self): |
| 59 if not self.config: | 58 if not self.config: |
| 60 logging.error('A configuration must be loaded prior to calling Detector._validate') | 59 logging.error('A configuration must be loaded prior to calling Detector._validate') |
| 61 return(False) | 60 return(False) |
| 62 else: | 61 else: |
| 63 return(self.validate()) | 62 return(self.validate()) |
| 64 | |
| 65 def _write_to_file(self, out_file): | 63 def _write_to_file(self, out_file): |
| 66 out_file = os.path.abspath(out_file) | 64 out_file = os.path.abspath(out_file) |
| 67 | 65 |
| 68 current_config_valid = self.validate() | 66 current_config_valid = self.validate() |
| 69 if not current_config_valid: | 67 if not current_config_valid: |
| 70 write_invalid_config = input_yesno(s=f'This {self.__class__.__name__} is currently '+ | 68 write_invalid_config = input_yesno(s=f'This {self.__class__.__name__} is not currently valid. Write the configuration to {out_file} anyways?', default='no') |
| 71 f'invalid. Write the configuration to {out_file} anyways?', default='no') | |
| 72 if not write_invalid_config: | 69 if not write_invalid_config: |
| 73 logging.info('In accordance with user input, the invalid configuration will '+ | 70 logging.info(f'In accordance with user input, the invalid configuration will not be written to {out_file}') |
| 74 f'not be written to {out_file}') | |
| 75 return | 71 return |
| 76 | 72 |
| 77 if os.access(out_file, os.W_OK): | 73 if os.access(out_file, os.W_OK): |
| 78 if os.path.exists(out_file): | 74 if os.path.exists(out_file): |
| 79 overwrite = input_yesno(s=f'{out_file} already exists. Overwrite?', default='no') | 75 overwrite = input_yesno(s=f'{out_file} already exists. Overwrite?', default='no') |
| 80 if overwrite: | 76 if overwrite: |
| 81 self.write_to_file(out_file) | 77 self.write_to_file(out_file) |
| 82 else: | 78 else: |
| 83 logging.info(f'In accordance with user input, {out_file} will not be '+ | 79 logging.info(f'In accordance with user input, {out_file} will not be overwritten') |
| 84 'overwritten') | |
| 85 else: | 80 else: |
| 86 self.write_to_file(out_file) | 81 self.write_to_file(out_file) |
| 87 else: | 82 else: |
| 88 logging.error(f'Insufficient permissions to write to {out_file}') | 83 logging.error(f'Insufficient permissions to write to {out_file}') |
| 89 | 84 |
| 94 def __init__(self, config_source, validate_yaml_pars=[]): | 89 def __init__(self, config_source, validate_yaml_pars=[]): |
| 95 self._validate_yaml_pars = validate_yaml_pars | 90 self._validate_yaml_pars = validate_yaml_pars |
| 96 super().__init__(config_source) | 91 super().__init__(config_source) |
| 97 | 92 |
| 98 def load_config_file(self): | 93 def load_config_file(self): |
| 99 if not os.path.splitext(self._config_file)[1]: | 94 with open(self.config_file, 'r') as infile: |
| 100 if os.path.isfile(f'{self._config_file}.yml'): | |
| 101 self._config_file = f'{self._config_file}.yml' | |
| 102 if os.path.isfile(f'{self._config_file}.yaml'): | |
| 103 self._config_file = f'{self._config_file}.yaml' | |
| 104 if not os.path.isfile(self._config_file): | |
| 105 logging.error(f'Unable to load {self._config_file}') | |
| 106 return(False) | |
| 107 with open(self._config_file, 'r') as infile: | |
| 108 config = yaml.safe_load(infile) | 95 config = yaml.safe_load(infile) |
| 109 if isinstance(config, dict): | 96 if isinstance(config, dict): |
| 110 return(config) | 97 return(config) |
| 111 else: | 98 else: |
| 112 logging.error(f'Unable to load {self._config_file} as a dictionary') | 99 logging.error(f'Unable to load {self.config_file} as a dictionary') |
| 113 return(False) | 100 return(False) |
| 114 | 101 |
| 115 def validate(self): | 102 def validate(self): |
| 116 if not self._validate_yaml_pars: | 103 if not self._validate_yaml_pars: |
| 117 logging.warning('There are no required parameters provided for this detector '+ | 104 logging.warning('There are no required parameters provided for this detector configuration.') |
| 118 'configuration') | |
| 119 return(True) | 105 return(True) |
| 120 | 106 |
| 121 def validate_nested_pars(config, validate_yaml_par): | 107 def validate_nested_pars(config, validate_yaml_par): |
| 108 | |
| 122 yaml_par_levels = validate_yaml_par.split(':') | 109 yaml_par_levels = validate_yaml_par.split(':') |
| 123 first_level_par = yaml_par_levels[0] | 110 first_level_par = yaml_par_levels[0] |
| 124 try: | 111 try: |
| 125 first_level_par = int(first_level_par) | 112 first_level_par = int(first_level_par) |
| 126 except: | 113 except: |
| 133 else: | 120 else: |
| 134 return(True) | 121 return(True) |
| 135 except: | 122 except: |
| 136 return(False) | 123 return(False) |
| 137 | 124 |
| 138 pars_missing = [p for p in self._validate_yaml_pars | 125 pars_missing = [p for p in self._validate_yaml_pars if not validate_nested_pars(self.config, p)] |
| 139 if not validate_nested_pars(self.config, p)] | |
| 140 if len(pars_missing) > 0: | 126 if len(pars_missing) > 0: |
| 141 logging.error(f'Missing item(s) in configuration: {", ".join(pars_missing)}') | 127 logging.error(f'Missing item(s) in configuration: {", ".join(pars_missing)}') |
| 142 return(False) | 128 return(False) |
| 143 else: | 129 else: |
| 144 return(True) | 130 return(True) |
| 161 @cache | 147 @cache |
| 162 def lens_magnification(self): | 148 def lens_magnification(self): |
| 163 lens_magnification = self.config.get('lens_magnification') | 149 lens_magnification = self.config.get('lens_magnification') |
| 164 if not isinstance(lens_magnification, (int, float)) or lens_magnification <= 0.: | 150 if not isinstance(lens_magnification, (int, float)) or lens_magnification <= 0.: |
| 165 illegal_value(lens_magnification, 'lens_magnification', 'detector file') | 151 illegal_value(lens_magnification, 'lens_magnification', 'detector file') |
| 166 logging.warning('Using default lens_magnification value of 1.0') | 152 logging.warning('Using default lens_magnification value of 1.0.') |
| 167 return(1.0) | 153 return(1.0) |
| 168 else: | 154 else: |
| 169 return(lens_magnification) | 155 return(lens_magnification) |
| 170 | 156 |
| 171 @property | 157 @property |
| 203 return(None) | 189 return(None) |
| 204 num_columns = pixels.get('columns') | 190 num_columns = pixels.get('columns') |
| 205 if not is_int(num_columns, 1): | 191 if not is_int(num_columns, 1): |
| 206 illegal_value(num_columns, 'columns', 'detector file') | 192 illegal_value(num_columns, 'columns', 'detector file') |
| 207 return(None) | 193 return(None) |
| 194 | |
| 208 return(num_rows, num_columns) | 195 return(num_rows, num_columns) |
| 209 | 196 |
| 210 | 197 |
| 211 class EDDDetectorConfig(YamlDetectorConfig): | 198 class EDDDetectorConfig(YamlDetectorConfig): |
| 212 def __init__(self, config_source): | 199 def __init__(self, config_source): |
| 242 illegal_value(self.config['max_E'], 'max_E') | 229 illegal_value(self.config['max_E'], 'max_E') |
| 243 return(None) | 230 return(None) |
| 244 | 231 |
| 245 @property | 232 @property |
| 246 def bin_energies(self): | 233 def bin_energies(self): |
| 247 return(self.slope * np.linspace(0, self.max_E, self.num_bins, endpoint=False) + | 234 return(self.slope * np.linspace(0, self.max_E, self.num_bins, endpoint=False) + self.intercept) |
| 248 self.intercept) | |
| 249 | 235 |
| 250 @property | 236 @property |
| 251 def tth_angle(self): | 237 def tth_angle(self): |
| 252 try: | 238 try: |
| 253 return(float(self.config['tth_angle'])) | 239 return(float(self.config['tth_angle'])) |
