comparison detector.py @ 65:f31ef7bfb430 draft

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