def __init__(self, graph, get_output=False, output_dims=2, scheduler=None, copy_inputs=False): self.output_tasks = [] self.sched = scheduler if scheduler else Ufo.Scheduler() self._started = False self.copy_inputs = copy_inputs if isinstance(graph, Ufo.TaskGraph): self.graph = graph roots = self.graph.get_roots() elif isinstance(graph, Ufo.TaskNode): self.graph = Ufo.TaskGraph() roots = [graph] else: msg = 'graph is neither Ufo.TaskGraph nor Ufo.TaskNode' raise ValueError(msg) # Initialize inputs self.input_tasks = {} self.ufo_buffers = {} for root in roots: self.input_tasks[root] = [] self.ufo_buffers[root] = [] num_inputs = root.get_num_inputs() for i in range(num_inputs): self.input_tasks[root].append(Ufo.InputTask()) self.ufo_buffers[root].append(None) self.graph.connect_nodes_full(self.input_tasks[root][i], root, i) if get_output: for i, leave in enumerate(self.graph.get_leaves()): self.output_tasks.append(Ufo.OutputTask()) self.output_tasks[-1].props.num_dims = output_dims self.graph.connect_nodes(leave, self.output_tasks[-1])
def _run(params, x_region, y_region, regions, index): """Execute one pass on all possible GPUs with slice ranges given by *regions*.""" from gi.repository import Ufo pm = Ufo.PluginManager() graph = Ufo.TaskGraph() scheduler = Ufo.FixedScheduler() gpus = scheduler.get_resources().get_gpu_nodes() num_gpus = len(gpus) broadcast = Ufo.CopyTask() source = _setup_source(params, pm, graph) graph.connect_nodes(source, broadcast) for i, region in enumerate(regions): subindex = index * num_gpus + i _setup_graph(pm, graph, subindex, x_region, y_region, region, params, broadcast, gpu=gpus[i]) scheduler.run(graph) duration = scheduler.props.time LOG.info('Execution time: {} s'.format(duration)) return duration
def measure_ufo(out_path, metric, axis, width, height): pm = Ufo.PluginManager() sched = Ufo.Scheduler() graph = Ufo.TaskGraph() input_path = 'data/measure.tif' image = make_input(width, height) tifffile.imsave(input_path, image) reader = pm.get_task('read') measure = pm.get_task('measure') output = Ufo.OutputTask() reader.props.path = input_path measure.props.axis = axis measure.props.metric = metric graph.connect_nodes(reader, measure) graph.connect_nodes(measure, output) sched.run(graph) buf = output.get_output_buffer() gpu_result = ufo.numpy.asarray(buf) write_image(out_path, gpu_result)
def __init__(self, graph, get_output=False): self.output_task = None self._started = False if isinstance(graph, Ufo.TaskGraph): self.graph = graph roots = self.graph.get_roots() elif isinstance(graph, Ufo.TaskNode): self.graph = Ufo.TaskGraph() roots = [graph] else: msg = 'graph is neither Ufo.TaskGraph nor Ufo.TaskNode' raise ValueError(msg) # Initialize inputs self.input_tasks = {} self.ufo_buffers = {} for root in roots: self.input_tasks[root] = [] self.ufo_buffers[root] = [] num_inputs = root.get_num_inputs() for i in range(num_inputs): self.input_tasks[root].append(Ufo.InputTask()) self.ufo_buffers[root].append(None) self.graph.connect_nodes_full(self.input_tasks[root][i], root, i) if get_output: self.output_task = Ufo.OutputTask() leaves = self.graph.get_leaves() self.graph.connect_nodes(leaves[0], self.output_task)
def compute_phase_spectrum_density(args): graph = Ufo.TaskGraph() scheduler = Ufo.Scheduler() build_power_spectrum_density_pipeline(args, graph, scheduler) # scheduler.run(graph) # runned inside for now duration = scheduler.props.time return duration
def run_flat_correct(args): graph = Ufo.TaskGraph() sched = Ufo.Scheduler() pm = Ufo.PluginManager() out_task = get_writer(args) flat_task = create_flat_correct_pipeline(args, graph) graph.connect_nodes(flat_task, out_task) sched.run(graph)
def generate_partial(append=False): graph = Ufo.TaskGraph() sched = Ufo.Scheduler() args.output_append = append writer = get_writer(args) sinos = create_sinogram_pipeline(args, graph) graph.connect_nodes(sinos, writer) sched.run(graph)
def run_flat_correct(args): graph = Ufo.TaskGraph() sched = Ufo.Scheduler() pm = Ufo.PluginManager() out_task = pm.get_task('write') out_task.props.filename = args.output flat_task = create_flat_correct_pipeline(args, graph) graph.connect_nodes(flat_task, out_task) sched.run(graph)
def run_preprocessing(args): graph = Ufo.TaskGraph() sched = Ufo.Scheduler() pm = Ufo.PluginManager() out_task = get_writer(args) current = create_preprocessing_pipeline(args, graph) graph.connect_nodes(current, out_task) sched.run(graph)
def generate_partial(append=False): pm = Ufo.PluginManager() graph = Ufo.TaskGraph() sched = Ufo.Scheduler() writer = pm.get_task('write') writer.props.filename = args.output writer.props.append = append sinos = create_sinogram_pipeline(args, graph) graph.connect_nodes(sinos, writer) sched.run(graph)
def __init__(self, graph): self.input_task = Ufo.InputTask() if isinstance(graph, Ufo.TaskGraph): self.graph = graph roots = self.graph.get_roots() self.graph.connect_nodes(self.input_task, roots[0]) elif isinstance(graph, Ufo.TaskNode): self.graph = Ufo.TaskGraph() self.graph.connect_nodes(self.input_task, graph) else: msg = 'graph is neither Ufo.TaskGraph nor Ufo.TaskNode' raise ValueError(msg) self.ufo_buffer = None
def test_wrong_connection(): from ufo import Read, FlatFieldCorrect, Write darks = Read() flats = Read() radios = Read() write = Write() ffc = FlatFieldCorrect() g = Ufo.TaskGraph() g.connect_nodes_full(radios.task, ffc.task, 0) g.connect_nodes_full(darks.task, ffc.task, 1) g.connect_nodes_full(flats.task, ffc.task, 0) g.connect_nodes(ffc.task, write.task) sched = Ufo.Scheduler() sched.run(g)
def initialize(self): self.data = self.get("DataStore").data() self.graph = Ufo.TaskGraph() self.sched = Ufo.Scheduler() manager = Ufo.PluginManager() self.read = manager.get_task('memory-in') self.sino = manager.get_task('transpose-projections') self.pad = manager.get_task('pad') self.fft = manager.get_task('fft') self.fltr = manager.get_task('filter') self.ifft = manager.get_task('ifft') self.bp = manager.get_task('backproject') self.crop = manager.get_task('crop') self.write= manager.get_task('memory-out') self.LogInfo("initialized, UFO Reconstruction") return True
def start_one(index): gpu_index, region = regions[index] scheduler = Ufo.FixedScheduler() scheduler.set_resources(resources[index]) graph = Ufo.TaskGraph() gpu = scheduler.get_resources().get_gpu_nodes()[gpu_index] region_index = run_number * len(resources) + index geometry = CTGeometry(args) if (len(args.center_position_z) == 1 and np.modf(args.center_position_z[0])[0] == 0 and geometry.is_simple_parallel_tomo): LOG.info( 'Simple tomography with integer z center, changing to center_position_z + 0.5 ' 'to avoid interpolation') geometry.args.center_position_z = ( geometry.args.center_position_z[0] + 0.5, ) if not args.disable_projection_crop: if not args.dry_run and (args.y or args.height): LOG.debug( '--y or --height specified, not optimizing projection region' ) else: geometry.optimize_args(region=region) opt_args = geometry.args if args.dry_run: source = get_task('dummy-data', number=args.number, width=args.width, height=args.height) else: source = None setup_graph(opt_args, graph, x_region, y_region, region, source=source, gpu=gpu, index=region_index, make_reader=True) LOG.debug('Pass: %d, device: %d, region: %s', run_number + 1, gpu_index, region) scheduler.run(graph) return scheduler.props.time
def __init__(self, axis_pos=None): self.pm = PluginManager() self.fft = self.pm.get_task('fft', dimensions=1) self.ifft = self.pm.get_task('ifft', dimensions=1) self.fltr = self.pm.get_task('filter') self.backprojector = self.pm.get_task('backproject') if axis_pos: self.backprojector.props.axis_pos = axis_pos graph = Ufo.TaskGraph() graph.connect_nodes(self.fft, self.fltr) graph.connect_nodes(self.fltr, self.ifft) graph.connect_nodes(self.ifft, self.backprojector) super(Backproject, self).__init__(graph, get_output=True) self.output_task.props.num_dims = 2
def ufo_dfi(tomo, center, recon, theta, **kwargs): """ Reconstruct object using UFO's Direct Fourier pipeline """ import gi gi.require_version('Ufo', '0.0') from gi.repository import Ufo theta = theta[1] - theta[0] center = center[0] g = Ufo.TaskGraph() pm = Ufo.PluginManager() sched = Ufo.Scheduler() input_task = Ufo.InputTask() output_task = Ufo.OutputTask() pad = pm.get_task('zeropad') fft = pm.get_task('fft') ifft = pm.get_task('ifft') dfi = pm.get_task('dfi-sinc') swap_forward = pm.get_task('swap-quadrants') swap_backward = pm.get_task('swap-quadrants') pad.set_properties(oversampling=1, center_of_rotation=center) fft.set_properties(dimensions=1, auto_zeropadding=False) ifft.set_properties(dimensions=2) dfi.set_properties(angle_step=theta) g.connect_nodes(input_task, pad) g.connect_nodes(pad, fft) g.connect_nodes(fft, dfi) g.connect_nodes(dfi, swap_forward) g.connect_nodes(swap_forward, ifft) g.connect_nodes(ifft, swap_backward) g.connect_nodes(swap_backward, output_task) args = (input_task, output_task, tomo, recon) thread = threading.Thread(target=_process_data, args=args) thread.start() sched.run(g) thread.join() logger.info("UFO+DFI run time: {}s".format(sched.props.time))
def transpose_ufo(width, height, path): pm = Ufo.PluginManager() graph = Ufo.TaskGraph() sched = Ufo.Scheduler() input_path = 'data/transpose.tif' image = make_input(width, height) tifffile.imsave(input_path, image) reader = pm.get_task('read') transpose = pm.get_task('transpose') writer = pm.get_task('write') reader.props.path = input_path writer.props.filename = path graph.connect_nodes(reader, transpose) graph.connect_nodes(transpose, writer) sched.run(graph)
def test_core_issue_64_fixed_expansion(): g = Ufo.TaskGraph() pm = Ufo.PluginManager() sched = Ufo.FixedScheduler() arch = Ufo.ArchGraph() gpus = arch.get_gpu_nodes() sched.set_gpu_nodes(arch, gpus) generate = pm.get_task('generate') null = pm.get_task('null') generate.set_properties(number=5, width=512, height=512) for gpu in gpus: median = pm.get_task('median-filter') median.set_proc_node(gpu) g.connect_nodes(generate, median) g.connect_nodes(median, null) sched.run(g)
def test_broadcast(): from ufo import Generate, Writer import glob with tempdir() as d: generate = Generate(number=5, width=512, height=512) write1 = Writer(filename=d.path('foo-%i.tif')) write2 = Writer(filename=d.path('bar-%i.tif')) g = Ufo.TaskGraph() g.connect_nodes(generate.task, write1.task) g.connect_nodes(generate.task, write2.task) sched = Ufo.Scheduler() sched.run(g) foos = glob.glob(d.path('foo-*')) bars = glob.glob(d.path('bar-*')) assert (len(foos) == 5) assert (len(bars) == 5)
def ufo_fbp(tomo, center, recon, theta, **kwargs): """ Reconstruct object using UFO's FBP pipeline """ import gi gi.require_version('Ufo', '0.0') from gi.repository import Ufo width = tomo.shape[2] theta = theta[1] - theta[0] center = center[0] g = Ufo.TaskGraph() pm = Ufo.PluginManager() sched = Ufo.Scheduler() input_task = Ufo.InputTask() output_task = Ufo.OutputTask() fft = pm.get_task('fft') ifft = pm.get_task('ifft') fltr = pm.get_task('filter') backproject = pm.get_task('backproject') ifft.set_properties(crop_width=width) backproject.set_properties(axis_pos=center, angle_step=theta, angle_offset=np.pi) g.connect_nodes(input_task, fft) g.connect_nodes(fft, fltr) g.connect_nodes(fltr, ifft) g.connect_nodes(ifft, backproject) g.connect_nodes(backproject, output_task) args = (input_task, output_task, tomo, recon) thread = threading.Thread(target=_process_data, args=args) thread.start() sched.run(g) thread.join() logger.info("UFO+FBP run time: {}s".format(sched.props.time))
def __init__(self, axis_pos=None, flat_row=None, dark_row=None): self.pm = PluginManager() self.sino_correction = self.pm.get_task('flat-field-correction') self.fft = self.pm.get_task('fft', dimensions=1) self.ifft = self.pm.get_task('ifft', dimensions=1) self.fltr = self.pm.get_task('filter') self.backprojector = self.pm.get_task('backproject') if axis_pos: self.backprojector.props.axis_pos = axis_pos self.sino_correction.props.sinogram_input = True graph = Ufo.TaskGraph() graph.connect_nodes(self.sino_correction, self.fft) graph.connect_nodes(self.fft, self.fltr) graph.connect_nodes(self.fltr, self.ifft) graph.connect_nodes(self.ifft, self.backprojector) super(FlatCorrectedBackproject, self).__init__(graph, get_output=True) self.flat_row = flat_row self.dark_row = dark_row
def tomo(params): # Create reader and writer if params.projections and params.sinograms: raise RuntimeError("Cannot specify both --projections and --sinograms.") if params.projections is None and params.sinograms is None: reader, width, height = get_dummy_reader(params) else: if params.projections: reader, width, height = get_projection_reader(params) else: reader, width, height = get_sinogram_reader(params) axis = params.axis or width / 2.0 if params.projections and params.resize: width /= params.resize height /= params.resize axis /= params.resize LOG.debug("Input dimensions: {}x{} pixels".format(width, height)) writer = get_writer(pm, params) # Setup graph depending on the chosen method and input data g = Ufo.TaskGraph() if params.projections is not None: if params.number: count = len(range(params.start, params.start + params.number, params.step)) else: count = len(get_filenames(params.projections)) LOG.debug("Number of projections: {}".format(count)) sino_output = get_task('transpose-projections', number=count) if params.darks and params.flats: g.connect_nodes(create_flat_correct_pipeline(params, g), sino_output) else: g.connect_nodes(reader, sino_output) if height: # Sinogram height is the one needed for further padding height = count else: sino_output = reader if params.method == 'fbp': fft = get_task('fft', dimensions=1) ifft = get_task('ifft', dimensions=1) fltr = get_task('filter', filter=params.projection_filter) bp = get_task('backproject', axis_pos=axis) if params.angle: bp.props.angle_step = params.angle if params.offset: bp.props.angle_offset = params.offset if width and height: # Pad the image with its extent to prevent reconstuction ring pad = get_task('pad') crop = get_task('crop') setup_padding(pad, crop, width, height, params.projection_padding_mode) LOG.debug("Padding input to: {}x{} pixels".format(pad.props.width, pad.props.height)) g.connect_nodes(sino_output, pad) g.connect_nodes(pad, fft) g.connect_nodes(fft, fltr) g.connect_nodes(fltr, ifft) g.connect_nodes(ifft, crop) g.connect_nodes(crop, bp) else: if params.crop_width: ifft.props.crop_width = int(params.crop_width) LOG.debug("Cropping to {} pixels".format(ifft.props.crop_width)) g.connect_nodes(sino_output, fft) g.connect_nodes(fft, fltr) g.connect_nodes(fltr, ifft) g.connect_nodes(ifft, bp) g.connect_nodes(bp, writer) if params.method in ('sart', 'sirt', 'sbtv', 'asdpocs'): projector = pm.get_task_from_package('ir', 'parallel-projector') projector.set_properties(model='joseph', is_forward=False) projector.set_properties(axis_position=axis) projector.set_properties(step=params.angle if params.angle else np.pi / 180.0) method = pm.get_task_from_package('ir', params.method) method.set_properties(projector=projector, num_iterations=params.num_iterations) if params.method in ('sart', 'sirt'): method.set_properties(relaxation_factor=params.relaxation_factor) if params.method == 'asdpocs': minimizer = pm.get_task_from_package('ir', 'sirt') method.set_properties(df_minimizer=minimizer) if params.method == 'sbtv': # FIXME: the lambda keyword is preventing from the following # assignment ... # method.props.lambda = params.lambda method.set_properties(mu=params.mu) g.connect_nodes(sino_output, method) g.connect_nodes(method, writer) if params.method == 'dfi': oversampling = params.oversampling or 1 pad = get_task('zeropad', center_of_rotation=axis, oversampling=oversampling) fft = get_task('fft', dimensions=1, auto_zeropadding=0) dfi = get_task('dfi-sinc') ifft = get_task('ifft', dimensions=2) swap_forward = get_task('swap-quadrants') swap_backward = get_task('swap-quadrants') if params.angle: dfi.props.angle_step = params.angle g.connect_nodes(sino_output, pad) g.connect_nodes(pad, fft) g.connect_nodes(fft, dfi) g.connect_nodes(dfi, swap_forward) g.connect_nodes(swap_forward, ifft) g.connect_nodes(ifft, swap_backward) if width: crop = get_task('crop') crop.set_properties(from_center=True, width=width, height=width) g.connect_nodes(swap_backward, crop) g.connect_nodes(crop, writer) else: g.connect_nodes(swap_backward, writer) scheduler = Ufo.Scheduler() if hasattr(scheduler.props, 'enable_tracing'): LOG.debug("Use tracing: {}".format(params.enable_tracing)) scheduler.props.enable_tracing = params.enable_tracing scheduler.run(g) duration = scheduler.props.time LOG.info("Execution time: {} s".format(duration)) return duration
def reset(self): self.graph = Ufo.TaskGraph()
def __init__(self, args, resources=None, gpu_index=0, do_normalization=False, region=None, copy_inputs=False): if args.width is None or args.height is None: raise GeneralBackprojectError('width and height must be set in GeneralBackprojectArgs') scheduler = Ufo.FixedScheduler() if resources: scheduler.set_resources(resources) gpu = scheduler.get_resources().get_gpu_nodes()[gpu_index] self.args = copy.deepcopy(args) x_region, y_region, z_region = get_reconstruction_regions(self.args, store=True, dtype=float) set_projection_filter_scale(self.args) if region is not None: self.args.region = region LOG.debug('Creating reconstructor for gpu %d, region: %s', gpu_index, self.args.region) geometry = CTGeometry(self.args) if not self.args.disable_projection_crop: geometry.optimize_args() self.args = geometry.args regions = make_runs([gpu], [gpu_index], x_region, y_region, self.args.region, DTYPE_CL_SIZE[self.args.store_type], slices_per_device=self.args.slices_per_device, slice_memory_coeff=self.args.slice_memory_coeff, data_splitting_policy=self.args.data_splitting_policy) if len(regions) > 1: raise GeneralBackprojectError('Region does not fit to the GPU memory') graph = Ufo.TaskGraph() # Normalization self.ffc = None self.do_normalization = do_normalization if do_normalization: self.ffc = get_task('flat-field-correct', processing_node=gpu) self.ffc.props.fix_nan_and_inf = self.args.fix_nan_and_inf self.ffc.props.absorption_correct = self.args.absorptivity self._darks_averaged = False self._flats_averaged = False self.dark_avg = get_task('average', processing_node=gpu) self.flat_avg = get_task('average', processing_node=gpu) graph.connect_nodes_full(self.dark_avg, self.ffc, 1) graph.connect_nodes_full(self.flat_avg, self.ffc, 2) (first, last) = setup_graph(self.args, graph, x_region, y_region, self.args.region, source=self.ffc, gpu=gpu, index=gpu_index, do_output=False, make_reader=False) output_dims = 2 if args.slice_metric: output_dims = 1 metric = self.args.slice_metric if args.slice_metric == 'sag': metric = 'sum' gradient_task = get_task('gradient', processing_node=gpu, direction='both_abs') graph.connect_nodes(last, gradient_task) last = gradient_task measure_task = get_task('measure', processing_node=gpu, axis=-1, metric=metric) graph.connect_nodes(last, measure_task) elif first == last: # There are no other processing steps other than back projection LOG.debug('Only back projection, no other processing') graph = first super().__init__(graph, get_output=True, output_dims=output_dims, scheduler=scheduler, copy_inputs=copy_inputs) if self.do_normalization: # Setup input tasks for normalization images averaging. Our parent picks up only the two # averagers and not the ffc's zero port for projections. self.input_tasks[self.ffc] = [Ufo.InputTask()] self.ufo_buffers[self.ffc] = [None] self.graph.connect_nodes_full(self.input_tasks[self.ffc][0], self.ffc, 0)