# HG changeset patch
# User rv43
# Date 1660833406 0
# Node ID 98a83f03d91be76a9c132be28b4276a4d3a82b1d
# Parent e544e5d110eb228468de9078c1b14d05dc38bc31
"planemo upload for repository https://github.com/rolfverberg/galaxytools commit a9ebbfca439737ae17ddcb0df84408155f964877"
diff -r e544e5d110eb -r 98a83f03d91b detector.py
--- a/detector.py Wed Aug 17 15:10:13 2022 +0000
+++ b/detector.py Thu Aug 18 14:36:46 2022 +0000
@@ -4,16 +4,16 @@
from functools import cache
from copy import deepcopy
-#from .general import *
-from general import illegal_value, is_int, is_num, input_yesno
+from .general import *
#from hexrd.instrument import HEDMInstrument, PlanarDetector
class DetectorConfig:
def __init__(self, config_source):
+
self._config_source = config_source
- if isinstance(self._config_source, str):
+ if isinstance(self._config_source, ((str, bytes, os.PathLike, int))):
self._config_file = self._config_source
self._config = self._load_config_file()
elif isinstance(self._config_source, dict):
@@ -26,8 +26,7 @@
self._valid = self._validate()
if not self.valid:
- logging.error(f'Cannot create a valid instance of {self.__class__.__name__} '+
- f'from {self._config_source}')
+ logging.error(f'Cannot create a valid instance of {self.__class__.__name__} from {self._config_source}')
def __repr__(self):
return(f'{self.__class__.__name__}({self._config_source.__repr__()})')
@@ -37,41 +36,38 @@
@property
def config_file(self):
return(self._config_file)
-
@property
def config(self):
return(deepcopy(self._config))
-
@property
def valid(self):
return(self._valid)
def load_config_file(self):
raise(NotImplementedError)
-
def validate(self):
raise(NotImplementedError)
def _load_config_file(self):
- return(self.load_config_file())
-
+ if not os.path.isfile(self.config_file):
+ logging.error(f'{self.config_file} is not a file.')
+ return(False)
+ else:
+ return(self.load_config_file())
def _validate(self):
if not self.config:
logging.error('A configuration must be loaded prior to calling Detector._validate')
return(False)
else:
return(self.validate())
-
def _write_to_file(self, out_file):
out_file = os.path.abspath(out_file)
current_config_valid = self.validate()
if not current_config_valid:
- write_invalid_config = input_yesno(s=f'This {self.__class__.__name__} is currently '+
- f'invalid. Write the configuration to {out_file} anyways?', default='no')
+ write_invalid_config = input_yesno(s=f'This {self.__class__.__name__} is not currently valid. Write the configuration to {out_file} anyways?', default='no')
if not write_invalid_config:
- logging.info('In accordance with user input, the invalid configuration will '+
- f'not be written to {out_file}')
+ logging.info(f'In accordance with user input, the invalid configuration will not be written to {out_file}')
return
if os.access(out_file, os.W_OK):
@@ -80,8 +76,7 @@
if overwrite:
self.write_to_file(out_file)
else:
- logging.info(f'In accordance with user input, {out_file} will not be '+
- 'overwritten')
+ logging.info(f'In accordance with user input, {out_file} will not be overwritten')
else:
self.write_to_file(out_file)
else:
@@ -96,29 +91,21 @@
super().__init__(config_source)
def load_config_file(self):
- if not os.path.splitext(self._config_file)[1]:
- if os.path.isfile(f'{self._config_file}.yml'):
- self._config_file = f'{self._config_file}.yml'
- if os.path.isfile(f'{self._config_file}.yaml'):
- self._config_file = f'{self._config_file}.yaml'
- if not os.path.isfile(self._config_file):
- logging.error(f'Unable to load {self._config_file}')
- return(False)
- with open(self._config_file, 'r') as infile:
+ with open(self.config_file, 'r') as infile:
config = yaml.safe_load(infile)
if isinstance(config, dict):
return(config)
else:
- logging.error(f'Unable to load {self._config_file} as a dictionary')
+ logging.error(f'Unable to load {self.config_file} as a dictionary')
return(False)
def validate(self):
if not self._validate_yaml_pars:
- logging.warning('There are no required parameters provided for this detector '+
- 'configuration')
+ logging.warning('There are no required parameters provided for this detector configuration.')
return(True)
def validate_nested_pars(config, validate_yaml_par):
+
yaml_par_levels = validate_yaml_par.split(':')
first_level_par = yaml_par_levels[0]
try:
@@ -135,8 +122,7 @@
except:
return(False)
- pars_missing = [p for p in self._validate_yaml_pars
- if not validate_nested_pars(self.config, p)]
+ pars_missing = [p for p in self._validate_yaml_pars if not validate_nested_pars(self.config, p)]
if len(pars_missing) > 0:
logging.error(f'Missing item(s) in configuration: {", ".join(pars_missing)}')
return(False)
@@ -163,7 +149,7 @@
lens_magnification = self.config.get('lens_magnification')
if not isinstance(lens_magnification, (int, float)) or lens_magnification <= 0.:
illegal_value(lens_magnification, 'lens_magnification', 'detector file')
- logging.warning('Using default lens_magnification value of 1.0')
+ logging.warning('Using default lens_magnification value of 1.0.')
return(1.0)
else:
return(lens_magnification)
@@ -205,6 +191,7 @@
if not is_int(num_columns, 1):
illegal_value(num_columns, 'columns', 'detector file')
return(None)
+
return(num_rows, num_columns)
@@ -244,8 +231,7 @@
@property
def bin_energies(self):
- return(self.slope * np.linspace(0, self.max_E, self.num_bins, endpoint=False) +
- self.intercept)
+ return(self.slope * np.linspace(0, self.max_E, self.num_bins, endpoint=False) + self.intercept)
@property
def tth_angle(self):
diff -r e544e5d110eb -r 98a83f03d91b fit.py
--- a/fit.py Wed Aug 17 15:10:13 2022 +0000
+++ b/fit.py Thu Aug 18 14:36:46 2022 +0000
@@ -8,7 +8,6 @@
"""
import sys
-import re
import logging
import numpy as np
@@ -19,8 +18,8 @@
from lmfit.models import ConstantModel, LinearModel, QuadraticModel, PolynomialModel,\
StepModel, RectangleModel, GaussianModel, LorentzianModel
-#from .general import *
-from general import is_index, index_nearest, quickPlot
+from .general import *
+#from general import *
# sigma = fwhm_factor*fwhm
fwhm_factor = {
diff -r e544e5d110eb -r 98a83f03d91b general.py
--- a/general.py Wed Aug 17 15:10:13 2022 +0000
+++ b/general.py Thu Aug 18 14:36:46 2022 +0000
@@ -23,6 +23,10 @@
from matplotlib.widgets import Button
except:
pass
+try:
+ import pyinputplus as pyip
+except:
+ pass
from ast import literal_eval
from copy import deepcopy
@@ -288,7 +292,7 @@
else:
return int(mo.group())
-def input_int(s=None, v_min=None, v_max=None, default=None, inset=None):
+def input_int(s=None, v_min=None, v_max=None, default=None):
if default is not None:
if not isinstance(default, int):
illegal_value(default, 'default', 'input_int')
@@ -298,14 +302,14 @@
default_string = ''
if v_min is not None:
if not isinstance(v_min, int):
- illegal_value(v_min, 'v_min', 'input_int')
+ illegal_value(vmin, 'vmin', 'input_int')
return None
if default is not None and default < v_min:
logging.error('Illegal v_min, default combination ({v_min}, {default})')
return None
if v_max is not None:
if not isinstance(v_max, int):
- illegal_value(v_max, 'v_max', 'input_int')
+ illegal_value(vmax, 'vmax', 'input_int')
return None
if v_min is not None and v_min > v_max:
logging.error(f'Illegal v_min, v_max combination ({v_min}, {v_max})')
@@ -313,13 +317,8 @@
if default is not None and default > v_max:
logging.error('Illegal default, v_max combination ({default}, {v_max})')
return None
- if inset is not None:
- if (not isinstance(inset, (tuple, list)) or False in [True if isinstance(i, int) else
- False for i in inset]):
- illegal_value(inset, 'inset', 'input_int')
- return None
if v_min is not None and v_max is not None:
- v_range = f' ({v_min}, {v_max})'
+ v_range = f' (in range [{v_min}, {v_max}])'
elif v_min is not None:
v_range = f' (>= {v_min})'
elif v_max is not None:
@@ -334,11 +333,8 @@
i = input()
if isinstance(i, str) and not len(i):
v = default
- print(f'{v}')
else:
v = literal_eval(i)
- if inset and v not in inset:
- raise ValueError(f'{v} not part of the set {inset}')
except (ValueError, TypeError, SyntaxError, MemoryError, RecursionError):
v = None
except:
@@ -375,7 +371,7 @@
logging.error('Illegal default, v_max combination ({default}, {v_max})')
return None
if v_min is not None and v_max is not None:
- v_range = f' ({v_min}, {v_max})'
+ v_range = f' (in range [{v_min}, {v_max}])'
elif v_min is not None:
v_range = f' (>= {v_min})'
elif v_max is not None:
@@ -390,7 +386,6 @@
i = input()
if isinstance(i, str) and not len(i):
v = default
- print(f'{v}')
else:
v = literal_eval(i)
except (ValueError, TypeError, SyntaxError, MemoryError, RecursionError):
@@ -415,7 +410,7 @@
logging.error(f'Illegal v_min, v_max combination ({v_min}, {v_max})')
return None
if v_min is not None and v_max is not None:
- v_range = f' (each value in ({v_min}, {v_max}))'
+ v_range = f' (each value in range [{v_min}, {v_max}])'
elif v_min is not None:
v_range = f' (each value >= {v_min})'
elif v_max is not None:
@@ -462,55 +457,15 @@
i = input()
if isinstance(i, str) and not len(i):
i = default
- print(f'{i}')
- if i is not None and i.lower() in 'yes':
+ if i.lower() in 'yes':
v = True
- elif i is not None and i.lower() in 'no':
+ elif i.lower() in 'no':
v = False
else:
print('Illegal input, enter yes or no')
v = input_yesno(s, default)
return v
-def input_menu(items, default=None, header=None):
- if not isinstance(items, (tuple, list)) or False in [True if isinstance(i, str) else False
- for i in items]:
- illegal_value(items, 'items', 'input_menu')
- return None
- if default is not None:
- if not (isinstance(default, str) and default in items):
- logging.error(f'Illegal value for default ({default}), must be in {items}')
- return None
- default_string = f' [{items.index(default)+1}]'
- else:
- default_string = ''
- if header is None:
- print(f'Choose one of the following items (1, {len(items)}){default_string}:')
- else:
- print(f'{header} (1, {len(items)}){default_string}:')
- for i, choice in enumerate(items):
- print(f' {i+1}: {choice}')
- try:
- choice = input()
- if isinstance(choice, str) and not len(choice):
- choice = items.index(default)
- print(f'{choice+1}')
- else:
- choice = literal_eval(choice)
- if isinstance(choice, int) and 1 <= choice <= len(items):
- choice -= 1
- else:
- raise ValueError
- except (ValueError, TypeError, SyntaxError, MemoryError, RecursionError):
- choice = None
- except:
- print('Unexpected error')
- raise
- if choice is None:
- print(f'Illegal choice, enter a number between 1 and {len(items)}')
- choice = input_menu(items, default)
- return choice
-
def create_mask(x, bounds=None, reverse_mask=False, current_mask=None):
# bounds is a pair of number in the same units a x
if not isinstance(x, (tuple, list, np.ndarray)) or not len(x):
@@ -537,11 +492,10 @@
return mask
def draw_mask_1d(ydata, xdata=None, current_index_ranges=None, current_mask=None,
- select_mask=True, num_index_ranges_max=None, title=None, legend=None, test_mode=False):
+ select_mask=True):
def draw_selections(ax):
ax.clear()
- ax.set_title(title)
- ax.legend([legend])
+ ax.set_title(axes_title)
ax.plot(xdata, ydata, 'k')
for (low, upp) in current_include:
xlow = 0.5*(xdata[max(0, low-1)]+xdata[low])
@@ -609,7 +563,7 @@
ydata = np.asarray(ydata)
if ydata.ndim > 1:
logging.warning(f'Illegal ydata dimension ({ydata.ndim})')
- return None, None
+ return None
num_data = ydata.size
if xdata is None:
xdata = np.arange(num_data)
@@ -617,34 +571,24 @@
xdata = np.asarray(xdata, dtype=np.float64)
if xdata.ndim > 1 or xdata.size != num_data:
logging.warning(f'Illegal xdata shape ({xdata.shape})')
- return None, None
+ return None
if not np.all(xdata[:-1] < xdata[1:]):
logging.warning('Illegal xdata: must be monotonically increasing')
- return None, None
+ return None
if current_index_ranges is not None:
if not isinstance(current_index_ranges, (tuple, list)):
logging.warning('Illegal current_index_ranges parameter ({current_index_ranges}, '+
f'{type(current_index_ranges)})')
- return None, None
+ return None
if not isinstance(select_mask, bool):
logging.warning('Illegal select_mask parameter ({select_mask}, {type(select_mask)})')
- return None, None
- if num_index_ranges_max is not None:
- logging.warning('num_index_ranges_max input not yet implemented in draw_mask_1d')
- if title is None:
- title = 'select ranges of data'
- elif not isinstance(title, str):
- illegal(title, 'title')
- title = ''
- if legend is None and not isinstance(title, str):
- illegal(legend, 'legend')
- legend = None
+ return None
if select_mask:
- title = f'Click and drag to {title} you wish to include'
+ axes_title = 'Click and drag to select ranges of data you wish to include.'
selection_color = 'green'
else:
- title = f'Click and drag to {title} you wish to exclude'
+ axes_title = 'Click and drag to select ranges of data you wish to exclude.'
selection_color = 'red'
# Set initial selected mask and the selected/unselected index ranges as needed
@@ -691,32 +635,29 @@
if current_include[-1][1] < num_data-1:
current_exclude.append((current_include[-1][1]+1, num_data-1))
- if not test_mode:
+ # Set up matplotlib figure
+ fig, ax = plt.subplots()
+ plt.subplots_adjust(bottom=0.2)
+ draw_selections(ax)
- # Set up matplotlib figure
- plt.close('all')
- fig, ax = plt.subplots()
- plt.subplots_adjust(bottom=0.2)
- draw_selections(ax)
-
- # Set up event handling for click-and-drag range selection
- cid_click = fig.canvas.mpl_connect('button_press_event', onclick)
- cid_release = fig.canvas.mpl_connect('button_release_event', onrelease)
+ # Set up event handling for click-and-drag range selection
+ cid_click = fig.canvas.mpl_connect('button_press_event', onclick)
+ cid_release = fig.canvas.mpl_connect('button_release_event', onrelease)
- # Set up confirm / clear range selection buttons
- confirm_b = Button(plt.axes([0.75, 0.05, 0.15, 0.075]), 'Confirm')
- clear_b = Button(plt.axes([0.59, 0.05, 0.15, 0.075]), 'Clear')
- cid_confirm = confirm_b.on_clicked(confirm_selection)
- cid_clear = clear_b.on_clicked(clear_last_selection)
+ # Set up confirm / clear range selection buttons
+ confirm_b = Button(plt.axes([0.75, 0.05, 0.15, 0.075]), 'Confirm')
+ clear_b = Button(plt.axes([0.59, 0.05, 0.15, 0.075]), 'Clear')
+ cid_confirm = confirm_b.on_clicked(confirm_selection)
+ cid_clear = clear_b.on_clicked(clear_last_selection)
- # Show figure
- plt.show(block=True)
+ # Show figure
+ plt.show()
- # Disconnect callbacks when figure is closed
- fig.canvas.mpl_disconnect(cid_click)
- fig.canvas.mpl_disconnect(cid_release)
- confirm_b.disconnect(cid_confirm)
- clear_b.disconnect(cid_clear)
+ # Disconnect callbacks when figure is closed
+ fig.canvas.mpl_disconnect(cid_click)
+ fig.canvas.mpl_disconnect(cid_release)
+ confirm_b.disconnect(cid_confirm)
+ clear_b.disconnect(cid_clear)
# Swap selection depending on select_mask
if not select_mask:
@@ -785,19 +726,21 @@
else:
name = ' '
# Check existing values
- use_input = False
+ use_input = 'no'
if (is_int(first_index, 0) and is_int(offset, 0) and is_int(num_imgs, 1)):
if offset < 0:
- use_input = input_yesno(f'\nCurrent{name}first index = {first_index}, '+
- 'use this value (y/n)?', 'y')
+ use_input = pyip.inputYesNo('\nCurrent'+name+f'first index = {first_index}, '+
+ 'use this value ([y]/n)? ', blank=True)
else:
- use_input = input_yesno(f'\nCurrent{name}first index/offset = '+
- f'{first_index}/{offset}, use these values (y/n)?', 'y')
+ use_input = pyip.inputYesNo('\nCurrent'+name+'first index/offset = '+
+ f'{first_index}/{offset}, use these values ([y]/n)? ',
+ blank=True)
if num_required is None:
- if use_input:
- use_input = input_yesno(f'Current number of{name}images = '+
- f'{num_imgs}, use this value (y/n)? ', 'y')
- if use_input:
+ if use_input != 'no':
+ use_input = pyip.inputYesNo('Current number of'+name+'images = '+
+ f'{num_imgs}, use this value ([y]/n)? ',
+ blank=True)
+ if use_input != 'no':
return first_index, offset, num_imgs
# Check range against requirements
@@ -823,27 +766,32 @@
use_all = f'Use all ([{first_index}, {last_index}])'
pick_offset = 'Pick a first index offset and a number of images'
pick_bounds = 'Pick the first and last index'
- choice = input_menu([use_all, pick_offset, pick_bounds], default=pick_offset)
- if not choice:
+ menuchoice = pyip.inputMenu([use_all, pick_offset, pick_bounds], numbered=True)
+ if menuchoice == use_all:
offset = 0
- elif choice == 1:
- offset = input_int('Enter the first index offset', 0, last_index-first_index)
+ elif menuchoice == pick_offset:
+ offset = pyip.inputInt('Enter the first index offset'+
+ f' [0, {last_index-first_index}]: ', min=0, max=last_index-first_index)
first_index += offset
if first_index == last_index:
num_imgs = 1
else:
- num_imgs = input_int('Enter the number of images', 1, num_imgs-offset)
+ num_imgs = pyip.inputInt(f'Enter the number of images [1, {num_imgs-offset}]: ',
+ min=1, max=num_imgs-offset)
else:
- offset = input_int('Enter the first index', first_index, last_index)
+ offset = pyip.inputInt(f'Enter the first index [{first_index}, {last_index}]: ',
+ min=first_index, max=last_index)-first_index
first_index += offset
- num_imgs = input_int('Enter the last index', first_index, last_index)-first_index+1
+ num_imgs = pyip.inputInt(f'Enter the last index [{first_index}, {last_index}]: ',
+ min=first_index, max=last_index)-first_index+1
else:
use_all = f'Use ([{first_index}, {first_index+num_required-1}])'
pick_offset = 'Pick the first index offset'
- choice = input_menu([use_all, pick_offset], pick_offset)
+ menuchoice = pyip.inputMenu([use_all, pick_offset], numbered=True)
offset = 0
- if choice == 1:
- offset = input_int('Enter the first index offset', 0, num_imgs-num_required)
+ if menuchoice == pick_offset:
+ offset = pyip.inputInt('Enter the first index offset'+
+ f'[0, {num_imgs-num_required}]: ', min=0, max=num_imgs-num_required)
first_index += offset
num_imgs = num_required
@@ -925,7 +873,7 @@
img_x_bounds[0]:img_x_bounds[1],img_y_bounds[0]:img_y_bounds[1]]
logging.info(f'... done in {time()-t0:.2f} seconds!')
else:
- illegal_value(filetype, 'filetype', 'loadImageStack')
+ illegal_value(filetype, 'filetype', 'findImageRange')
return img_stack
def combine_tiffs_in_h5(files, num_imgs, h5_filename):
@@ -1136,8 +1084,8 @@
illegal_value(x_upp, 'x_upp', 'selectArrayBounds')
return None
quickPlot((range(len_a), a), vlines=(x_low,x_upp), title=title)
- if not input_yesno(f'\nCurrent array bounds: [{x_low}, {x_upp}] '+
- 'use these values (y/n)?', 'y'):
+ if pyip.inputYesNo(f'\nCurrent array bounds: [{x_low}, {x_upp}], '+
+ 'use these values ([y]/n)? ', blank=True) == 'no':
x_low = None
x_upp = None
else:
@@ -1150,13 +1098,17 @@
x_low_max = len_a-num_x_min
while True:
quickPlot(range(x_min, x_max), a[x_min:x_max], title=title)
- zoom_flag = input_yesno('Set lower data bound (y) or zoom in (n)?', 'y')
- if zoom_flag:
- x_low = input_int(' Set lower data bound', 0, x_low_max)
+ zoom_flag = pyip.inputInt('Set lower data bound ([0]) or zoom in (1)?: ',
+ min=0, max=1, blank=True)
+ if zoom_flag == 1:
+ x_min = pyip.inputInt(f' Set lower zoom index [0, {x_low_max}]: ',
+ min=0, max=x_low_max)
+ x_max = pyip.inputInt(f' Set upper zoom index [{x_min+1}, {x_low_max+1}]: ',
+ min=x_min+1, max=x_low_max+1)
+ else:
+ x_low = pyip.inputInt(f' Set lower data bound [0, {x_low_max}]: ',
+ min=0, max=x_low_max)
break
- else:
- x_min = input_int(' Set lower zoom index', 0, x_low_max)
- x_max = input_int(' Set upper zoom index', x_min+1, x_low_max+1)
else:
if not is_int(x_low, 0, len_a-num_x_min):
illegal_value(x_low, 'x_low', 'selectArrayBounds')
@@ -1167,20 +1119,24 @@
x_upp_min = x_min
while True:
quickPlot(range(x_min, x_max), a[x_min:x_max], title=title)
- zoom_flag = input_yesno('Set upper data bound (y) or zoom in (n)?', 'y')
- if zoom_flag:
- x_upp = input_int(' Set upper data bound', x_upp_min, len_a)
+ zoom_flag = pyip.inputInt('Set upper data bound ([0]) or zoom in (1)?: ',
+ min=0, max=1, blank=True)
+ if zoom_flag == 1:
+ x_min = pyip.inputInt(f' Set upper zoom index [{x_upp_min}, {len_a-1}]: ',
+ min=x_upp_min, max=len_a-1)
+ x_max = pyip.inputInt(f' Set upper zoom index [{x_min+1}, {len_a}]: ',
+ min=x_min+1, max=len_a)
+ else:
+ x_upp = pyip.inputInt(f' Set upper data bound [{x_upp_min}, {len_a}]: ',
+ min=x_upp_min, max=len_a)
break
- else:
- x_min = input_int(' Set upper zoom index', x_upp_min, len_a-1)
- x_max = input_int(' Set upper zoom index', x_min+1, len_a)
else:
if not is_int(x_upp, x_low+num_x_min, len_a):
illegal_value(x_upp, 'x_upp', 'selectArrayBounds')
return None
print(f'lower bound = {x_low} (inclusive)\nupper bound = {x_upp} (exclusive)]')
quickPlot((range(len_a), a), vlines=(x_low,x_upp), title=title)
- if not input_yesno('Accept these bounds (y/n)?', 'y'):
+ if pyip.inputYesNo('Accept these bounds ([y]/n)?: ', blank=True) == 'no':
x_low, x_upp = selectArrayBounds(a, None, None, num_x_min, title=title)
clearPlot(title)
return x_low, x_upp
@@ -1228,13 +1184,17 @@
else:
quickImshow(a[min_:max_,:], title=title, aspect='auto',
extent=[0,a.shape[1], max_,min_])
- zoom_flag = input_yesno('Set lower data bound (y) or zoom in (n)?', 'y')
+ zoom_flag = pyip.inputInt('Set lower data bound (0) or zoom in (1)?: ',
+ min=0, max=1)
if zoom_flag:
- low = input_int(' Set lower data bound', 0, low_max)
+ min_ = pyip.inputInt(f' Set lower zoom index [0, {low_max}]: ',
+ min=0, max=low_max)
+ max_ = pyip.inputInt(f' Set upper zoom index [{min_+1}, {low_max+1}]: ',
+ min=min_+1, max=low_max+1)
+ else:
+ low = pyip.inputInt(f' Set lower data bound [0, {low_max}]: ',
+ min=0, max=low_max)
break
- else:
- min_ = input_int(' Set lower zoom index', 0, low_max)
- max_ = input_int(' Set upper zoom index', min_+1, low_max+1)
else:
if not is_int(low, 0, a.shape[axis]-num_min):
illegal_value(low, 'low', 'selectImageBounds')
@@ -1250,13 +1210,17 @@
else:
quickImshow(a[min_:max_,:], title=title, aspect='auto',
extent=[0,a.shape[1], max_,min_])
- zoom_flag = input_yesno('Set upper data bound (y) or zoom in (n)?', 'y')
+ zoom_flag = pyip.inputInt('Set upper data bound (0) or zoom in (1)?: ',
+ min=0, max=1)
if zoom_flag:
- upp = input_int(' Set upper data bound', upp_min, a.shape[axis])
+ min_ = pyip.inputInt(f' Set upper zoom index [{upp_min}, {a.shape[axis]-1}]: ',
+ min=upp_min, max=a.shape[axis]-1)
+ max_ = pyip.inputInt(f' Set upper zoom index [{min_+1}, {a.shape[axis]}]: ',
+ min=min_+1, max=a.shape[axis])
+ else:
+ upp = pyip.inputInt(f' Set upper data bound [{upp_min}, {a.shape[axis]}]: ',
+ min=upp_min, max=a.shape[axis])
break
- else:
- min_ = input_int(' Set upper zoom index', upp_min, a.shape[axis]-1)
- max_ = input_int(' Set upper zoom index', min_+1, a.shape[axis])
else:
if not is_int(upp, low+num_min, a.shape[axis]):
illegal_value(upp, 'upp', 'selectImageBounds')
@@ -1273,12 +1237,13 @@
print(f'lower bound = {low} (inclusive)\nupper bound = {upp} (exclusive)')
quickImshow(a_tmp, title=title)
del a_tmp
- if not input_yesno('Accept these bounds (y/n)?', 'y'):
+ if pyip.inputYesNo('Accept these bounds ([y]/n)?: ', blank=True) == 'no':
bounds = selectImageBounds(a, axis, low=low_save, upp=upp_save, num_min=num_min_save,
title=title)
return bounds
+
class Config:
"""Base class for processing a config file or dictionary.
"""
@@ -1318,7 +1283,7 @@
self.config = {item[0].strip():literal_eval(item[1].strip()) for item in
[line.split('#')[0].split('=') for line in lines if '=' in line.split('#')[0]]}
else:
- illegal_value(self.suffix, 'config file extension', 'Config.loadFile')
+ illegal_value(self.suffix, 'config file extension', 'loadFile')
# Make sure config file was correctly loaded
if isinstance(self.config, dict):
@@ -1330,6 +1295,7 @@
def loadDict(self, config_dict):
"""Takes a dictionary and places it into self.config.
"""
+ exit('loadDict not tested yet, what format do we follow: txt or yaml?')
if self.load_flag:
logging.warning('Overwriting the previously loaded config file')
@@ -1337,7 +1303,7 @@
self.config = config_dict
self.load_flag = True
else:
- illegal_value(config_dict, 'dictionary config object', 'Config.loadDict')
+ illegal_value(config_dict, 'dictionary config object', 'loadDict')
self.config = {}
def saveFile(self, config_file):
@@ -1345,7 +1311,7 @@
"""
suffix = os.path.splitext(config_file)[1]
if suffix != '.yml' and suffix != '.yaml':
- illegal_value(suffix, 'config file extension', 'Config.saveFile')
+ illegal_value(suffix, 'config file extension', 'saveFile')
# Check if config file exists
if os.path.isfile(config_file):
@@ -1358,31 +1324,15 @@
yaml.safe_dump(self.config, f)
def validate(self, pars_required, pars_missing=None):
- """Returns False if any required keys are missing.
+ """Returns False if any required first level keys are missing.
"""
if not self.load_flag:
logging.error('Load a config file prior to calling Config.validate')
-
- def validate_nested_pars(config, par):
- par_levels = par.split(':')
- first_level_par = par_levels[0]
- try:
- first_level_par = int(first_level_par)
- except:
- pass
- try:
- next_level_config = config[first_level_par]
- if len(par_levels) > 1:
- next_level_par = ':'.join(par_levels[1:])
- return validate_nested_pars(next_level_config, next_level_par)
- else:
- return True
- except:
- return False
-
- pars_missing = [p for p in pars_required if not validate_nested_pars(self.config, p)]
- if len(pars_missing) > 0:
- logging.error(f'Missing item(s) in configuration: {", ".join(pars_missing)}')
+ pars = [p for p in pars_required if p not in self.config]
+ if isinstance(pars_missing, list):
+ pars_missing.extend(pars)
+ elif pars_missing is not None:
+ illegal_value(pars_missing, 'pars_missing', 'Config.validate')
+ if len(pars) > 0:
return False
- else:
- return True
+ return True
diff -r e544e5d110eb -r 98a83f03d91b tomo.py
--- a/tomo.py Wed Aug 17 15:10:13 2022 +0000
+++ b/tomo.py Thu Aug 18 14:36:46 2022 +0000
@@ -41,7 +41,6 @@
from detector import TomoDetectorConfig
from fit import Fit
-#from msnctools.general import illegal_value, is_int, is_num, is_index_range, get_trailing_int, \
from general import illegal_value, is_int, is_num, is_index_range, get_trailing_int, \
input_int, input_num, input_yesno, input_menu, findImageFiles, loadImageStack, clearPlot, \
draw_mask_1d, quickPlot, clearImshow, quickImshow, combine_tiffs_in_h5, Config
diff -r e544e5d110eb -r 98a83f03d91b tomo_macros.xml
--- a/tomo_macros.xml Wed Aug 17 15:10:13 2022 +0000
+++ b/tomo_macros.xml Thu Aug 18 14:36:46 2022 +0000
@@ -17,7 +17,10 @@
+
+
diff -r e544e5d110eb -r 98a83f03d91b tomo_setup.py
--- a/tomo_setup.py Wed Aug 17 15:10:13 2022 +0000
+++ b/tomo_setup.py Thu Aug 18 14:36:46 2022 +0000
@@ -127,7 +127,6 @@
filepath = fields[0]
element_identifier = fields[1] if len(fields) > 1 else fields[0].split('/')[-1]
datasets.append({'element_identifier' : element_identifier, 'filepath' : filepath})
- print(f'datasets:\n{datasets}')
logging.debug(f'datasets:\n{datasets}')
if input_type == 'files' and len(datasets) != num_stack:
raise ValueError('Inconsistent number of input files provided.')
@@ -160,7 +159,6 @@
else:
collection = {'name' : name, 'filepaths' : [filepath]}
collections.append(collection)
- print(f'collections:\n{collections}')
logging.debug(f'collections:\n{collections}')
# Instantiate Tomo object