annotate msnc_tools.py @ 0:f35c772fed27 draft

Uploaded
author rv43
date Thu, 24 Mar 2022 16:57:09 +0000
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
f35c772fed27 Uploaded
rv43
parents:
diff changeset
1 #!/usr/bin/env python3
f35c772fed27 Uploaded
rv43
parents:
diff changeset
2
f35c772fed27 Uploaded
rv43
parents:
diff changeset
3 # -*- coding: utf-8 -*-
f35c772fed27 Uploaded
rv43
parents:
diff changeset
4 """
f35c772fed27 Uploaded
rv43
parents:
diff changeset
5 Created on Mon Dec 6 15:36:22 2021
f35c772fed27 Uploaded
rv43
parents:
diff changeset
6
f35c772fed27 Uploaded
rv43
parents:
diff changeset
7 @author: rv43
f35c772fed27 Uploaded
rv43
parents:
diff changeset
8 """
f35c772fed27 Uploaded
rv43
parents:
diff changeset
9
f35c772fed27 Uploaded
rv43
parents:
diff changeset
10 import logging
f35c772fed27 Uploaded
rv43
parents:
diff changeset
11
f35c772fed27 Uploaded
rv43
parents:
diff changeset
12 import os
f35c772fed27 Uploaded
rv43
parents:
diff changeset
13 import sys
f35c772fed27 Uploaded
rv43
parents:
diff changeset
14 import re
f35c772fed27 Uploaded
rv43
parents:
diff changeset
15 import yaml
f35c772fed27 Uploaded
rv43
parents:
diff changeset
16 import h5py
f35c772fed27 Uploaded
rv43
parents:
diff changeset
17 import pyinputplus as pyip
f35c772fed27 Uploaded
rv43
parents:
diff changeset
18 import numpy as np
f35c772fed27 Uploaded
rv43
parents:
diff changeset
19 import imageio as img
f35c772fed27 Uploaded
rv43
parents:
diff changeset
20 import matplotlib.pyplot as plt
f35c772fed27 Uploaded
rv43
parents:
diff changeset
21 from time import time
f35c772fed27 Uploaded
rv43
parents:
diff changeset
22 from ast import literal_eval
f35c772fed27 Uploaded
rv43
parents:
diff changeset
23 from lmfit.models import StepModel, RectangleModel
f35c772fed27 Uploaded
rv43
parents:
diff changeset
24
f35c772fed27 Uploaded
rv43
parents:
diff changeset
25 def depth_list(L): return isinstance(L, list) and max(map(depth_list, L))+1
f35c772fed27 Uploaded
rv43
parents:
diff changeset
26 def depth_tuple(T): return isinstance(T, tuple) and max(map(depth_tuple, T))+1
f35c772fed27 Uploaded
rv43
parents:
diff changeset
27
f35c772fed27 Uploaded
rv43
parents:
diff changeset
28 def is_int(v, v_min=None, v_max=None):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
29 """Value is an integer in range v_min <= v <= v_max.
f35c772fed27 Uploaded
rv43
parents:
diff changeset
30 """
f35c772fed27 Uploaded
rv43
parents:
diff changeset
31 if not isinstance(v, int):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
32 return False
f35c772fed27 Uploaded
rv43
parents:
diff changeset
33 if (v_min != None and v < v_min) or (v_max != None and v > v_max):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
34 return False
f35c772fed27 Uploaded
rv43
parents:
diff changeset
35 return True
f35c772fed27 Uploaded
rv43
parents:
diff changeset
36
f35c772fed27 Uploaded
rv43
parents:
diff changeset
37 def is_num(v, v_min=None, v_max=None):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
38 """Value is a number in range v_min <= v <= v_max.
f35c772fed27 Uploaded
rv43
parents:
diff changeset
39 """
f35c772fed27 Uploaded
rv43
parents:
diff changeset
40 if not isinstance(v, (int,float)):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
41 return False
f35c772fed27 Uploaded
rv43
parents:
diff changeset
42 if (v_min != None and v < v_min) or (v_max != None and v > v_max):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
43 return False
f35c772fed27 Uploaded
rv43
parents:
diff changeset
44 return True
f35c772fed27 Uploaded
rv43
parents:
diff changeset
45
f35c772fed27 Uploaded
rv43
parents:
diff changeset
46 def is_index(v, v_min=0, v_max=None):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
47 """Value is an array index in range v_min <= v < v_max.
f35c772fed27 Uploaded
rv43
parents:
diff changeset
48 """
f35c772fed27 Uploaded
rv43
parents:
diff changeset
49 if not isinstance(v, int):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
50 return False
f35c772fed27 Uploaded
rv43
parents:
diff changeset
51 if v < v_min or (v_max != None and v >= v_max):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
52 return False
f35c772fed27 Uploaded
rv43
parents:
diff changeset
53 return True
f35c772fed27 Uploaded
rv43
parents:
diff changeset
54
f35c772fed27 Uploaded
rv43
parents:
diff changeset
55 def is_index_range(v, v_min=0, v_max=None):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
56 """Value is an array index range in range v_min <= v[0] <= v[1] < v_max.
f35c772fed27 Uploaded
rv43
parents:
diff changeset
57 """
f35c772fed27 Uploaded
rv43
parents:
diff changeset
58 if not (isinstance(v, list) and len(v) == 2 and isinstance(v[0], int) and
f35c772fed27 Uploaded
rv43
parents:
diff changeset
59 isinstance(v[1], int)):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
60 return False
f35c772fed27 Uploaded
rv43
parents:
diff changeset
61 if not 0 <= v[0] < v[1] or (v_max != None and v[1] >= v_max):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
62 return False
f35c772fed27 Uploaded
rv43
parents:
diff changeset
63 return True
f35c772fed27 Uploaded
rv43
parents:
diff changeset
64
f35c772fed27 Uploaded
rv43
parents:
diff changeset
65 def illegal_value(name, value, location=None, exit_flag=False):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
66 if not isinstance(location, str):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
67 location = ''
f35c772fed27 Uploaded
rv43
parents:
diff changeset
68 else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
69 location = f'in {location} '
f35c772fed27 Uploaded
rv43
parents:
diff changeset
70 if isinstance(name, str):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
71 logging.error(f'Illegal value for {name} {location}({value}, {type(value)})')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
72 else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
73 logging.error(f'Illegal value {location}({value}, {type(value)})')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
74 if exit_flag:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
75 exit(1)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
76
f35c772fed27 Uploaded
rv43
parents:
diff changeset
77 def get_trailing_int(string):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
78 indexRegex = re.compile(r'\d+$')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
79 mo = indexRegex.search(string)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
80 if mo == None:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
81 return None
f35c772fed27 Uploaded
rv43
parents:
diff changeset
82 else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
83 return int(mo.group())
f35c772fed27 Uploaded
rv43
parents:
diff changeset
84
f35c772fed27 Uploaded
rv43
parents:
diff changeset
85 def findImageFiles(path, filetype, name=None, select_range=False, num_required=None):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
86 if isinstance(name, str):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
87 name = f' {name} '
f35c772fed27 Uploaded
rv43
parents:
diff changeset
88 else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
89 name = ' '
f35c772fed27 Uploaded
rv43
parents:
diff changeset
90 # Find available index range
f35c772fed27 Uploaded
rv43
parents:
diff changeset
91 if filetype == 'tif':
f35c772fed27 Uploaded
rv43
parents:
diff changeset
92 if not isinstance(path, str) and not os.path.isdir(path):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
93 illegal_value('path', path, 'findImageRange')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
94 return -1, 0, []
f35c772fed27 Uploaded
rv43
parents:
diff changeset
95 indexRegex = re.compile(r'\d+')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
96 # At this point only tiffs
f35c772fed27 Uploaded
rv43
parents:
diff changeset
97 files = sorted([f for f in os.listdir(path) if os.path.isfile(os.path.join(path, f)) and
f35c772fed27 Uploaded
rv43
parents:
diff changeset
98 f.endswith('.tif') and indexRegex.search(f)])
f35c772fed27 Uploaded
rv43
parents:
diff changeset
99 num_imgs = len(files)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
100 if num_imgs < 1:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
101 logging.warning('No available'+name+'files')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
102 return -1, 0, []
f35c772fed27 Uploaded
rv43
parents:
diff changeset
103 first_index = indexRegex.search(files[0]).group()
f35c772fed27 Uploaded
rv43
parents:
diff changeset
104 last_index = indexRegex.search(files[-1]).group()
f35c772fed27 Uploaded
rv43
parents:
diff changeset
105 if first_index == None or last_index == None:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
106 logging.error('Unable to find correctly indexed'+name+'images')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
107 return -1, 0, []
f35c772fed27 Uploaded
rv43
parents:
diff changeset
108 first_index = int(first_index)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
109 last_index = int(last_index)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
110 if num_imgs != last_index-first_index+1:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
111 logging.error('Non-consecutive set of indices for'+name+'images')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
112 return -1, 0, []
f35c772fed27 Uploaded
rv43
parents:
diff changeset
113 paths = [os.path.join(path, f) for f in files]
f35c772fed27 Uploaded
rv43
parents:
diff changeset
114 elif filetype == 'h5':
f35c772fed27 Uploaded
rv43
parents:
diff changeset
115 if not isinstance(path, str) or not os.path.isfile(path):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
116 illegal_value('path', path, 'findImageRange')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
117 return -1, 0, []
f35c772fed27 Uploaded
rv43
parents:
diff changeset
118 # At this point only h5 in alamo2 detector style
f35c772fed27 Uploaded
rv43
parents:
diff changeset
119 first_index = 0
f35c772fed27 Uploaded
rv43
parents:
diff changeset
120 with h5py.File(path, 'r') as f:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
121 num_imgs = f['entry/instrument/detector/data'].shape[0]
f35c772fed27 Uploaded
rv43
parents:
diff changeset
122 last_index = num_imgs-1
f35c772fed27 Uploaded
rv43
parents:
diff changeset
123 paths = [path]
f35c772fed27 Uploaded
rv43
parents:
diff changeset
124 else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
125 illegal_value('filetype', filetype, 'findImageRange')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
126 return -1, 0, []
f35c772fed27 Uploaded
rv43
parents:
diff changeset
127 logging.debug('\nNumber of available'+name+f'images: {num_imgs}')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
128 logging.debug('Index range of available'+name+f'images: [{first_index}, '+
f35c772fed27 Uploaded
rv43
parents:
diff changeset
129 f'{last_index}]')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
130
f35c772fed27 Uploaded
rv43
parents:
diff changeset
131 return first_index, num_imgs, paths
f35c772fed27 Uploaded
rv43
parents:
diff changeset
132
f35c772fed27 Uploaded
rv43
parents:
diff changeset
133 def selectImageRange(first_index, offset, num_imgs, name=None, num_required=None):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
134 if isinstance(name, str):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
135 name = f' {name} '
f35c772fed27 Uploaded
rv43
parents:
diff changeset
136 else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
137 name = ' '
f35c772fed27 Uploaded
rv43
parents:
diff changeset
138 # Check existing values
f35c772fed27 Uploaded
rv43
parents:
diff changeset
139 use_input = 'no'
f35c772fed27 Uploaded
rv43
parents:
diff changeset
140 if (is_int(first_index, 0) and is_int(offset, 0) and is_int(num_imgs, 1)):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
141 if offset < 0:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
142 use_input = pyip.inputYesNo('\nCurrent'+name+f'first index = {first_index}, '+
f35c772fed27 Uploaded
rv43
parents:
diff changeset
143 'use this value ([y]/n)? ', blank=True)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
144 else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
145 use_input = pyip.inputYesNo('\nCurrent'+name+'first index/offset = '+
f35c772fed27 Uploaded
rv43
parents:
diff changeset
146 f'{first_index}/{offset}, use these values ([y]/n)? ',
f35c772fed27 Uploaded
rv43
parents:
diff changeset
147 blank=True)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
148 if use_input != 'no':
f35c772fed27 Uploaded
rv43
parents:
diff changeset
149 use_input = pyip.inputYesNo('Current number of'+name+'images = '+
f35c772fed27 Uploaded
rv43
parents:
diff changeset
150 f'{num_imgs}, use this value ([y]/n)? ',
f35c772fed27 Uploaded
rv43
parents:
diff changeset
151 blank=True)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
152 if use_input == 'yes':
f35c772fed27 Uploaded
rv43
parents:
diff changeset
153 return first_index, offset, num_imgs
f35c772fed27 Uploaded
rv43
parents:
diff changeset
154
f35c772fed27 Uploaded
rv43
parents:
diff changeset
155 # Check range against requirements
f35c772fed27 Uploaded
rv43
parents:
diff changeset
156 if num_imgs < 1:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
157 logging.warning('No available'+name+'images')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
158 return -1, -1, 0
f35c772fed27 Uploaded
rv43
parents:
diff changeset
159 if num_required == None:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
160 if num_imgs == 1:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
161 return first_index, 0, 1
f35c772fed27 Uploaded
rv43
parents:
diff changeset
162 else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
163 if not is_int(num_required, 1):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
164 illegal_value('num_required', num_required, 'selectImageRange')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
165 return -1, -1, 0
f35c772fed27 Uploaded
rv43
parents:
diff changeset
166 if num_imgs < num_required:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
167 logging.error('Unable to find the required'+name+
f35c772fed27 Uploaded
rv43
parents:
diff changeset
168 f'images ({num_imgs} out of {num_required})')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
169 return -1, -1, 0
f35c772fed27 Uploaded
rv43
parents:
diff changeset
170
f35c772fed27 Uploaded
rv43
parents:
diff changeset
171 # Select index range
f35c772fed27 Uploaded
rv43
parents:
diff changeset
172 if num_required == None:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
173 last_index = first_index+num_imgs
f35c772fed27 Uploaded
rv43
parents:
diff changeset
174 use_all = f'Use all ([{first_index}, {last_index}])'
f35c772fed27 Uploaded
rv43
parents:
diff changeset
175 pick_offset = 'Pick a first index offset and a number of images'
f35c772fed27 Uploaded
rv43
parents:
diff changeset
176 pick_bounds = 'Pick the first and last index'
f35c772fed27 Uploaded
rv43
parents:
diff changeset
177 menuchoice = pyip.inputMenu([use_all, pick_offset, pick_bounds], numbered=True)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
178 if menuchoice == use_all:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
179 offset = 0
f35c772fed27 Uploaded
rv43
parents:
diff changeset
180 elif menuchoice == pick_offset:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
181 offset = pyip.inputInt('Enter the first index offset'+
f35c772fed27 Uploaded
rv43
parents:
diff changeset
182 f' [0, {last_index-first_index}]: ', min=0, max=last_index-first_index)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
183 first_index += offset
f35c772fed27 Uploaded
rv43
parents:
diff changeset
184 if first_index == last_index:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
185 num_imgs = 1
f35c772fed27 Uploaded
rv43
parents:
diff changeset
186 else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
187 num_imgs = pyip.inputInt(f'Enter the number of images [1, {num_imgs}]: ',
f35c772fed27 Uploaded
rv43
parents:
diff changeset
188 min=1, max=num_imgs)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
189 else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
190 offset = pyip.inputInt(f'Enter the first index [{first_index}, {last_index}]: ',
f35c772fed27 Uploaded
rv43
parents:
diff changeset
191 min=first_index, max=last_index)-first_index
f35c772fed27 Uploaded
rv43
parents:
diff changeset
192 first_index += offset
f35c772fed27 Uploaded
rv43
parents:
diff changeset
193 num_imgs = pyip.inputInt(f'Enter the last index [{first_index}, {last_index}]: ',
f35c772fed27 Uploaded
rv43
parents:
diff changeset
194 min=first_index, max=last_index)-first_index+1
f35c772fed27 Uploaded
rv43
parents:
diff changeset
195 else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
196 use_all = f'Use ([{first_index}, {first_index+num_required-1}])'
f35c772fed27 Uploaded
rv43
parents:
diff changeset
197 pick_offset = 'Pick the first index offset'
f35c772fed27 Uploaded
rv43
parents:
diff changeset
198 menuchoice = pyip.inputMenu([use_all, pick_offset], numbered=True)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
199 offset = 0
f35c772fed27 Uploaded
rv43
parents:
diff changeset
200 if menuchoice == pick_offset:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
201 offset = pyip.inputInt('Enter the first index offset'+
f35c772fed27 Uploaded
rv43
parents:
diff changeset
202 f'[0, {num_imgs-num_required}]: ', min=0, max=num_imgs-num_required)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
203 first_index += offset
f35c772fed27 Uploaded
rv43
parents:
diff changeset
204 num_imgs = num_required
f35c772fed27 Uploaded
rv43
parents:
diff changeset
205
f35c772fed27 Uploaded
rv43
parents:
diff changeset
206 return first_index, offset, num_imgs
f35c772fed27 Uploaded
rv43
parents:
diff changeset
207
f35c772fed27 Uploaded
rv43
parents:
diff changeset
208 def loadImage(f, img_x_bounds=None, img_y_bounds=None):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
209 """Load a single image from file.
f35c772fed27 Uploaded
rv43
parents:
diff changeset
210 """
f35c772fed27 Uploaded
rv43
parents:
diff changeset
211 if not os.path.isfile(f):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
212 logging.error(f'Unable to load {f}')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
213 return None
f35c772fed27 Uploaded
rv43
parents:
diff changeset
214 img_read = img.imread(f)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
215 if not img_x_bounds:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
216 img_x_bounds = [0, img_read.shape[0]]
f35c772fed27 Uploaded
rv43
parents:
diff changeset
217 else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
218 if (not isinstance(img_x_bounds, list) or len(img_x_bounds) != 2 or
f35c772fed27 Uploaded
rv43
parents:
diff changeset
219 not (0 <= img_x_bounds[0] < img_x_bounds[1] <= img_read.shape[0])):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
220 logging.error(f'inconsistent row dimension in {f}')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
221 return None
f35c772fed27 Uploaded
rv43
parents:
diff changeset
222 if not img_y_bounds:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
223 img_y_bounds = [0, img_read.shape[1]]
f35c772fed27 Uploaded
rv43
parents:
diff changeset
224 else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
225 if (not isinstance(img_y_bounds, list) or len(img_y_bounds) != 2 or
f35c772fed27 Uploaded
rv43
parents:
diff changeset
226 not (0 <= img_y_bounds[0] < img_y_bounds[1] <= img_read.shape[0])):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
227 logging.error(f'inconsistent column dimension in {f}')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
228 return None
f35c772fed27 Uploaded
rv43
parents:
diff changeset
229 return img_read[img_x_bounds[0]:img_x_bounds[1],img_y_bounds[0]:img_y_bounds[1]]
f35c772fed27 Uploaded
rv43
parents:
diff changeset
230
f35c772fed27 Uploaded
rv43
parents:
diff changeset
231 def loadImageStack(files, filetype, img_offset, num_imgs, num_img_skip=0,
f35c772fed27 Uploaded
rv43
parents:
diff changeset
232 img_x_bounds=None, img_y_bounds=None):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
233 """Load a set of images and return them as a stack.
f35c772fed27 Uploaded
rv43
parents:
diff changeset
234 """
f35c772fed27 Uploaded
rv43
parents:
diff changeset
235 logging.debug(f'img_offset = {img_offset}')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
236 logging.debug(f'num_imgs = {num_imgs}')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
237 logging.debug(f'num_img_skip = {num_img_skip}')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
238 logging.debug(f'\nfiles:\n{files}\n')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
239 img_stack = np.array([])
f35c772fed27 Uploaded
rv43
parents:
diff changeset
240 if filetype == 'tif':
f35c772fed27 Uploaded
rv43
parents:
diff changeset
241 img_read_stack = []
f35c772fed27 Uploaded
rv43
parents:
diff changeset
242 i = 1
f35c772fed27 Uploaded
rv43
parents:
diff changeset
243 t0 = time()
f35c772fed27 Uploaded
rv43
parents:
diff changeset
244 for f in files[img_offset:img_offset+num_imgs:num_img_skip+1]:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
245 if not i%20:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
246 logging.info(f' loading {i}/{num_imgs}: {f}')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
247 else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
248 logging.debug(f' loading {i}/{num_imgs}: {f}')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
249 img_read = loadImage(f, img_x_bounds, img_y_bounds)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
250 img_read_stack.append(img_read)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
251 i += num_img_skip+1
f35c772fed27 Uploaded
rv43
parents:
diff changeset
252 img_stack = np.stack([img_read for img_read in img_read_stack])
f35c772fed27 Uploaded
rv43
parents:
diff changeset
253 logging.info(f'... done in {time()-t0:.2f} seconds!')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
254 logging.debug(f'img_stack shape = {np.shape(img_stack)}')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
255 del img_read_stack, img_read
f35c772fed27 Uploaded
rv43
parents:
diff changeset
256 elif filetype == 'h5':
f35c772fed27 Uploaded
rv43
parents:
diff changeset
257 if not isinstance(files[0], str) and not os.path.isfile(files[0]):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
258 illegal_value('files[0]', files[0], 'loadImageStack')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
259 return img_stack
f35c772fed27 Uploaded
rv43
parents:
diff changeset
260 t0 = time()
f35c772fed27 Uploaded
rv43
parents:
diff changeset
261 with h5py.File(files[0], 'r') as f:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
262 shape = f['entry/instrument/detector/data'].shape
f35c772fed27 Uploaded
rv43
parents:
diff changeset
263 if len(shape) != 3:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
264 logging.error(f'inconsistent dimensions in {files[0]}')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
265 if not img_x_bounds:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
266 img_x_bounds = [0, shape[1]]
f35c772fed27 Uploaded
rv43
parents:
diff changeset
267 else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
268 if (not isinstance(img_x_bounds, list) or len(img_x_bounds) != 2 or
f35c772fed27 Uploaded
rv43
parents:
diff changeset
269 not (0 <= img_x_bounds[0] < img_x_bounds[1] <= shape[1])):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
270 logging.error(f'inconsistent row dimension in {files[0]}')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
271 if not img_y_bounds:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
272 img_y_bounds = [0, shape[2]]
f35c772fed27 Uploaded
rv43
parents:
diff changeset
273 else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
274 if (not isinstance(img_y_bounds, list) or len(img_y_bounds) != 2 or
f35c772fed27 Uploaded
rv43
parents:
diff changeset
275 not (0 <= img_y_bounds[0] < img_y_bounds[1] <= shape[2])):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
276 logging.error(f'inconsistent column dimension in {files[0]}')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
277 img_stack = f.get('entry/instrument/detector/data')[
f35c772fed27 Uploaded
rv43
parents:
diff changeset
278 img_offset:img_offset+num_imgs:num_img_skip+1,
f35c772fed27 Uploaded
rv43
parents:
diff changeset
279 img_x_bounds[0]:img_x_bounds[1],img_y_bounds[0]:img_y_bounds[1]]
f35c772fed27 Uploaded
rv43
parents:
diff changeset
280 logging.info(f'... done in {time()-t0:.2f} seconds!')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
281 else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
282 illegal_value('filetype', filetype, 'findImageRange')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
283 return img_stack
f35c772fed27 Uploaded
rv43
parents:
diff changeset
284
f35c772fed27 Uploaded
rv43
parents:
diff changeset
285 def clearFig(title):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
286 if not isinstance(title, str):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
287 illegal_value('title', title, 'clearFig')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
288 return
f35c772fed27 Uploaded
rv43
parents:
diff changeset
289 plt.close(fig=re.sub(r"\s+", '_', title))
f35c772fed27 Uploaded
rv43
parents:
diff changeset
290
f35c772fed27 Uploaded
rv43
parents:
diff changeset
291 def quickImshow(a, title=None, path=None, name=None, save_fig=False, save_only=False,
f35c772fed27 Uploaded
rv43
parents:
diff changeset
292 clear=True, **kwargs):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
293 if title != None and not isinstance(title, str):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
294 illegal_value('title', title, 'quickImshow')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
295 return
f35c772fed27 Uploaded
rv43
parents:
diff changeset
296 if path is not None and not isinstance(path, str):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
297 illegal_value('path', path, 'quickImshow')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
298 return
f35c772fed27 Uploaded
rv43
parents:
diff changeset
299 if not isinstance(save_fig, bool):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
300 illegal_value('save_fig', save_fig, 'quickImshow')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
301 return
f35c772fed27 Uploaded
rv43
parents:
diff changeset
302 if not isinstance(save_only, bool):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
303 illegal_value('save_only', save_only, 'quickImshow')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
304 return
f35c772fed27 Uploaded
rv43
parents:
diff changeset
305 if not isinstance(clear, bool):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
306 illegal_value('clear', clear, 'quickImshow')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
307 return
f35c772fed27 Uploaded
rv43
parents:
diff changeset
308 if not title:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
309 title='quick_imshow'
f35c772fed27 Uploaded
rv43
parents:
diff changeset
310 else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
311 title = re.sub(r"\s+", '_', title)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
312 if name is None:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
313 if path is None:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
314 path = f'{title}.png'
f35c772fed27 Uploaded
rv43
parents:
diff changeset
315 else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
316 path = f'{path}/{title}.png'
f35c772fed27 Uploaded
rv43
parents:
diff changeset
317 else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
318 if path is None:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
319 path = name
f35c772fed27 Uploaded
rv43
parents:
diff changeset
320 else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
321 path = f'{path}/{name}'
f35c772fed27 Uploaded
rv43
parents:
diff changeset
322 if clear:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
323 plt.close(fig=title)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
324 if save_only:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
325 plt.figure(title)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
326 plt.imshow(a, **kwargs)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
327 plt.savefig(path)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
328 plt.close(fig=title)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
329 #plt.imsave(f'{title}.png', a, **kwargs)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
330 else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
331 plt.ion()
f35c772fed27 Uploaded
rv43
parents:
diff changeset
332 plt.figure(title)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
333 plt.imshow(a, **kwargs)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
334 if save_fig:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
335 plt.savefig(path)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
336 plt.pause(1)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
337
f35c772fed27 Uploaded
rv43
parents:
diff changeset
338 def quickPlot(*args, title=None, path=None, name=None, save_fig=False, save_only=False,
f35c772fed27 Uploaded
rv43
parents:
diff changeset
339 clear=True, **kwargs):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
340 if title != None and not isinstance(title, str):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
341 illegal_value('title', title, 'quickPlot')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
342 return
f35c772fed27 Uploaded
rv43
parents:
diff changeset
343 if path is not None and not isinstance(path, str):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
344 illegal_value('path', path, 'quickPlot')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
345 return
f35c772fed27 Uploaded
rv43
parents:
diff changeset
346 if not isinstance(save_fig, bool):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
347 illegal_value('save_fig', save_fig, 'quickPlot')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
348 return
f35c772fed27 Uploaded
rv43
parents:
diff changeset
349 if not isinstance(save_only, bool):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
350 illegal_value('save_only', save_only, 'quickPlot')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
351 return
f35c772fed27 Uploaded
rv43
parents:
diff changeset
352 if not isinstance(clear, bool):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
353 illegal_value('clear', clear, 'quickPlot')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
354 return
f35c772fed27 Uploaded
rv43
parents:
diff changeset
355 if not title:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
356 title = 'quick_plot'
f35c772fed27 Uploaded
rv43
parents:
diff changeset
357 else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
358 title = re.sub(r"\s+", '_', title)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
359 if name is None:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
360 if path is None:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
361 path = f'{title}.png'
f35c772fed27 Uploaded
rv43
parents:
diff changeset
362 else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
363 path = f'{path}/{title}.png'
f35c772fed27 Uploaded
rv43
parents:
diff changeset
364 else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
365 if path is None:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
366 path = name
f35c772fed27 Uploaded
rv43
parents:
diff changeset
367 else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
368 path = f'{path}/{name}'
f35c772fed27 Uploaded
rv43
parents:
diff changeset
369 if clear:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
370 plt.close(fig=title)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
371 if save_only:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
372 plt.figure(title)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
373 if depth_tuple(args) > 1:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
374 for y in args:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
375 plt.plot(*y, **kwargs)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
376 else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
377 plt.plot(*args, **kwargs)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
378 plt.savefig(path)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
379 plt.close(fig=title)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
380 else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
381 plt.ion()
f35c772fed27 Uploaded
rv43
parents:
diff changeset
382 plt.figure(title)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
383 if depth_tuple(args) > 1:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
384 for y in args:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
385 plt.plot(*y, **kwargs)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
386 else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
387 plt.plot(*args, **kwargs)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
388 if save_fig:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
389 plt.savefig(path)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
390 plt.pause(1)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
391
f35c772fed27 Uploaded
rv43
parents:
diff changeset
392 def selectArrayBounds(a, x_low=None, x_upp=None, num_x_min=None,
f35c772fed27 Uploaded
rv43
parents:
diff changeset
393 title='select array bounds'):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
394 """Interactively select the lower and upper data bounds for a numpy array.
f35c772fed27 Uploaded
rv43
parents:
diff changeset
395 """
f35c772fed27 Uploaded
rv43
parents:
diff changeset
396 if not isinstance(a, np.ndarray) or a.ndim != 1:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
397 logging.error('Illegal array type or dimension in selectArrayBounds')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
398 return None
f35c772fed27 Uploaded
rv43
parents:
diff changeset
399 if num_x_min == None:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
400 num_x_min = 1
f35c772fed27 Uploaded
rv43
parents:
diff changeset
401 else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
402 if num_x_min < 2 or num_x_min > a.size:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
403 logging.warning('Illegal input for num_x_min in selectArrayBounds, input ignored')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
404 num_x_min = 1
f35c772fed27 Uploaded
rv43
parents:
diff changeset
405 if x_low == None:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
406 x_min = 0
f35c772fed27 Uploaded
rv43
parents:
diff changeset
407 x_max = a.size
f35c772fed27 Uploaded
rv43
parents:
diff changeset
408 x_low_max = a.size-num_x_min
f35c772fed27 Uploaded
rv43
parents:
diff changeset
409 while True:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
410 quickPlot(range(x_min, x_max), a[x_min:x_max], title=title)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
411 zoom_flag = pyip.inputInt('Set lower data bound (0) or zoom in (1)?: ',
f35c772fed27 Uploaded
rv43
parents:
diff changeset
412 min=0, max=1)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
413 if zoom_flag:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
414 x_min = pyip.inputInt(f' Set lower zoom index [0, {x_low_max}]: ',
f35c772fed27 Uploaded
rv43
parents:
diff changeset
415 min=0, max=x_low_max)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
416 x_max = pyip.inputInt(f' Set upper zoom index [{x_min+1}, {x_low_max+1}]: ',
f35c772fed27 Uploaded
rv43
parents:
diff changeset
417 min=x_min+1, max=x_low_max+1)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
418 else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
419 x_low = pyip.inputInt(f' Set lower data bound [0, {x_low_max}]: ',
f35c772fed27 Uploaded
rv43
parents:
diff changeset
420 min=0, max=x_low_max)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
421 break
f35c772fed27 Uploaded
rv43
parents:
diff changeset
422 else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
423 if not is_int(x_low, 0, a.size-num_x_min):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
424 illegal_value('x_low', x_low, 'selectArrayBounds')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
425 return None
f35c772fed27 Uploaded
rv43
parents:
diff changeset
426 if x_upp == None:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
427 x_min = x_low+num_x_min
f35c772fed27 Uploaded
rv43
parents:
diff changeset
428 x_max = a.size
f35c772fed27 Uploaded
rv43
parents:
diff changeset
429 x_upp_min = x_min
f35c772fed27 Uploaded
rv43
parents:
diff changeset
430 while True:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
431 quickPlot(range(x_min, x_max), a[x_min:x_max], title=title)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
432 zoom_flag = pyip.inputInt('Set upper data bound (0) or zoom in (1)?: ',
f35c772fed27 Uploaded
rv43
parents:
diff changeset
433 min=0, max=1)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
434 if zoom_flag:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
435 x_min = pyip.inputInt(f' Set upper zoom index [{x_upp_min}, {a.size-1}]: ',
f35c772fed27 Uploaded
rv43
parents:
diff changeset
436 min=x_upp_min, max=a.size-1)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
437 x_max = pyip.inputInt(f' Set upper zoom index [{x_min+1}, {a.size}]: ',
f35c772fed27 Uploaded
rv43
parents:
diff changeset
438 min=x_min+1, max=a.size)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
439 else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
440 x_upp = pyip.inputInt(f' Set upper data bound [{x_upp_min}, {a.size}]: ',
f35c772fed27 Uploaded
rv43
parents:
diff changeset
441 min=x_upp_min, max=a.size)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
442 break
f35c772fed27 Uploaded
rv43
parents:
diff changeset
443 else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
444 if not is_int(x_upp, x_low+num_x_min, a.size):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
445 illegal_value('x_upp', x_upp, 'selectArrayBounds')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
446 return None
f35c772fed27 Uploaded
rv43
parents:
diff changeset
447 print(f'lower bound = {x_low} (inclusive)\nupper bound = {x_upp} (exclusive)]')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
448 bounds = [x_low, x_upp]
f35c772fed27 Uploaded
rv43
parents:
diff changeset
449 #quickPlot(range(bounds[0], bounds[1]), a[bounds[0]:bounds[1]], title=title)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
450 quickPlot((range(a.size), a), ([bounds[0], bounds[0]], [a.min(), a.max()], 'r-'),
f35c772fed27 Uploaded
rv43
parents:
diff changeset
451 ([bounds[1], bounds[1]], [a.min(), a.max()], 'r-'), title=title)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
452 if pyip.inputYesNo('Accept these bounds ([y]/n)?: ', blank=True) == 'no':
f35c772fed27 Uploaded
rv43
parents:
diff changeset
453 bounds = selectArrayBounds(a, title=title)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
454 return bounds
f35c772fed27 Uploaded
rv43
parents:
diff changeset
455
f35c772fed27 Uploaded
rv43
parents:
diff changeset
456 def selectImageBounds(a, axis, low=None, upp=None, num_min=None,
f35c772fed27 Uploaded
rv43
parents:
diff changeset
457 title='select array bounds'):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
458 """Interactively select the lower and upper data bounds for a 2D numpy array.
f35c772fed27 Uploaded
rv43
parents:
diff changeset
459 """
f35c772fed27 Uploaded
rv43
parents:
diff changeset
460 if not isinstance(a, np.ndarray) or a.ndim != 2:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
461 logging.error('Illegal array type or dimension in selectImageBounds')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
462 return None
f35c772fed27 Uploaded
rv43
parents:
diff changeset
463 if axis < 0 or axis >= a.ndim:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
464 illegal_value('axis', axis, 'selectImageBounds')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
465 return None
f35c772fed27 Uploaded
rv43
parents:
diff changeset
466 if num_min == None:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
467 num_min = 1
f35c772fed27 Uploaded
rv43
parents:
diff changeset
468 else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
469 if num_min < 2 or num_min > a.shape[axis]:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
470 logging.warning('Illegal input for num_min in selectImageBounds, input ignored')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
471 num_min = 1
f35c772fed27 Uploaded
rv43
parents:
diff changeset
472 if low == None:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
473 min_ = 0
f35c772fed27 Uploaded
rv43
parents:
diff changeset
474 max_ = a.shape[axis]
f35c772fed27 Uploaded
rv43
parents:
diff changeset
475 low_max = a.shape[axis]-num_min
f35c772fed27 Uploaded
rv43
parents:
diff changeset
476 while True:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
477 if axis:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
478 quickImshow(a[:,min_:max_], title=title, aspect='auto',
f35c772fed27 Uploaded
rv43
parents:
diff changeset
479 extent=[min_,max_,a.shape[0],0])
f35c772fed27 Uploaded
rv43
parents:
diff changeset
480 else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
481 quickImshow(a[min_:max_,:], title=title, aspect='auto',
f35c772fed27 Uploaded
rv43
parents:
diff changeset
482 extent=[0,a.shape[1], max_,min_])
f35c772fed27 Uploaded
rv43
parents:
diff changeset
483 zoom_flag = pyip.inputInt('Set lower data bound (0) or zoom in (1)?: ',
f35c772fed27 Uploaded
rv43
parents:
diff changeset
484 min=0, max=1)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
485 if zoom_flag:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
486 min_ = pyip.inputInt(f' Set lower zoom index [0, {low_max}]: ',
f35c772fed27 Uploaded
rv43
parents:
diff changeset
487 min=0, max=low_max)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
488 max_ = pyip.inputInt(f' Set upper zoom index [{min_+1}, {low_max+1}]: ',
f35c772fed27 Uploaded
rv43
parents:
diff changeset
489 min=min_+1, max=low_max+1)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
490 else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
491 low = pyip.inputInt(f' Set lower data bound [0, {low_max}]: ',
f35c772fed27 Uploaded
rv43
parents:
diff changeset
492 min=0, max=low_max)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
493 break
f35c772fed27 Uploaded
rv43
parents:
diff changeset
494 else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
495 if not is_int(low, 0, a.shape[axis]-num_min):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
496 illegal_value('low', low, 'selectImageBounds')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
497 return None
f35c772fed27 Uploaded
rv43
parents:
diff changeset
498 if upp == None:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
499 min_ = low+num_min
f35c772fed27 Uploaded
rv43
parents:
diff changeset
500 max_ = a.shape[axis]
f35c772fed27 Uploaded
rv43
parents:
diff changeset
501 upp_min = min_
f35c772fed27 Uploaded
rv43
parents:
diff changeset
502 while True:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
503 if axis:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
504 quickImshow(a[:,min_:max_], title=title, aspect='auto',
f35c772fed27 Uploaded
rv43
parents:
diff changeset
505 extent=[min_,max_,a.shape[0],0])
f35c772fed27 Uploaded
rv43
parents:
diff changeset
506 else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
507 quickImshow(a[min_:max_,:], title=title, aspect='auto',
f35c772fed27 Uploaded
rv43
parents:
diff changeset
508 extent=[0,a.shape[1], max_,min_])
f35c772fed27 Uploaded
rv43
parents:
diff changeset
509 zoom_flag = pyip.inputInt('Set upper data bound (0) or zoom in (1)?: ',
f35c772fed27 Uploaded
rv43
parents:
diff changeset
510 min=0, max=1)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
511 if zoom_flag:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
512 min_ = pyip.inputInt(f' Set upper zoom index [{upp_min}, {a.shape[axis]-1}]: ',
f35c772fed27 Uploaded
rv43
parents:
diff changeset
513 min=upp_min, max=a.shape[axis]-1)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
514 max_ = pyip.inputInt(f' Set upper zoom index [{min_+1}, {a.shape[axis]}]: ',
f35c772fed27 Uploaded
rv43
parents:
diff changeset
515 min=min_+1, max=a.shape[axis])
f35c772fed27 Uploaded
rv43
parents:
diff changeset
516 else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
517 upp = pyip.inputInt(f' Set upper data bound [{upp_min}, {a.shape[axis]}]: ',
f35c772fed27 Uploaded
rv43
parents:
diff changeset
518 min=upp_min, max=a.shape[axis])
f35c772fed27 Uploaded
rv43
parents:
diff changeset
519 break
f35c772fed27 Uploaded
rv43
parents:
diff changeset
520 else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
521 if not is_int(upp, low+num_min, a.shape[axis]):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
522 illegal_value('upp', upp, 'selectImageBounds')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
523 return None
f35c772fed27 Uploaded
rv43
parents:
diff changeset
524 print(f'lower bound = {low} (inclusive)\nupper bound = {upp} (exclusive)')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
525 bounds = [low, upp]
f35c772fed27 Uploaded
rv43
parents:
diff changeset
526 a_tmp = a
f35c772fed27 Uploaded
rv43
parents:
diff changeset
527 if axis:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
528 a_tmp[:,bounds[0]] = a.max()
f35c772fed27 Uploaded
rv43
parents:
diff changeset
529 a_tmp[:,bounds[1]] = a.max()
f35c772fed27 Uploaded
rv43
parents:
diff changeset
530 else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
531 a_tmp[bounds[0],:] = a.max()
f35c772fed27 Uploaded
rv43
parents:
diff changeset
532 a_tmp[bounds[1],:] = a.max()
f35c772fed27 Uploaded
rv43
parents:
diff changeset
533 quickImshow(a_tmp, title=title)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
534 if pyip.inputYesNo('Accept these bounds ([y]/n)?: ', blank=True) == 'no':
f35c772fed27 Uploaded
rv43
parents:
diff changeset
535 bounds = selectImageBounds(a, title=title)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
536 return bounds
f35c772fed27 Uploaded
rv43
parents:
diff changeset
537
f35c772fed27 Uploaded
rv43
parents:
diff changeset
538 def fitStep(x=None, y=None, model='step', form='arctan'):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
539 if not isinstance(y, np.ndarray) or y.ndim != 1:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
540 logging.error('Illegal array type or dimension for y in fitStep')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
541 return
f35c772fed27 Uploaded
rv43
parents:
diff changeset
542 if isinstance(x, type(None)):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
543 x = np.array(range(y.size))
f35c772fed27 Uploaded
rv43
parents:
diff changeset
544 elif not isinstance(x, np.ndarray) or x.ndim != 1 or x.size != y.size:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
545 logging.error('Illegal array type or dimension for x in fitStep')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
546 return
f35c772fed27 Uploaded
rv43
parents:
diff changeset
547 if not isinstance(model, str) or not model in ('step', 'rectangle'):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
548 illegal_value('model', model, 'fitStepModel')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
549 return
f35c772fed27 Uploaded
rv43
parents:
diff changeset
550 if not isinstance(form, str) or not form in ('linear', 'atan', 'arctan', 'erf', 'logistic'):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
551 illegal_value('form', form, 'fitStepModel')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
552 return
f35c772fed27 Uploaded
rv43
parents:
diff changeset
553
f35c772fed27 Uploaded
rv43
parents:
diff changeset
554 if model == 'step':
f35c772fed27 Uploaded
rv43
parents:
diff changeset
555 mod = StepModel(form=form)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
556 else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
557 mod = RectangleModel(form=form)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
558 pars = mod.guess(y, x=x)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
559 out = mod.fit(y, pars, x=x)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
560 #print(out.fit_report())
f35c772fed27 Uploaded
rv43
parents:
diff changeset
561 #quickPlot((x,y),(x,out.best_fit))
f35c772fed27 Uploaded
rv43
parents:
diff changeset
562 return out.best_values
f35c772fed27 Uploaded
rv43
parents:
diff changeset
563
f35c772fed27 Uploaded
rv43
parents:
diff changeset
564 class Config:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
565 """Base class for processing a config file or dictionary.
f35c772fed27 Uploaded
rv43
parents:
diff changeset
566 """
f35c772fed27 Uploaded
rv43
parents:
diff changeset
567 def __init__(self, config_file=None, config_dict=None):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
568 self.config = {}
f35c772fed27 Uploaded
rv43
parents:
diff changeset
569 self.load_flag = False
f35c772fed27 Uploaded
rv43
parents:
diff changeset
570 self.suffix = None
f35c772fed27 Uploaded
rv43
parents:
diff changeset
571
f35c772fed27 Uploaded
rv43
parents:
diff changeset
572 # Load config file
f35c772fed27 Uploaded
rv43
parents:
diff changeset
573 if config_file is not None and config_dict is not None:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
574 logging.warning('Ignoring config_dict (both config_file and config_dict are specified)')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
575 if config_file is not None:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
576 self.loadFile(config_file)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
577 elif config_dict is not None:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
578 self.loadDict(config_dict)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
579
f35c772fed27 Uploaded
rv43
parents:
diff changeset
580 def loadFile(self, config_file):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
581 """Load a config file.
f35c772fed27 Uploaded
rv43
parents:
diff changeset
582 """
f35c772fed27 Uploaded
rv43
parents:
diff changeset
583 if self.load_flag:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
584 logging.warning('Overwriting any previously loaded config file')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
585 self.config = {}
f35c772fed27 Uploaded
rv43
parents:
diff changeset
586
f35c772fed27 Uploaded
rv43
parents:
diff changeset
587 # Ensure config file exists
f35c772fed27 Uploaded
rv43
parents:
diff changeset
588 if not os.path.isfile(config_file):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
589 logging.error(f'Unable to load {config_file}')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
590 return
f35c772fed27 Uploaded
rv43
parents:
diff changeset
591
f35c772fed27 Uploaded
rv43
parents:
diff changeset
592 # Load config file
f35c772fed27 Uploaded
rv43
parents:
diff changeset
593 self.suffix = os.path.splitext(config_file)[1]
f35c772fed27 Uploaded
rv43
parents:
diff changeset
594 if self.suffix == '.yml' or self.suffix == '.yaml':
f35c772fed27 Uploaded
rv43
parents:
diff changeset
595 with open(config_file, 'r') as f:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
596 self.config = yaml.safe_load(f)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
597 elif self.suffix == '.txt':
f35c772fed27 Uploaded
rv43
parents:
diff changeset
598 with open(config_file, 'r') as f:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
599 lines = f.read().splitlines()
f35c772fed27 Uploaded
rv43
parents:
diff changeset
600 self.config = {item[0].strip():literal_eval(item[1].strip()) for item in
f35c772fed27 Uploaded
rv43
parents:
diff changeset
601 [line.split('#')[0].split('=') for line in lines if '=' in line.split('#')[0]]}
f35c772fed27 Uploaded
rv43
parents:
diff changeset
602 else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
603 logging.error(f'Illegal config file extension: {self.suffix}')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
604
f35c772fed27 Uploaded
rv43
parents:
diff changeset
605 # Make sure config file was correctly loaded
f35c772fed27 Uploaded
rv43
parents:
diff changeset
606 if isinstance(self.config, dict):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
607 self.load_flag = True
f35c772fed27 Uploaded
rv43
parents:
diff changeset
608 else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
609 logging.error(f'Unable to load dictionary from config file: {config_file}')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
610 self.config = {}
f35c772fed27 Uploaded
rv43
parents:
diff changeset
611
f35c772fed27 Uploaded
rv43
parents:
diff changeset
612 def loadDict(self, config_dict):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
613 """Takes a dictionary and places it into self.config.
f35c772fed27 Uploaded
rv43
parents:
diff changeset
614 """
f35c772fed27 Uploaded
rv43
parents:
diff changeset
615 exit('loadDict not tested yet, what format do we follow: txt or yaml?')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
616 if self.load_flag:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
617 logging.warning('Overwriting the previously loaded config file')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
618
f35c772fed27 Uploaded
rv43
parents:
diff changeset
619 if isinstance(config_dict, dict):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
620 self.config = config_dict
f35c772fed27 Uploaded
rv43
parents:
diff changeset
621 self.load_flag = True
f35c772fed27 Uploaded
rv43
parents:
diff changeset
622 else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
623 logging.error(f'Illegal dictionary config object: {config_dict}')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
624 self.config = {}
f35c772fed27 Uploaded
rv43
parents:
diff changeset
625
f35c772fed27 Uploaded
rv43
parents:
diff changeset
626 def saveFile(self, config_file):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
627 """Save the config file (as a yaml file only right now).
f35c772fed27 Uploaded
rv43
parents:
diff changeset
628 """
f35c772fed27 Uploaded
rv43
parents:
diff changeset
629 suffix = os.path.splitext(config_file)[1]
f35c772fed27 Uploaded
rv43
parents:
diff changeset
630 if suffix != '.yml' and suffix != '.yaml':
f35c772fed27 Uploaded
rv43
parents:
diff changeset
631 logging.error(f'Illegal config file extension: {suffix}')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
632
f35c772fed27 Uploaded
rv43
parents:
diff changeset
633 # Check if config file exists
f35c772fed27 Uploaded
rv43
parents:
diff changeset
634 if os.path.isfile(config_file):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
635 logging.info(f'Updating {config_file}')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
636 else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
637 logging.info(f'Saving {config_file}')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
638
f35c772fed27 Uploaded
rv43
parents:
diff changeset
639 # Save config file
f35c772fed27 Uploaded
rv43
parents:
diff changeset
640 with open(config_file, 'w') as f:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
641 yaml.dump(self.config, f)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
642
f35c772fed27 Uploaded
rv43
parents:
diff changeset
643 def validate(self, pars_required, pars_missing=None):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
644 """Returns False if any required first level keys are missing.
f35c772fed27 Uploaded
rv43
parents:
diff changeset
645 """
f35c772fed27 Uploaded
rv43
parents:
diff changeset
646 if not self.load_flag:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
647 logging.error('Load a config file prior to calling Config.validate')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
648 pars = [p for p in pars_required if p not in self.config]
f35c772fed27 Uploaded
rv43
parents:
diff changeset
649 if isinstance(pars_missing, list):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
650 pars_missing.extend(pars)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
651 elif pars_missing is not None:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
652 illegal_value('pars_missing', pars_missing, 'Config.validate')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
653 if len(pars) > 0:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
654 return False
f35c772fed27 Uploaded
rv43
parents:
diff changeset
655 return True
f35c772fed27 Uploaded
rv43
parents:
diff changeset
656
f35c772fed27 Uploaded
rv43
parents:
diff changeset
657 #RV FIX this is for a txt file, obsolete?
f35c772fed27 Uploaded
rv43
parents:
diff changeset
658 # def update_txt(self, config_file, key, value, search_string=None, header=None):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
659 # if not self.load_flag:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
660 # logging.error('Load a config file prior to calling Config.update')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
661 #
f35c772fed27 Uploaded
rv43
parents:
diff changeset
662 # if not os.path.isfile(config_file):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
663 # logging.error(f'Unable to load {config_file}')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
664 # lines = []
f35c772fed27 Uploaded
rv43
parents:
diff changeset
665 # else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
666 # with open(config_file, 'r') as f:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
667 # lines = f.read().splitlines()
f35c772fed27 Uploaded
rv43
parents:
diff changeset
668 # config = {item[0].strip():literal_eval(item[1].strip()) for item in
f35c772fed27 Uploaded
rv43
parents:
diff changeset
669 # [line.split('#')[0].split('=') for line in lines if '=' in line.split('#')[0]]}
f35c772fed27 Uploaded
rv43
parents:
diff changeset
670 # if not isinstance(key, str):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
671 # illegal_value('key', key, 'Config.update')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
672 # return config
f35c772fed27 Uploaded
rv43
parents:
diff changeset
673 # if isinstance(value, str):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
674 # newline = f"{key} = '{value}'"
f35c772fed27 Uploaded
rv43
parents:
diff changeset
675 # else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
676 # newline = f'{key} = {value}'
f35c772fed27 Uploaded
rv43
parents:
diff changeset
677 # if key in config.keys():
f35c772fed27 Uploaded
rv43
parents:
diff changeset
678 # # Update key with value
f35c772fed27 Uploaded
rv43
parents:
diff changeset
679 # for index,line in enumerate(lines):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
680 # if '=' in line:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
681 # item = line.split('#')[0].split('=')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
682 # if item[0].strip() == key:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
683 # lines[index] = newline
f35c772fed27 Uploaded
rv43
parents:
diff changeset
684 # break
f35c772fed27 Uploaded
rv43
parents:
diff changeset
685 # else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
686 # # Insert new key/value pair
f35c772fed27 Uploaded
rv43
parents:
diff changeset
687 # if search_string != None:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
688 # if isinstance(search_string, str):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
689 # search_string = [search_string]
f35c772fed27 Uploaded
rv43
parents:
diff changeset
690 # elif not isinstance(search_string, (tuple, list)):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
691 # illegal_value('search_string', search_string, 'Config.update')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
692 # search_string = None
f35c772fed27 Uploaded
rv43
parents:
diff changeset
693 # update_flag = False
f35c772fed27 Uploaded
rv43
parents:
diff changeset
694 # if search_string != None:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
695 # indices = [[index for index,line in enumerate(lines) if item in line]
f35c772fed27 Uploaded
rv43
parents:
diff changeset
696 # for item in search_string]
f35c772fed27 Uploaded
rv43
parents:
diff changeset
697 # for i,index in enumerate(indices):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
698 # if index:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
699 # if len(search_string) > 1 and key < search_string[i]:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
700 # lines.insert(index[0], newline)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
701 # else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
702 # lines.insert(index[0]+1, newline)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
703 # update_flag = True
f35c772fed27 Uploaded
rv43
parents:
diff changeset
704 # break
f35c772fed27 Uploaded
rv43
parents:
diff changeset
705 # if not update_flag:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
706 # if isinstance(header, str):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
707 # lines += ['', header, newline]
f35c772fed27 Uploaded
rv43
parents:
diff changeset
708 # else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
709 # lines += ['', newline]
f35c772fed27 Uploaded
rv43
parents:
diff changeset
710 # # Write updated config file
f35c772fed27 Uploaded
rv43
parents:
diff changeset
711 # with open(config_file, 'w') as f:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
712 # for line in lines:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
713 # f.write(f'{line}\n')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
714 # # Update loaded config
f35c772fed27 Uploaded
rv43
parents:
diff changeset
715 # config['key'] = value
f35c772fed27 Uploaded
rv43
parents:
diff changeset
716 #
f35c772fed27 Uploaded
rv43
parents:
diff changeset
717 #RV update and bring into Config if needed again
f35c772fed27 Uploaded
rv43
parents:
diff changeset
718 #def search(config_file, search_string):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
719 # if not os.path.isfile(config_file):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
720 # logging.error(f'Unable to load {config_file}')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
721 # return False
f35c772fed27 Uploaded
rv43
parents:
diff changeset
722 # with open(config_file, 'r') as f:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
723 # lines = f.read()
f35c772fed27 Uploaded
rv43
parents:
diff changeset
724 # if search_string in lines:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
725 # return True
f35c772fed27 Uploaded
rv43
parents:
diff changeset
726 # return False
f35c772fed27 Uploaded
rv43
parents:
diff changeset
727
f35c772fed27 Uploaded
rv43
parents:
diff changeset
728 class Detector:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
729 """Class for processing a detector info file or dictionary.
f35c772fed27 Uploaded
rv43
parents:
diff changeset
730 """
f35c772fed27 Uploaded
rv43
parents:
diff changeset
731 def __init__(self, detector_id):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
732 self.detector = {}
f35c772fed27 Uploaded
rv43
parents:
diff changeset
733 self.load_flag = False
f35c772fed27 Uploaded
rv43
parents:
diff changeset
734 self.validate_flag = False
f35c772fed27 Uploaded
rv43
parents:
diff changeset
735
f35c772fed27 Uploaded
rv43
parents:
diff changeset
736 # Load detector file
f35c772fed27 Uploaded
rv43
parents:
diff changeset
737 self.loadFile(detector_id)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
738
f35c772fed27 Uploaded
rv43
parents:
diff changeset
739 def loadFile(self, detector_id):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
740 """Load a detector file.
f35c772fed27 Uploaded
rv43
parents:
diff changeset
741 """
f35c772fed27 Uploaded
rv43
parents:
diff changeset
742 if self.load_flag:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
743 logging.warning('Overwriting the previously loaded detector file')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
744 self.detector = {}
f35c772fed27 Uploaded
rv43
parents:
diff changeset
745
f35c772fed27 Uploaded
rv43
parents:
diff changeset
746 # Ensure detector file exists
f35c772fed27 Uploaded
rv43
parents:
diff changeset
747 if not isinstance(detector_id, str):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
748 illegal_value('detector_id', detector_id, 'Detector.loadFile')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
749 return
f35c772fed27 Uploaded
rv43
parents:
diff changeset
750 detector_file = f'{detector_id}.yaml'
f35c772fed27 Uploaded
rv43
parents:
diff changeset
751 if not os.path.isfile(detector_file):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
752 detector_file = self.config['detector_id']+'.yaml'
f35c772fed27 Uploaded
rv43
parents:
diff changeset
753 if not os.path.isfile(detector_file):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
754 logging.error(f'Unable to load detector info file for {detector_id}')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
755 return
f35c772fed27 Uploaded
rv43
parents:
diff changeset
756
f35c772fed27 Uploaded
rv43
parents:
diff changeset
757 # Load detector file
f35c772fed27 Uploaded
rv43
parents:
diff changeset
758 with open(detector_file, 'r') as f:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
759 self.detector = yaml.safe_load(f)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
760
f35c772fed27 Uploaded
rv43
parents:
diff changeset
761 # Make sure detector file was correctly loaded
f35c772fed27 Uploaded
rv43
parents:
diff changeset
762 if isinstance(self.detector, dict):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
763 self.load_flag = True
f35c772fed27 Uploaded
rv43
parents:
diff changeset
764 else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
765 logging.error(f'Unable to load dictionary from detector file: {detector_file}')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
766 self.detector = {}
f35c772fed27 Uploaded
rv43
parents:
diff changeset
767
f35c772fed27 Uploaded
rv43
parents:
diff changeset
768 def validate(self):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
769 """Returns False if any config parameters is illegal or missing.
f35c772fed27 Uploaded
rv43
parents:
diff changeset
770 """
f35c772fed27 Uploaded
rv43
parents:
diff changeset
771 if not self.load_flag:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
772 logging.error('Load a detector file prior to calling Detector.validate')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
773
f35c772fed27 Uploaded
rv43
parents:
diff changeset
774 # Check for required first-level keys
f35c772fed27 Uploaded
rv43
parents:
diff changeset
775 pars_required = ['detector', 'lens_magnification']
f35c772fed27 Uploaded
rv43
parents:
diff changeset
776 pars_missing = [p for p in pars_required if p not in self.detector]
f35c772fed27 Uploaded
rv43
parents:
diff changeset
777 if len(pars_missing) > 0:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
778 logging.error(f'Missing item(s) in detector file: {", ".join(pars_missing)}')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
779 return False
f35c772fed27 Uploaded
rv43
parents:
diff changeset
780
f35c772fed27 Uploaded
rv43
parents:
diff changeset
781 is_valid = True
f35c772fed27 Uploaded
rv43
parents:
diff changeset
782
f35c772fed27 Uploaded
rv43
parents:
diff changeset
783 # Check detector pixel config keys
f35c772fed27 Uploaded
rv43
parents:
diff changeset
784 pixels = self.detector['detector'].get('pixels')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
785 if not pixels:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
786 pars_missing.append('detector:pixels')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
787 else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
788 rows = pixels.get('rows')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
789 if not rows:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
790 pars_missing.append('detector:pixels:rows')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
791 columns = pixels.get('columns')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
792 if not columns:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
793 pars_missing.append('detector:pixels:columns')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
794 size = pixels.get('size')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
795 if not size:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
796 pars_missing.append('detector:pixels:size')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
797
f35c772fed27 Uploaded
rv43
parents:
diff changeset
798 if not len(pars_missing):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
799 self.validate_flag = True
f35c772fed27 Uploaded
rv43
parents:
diff changeset
800 else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
801 is_valid = False
f35c772fed27 Uploaded
rv43
parents:
diff changeset
802
f35c772fed27 Uploaded
rv43
parents:
diff changeset
803 return is_valid
f35c772fed27 Uploaded
rv43
parents:
diff changeset
804
f35c772fed27 Uploaded
rv43
parents:
diff changeset
805 def getPixelSize(self):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
806 """Returns the detector pixel size.
f35c772fed27 Uploaded
rv43
parents:
diff changeset
807 """
f35c772fed27 Uploaded
rv43
parents:
diff changeset
808 if not self.validate_flag:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
809 logging.error('Validate detector file info prior to calling Detector.getPixelSize')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
810
f35c772fed27 Uploaded
rv43
parents:
diff changeset
811 lens_magnification = self.detector.get('lens_magnification')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
812 if not isinstance(lens_magnification, (int,float)) or lens_magnification <= 0.:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
813 illegal_value('lens_magnification', lens_magnification, 'detector file')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
814 return 0
f35c772fed27 Uploaded
rv43
parents:
diff changeset
815 pixel_size = self.detector['detector'].get('pixels').get('size')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
816 if isinstance(pixel_size, (int,float)):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
817 if pixel_size <= 0.:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
818 illegal_value('pixel_size', pixel_size, 'detector file')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
819 return 0
f35c772fed27 Uploaded
rv43
parents:
diff changeset
820 pixel_size /= lens_magnification
f35c772fed27 Uploaded
rv43
parents:
diff changeset
821 elif isinstance(pixel_size, list):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
822 if ((len(pixel_size) > 2) or
f35c772fed27 Uploaded
rv43
parents:
diff changeset
823 (len(pixel_size) == 2 and pixel_size[0] != pixel_size[1])):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
824 illegal_value('pixel size', pixel_size, 'detector file')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
825 return 0
f35c772fed27 Uploaded
rv43
parents:
diff changeset
826 elif not is_num(pixel_size[0], 0.):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
827 illegal_value('pixel size', pixel_size, 'detector file')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
828 return 0
f35c772fed27 Uploaded
rv43
parents:
diff changeset
829 else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
830 pixel_size = pixel_size[0]/lens_magnification
f35c772fed27 Uploaded
rv43
parents:
diff changeset
831 else:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
832 illegal_value('pixel size', pixel_size, 'detector file')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
833 return 0
f35c772fed27 Uploaded
rv43
parents:
diff changeset
834
f35c772fed27 Uploaded
rv43
parents:
diff changeset
835 return pixel_size
f35c772fed27 Uploaded
rv43
parents:
diff changeset
836
f35c772fed27 Uploaded
rv43
parents:
diff changeset
837 def getDimensions(self):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
838 """Returns the detector pixel dimensions.
f35c772fed27 Uploaded
rv43
parents:
diff changeset
839 """
f35c772fed27 Uploaded
rv43
parents:
diff changeset
840 if not self.validate_flag:
f35c772fed27 Uploaded
rv43
parents:
diff changeset
841 logging.error('Validate detector file info prior to calling Detector.getDimensions')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
842
f35c772fed27 Uploaded
rv43
parents:
diff changeset
843 pixels = self.detector['detector'].get('pixels')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
844 num_rows = pixels.get('rows')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
845 if not is_int(num_rows, 1):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
846 illegal_value('rows', num_rows, 'detector file')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
847 return (0, 0)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
848 num_columns = pixels.get('columns')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
849 if not is_int(num_columns, 1):
f35c772fed27 Uploaded
rv43
parents:
diff changeset
850 illegal_value('columns', num_columns, 'detector file')
f35c772fed27 Uploaded
rv43
parents:
diff changeset
851 return (0, 0)
f35c772fed27 Uploaded
rv43
parents:
diff changeset
852
f35c772fed27 Uploaded
rv43
parents:
diff changeset
853 return num_rows, num_columns