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