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']))