|
@@ -133,6 +133,7 @@ class StatusBar(object):
|
|
|
self.c = colors
|
|
|
|
|
|
def update(self, s):
|
|
|
+ self.window.clear()
|
|
|
self.window.bkgd(' ', self.c.get(Colors.STATUS_BAR))
|
|
|
self.window.addstr(s, self.c.get(Colors.STATUS_BAR))
|
|
|
|
|
@@ -255,10 +256,38 @@ class Parameters(object):
|
|
|
self.angle = angle
|
|
|
|
|
|
|
|
|
+class Dataset(object):
|
|
|
+
|
|
|
+ def __init__(self, path):
|
|
|
+ self.path = path
|
|
|
+ self.prefix = os.path.basename(path)
|
|
|
+
|
|
|
+ def __repr__(self):
|
|
|
+ return '<Dataset(prefix={})>'.format(self.prefix)
|
|
|
+
|
|
|
+
|
|
|
class Application(object):
|
|
|
def __init__(self, config):
|
|
|
self.config = config
|
|
|
self.running = True
|
|
|
+ self.datasets = []
|
|
|
+ self.known = set()
|
|
|
+ self.current = None
|
|
|
+ self.index = -1
|
|
|
+
|
|
|
+ def scan(self):
|
|
|
+ new = []
|
|
|
+
|
|
|
+ for p in os.listdir(self.config.destination):
|
|
|
+ path = os.path.join(self.config.destination, p)
|
|
|
+ if os.path.isdir(path) and p not in self.known:
|
|
|
+ new.append(Dataset(path))
|
|
|
+ self.known.add(p)
|
|
|
+
|
|
|
+ if new:
|
|
|
+ for d in new:
|
|
|
+ self.log.highlight("Found new dataset {}".format(d.prefix))
|
|
|
+ self.datasets.append(d)
|
|
|
|
|
|
def run_command(self, cmd):
|
|
|
try:
|
|
@@ -284,16 +313,12 @@ class Application(object):
|
|
|
self.log.error("{}".format(e))
|
|
|
return False
|
|
|
|
|
|
- @property
|
|
|
- def prefix(self):
|
|
|
- return os.path.basename(self.config.destination)
|
|
|
-
|
|
|
@property
|
|
|
def params_name(self):
|
|
|
- return '{}params.json'.format(self.prefix)
|
|
|
+ return '{}params.json'.format(self.current.prefix)
|
|
|
|
|
|
def read_info(self):
|
|
|
- info_file = os.path.join(self.config.destination, '{}.info'.format(self.prefix))
|
|
|
+ info_file = os.path.join(self.current.path, '{}.info'.format(self.current.prefix))
|
|
|
return read_info_file(info_file)
|
|
|
|
|
|
def read_optimal_params(self, scale=1.0):
|
|
@@ -309,7 +334,7 @@ class Application(object):
|
|
|
axis = (float(info['Col_end']) + 1) / 2.0
|
|
|
axis_step = 0.25
|
|
|
|
|
|
- fname = os.path.join(self.config.destination, '{}0000.edf'.format(self.prefix))
|
|
|
+ fname = os.path.join(self.current.path, '{}0000.edf'.format(self.current.prefix))
|
|
|
header = read_edf_id19_header(fname)
|
|
|
motor_pos = extract_motor_positions(header)
|
|
|
|
|
@@ -321,14 +346,14 @@ class Application(object):
|
|
|
|
|
|
x_region = 960
|
|
|
y_region = 960
|
|
|
- fc_path = '{prefix}/fc'.format(prefix=self.prefix)
|
|
|
+ fc_path = '{path}/fc'.format(path=self.current.path)
|
|
|
|
|
|
if resize:
|
|
|
x_region /= 2
|
|
|
y_region /= 2
|
|
|
axis /= 2
|
|
|
axis_step /= 2
|
|
|
- fc_path = '{prefix}/fc-small'.format(prefix=self.prefix)
|
|
|
+ fc_path = '{path}/fc-small'.format(path=self.current.path)
|
|
|
|
|
|
axis_start = axis - slices_per_device * axis_step
|
|
|
axis_stop = axis + slices_per_device * axis_step
|
|
@@ -341,10 +366,10 @@ class Application(object):
|
|
|
' --axis-range={ax_start},{ax_stop},{ax_step}'
|
|
|
' --lamino-angle-range={an_start},{an_stop},{an_step}'
|
|
|
' --metric kurtosis --z-metric kurtosis'
|
|
|
- ' --tmp-output {prefix}/tmp'
|
|
|
+ ' --tmp-output {path}/tmp'
|
|
|
.format(ax_start=axis_start, ax_stop=axis_stop, ax_step=axis_step,
|
|
|
an_start=angle_start, an_stop=angle_stop, an_step=angle_step,
|
|
|
- prefix=self.prefix))
|
|
|
+ path=self.current.path))
|
|
|
|
|
|
params = ('--x-region="-{x_region},{x_region},1"'
|
|
|
' --y-region="-{y_region},{y_region},1"'
|
|
@@ -359,11 +384,16 @@ class Application(object):
|
|
|
' {opt_params}'
|
|
|
' --reco-params "{params}"'
|
|
|
' --params-filename {params_name}'
|
|
|
- .format(opt_params=opt_params, params=params, params_name=self.params_name,
|
|
|
- fc_path=fc_path, prefix=self.prefix))
|
|
|
+ .format(opt_params=opt_params, params=params, params_name=self.params_name, fc_path=fc_path))
|
|
|
|
|
|
return self.run_command(cmd)
|
|
|
|
|
|
+ def update_statusbar(self):
|
|
|
+ self.log.info("Current dataset: {}".format(self.current.prefix))
|
|
|
+
|
|
|
+ if self.current:
|
|
|
+ self.status_bar.update("Current: {} [{}/{}]".format(self.current.prefix, self.index + 1, len(self.datasets)))
|
|
|
+
|
|
|
def on_reconstruct(self):
|
|
|
self.log.highlight("Reconstructing ...")
|
|
|
|
|
@@ -412,8 +442,8 @@ class Application(object):
|
|
|
def on_flat_correct(self):
|
|
|
self.log.highlight("Flat field correction ...")
|
|
|
info = self.read_info()
|
|
|
- path = self.config.destination
|
|
|
- data = dict(path=path, prefix=self.prefix, num=info['TOMO_N'], step=1)
|
|
|
+ path = self.current.path
|
|
|
+ data = dict(path=path, prefix=self.current.prefix, num=info['TOMO_N'], step=1)
|
|
|
|
|
|
cmd = ('tofu flatcorrect --verbose'
|
|
|
' --reduction-mode median'
|
|
@@ -464,6 +494,16 @@ class Application(object):
|
|
|
|
|
|
return False
|
|
|
|
|
|
+ def on_next_dataset(self):
|
|
|
+ self.index = (self.index + 1) % len(self.datasets)
|
|
|
+ self.current = self.datasets[self.index]
|
|
|
+ self.update_statusbar()
|
|
|
+
|
|
|
+ def on_previous_dataset(self):
|
|
|
+ self.index = (self.index - 1) % len(self.datasets)
|
|
|
+ self.current = self.datasets[self.index]
|
|
|
+ self.update_statusbar()
|
|
|
+
|
|
|
def do_nothing(self):
|
|
|
return True
|
|
|
|
|
@@ -477,10 +517,10 @@ class Application(object):
|
|
|
bottom_pane = screen.subwin(height - 1, width, 1, 0)
|
|
|
|
|
|
left_pane = bottom_pane.subwin(height - 1, width / 4, 1, 0)
|
|
|
- right_pane = bottom_pane.subwin(height - 1, 2 * width / 4, 1, width / 4)
|
|
|
+ right_pane = bottom_pane.subwin(height - 1, 3 * width / 4, 1, width / 4)
|
|
|
|
|
|
- status_bar = StatusBar(top_pane, colors)
|
|
|
- status_bar.update('Cockpit')
|
|
|
+ self.status_bar = StatusBar(top_pane, colors)
|
|
|
+ self.status_bar.update('Cockpit')
|
|
|
|
|
|
cmd_window = CommandList(left_pane, colors)
|
|
|
|
|
@@ -492,41 +532,59 @@ class Application(object):
|
|
|
quick_optimize = Action('q', 'Quick optimization', self.on_quick_optimize, machine.QUICK_OPTIMIZE)
|
|
|
optimize = Action('o', 'Optimization', self.on_optimize, machine.OPTIMIZE)
|
|
|
reconstruct = Action('r', 'Reconstruct', self.on_reconstruct, machine.RECONSTRUCT)
|
|
|
+ flatcorrect = Action('f', 'Flat correct', self.on_flat_correct, machine.FLATCORRECT)
|
|
|
+ next_dataset = Action('n', 'Next dataset', self.on_next_dataset, machine.START)
|
|
|
+ previous_dataset = Action('p', 'Previous dataset', self.on_previous_dataset, machine.START)
|
|
|
|
|
|
machine.add_action(machine.START, sync)
|
|
|
machine.add_action(machine.START, quick_optimize)
|
|
|
machine.add_action(machine.START, optimize)
|
|
|
+ machine.add_action(machine.START, next_dataset)
|
|
|
+ machine.add_action(machine.START, previous_dataset)
|
|
|
machine.add_action(machine.START, quit)
|
|
|
|
|
|
machine.add_action(machine.SYNC, quit)
|
|
|
|
|
|
machine.add_action(machine.QUICK_OPTIMIZE, reconstruct)
|
|
|
machine.add_action(machine.QUICK_OPTIMIZE, optimize)
|
|
|
+ machine.add_action(machine.QUICK_OPTIMIZE, next_dataset)
|
|
|
+ machine.add_action(machine.QUICK_OPTIMIZE, previous_dataset)
|
|
|
machine.add_action(machine.QUICK_OPTIMIZE, quit)
|
|
|
|
|
|
- machine.add_action(machine.OPTIMIZE, reconstruct)
|
|
|
machine.add_action(machine.OPTIMIZE, quick_optimize)
|
|
|
+ machine.add_action(machine.OPTIMIZE, reconstruct)
|
|
|
+ machine.add_action(machine.OPTIMIZE, next_dataset)
|
|
|
+ machine.add_action(machine.OPTIMIZE, previous_dataset)
|
|
|
machine.add_action(machine.OPTIMIZE, quit)
|
|
|
|
|
|
machine.add_action(machine.CLEAN, sync)
|
|
|
machine.add_action(machine.CLEAN, quit)
|
|
|
|
|
|
- if os.path.exists(self.params_name):
|
|
|
- machine.add_action(machine.START, reconstruct)
|
|
|
+ machine.add_action(machine.FLATCORRECT, quick_optimize)
|
|
|
+ machine.add_action(machine.FLATCORRECT, optimize)
|
|
|
+ machine.add_action(machine.FLATCORRECT, next_dataset)
|
|
|
+ machine.add_action(machine.FLATCORRECT, previous_dataset)
|
|
|
+ machine.add_action(machine.FLATCORRECT, quit)
|
|
|
+
|
|
|
+ self.log = LogList(right_pane, colors)
|
|
|
+ self.log.info('Source dir set to {}'.format(self.config.source))
|
|
|
+ self.log.info('Destination dir set to {}'.format(self.config.destination))
|
|
|
+
|
|
|
+ self.scan()
|
|
|
|
|
|
- if not have_flats(self.config.destination):
|
|
|
- flatcorrect = Action('f', 'Flat correct', self.on_flat_correct, machine.FLATCORRECT)
|
|
|
+ if self.datasets:
|
|
|
+ self.index = 0
|
|
|
+ self.current = self.datasets[0]
|
|
|
+
|
|
|
+ if not have_flats(self.current.path):
|
|
|
machine.add_action(machine.START, flatcorrect)
|
|
|
machine.add_action(machine.SYNC, flatcorrect)
|
|
|
- machine.add_action(machine.FLATCORRECT, quick_optimize)
|
|
|
- machine.add_action(machine.FLATCORRECT, optimize)
|
|
|
- machine.add_action(machine.FLATCORRECT, quit)
|
|
|
|
|
|
- cmd_window.set_actions(machine.actions)
|
|
|
+ if os.path.exists(self.params_name):
|
|
|
+ machine.add_action(machine.START, reconstruct)
|
|
|
|
|
|
- self.log = LogList(right_pane, colors)
|
|
|
- self.log.info('Source dir set to {}'.format(self.config.source))
|
|
|
- self.log.info('Destination dir set to {}'.format(self.config.destination))
|
|
|
+ self.update_statusbar()
|
|
|
+ cmd_window.set_actions(machine.actions)
|
|
|
|
|
|
while self.running:
|
|
|
ci = screen.getch()
|
|
@@ -543,6 +601,7 @@ class Application(object):
|
|
|
elif ci == curses.KEY_BACKSPACE:
|
|
|
cmd_window.backspace()
|
|
|
|
|
|
+ self.scan()
|
|
|
screen.refresh()
|
|
|
|
|
|
def run(self):
|