comparison tomo_setup.py @ 60:52db7707ff48 draft

"planemo upload for repository https://github.com/rolfverberg/galaxytools commit 9a07ab3099737ee0d99e82739b55048f89c36bc6-dirty"
author rv43
date Tue, 16 Aug 2022 21:23:10 +0000
parents feb2a5fc7c76
children 75dd6e15f628
comparison
equal deleted inserted replaced
59:feb2a5fc7c76 60:52db7707ff48
9 import argparse 9 import argparse
10 import numpy as np 10 import numpy as np
11 import tracemalloc 11 import tracemalloc
12 12
13 from tomo import Tomo 13 from tomo import Tomo
14 from general import get_trailing_int
14 15
15 #from memory_profiler import profile 16 #from memory_profiler import profile
16 #@profile 17 #@profile
17 def __main__(): 18 def __main__():
18 19
25 parser.add_argument('--inputfiles', 26 parser.add_argument('--inputfiles',
26 default='inputfiles.txt', 27 default='inputfiles.txt',
27 help='Input file collections') 28 help='Input file collections')
28 parser.add_argument('-c', '--config', 29 parser.add_argument('-c', '--config',
29 help='Input config file') 30 help='Input config file')
31 parser.add_argument('--detector',
32 help='Detector info (number of rows and columns, and pixel size)')
30 parser.add_argument('--num_theta', 33 parser.add_argument('--num_theta',
31 help='Number of theta angles') 34 help='Number of theta angles')
32 parser.add_argument('--theta_range', 35 parser.add_argument('--theta_range',
33 help='Theta range (lower bound, upper bound)') 36 help='Theta range (lower bound, upper bound)')
34 parser.add_argument('--output_config', 37 parser.add_argument('--output_config',
51 if not isinstance(level, int): 54 if not isinstance(level, int):
52 raise ValueError(f'Invalid log_level: {log_level}') 55 raise ValueError(f'Invalid log_level: {log_level}')
53 logging.basicConfig(format=logging_format, level=level, force=True, 56 logging.basicConfig(format=logging_format, level=level, force=True,
54 handlers=[logging.StreamHandler()]) 57 handlers=[logging.StreamHandler()])
55 58
59 # Check command line arguments
56 logging.info(f'config = {args.config}') 60 logging.info(f'config = {args.config}')
61 if args.detector is None:
62 logging.info(f'detector = {args.detector}')
63 else:
64 logging.info(f'detector = {args.detector.split()}')
57 logging.info(f'num_theta = {args.num_theta}') 65 logging.info(f'num_theta = {args.num_theta}')
58 if args.theta_range is None: 66 if args.theta_range is None:
59 logging.info(f'theta_range = {args.theta_range}') 67 logging.info(f'theta_range = {args.theta_range}')
60 else: 68 else:
61 logging.info(f'theta_range = {args.theta_range.split()}') 69 logging.info(f'theta_range = {args.theta_range.split()}')
62 logging.info(f'output_config = {args.output_config}') 70 logging.info(f'output_config = {args.output_config}')
63 logging.info(f'output_data = {args.output_data}') 71 logging.info(f'output_data = {args.output_data}')
64 logging.info(f'log = {args.log}') 72 logging.info(f'log = {args.log}')
65 logging.debug(f'is log stdout? {args.log is sys.stdout}') 73 logging.debug(f'is log stdout? {args.log is sys.stdout}')
66 74 if args.detector is not None and len(args.detector.split()) != 3:
67 # Read tool config input 75 raise ValueError(f'Invalid detector: {args.detector}')
76 if args.num_theta is None or int(args.num_theta) < 1:
77 raise ValueError(f'Invalid num_theta: {args.num_theta}')
78 if args.theta_range is not None and len(args.theta_range.split()) != 2:
79 raise ValueError(f'Invalid theta_range: {args.theta_range}')
80 num_theta = int(args.num_theta)
81
82 # Read and check tool config input
68 inputconfig = [] 83 inputconfig = []
69 with open(args.inputconfig) as f: 84 with open(args.inputconfig) as f:
70 inputconfig = [line.strip() for line in f if line.strip() and not line.startswith('#')] 85 inputconfig = [line.strip() for line in f if line.strip() and not line.startswith('#')]
71 assert(len(inputconfig) >= 6) 86 assert(len(inputconfig) >= 6)
72 config_type = inputconfig[0] 87 config_type = inputconfig[0]
76 num_imgs = [int(x.strip()) for x in inputconfig[4].split()] 91 num_imgs = [int(x.strip()) for x in inputconfig[4].split()]
77 img_offsets = [int(x.strip()) for x in inputconfig[5].split()] 92 img_offsets = [int(x.strip()) for x in inputconfig[5].split()]
78 if config_type == 'config_manual': 93 if config_type == 'config_manual':
79 assert(len(inputconfig) == 7) 94 assert(len(inputconfig) == 7)
80 ref_heights = [float(x.strip()) for x in inputconfig[6].split()] 95 ref_heights = [float(x.strip()) for x in inputconfig[6].split()]
96 assert(args.detector is not None)
97 assert(args.theta_range is not None)
81 else: 98 else:
82 ref_heights = None 99 ref_heights = None
83 logging.info(f'config_type = {config_type} {type(config_type)}') 100 logging.info(f'config_type = {config_type} {type(config_type)}')
84 logging.info(f'input_type = {input_type} {type(input_type)}') 101 logging.info(f'input_type = {input_type} {type(input_type)}')
85 logging.info(f'num_stack = {num_stack} {type(num_stack)}') 102 logging.info(f'num_stack = {num_stack} {type(num_stack)}')
86 logging.info(f'stack_types = {stack_types} {type(stack_types)}') 103 logging.info(f'stack_types = {stack_types} {type(stack_types)}')
87 logging.info(f'num_imgs = {num_imgs} {type(num_imgs)}') 104 logging.info(f'num_imgs = {num_imgs} {type(num_imgs)}')
88 logging.info(f'img_offsets = {img_offsets} {type(img_offsets)}') 105 logging.info(f'img_offsets = {img_offsets} {type(img_offsets)}')
89 logging.info(f'ref_heights = {ref_heights} {type(ref_heights)}') 106 logging.info(f'ref_heights = {ref_heights} {type(ref_heights)}')
107 if config_type != 'config_file' and config_type != 'config_manual':
108 raise ValueError('Invalid input config provided.')
109 if input_type != 'collections' and input_type != 'files':
110 raise ValueError('Invalid input config provided.')
111 if len(stack_types) != num_stack:
112 raise ValueError('Invalid input config provided.')
113 if len(num_imgs) != num_stack:
114 raise ValueError('Invalid input config provided.')
115 if len(img_offsets) != num_stack:
116 raise ValueError('Invalid input config provided.')
117 if ref_heights is not None and len(ref_heights) != num_stack:
118 raise ValueError('Invalid input config provided.')
90 119
91 # Read input files and collect data files info 120 # Read input files and collect data files info
92 datasets = [] 121 datasets = []
93 with open(args.inputfiles) as f: 122 with open(args.inputfiles) as f:
94 for line in f: 123 for line in f:
95 if not line.strip() or line.startswith('#'): 124 if not line.strip() or line.startswith('#'):
96 continue 125 continue
97 fields = [x.strip() for x in line.split('\t')] 126 fields = [x.strip() for x in line.split('\t')]
98 filepath = fields[0] 127 filepath = fields[0]
99 element_identifier = fields[1] if len(fields) > 1 else fields[0].split('/')[-1] 128 element_identifier = fields[1] if len(fields) > 1 else fields[0].split('/')[-1]
100 datasets.append({'element_identifier' : fields[1], 'filepath' : filepath}) 129 datasets.append({'element_identifier' : element_identifier, 'filepath' : filepath})
130 print(f'datasets:\n{datasets}')
101 logging.debug(f'datasets:\n{datasets}') 131 logging.debug(f'datasets:\n{datasets}')
102 print(f'datasets:\n{datasets}') 132 if input_type == 'files' and len(datasets) != num_stack:
133 raise ValueError('Inconsistent number of input files provided.')
103 134
104 # Read and sort data files 135 # Read and sort data files
105 collections = [] 136 collections = []
106 for dataset in datasets: 137 stack_index = 1
107 element_identifier = [x.strip() for x in dataset['element_identifier'].split('_')] 138 for i, dataset in enumerate(datasets):
108 if len(element_identifier) > 1: 139 if input_type == 'collections':
109 name = element_identifier[0] 140 element_identifier = [x.strip() for x in dataset['element_identifier'].split('_')]
141 if len(element_identifier) > 1:
142 name = element_identifier[0]
143 else:
144 name = 'other'
110 else: 145 else:
111 name = 'other' 146 if stack_types[i] == 'tdf' or stack_types[i] == 'tbf':
147 name = stack_types[i]
148 elif stack_types[i] == 'data':
149 name = f'set{stack_index}'
150 stack_index += 1
151 else:
152 raise ValueError('Invalid input config provided.')
112 filepath = dataset['filepath'] 153 filepath = dataset['filepath']
113 print(f'element_identifier = {element_identifier} {len(element_identifier)}')
114 print(f'name = {name}')
115 print(f'filepath = {filepath}')
116 if not len(collections): 154 if not len(collections):
117 collections = [{'name' : name, 'filepaths' : [filepath]}] 155 collections = [{'name' : name, 'filepaths' : [filepath]}]
118 else: 156 else:
119 collection = [c for c in collections if c['name'] == name] 157 collection = [c for c in collections if c['name'] == name]
120 if len(collection): 158 if len(collection):
121 collection[0]['filepaths'].append(filepath) 159 collection[0]['filepaths'].append(filepath)
122 else: 160 else:
123 collection = {'name' : name, 'filepaths' : [filepath]} 161 collection = {'name' : name, 'filepaths' : [filepath]}
124 collections.append(collection) 162 collections.append(collection)
163 print(f'collections:\n{collections}')
125 logging.debug(f'collections:\n{collections}') 164 logging.debug(f'collections:\n{collections}')
126 print(f'collections:\n{collections}')
127 return
128 165
129 # Instantiate Tomo object 166 # Instantiate Tomo object
130 tomo = Tomo(config_file=args.config, config_out=args.output_config, log_level=log_level, 167 tomo = Tomo(config_file=args.config, config_out=args.output_config, log_level=log_level,
131 log_stream=args.log, galaxy_flag=True) 168 log_stream=args.log, galaxy_flag=True)
132 if not tomo.is_valid: 169 if config_type == 'config_file':
133 raise ValueError('Invalid config file provided.') 170 if not tomo.is_valid:
171 raise ValueError('Invalid config file provided.')
172 else:
173 assert(tomo.config is None)
174 tomo.config = {}
134 logging.debug(f'config:\n{tomo.config}') 175 logging.debug(f'config:\n{tomo.config}')
135 176
177 # Set detector inputs
178 if config_type == 'config_manual':
179 detector = args.detector.split()
180 tomo.config['detector'] = {'rows' : int(detector[0]),
181 'columns' : int(detector[1]), 'pixel_size' : float(detector[2])}
182
136 # Set theta inputs 183 # Set theta inputs
137 theta_range = args.theta_range.split()
138 config_theta_range = tomo.config.get('theta_range') 184 config_theta_range = tomo.config.get('theta_range')
139 if config_theta_range is None: 185 if config_theta_range is None:
140 config_tomo.config['theta_range'] = {'start' : float(theta_range[0]), 186 tomo.config['theta_range'] = {'num' : num_theta}
141 'end' : float(theta_range[1]), 'num' : int(theta_range[2])} 187 config_theta_range = tomo.config['theta_range']
142 else: 188 else:
189 config_theta_range['num'] = num_theta
190 if config_type == 'config_manual':
191 theta_range = args.theta_range.split()
143 config_theta_range['start'] = float(theta_range[0]) 192 config_theta_range['start'] = float(theta_range[0])
144 config_theta_range['end'] = float(theta_range[1]) 193 config_theta_range['end'] = float(theta_range[1])
145 config_theta_range['num'] = int(theta_range[2])
146 194
147 # Find dark field files 195 # Find dark field files
148 dark_field = tomo.config['dark_field'] 196 dark_field = tomo.config.get('dark_field')
149 tdf_files = [c['filepaths'] for c in collections if c['name'] == 'tdf'] 197 tdf_files = [c['filepaths'] for c in collections if c['name'] == 'tdf']
150 if len(tdf_files) != 1 or len(tdf_files[0]) < 1: 198 if len(tdf_files) != 1 or len(tdf_files[0]) < 1:
151 logging.warning('Unable to obtain dark field files') 199 logging.warning('Unable to obtain dark field files')
152 assert(dark_field['data_path'] is None) 200 if config_type == 'config_file':
153 assert(dark_field['img_start'] == -1) 201 assert(dark_field is not None)
154 assert(not dark_field['num']) 202 assert(dark_field['data_path'] is None)
203 assert(dark_field['img_start'] == -1)
204 assert(not dark_field['num'])
205 else:
206 tomo.config['dark_field'] = {'data_path' : None, 'img_start' : -1, 'num' : 0}
155 tdf_files = [None] 207 tdf_files = [None]
156 num_collections = 0 208 num_collections = 0
157 else: 209 else:
158 dark_field['img_offset'] = args.tomo_ranges[0] 210 if config_type == 'config_file':
159 dark_field['num'] = args.tomo_ranges[1] 211 assert(dark_field is not None)
212 assert(dark_field['data_path'] is not None)
213 assert(dark_field.get('img_start') is not None)
214 else:
215 tomo.config['dark_field'] = {'data_path' : tdf_files[0], 'img_start' : 0}
216 dark_field = tomo.config['dark_field']
217 tdf_index = [i for i,c in enumerate(collections) if c['name'] == 'tdf']
218 tdf_index_check = [i for i,s in enumerate(stack_types) if s == 'tdf']
219 if tdf_index != tdf_index_check:
220 raise ValueError(f'Inconsistent tdf_index ({tdf_index} vs. {tdf_index_check}).')
221 tdf_index = tdf_index[0]
222 dark_field['img_offset'] = img_offsets[tdf_index]
223 dark_field['num'] = num_imgs[tdf_index]
160 num_collections = 1 224 num_collections = 1
161 225
162 # Find bright field files 226 # Find bright field files
163 bright_field = tomo.config['bright_field'] 227 bright_field = tomo.config.get('bright_field')
164 bright_field['img_offset'] = args.tomo_ranges[2*num_collections]
165 bright_field['num'] = args.tomo_ranges[2*num_collections+1]
166 tbf_files = [c['filepaths'] for c in collections if c['name'] == 'tbf'] 228 tbf_files = [c['filepaths'] for c in collections if c['name'] == 'tbf']
167 if len(tbf_files) != 1 or len(tbf_files[0]) < 1: 229 if len(tbf_files) != 1 or len(tbf_files[0]) < 1:
168 exit('Unable to obtain bright field files') 230 exit('Unable to obtain bright field files')
231 if config_type == 'config_file':
232 assert(bright_field is not None)
233 assert(bright_field['data_path'] is not None)
234 assert(bright_field.get('img_start') is not None)
235 else:
236 tomo.config['bright_field'] = {'data_path' : tbf_files[0], 'img_start' : 0}
237 bright_field = tomo.config['bright_field']
238 tbf_index = [i for i,c in enumerate(collections) if c['name'] == 'tbf']
239 tbf_index_check = [i for i,s in enumerate(stack_types) if s == 'tbf']
240 if tbf_index != tbf_index_check:
241 raise ValueError(f'Inconsistent tbf_index ({tbf_index} vs. {tbf_index_check}).')
242 tbf_index = tbf_index[0]
243 bright_field['img_offset'] = img_offsets[tbf_index]
244 bright_field['num'] = num_imgs[tbf_index]
169 num_collections += 1 245 num_collections += 1
170 246
171 # Find tomography files 247 # Find tomography files
172 stack_info = tomo.config['stack_info'] 248 stack_info = tomo.config.get('stack_info')
173 if stack_info['num'] != len(collections) - num_collections: 249 if config_type == 'config_file':
174 raise ValueError('Inconsistent number of tomography data image sets') 250 assert(stack_info is not None)
251 if stack_info['num'] != len(collections) - num_collections:
252 raise ValueError('Inconsistent number of tomography data image sets')
253 assert(stack_info.get('stacks') is not None)
254 for stack in stack_info['stacks']:
255 assert(stack['data_path'] is not None)
256 assert(stack.get('img_start') is not None)
257 assert(stack.get('index') is not None)
258 assert(stack.get('ref_height') is not None)
259 else:
260 tomo.config['stack_info'] = {'num' : len(collections) - num_collections, 'stacks' : []}
261 stack_info = tomo.config['stack_info']
262 for i in range(stack_info['num']):
263 stack_info['stacks'].append({'img_start' : 0, 'index' : i+1})
175 tomo_stack_files = [] 264 tomo_stack_files = []
176 for stack in stack_info['stacks']: 265 for stack in stack_info['stacks']:
177 stack['img_offset'] = args.tomo_ranges[2*num_collections] 266 index = stack['index']
178 stack['num'] = args.tomo_ranges[2*num_collections+1] 267 tomo_files = [c['filepaths'] for c in collections if c['name'] == f'set{index}']
179 tomo_files = [c['filepaths'] for c in collections if c['name'] == f'set{stack["index"]}']
180 if len(tomo_files) != 1 or len(tomo_files[0]) < 1: 268 if len(tomo_files) != 1 or len(tomo_files[0]) < 1:
181 exit(f'Unable to obtain tomography images for set {stack["index"]}') 269 exit(f'Unable to obtain tomography images for set {index}')
270 tomo_index = [i for i,c in enumerate(collections) if c['name'] == f'set{index}']
271 if len(tomo_index) != 1:
272 raise ValueError(f'Illegal tomo_index ({tomo_index}).')
273 tomo_index = tomo_index[0]
274 stack['img_offset'] = img_offsets[tomo_index]
275 assert(num_imgs[tomo_index] == -1)
276 stack['num'] = num_theta
277 if config_type == 'config_manual':
278 if len(tomo_files) == 1:
279 stack['data_path'] = tomo_files[0]
280 stack['ref_height'] = ref_heights[tomo_index]
182 tomo_stack_files.append(tomo_files[0]) 281 tomo_stack_files.append(tomo_files[0])
183 num_collections += 1 282 num_collections += 1
283 if num_collections != num_stack:
284 raise ValueError('Inconsistent number of data image sets')
285 print(f'config:\n{tomo.config}')
286 return
184 287
185 # Preprocess the image files 288 # Preprocess the image files
186 galaxy_param = {'tdf_files' : tdf_files[0], 'tbf_files' : tbf_files[0], 289 galaxy_param = {'tdf_files' : tdf_files[0], 'tbf_files' : tbf_files[0],
187 'tomo_stack_files' : tomo_stack_files, 'output_name' : args.output_data} 290 'tomo_stack_files' : tomo_stack_files, 'output_name' : args.output_data}
188 tomo.genTomoStacks(galaxy_param) 291 tomo.genTomoStacks(galaxy_param)