Ejemplo n.º 1
0
  def setSource(self, source, index = all):
    #initialize sources and axis settings

    if index is all:  
      if isinstance(source, tuple):
        source = list(source);
      if not isinstance(source, list):
        source = [source];
      if self.nsources != len(source):
        raise RuntimeError('Number of sources does not match!');
      source  = [io.as_source(s) for s in source];
      index = range(self.nsources);
    else:
      s = self.sources;
      s[index] = io.as_source(source);
      source = s;
      index = [index];
    
    for i in index:
      s = source[i];
      if s.shape != self.source_shape:
        raise RuntimeError('Shape of sources does not match!');
      
      if s.dtype == bool:
        self.sources[i] = s.view('uint8');
     
      if s.ndim == 2:
        s.shape = s.shape + (1,);
      if s.ndim != 3:
        raise RuntimeError('Sources dont have dimensions 2 or 3 but %d in source %d!' % (s.ndim, i));
      
      self.image_items[i].updateImage(s[self.source_slice[:s.ndims]]);
    
    self.sources = source;
Ejemplo n.º 2
0
def find_intensity(source, label, max_label=None, method='sum', verbose=False):
    """Find integrated intensity given object shapes as labled image.
      
  Arguments
  ---------
  source : array, str, or Source
    Source to measure intensities from.
  label : array, str, or Source
    Labeled image with a separate label for each object.
  max_label : int or None
    Maximal label to include. If None use all.
  method : {'sum', 'mean', 'max', 'min'}
    Method to use to measure the intensities in each object's area.
  verbose : bool 
    If True, print progress information.
  
  Returns
  -------
  intensities : array
    Measured intensities. 
  """

    if verbose:
        timer = tmr.Timer()
        hdict.pprint(head='Intensity detection:',
                     max_label=max_label,
                     method=method)

    source = io.as_source(source).array
    label = io.as_source(label)

    if max_label is None:
        max_label = label.max()

    if method.lower() == 'sum':
        measure = scipy.ndimage.measurements.sum
    elif method.lower() == 'mean':
        measure = scipy.ndimage.measurements.mean
    elif method.lower() == 'max':
        measure = scipy.ndimage.measurements.maximum
    elif method.lower() == 'min':
        measure = scipy.ndimage.measurements.minimum
    else:
        raise RuntimeError('Unkown method %r!' % (method, ))

    intensities = measure(label,
                          labels=label,
                          index=np.arange(1, max_label + 1))

    if verbose:
        timer.print_elapsed_time(head='Intensity detection')

    return intensities
Ejemplo n.º 3
0
def flatfield_from_line(line, shape, axis = 0, dtype = float):
  """Creates a 2d flat field image from a 1d line of estimated intensities.
  
  Arguments
  ---------
  line : array
    Array of intensities along the specified axis.
  shape : tuple
    Shape of the resulting image.
  axis : int
    Axis of the flat field line estimate.
  
  Returns
  -------
  flatfield : array 
    Full 2d flat field.
  """
  line = io.as_source(line);
  
  if isinstance(shape, int):
    shape = (line.shape[0], shape) if axis == 0 else (shape, line.shape[0]);
  if shape[axis] != line.shape[0]:
    raise ValueError('Line shape %d does not match image shape %d!' % (line.shape[0], shape[axis]));
  
  shape = shape[axis];
  flatfield = np.array([line.array] * shape, dtype=dtype)
  if axis == 1:
    flatfield = flatfield.T;
  
  return flatfield;
Ejemplo n.º 4
0
def filter_cells(source, sink, thresholds):
    """Filter a array of detected cells according to the thresholds.
  
  Arguments
  ---------
  source : str, array or Source
    The source for the cell data.
  sink : str, array or Source
    The sink for the results.
  thresholds : dict
    Dictionary of the form {name : threshold} where name refers to the 
    column in the cell data and threshold can be None, a float 
    indicating a minimal threshold or a tuple (min,max) where min,max can be
    None or a minimal and maximal threshold value.
  
  Returns
  -------
  sink : str, array or Source
    The thresholded cell data.
  """
    source = io.as_source(source)

    ids = np.ones(source.shape[0], dtype=bool)
    for k, t in thresholds.items():
        if t:
            if not isinstance(t, (tuple, list)):
                t = (t, None)
            if t[0] is not None:
                ids = np.logical_and(ids, t[0] <= source[k])
            if t[1] is not None:
                ids = np.logical_and(ids, t[1] > source[k])
    cells_filtered = source[ids]

    return io.write(sink, cells_filtered)
Ejemplo n.º 5
0
def read_group(sources, combine=True, **args):
    """Turn a list of sources for data into a numpy stack.
  
  Arguments
  ---------
  sources : list of str or sources
     The sources to combine.
  combine : bool
    If true combine the sources to ndarray, oterhwise return a list.
  
  Returns
  -------
  group : array or list
    The gorup data.
  """

    #check if stack already:
    if isinstance(sources, np.ndarray):
        return sources

    #read the individual files
    group = []
    for f in sources:
        data = io.as_source(f, **args).array
        data = np.reshape(data, (1, ) + data.shape)
        group.append(data)

    if combine:
        return np.vstack(group)
    else:
        return group
Ejemplo n.º 6
0
def write_header_from_source(source, filename=None, header=None):
    """Create a mhd header file for a source file.
  
  Arguments
  ---------
  source : Source specification
    Source file or class to create a mhd header file for.
  filename : str or None
    Filename of the mhd file. If None, the source location with extension 'mhd' is used.
  header : dict or None
    Optional additional entries for the header file.
  
  Returns
  -------
  filename : str
    The filename of the mhd header.
  """
    import ClearMap.IO.IO as io
    source = io.as_source(source)

    mhd_header = header_from_source(source, header=header)

    if filename is None:
        filename = source.location + '.mhd'

    return write_header(filename, mhd_header)
Ejemplo n.º 7
0
 def as_memory_block(self):
     source = io.as_source(self.as_memory())
     return Block(source=source,
                  slicing=slice(None),
                  valid_slicing=self.valid.slicing,
                  index=self.index,
                  neighbours=self.neighbours)
Ejemplo n.º 8
0
def find_size(label, max_label=None, verbose=False):
    """Find size given object shapes as a labled image

  Arguments
  ---------
  label : array, str or Source
    Labeled image in which each object has its own label.
  max_label : int or None
    Maximal label to include, if None use all label.
  verbose : bool
    Print progress info.
    
  Returns
  -------
  sizes : array
    Measured intensities 
  """

    if verbose:
        timer = tmr.Timer()
        hdict.pprint(head='Size detection:', max_label=max_label)

    label = io.as_source(label)

    if max_label is None:
        max_label = int(label.max())

    sizes = scipy.ndimage.measurements.sum(np.ones(label.shape, dtype=bool),
                                           labels=label,
                                           index=np.arange(1, max_label + 1))

    if verbose:
        timer.print_elapsed_time(head='Size detection')

    return sizes
Ejemplo n.º 9
0
def block_axes(source, axes=None):
    """Determine the axes for block processing from source order.
  
  Arguments
  ---------
  source : array or Source
    The source on which the block processing is used.
  axes : list or None
    The axes over which to split the block processing.
  
  Returns
  -------
   axes : list or None
    The axes over which to split the block processing.
  """
    if axes is all:
        axes = [d for d in range(source.ndim)]
    if axes is not None:
        if np.max(axes) >= source.ndim or np.min(axes) < 0:
            raise ValueError(
                'Axes specification %r for source with dimnesion %d not valid!'
                % (axes, source.ndim))
        return axes

    source = io.as_source(source)
    if source.order == 'F':
        axes = [source.ndim - 1]
    else:
        axes = [0]

    return axes
Ejemplo n.º 10
0
 def create_debug(self, ftype, slicing, debug = None, **kwargs):
   if debug is None:
     debug = self.debug;
   if debug is None:
     debug = 'debug';
   self.debug = None;
   source = io.as_source(self.filename(ftype, **kwargs));
   self.debug = debug;
   return io.write(self.filename(ftype, **kwargs), np.asarray(source[slicing], order='F'));
Ejemplo n.º 11
0
def detect_shape(source, seeds, threshold=None, verbose=False):
    """Detect object shapes by generatng a labeled image from seeds.
  
  Arguments
  ---------
  source : array, str or Source
    Source image.
  seeds : array, str or Source
    Cell centers as point coordinates.
  threshold : float or None
    Threshold to determine mask for watershed, pixel below this are
    treated as background. If None, the seeds are expanded indefinately.
  verbose :bool
    If True, print progress info.
  
  Returns
  -------
  shapes : array
    Labeled image, where each label indicates a object. 
  """

    if verbose:
        timer = tmr.Timer()
        hdict.pprint(head='Shape detection', threshold=threshold)

    source = io.as_source(source).array
    seeds = io.as_source(seeds)

    if threshold is None:
        mask = None
    else:
        mask = source > threshold

    peaks = vox.voxelize(seeds,
                         shape=source.shape,
                         weights=np.arange(1, seeds.shape[0] + 1)).array
    shapes = skimage.morphology.watershed(-source, peaks, mask=mask)
    #shapes = watershed_ift(-source.astype('uint16'), peaks);
    #shapes[numpy.logical_not(mask)] = 0;

    if verbose:
        timer.print_elapsed_time('Shape detection')

    return shapes
Ejemplo n.º 12
0
    def initializeSources(self, source, scale=None, axis=None, update=True):
        #initialize sources and axis settings
        if isinstance(source, tuple):
            source = list(source)
        if not isinstance(source, list):
            source = [source]
        self.nsources = len(source)
        self.sources = [io.as_source(s) for s in source]

        # avoid bools
        for i, s in enumerate(self.sources):
            if s.dtype == bool:
                self.sources[i] = s.view('uint8')

        # # ensure 3d images
        # for i,s in enumerate(self.sources):
        #   if s.ndim == 2:
        #     s = s.view();
        #     s.shape = s.shape + (1,);
        #     self.sources[i] = s;
        #   if s.ndim != 3:
        #     raise RuntimeError('Sources dont have dimensions 2 or 3 but %d in source %d!' % (s.ndim, i));

        # source shapes
        self.source_shape = self.shape3d(self.sources[0].shape)
        for s in self.sources:
            if s.ndim > 3:
                raise RuntimeError('Source has %d > 3 dimensions: %r!' %
                                   (s.ndim, s))
            if self.shape3d(s.shape) != self.source_shape:
                raise RuntimeError('Sources shape %r vs %r in source %r!' %
                                   (self.source_shape, s.shape, s))

        self.source_shape2 = np.array(
            np.array(self.source_shape, dtype=float) / 2, dtype=int)
        # for i,s in enumerate(self.sources):
        #

        # slicing
        if axis is None:
            axis = 2
        self.source_axis = axis
        self.source_index = self.source_shape2

        # scaling
        if scale is None:
            scale = np.ones(3)
        else:
            scale = np.array(scale)
        scale = np.hstack([scale, [1] * 3])[:3]
        self.source_scale = scale
        #print(self.source_shape, self.source_scale)

        self.updateSourceRange()
        self.updateSourceSlice()
Ejemplo n.º 13
0
def plot_3d(source,
            colormap=None,
            view=None,
            title=None,
            center_view=True,
            **kwargs):
    """Plot 3d volume.
  
  Arguments
  ---------
  source : array
    The 3d volume.
  title : str or None
    Window title.
  view : view or None
    Add plot to this view. if given.
    
  Returns
  -------
  view : view
    The view of the plot.
  """
    #visual
    #VolumePlot3D = vispy.scene.visuals.create_visual_node(vispy.visuals.VolumeVisual)
    VolumePlot3D = vispy.scene.visuals.create_visual_node(vvi.VolumeVisual)

    #view
    title = title if title is not None else 'plot_3d'
    #center = (np.array(source.shape) // 2);
    view = initialize_view(view, title=title, fov=0,
                           depth_value=10**8)  #, center=center)

    #style
    style = dict(cmap=grays_alpha(),
                 method='translucent',
                 relative_step_size=0.5)
    style.update(**kwargs)

    #source
    source = io.as_source(source)[:]
    if source.dtype == bool:
        source = source.view(dtype='uint8')

    #orient
    source = source.transpose([2, 1, 0])

    #plot
    p = VolumePlot3D(source, parent=view.scene, **style)
    #view.camera.set_range();

    if center_view:
        _center_view(view)

    return p
Ejemplo n.º 14
0
def _initialize_source(source, as_source = False, as_1d = False, return_shape = False, return_strides = False):
  """Initialize a source for parallel array processing.
  
  Arguments
  ---------
  source : source specification
    The source to initialize.
  as_source : bool
    If True, return source as Source class. If false, a buffer compatible with
    cython memory views is returned.
  return_shape : bool
    If True, also return shape of the source.
  return_strides : bool
    If True, also return the element strides of the source.
  
  Returns
  -------
  source : Source or buffer
    The intialized source.
  shape : tuple of int
    Shape of the source.
  return_Strides : tuple of int
    Element strides of the source. 
  """
  source = io.as_source(source)

  if return_shape:
    shape = source.shape;
  
  if return_strides:
    strides = source.element_strides;
    
  if not as_source:
    #make sure the source is a buffer compatible with cython memoryviews
    source = source.as_buffer();

  if source.dtype == bool:
    source = source.view('uint8');  

  if as_1d:
    source = source.reshape(-1, order = 'A');

  
  
  result = (source,);  
  if return_shape:
    result += (shape,);
  if return_strides:
    result += (strides,);
  
  if len(result) == 1:
    return result[0];
  else:
    return result;
Ejemplo n.º 15
0
def _test():
    import numpy as np  #analysis:ok
    import ClearMap.ParallelProcessing.Block as blk

    import ClearMap.IO.IO as io
    source = io.as_source(np.asarray(np.random.rand(50, 100, 200), order='F'))

    block = blk.Block(source=source,
                      index=(1, 2, 3),
                      blocks_shape=(10, 20, 30))

    print(block.n_iterations)
    print(block.iteration)

    print(block.iteration_info())
Ejemplo n.º 16
0
def binary_statistics(source):
  """Counts the binarization types.
  
  Arguments
  ---------
  source : array
    The status array of the binarization process.
  
  Returns
  -------
  statistics : dict
    A dict with entires {description : count}.
  """
  status, counts = np.unique(io.as_source(source)[:], return_counts = True);
  return {status_to_description(s) : c for s,c in zip(status, counts)}
Ejemplo n.º 17
0
def _test():
    import numpy as np
    import ClearMap.IO.IO as io
    import ClearMap.Visualization.Plot3d as p3d
    import ClearMap.Tests.Files as tsf
    import ClearMap.ImageProcessing.Skeletonization.PK12 as PK12
    from importlib import reload
    reload(PK12)

    #Lookup tables
    #lut = PK12.generate_lookup_table();
    #np.save(PK12.filename, lut);
    #lut.sum()

    #lutnr = PK12.generate_lookup_table(function=PK12.match_non_removable, verbose = True);
    #np.save(PK12.filename_non_removable, lutnr);
    #lutnr.sum()

    #Skeletonization
    reload(PK12)
    binary = tsf.skeleton_binary
    binary_array = np.array(io.as_source(binary))

    #default version
    skeleton = PK12.skeletonize(binary_array.copy(),
                                delete_border=True,
                                verbose=True)
    p3d.plot([[binary_array, skeleton]])

    #fast index version
    skeleton = PK12.skeletonize_index(binary_array.copy(),
                                      delete_border=True,
                                      verbose=True)
    p3d.plot([[binary_array, skeleton]])

    # plotting
    import ClearMap.Visualization.Plot3d as p3d
    p3d.plot_3d(binary_array[:150, :150, :150], cmap=p3d.grays_alpha(0.05))
    p3d.plot_3d(skeleton[:150, :150, :150],
                cmap=p3d.single_color_colormap('red', alpha=0.8))

    #save for figure
    import scipy.io as sio
    sio.savemat('binary.mat', {'binary': binary_array[:100, :100, :100]})
    sio.savemat('binary_skeleton.mat',
                {'skeleton': skeleton[:100, :100, :100]})
Ejemplo n.º 18
0
def process(function,
            source,
            sink=None,
            axes=None,
            size_max=None,
            size_min=None,
            overlap=None,
            optimization=True,
            optimization_fix='all',
            neighbours=False,
            function_type=None,
            as_memory=False,
            return_result=False,
            return_blocks=False,
            processes=None,
            verbose=False,
            **kwargs):
    """Create blocks and process a function on them in parallel.
  
  Arguments
  ---------
  function : function
    The main data processing script.
  source : str, Source, or list
    The source or list of sources to apply a function to 
  sink : str, Source, list, or None
    The sink or list of sinks to write the result to.
    If None, return single array.
  axes : int, list of ints, or None
    Axes along which to split the source. If None, the 
    splitting is determined automaticlly from the order of the array.
  size_max : int, list of ints or None
    Maximal size of a block along the axes. 
    If None, :const:`default_size_max` is used.
  size_min : int or list of ints
    Minial size of a block along the axes. 
    If None, :const:`default_size_min` is used.
  overlap : int, list of ints or None
    Minimal overlap between blocks along the axes.
    If None, :const:`default_overlap` is used.
  optimization : bool or list of bools
    If True, optimize block sizes to best fit number of processes.
  optimization_fix : 'increase', 'decrease', 'all' or None or list
    Increase, decrease or optimally change the block size when optimization 
    is active.
  neighbours : bool
    If True, also include information about the neighbourhood in the blocks.
  function_type : 'array', 'source', 'block' or None
    The function type passed. If None, 'array' is used.
    
    * 'array'
      Reading and writing the valid slices from the blocks is automatic 
      and the function gets passed numpy arrays.
    * 'source' 
      Reading and writing the valid slices from the blocks is automatic 
      and the function gets passed Source classes as inputs. 
    * 'block' 
      The function is assumed to act on and update blocks itself.
    
  as_memory : bool
    If True, load full blocks into memory before applying the function.
    Can be useful to reduce frequent reading and writing operations of memmaps.
  return_result : bool
    If True, return the results of the proceessing functions.
  return_blocks : bool
    If True, return the block information used to distribute the processing.
  processes : int
    The number of parallel processes, if 'serial', use serial processing.
  verbose : bool
    Print information on sub-stack generation.
      
  Returns
  -------
  sink : str, Source, list or array 
    The results of the processing.
  
  Note
  ----
  This implementation only supports processing into sinks with the same shape as the source.
  """
    #sources and sinks
    if isinstance(source, list):
        sources = source
    else:
        sources = [source]
    sources = [io.as_source(s).as_virtual() for s in sources]

    #if sink is None:
    #  sink = sma.Source(shape=sources[0].shape, dtype=sources[0].dtype, order=sources[0].order);
    if isinstance(sink, list):
        sinks = sink
    elif sink is None:
        sinks = []
    else:
        sinks = [sink]

    sinks = [io.initialize(s, hint=sources[0]) for s in sinks]
    sinks = [io.as_source(s).as_virtual() for s in sinks]

    axes = block_axes(sources[0], axes=axes)

    split = ft.partial(split_into_blocks,
                       processes=processes,
                       axes=axes,
                       size_max=size_max,
                       size_min=size_min,
                       overlap=overlap,
                       optimization=optimization,
                       optimization_fix=optimization_fix,
                       neighbours=neighbours,
                       verbose=False)

    source_blocks = [split(s) for s in sources]
    sink_blocks = [split(s) for s in sinks]
    n_blocks = len(source_blocks[0])

    source_blocks = [[blocks[i] for blocks in source_blocks]
                     for i in range(n_blocks)]
    sink_blocks = [[blocks[i] for blocks in sink_blocks]
                   for i in range(n_blocks)]

    if function_type is None:
        function_type = 'array'
    if function_type == 'block':
        func = ft.partial(process_block_block,
                          function=function,
                          as_memory=as_memory,
                          return_result=return_result,
                          verbose=verbose,
                          **kwargs)
    elif function_type == 'source':
        func = ft.partial(process_block_source,
                          function=function,
                          as_memory=as_memory,
                          as_array=False,
                          verbose=verbose,
                          **kwargs)
    elif function_type == 'array':
        func = ft.partial(process_block_source,
                          function=function,
                          as_memory=as_memory,
                          as_array=True,
                          verbose=verbose,
                          **kwargs)
    else:
        raise ValueError(
            "function type %r not 'array', 'source', 'block' or None!")

    if not isinstance(processes, int) and processes != "serial":
        processes = mp.cpu_count()

    if verbose:
        timer = tmr.Timer()
        print("Processing %d blocks with function %r." %
              (n_blocks, function.__name__))

    if isinstance(processes, int):
        #from bounded_pool_executor import BoundedProcessPoolExecutor
        with cf.ProcessPoolExecutor(max_workers=processes) as executor:
            #with BoundedProcessPoolExecutor(max_workers=processes) as executor:
            futures = [
                executor.submit(func, *args)
                for args in zip(source_blocks, sink_blocks)
            ]
            result = [f.result() for f in futures]
            #executor.map(function, source_blocks, sink_blocks)
    else:
        result = [func(*args) for args in zip(source_blocks, sink_blocks)]
        #analysis:ignore

    if verbose:
        timer.print_elapsed_time("Processed %d blocks with function %r" %
                                 (n_blocks, function.__name__))

    #gc.collect();

    if return_result:
        ret = result
    else:
        ret = sink
    if return_blocks:
        ret = (ret, [source_blocks, sink_blocks])
    return ret
Ejemplo n.º 19
0
def transform(source, sink = [], transform_parameter_file = None, transform_directory = None, result_directory = None):
  """Transform a raw data set to reference using the elastix alignment results.
  
  Arguments
  ---------
  source : str or array
    Image source to be transformed.
  sink : str, [] or None
    Image sink to save transformed image to. If [] return the default name 
    of the data file generated by transformix.
  transform_parameter_file : str or None
    Parameter file for the primary transformation. 
    If None, the file is determined from the transform_directory.
  transform_directory : str or None
    Result directory of elastix alignment. 
    If None the transform_parameter_file has to be given.
  result_directory : str or None
    The directorty for the transformix results.
      
  Returns
  -------
  transformed : array or st
    Array or file name of the transformed data.
      
  Note
  ----
  If the map determined by elastix is
  :math:`T: \\mathrm{fixed} \\rightarrow \\mathrm{moving}`, 
  transformix on data works as :math:`T^{-1}(\\mathrm{data})`.
  """
  check_elastix_initialized();  
  
  # image
  source = io.as_source(source);
  if isinstance(source, io.tif.Source):
    imgname = source.location;
    delete_image = None;
  else:
    imgname = os.path.join(tempfile.gettempdir(), 'elastix_input.tif');
    io.write(source, imgname);
    delete_image = imgname;

  # result directory
  delete_result_directory = None;
  if result_directory == None:
    resultdirname = os.path.join(tempfile.gettempdir(), 'elastix_output');
    delete_result_directory = resultdirname;
  else:
    resultdirname = result_directory;
     
  if not os.path.exists(resultdirname):
    os.makedirs(resultdirname);
  
  # tranformation parameter
  transform_parameter_dir, transform_parameter_file = transform_directory_and_file(transform_parameter_file = transform_parameter_file, transform_directory = transform_directory);
  
  set_path_transform_files(transform_parameter_dir);
 
  #transformix -in inputImage.ext -out outputDirectory -tp TransformParameters.txx
  cmd = '%s -in %s -out %s -tp %s' % (transformix_binary, imgname, resultdirname, transform_parameter_file);
  
  res = os.system(cmd);
  
  if res != 0:
    raise RuntimeError('transform_data: failed executing: ' + cmd);
  
  # read data and clean up
  if delete_image is not None:
      os.remove(delete_image);
  
  if sink == []:
    return result_data_file(resultdirname);
  elif sink is None:
    resultfile = result_data_file(resultdirname);
    result = io.read(resultfile);
  elif isinstance(sink, str):
    resultfile = result_data_file(resultdirname);
    result = io.convert(resultfile, sink);
  else:
    raise RuntimeError('transform_data: sink not valid!');
    
  if delete_result_directory is not None:
    shutil.rmtree(delete_result_directory);
  
  return result;
Ejemplo n.º 20
0
def resample_points(source, sink = None, resample_source = None, resample_sink = None, 
                    orientation = None, source_shape = None, sink_shape = None,
                    source_resolution = None, sink_resolution = None, **args):
  """Resample points from original coordiantes to resampled ones.
  
  Arguments
  ---------
  source : str or array
    Points to be resampled.
  sink : str or None
    Sink for the resmapled point coordinates.
  orientation : tuple
    Orientation as specified in :func:`resample`.
  resample_source : str, array or None
    Optional source as in :func:`resample`.
  resample_sink: str, array or None
    Optional sink used in :func:`resample`.
  source_shape : tuple or None
    Optional value of source_shape as in :func:`resample`.
  source_resolution : tuple or None
    Optional value of source_resolution as in :func:`resample`.
  sink_resolution : tuple or None
    Optional value of sink_resolution as in :func:`resample`.
      
  Returns
  -------
  resmapled : array or str
    Sink for the resampled point coordinates.

  Notes
  -----
  * The resampling of points here corresponds to he resampling of an image 
    in :func:`resample`.
  * The arguments should be passed exactly as in :func:`resample` except soure
    and sink that point to the point sources. 
    Use resample_source and resmaple_sink to pass the source and sink values
    used in :func:`resample`.
  """
  #orientation
  orientation = format_orientation(orientation);
  
  #original source info
  if source_shape is None:
    if source_resolution is None and resample_source is None:
      raise ValueError('Either source_shape, source_resolution or resample_source must to be given!')
    if resample_source is not None:
      source_shape = io.shape(resample_source);

  #original sink info
  if sink_shape is None and sink_resolution is None: 
    if resample_sink is None:
      sink_shape = io.shape(source);
    else:
      sink_shape = io.shape(resample_sink);
  
  source_shape, sink_shape, source_resolution, sink_resolution = \
      resample_shape(source_shape=source_shape, sink_shape=sink_shape, 
                     source_resolution=source_resolution, sink_resolution=sink_resolution, 
                     orientation=orientation);
  
  sink_shape_in_source_orientation = orient_shape(sink_shape, orientation, inverse=True);
  
  resample_factor = [float(t)/float(s) for s,t in zip(source_shape, sink_shape_in_source_orientation)];
  
  points = io.as_source(source);
  resampled = points[:] * resample_factor;
  
  # reorient points
  if orientation is not None:
    #permute
    per = orientation_to_permuation(orientation);
    resampled = resampled.transpose(per);

    #reverse axes
    reslice = False;
    slicing = [slice(None)] * len(source_shape);
    for d,o in enumerate(orientation):
      if o < 0:
        slicing[d] = slice(None, None, -1);
        reslice = True;
    if reslice:
      resampled = resampled[slicing];
  
  return io.write(sink, resampled);
Ejemplo n.º 21
0
def resample_inverse(source, sink = None, 
                     resample_source = None, resample_sink = None,
                     orientation = None, 
                     source_shape = None, source_resolution = None, 
                     sink_shape = None, sink_resolution = None, 
                     axes_order = None, method = 'memmap',
                     interpolation = 'linear', 
                     processes = None, verbose = True, **args):
  """Resample data inversely to :func:`resample` routine.
  
  Arguments
  ---------
  source : str, array
    Source to be inversly resampled (e.g. sink in :func:`resample`).
  sink : str or None
    Sink to write the inversly resampled image to.
  resample_source : str, array or None
    Optional source in :func:`resample`.
  resmaple_sink: str, array or None
    Optional sink used in :func:`resample`.
  orientation : tuple
    Orientation as specified as in :func:`resample`.
  source_shape : tuple or None
    Optional value of source_shape as in :func:`resample`.
  source_resolution : tuple or None
    Optional value of source_resolution as in :func:`resample`.
  sink_resolution : tuple or None
    Optional value of sink_resolution as in :func:`resample`.
  processing_directory : str or None
    Optional directory in which to perform resmapling in parallel.
    If None, a temporary directry will be created.
  axis_order : list of tuples of int or None
    The axes pairs along which to resample the data as in :func:`resample`.
  method : 'shared' or 'memmap'
    Method to handle intermediate resampling results. If 'shared' use shared 
    memory, otherwise use a memory map on disk.
  interpolation : str
    Method to use for interpolating to the resmapled image. 
  processes int or None
    Number of processes to use for parallel resampling.
  verbose : bool
    If True, print progress information.
   
  Returns
  -------
  resampled : array or str
     Data or file name of inversly resampled image.

  Notes
  -----
  * All arguments, except source and sink should be passed as :func:`resample`
    to invert the resmapling.
  """   
  source = io.as_source(source);
  ndim = source.ndim;
  dtype = source.dtype;
  
  #orientation
  orientation = format_orientation(orientation);
  orientation_inverse = inverse_orientation(orientation);
  
  #original source info
  if source_shape is None:
    if source_resolution is None and resample_source is None:
      raise ValueError('Either source_shape, source_resolution or resample_source must to be given!')
    if resample_source is not None:
      source_shape = io.shape(resample_source);
  
  #original sink info
  if sink_shape is None and sink_resolution is None: 
    if resample_sink is None:
      sink_shape = io.shape(source);
    else:
      sink_shape = io.shape(resample_sink);
  
  source_shape, sink_shape, source_resolution, sink_resolution = \
      resample_shape(source_shape=source_shape, sink_shape=sink_shape, 
                     source_resolution=source_resolution, sink_resolution=sink_resolution, 
                     orientation=orientation);
  
  sink_shape_in_source_orientation = orient_shape(sink_shape, orientation, inverse=True);
  
  axes_order, shape_order = _axes_order(axes_order, source, source_shape, sink_shape_in_source_orientation);
 
  interpolation = _interpolation_to_cv2(interpolation);                                   

  if processes is None or not processes == 'serial':
      processes = io.mp.cpu_count();
  
  #reversed orientation
  if not orientation is None:
    #reverse axes
    slicing = [slice(None)] * ndim;
    reslice = False;
    for d,o in enumerate(orientation):
      if o < 0:
        slicing[d] = slice(None, None, -1);
        reslice = True;
    if reslice:
      source = source[slicing];   
    
    #re-orient
    per = orientation_to_permuation(orientation_inverse);
    source = io.read(source);
    source = source.transpose(per);
    source = io.sma.as_shared(source);
 
  #reverse resampling steps
  axes_order = axes_order[::-1];
  
  shape_order = shape_order[:-1];
  shape_order = shape_order[::-1];
  shape_order = shape_order + [source_shape]
  #print(axes_order, shape_order)
  
  #reverse resampling
  n_steps = len(axes_order);
  last_source = source;
  delete_files = [];
  #print(last_source)
  for step, axes, shape in zip(range(n_steps), axes_order, shape_order):
    if step == n_steps-1:
      resampled = io.initialize(source=sink, shape=shape, dtype=dtype, memory='shared', as_source=True); 
    else:
      if method == 'shared':
        resampled = io.sma.create(shape, dtype=dtype, order='C', as_source=True);
      else:
        location = tempfile.mktemp() + '.npy';
        resampled = io.mmp.create(location, shape=shape, dtype=dtype, order='C', as_source=True);
        delete_files.append(location);

    #indices for non-resampled axes
    indices = tuple([range(s) for d,s in enumerate(shape) if d not in axes]);
    indices = [i for i in itertools.product(*indices)];
    n_indices = len(indices);
    
    #resample step
    last_source_virtual = last_source.as_virtual();
    resampled_virtual = resampled.as_virtual();
    _resample = ft.partial(_resample_2d, source=last_source_virtual, sink=resampled_virtual, axes=axes, shape=shape, 
                                         interpolation=interpolation, n_indices=n_indices, verbose=verbose)                       
    
    if processes == 'serial': 
      for index in indices:
        _resample(index=index);
    else:
      with concurrent.futures.ProcessPoolExecutor(processes) as executor:
        executor.map(_resample, indices);
        
    last_source = resampled;
  
  for f in delete_files:
      io.delete_file(f);  
  
  sink = resampled.as_real();
      
  return sink;
Ejemplo n.º 22
0
def resample(source, sink = None, orientation = None, 
             sink_shape = None, source_resolution = None, sink_resolution = None, 
             interpolation = 'linear', axes_order = None, method = 'shared',
             processes = None, verbose = True):
  """Resample data of source in new shape/resolution and orientation.
  
  Arguments
  ---------
  source : str or array
    The source to be resampled.
  sink : str or None
    The sink for the resampled image.
  orientation : tuple or None:
    The orientation specified by permuation and change in sign of (1,2,3).
  sink_shape : tuple or None
    The target shape of the resampled sink.
  source_resolution : tuple or None
    The resolution of the source (in length per pixel).
  sink_resolution : tuple or None
    The resolution of the resampled source (in length per pixel).
  interpolation : str 
    The method to use for interpolating to the resmapled array.
  axis_order : str, list of tuples of int or None
    The axes pairs along which to resample the data at each step.
    If None, this is detertmined automatically. For a FileList source, 
    setting the first tuple should point to axis not indicating files.
    If 'size' the axis order is determined automatically to maximally reduce 
    the size of the array in each resmapling step.
    If 'order' the axis order is chosed automatically to optimize io speed.
  method : 'shared' or 'memmap'
    Method to handle intermediate resampling results. If 'shared' use shared 
    memory, otherwise use a memory map on disk.
  processes : int, None or 'serial'
    Number of processes to use for parallel resampling, if None use maximal 
    processes avaialable, if 'serial' process in serial.
  verbose : bool
    If True, display progress information.
  
  Returns
  -------
  sink : array or str
    The data or filename of resampled sink.

  Notes
  -----
  * Resolutions are assumed to be given for the axes of the intrinsic 
    orientation of the data and reference (as when viewed by ImageJ).
  * Orientation: permuation of 1,2,3 with potential sign, indicating which 
    axes map onto the reference axes, a negative sign indicates reversal 
    of that particular axes.
  * Only a minimal set of information to determine the resampling parameter 
    has to be given, e.g. source_shape and sink_shape.
  * The resampling is done by iterating two dimensional resampling steps.
  """
  #TODO: write full nd resampling routine extending cv2 lib.
  if verbose:
    timer = tmr.Timer();
  
  source = io.as_source(source);
  source_shape = source.shape;
  ndim = len(source_shape);
  dtype = source.dtype;
  order = source.order;
  
  orientation = format_orientation(orientation);
  
  source_shape, sink_shape, source_resolution, sink_resolution = \
     resample_shape(source_shape=source_shape, sink_shape=sink_shape, 
                    source_resolution=source_resolution, sink_resolution=sink_resolution, 
                    orientation=orientation);
  
  sink_shape_in_source_orientation = orient_shape(sink_shape, orientation, inverse=True);
                                   
  interpolation = _interpolation_to_cv2(interpolation);                                   

  if not isinstance(processes, int) and processes != 'serial':
    processes = io.mp.cpu_count();
  
  #detemine order of resampling
  axes_order, shape_order = _axes_order(axes_order, source, sink_shape_in_source_orientation, order=order);
  #print(axes_order, shape_order) 
  
  if len(axes_order) == 0:
    if verbose:
      print('resampling: no resampling necessary, source has same size as sink!');
    if sink != source:
      return io.write(sink, source);
    else:
      return source;
  
  #resample
  n_steps = len(axes_order);
  last_source = source;
  delete_files = [];
  for step, axes, shape in zip(range(n_steps), axes_order, shape_order):
    if step == n_steps-1 and orientation is None:
      resampled = io.initialize(source=sink, shape=sink_shape, dtype=dtype, as_source=True); 
    else:
      if method == 'shared':
        resampled = io.sma.create(shape, dtype=dtype, order=order, as_source=True);
      else:
        location = tempfile.mktemp() + '.npy';
        resampled = io.mmp.create(location, shape=shape, dtype=dtype, order=order, as_source=True);
        delete_files.append(location);
    #print(resampled)

    #indices for non-resampled axes
    indices = tuple([range(s) for d,s in enumerate(shape) if d not in axes]);
    indices = [i for i in itertools.product(*indices)];
    n_indices = len(indices);
    
    #resample step
    last_source_virtual = last_source.as_virtual();
    resampled_virtual = resampled.as_virtual();
    _resample = ft.partial(_resample_2d, source=last_source_virtual, sink=resampled_virtual, axes=axes, shape=shape, 
                                         interpolation=interpolation, n_indices=n_indices, verbose=verbose)                       
    
    if processes == 'serial': 
      for index in indices:
        _resample(index=index);
    else:
      #print(processes);
      with concurrent.futures.ProcessPoolExecutor(processes) as executor:
        executor.map(_resample, indices);
        
    last_source = resampled;
  
  #fix orientation
  if not orientation is None:
    #permute
    per = orientation_to_permuation(orientation);
    resampled = resampled.transpose(per);

    #reverse axes
    reslice = False;
    slicing = [slice(None)] * ndim;
    for d,o in enumerate(orientation):
      if o < 0:
        slicing[d] = slice(None, None, -1);
        reslice = True;
    if reslice:
      resampled = resampled[slicing];
      
    if verbose:
      print("resample: re-oriented shape %r!" % (resampled.shape,))
  
    sink = io.write(sink, resampled);
  else: 
    sink = resampled;
  
  for f in delete_files:
      io.delete_file(f);
  
  if verbose:
    timer.print_elapsed_time('Resampling')
    
  return sink;
Ejemplo n.º 23
0
def smooth_by_configuration(source, sink = None, iterations = 1, 
                            processing_parameter = None,
                            processes = None, verbose = False):
  """Smooth a binary source using the local configuration around each pixel.
  
  Arguments
  ---------
  source : array or Source
    The binary source to smooth.
  sink : array, Source or None
    The sink to write result of smoothing. If None, return array.
  iterations : int
    Number of smoothing iterations.
  processing_parameter : None or dict
    The parameter passed to 
    :func:`ClearMap.ParallelProcessing.BlockProcessing.process`.
  processes : int or None
    number of processes to use.
  verbose : bool
    If True, print progress information.
    
  Returns
  -------
  smoothed : array or Source
    Thre smoothed binary array.

  Note
  ----
  The algorithm is based on a topological smoothing operation defined by adding
  or removing forground pixels based on the local topology of the binary array.
  """
  if verbose:
    print('Binary smoothing: initialized!');
    timer = tmr.Timer();
  
  #smoothing function
  smooth = functools.partial(smooth_by_configuration_block, iterations=iterations, verbose=False);
  smooth.__name__ = 'smooth_by_configuration'
  
  #initialize sources and sinks
  source = io.as_source(source);
  sink   = io.initialize(sink, shape=source.shape, dtype=bool, order=source.order); 
  
  #block processing parameter
  block_processing_parameter = dict(axes = bp.block_axes(source), 
                                    as_memory=True, 
                                    overlap=None, 
                                    function_type='source',
                                    processes=processes, 
                                    verbose=verbose);
  if processing_parameter is not None:
    block_processing_parameter.update(processing_parameter);
  if not 'overlap' in block_processing_parameter or block_processing_parameter['overlap'] is None:
    block_processing_parameter['overlap'] = 2 + 2 * iterations;
  if not 'size_min' in block_processing_parameter or block_processing_parameter['size_min'] is None:
    block_processing_parameter['size_min'] = 2 + 2 * iterations + 1;
  if not 'axes' in block_processing_parameter or block_processing_parameter['axes'] is None:
    block_processing_parameter['axes'] = bp.block_axes(source);
  #print(block_processing_parameter)
  
  #block process
  bp.process(smooth, source, sink, **block_processing_parameter);
  
  if verbose:
    timer.print_elapsed_time('Binary smoothing: done');
  
  return sink;
Ejemplo n.º 24
0
def measure_expression(source,
                       points,
                       search_radius,
                       method='max',
                       sink=None,
                       processes=None,
                       verbose=False):
    """Measures the expression around a list of points in a source.
  
  Arguments
  ---------
  source : array 
    Source for measurement.
  points : array
    List of indices to measure radis for.
  search_radius : int or array
    List of search radii to use around each point. If int  use
    this radius for all points. Array should be of length of points.
  method : 'max' or 'min', 'mean'
    Measurement type.
  processes : int or None
    Number of processes to use.
  verbose : bool
    If True, print progress info.  
    
    
  """
    source = io.as_source(source)
    ndim = source.ndim

    if verbose:
        timer = tmr.Timer()
        print('Measuring expression of %d points in array of shape %r.' %
              (points.shape[0], source.shape))

    if not hasattr(search_radius, '__len__'):
        search_radius = search_radius * np.ones(points.shape[0])
    if len(search_radius) != len(points):
        raise ValueError('The search_radius is not valid!')

    indices, radii_indices = search_indices(search_radius, ndim)

    if method == 'max':
        expression = mpl.measure_max(source,
                                     points,
                                     indices,
                                     radii_indices,
                                     sink=sink,
                                     processes=processes,
                                     verbose=verbose)
    elif method == 'min':
        expression = mpl.measure_min(source,
                                     points,
                                     indices,
                                     radii_indices,
                                     sink=sink,
                                     processes=processes,
                                     verbose=verbose)
    elif method == 'mean':
        expression = mpl.measure_mean(source,
                                      points,
                                      indices,
                                      radii_indices,
                                      sink=sink,
                                      processes=processes,
                                      verbose=verbose)
    elif method == 'sum':
        expression = mpl.measure_sum(source,
                                     points,
                                     indices,
                                     radii_indices,
                                     sink=sink,
                                     processes=processes,
                                     verbose=verbose)
    else:
        raise ValueError("Method %r not in 'max', 'min', 'mean'" % method)

    if verbose:
        timer.print_elapsed_time('Measuring expression done')

    return expression
Ejemplo n.º 25
0
def detect_cells_block(source, parameter=default_cell_detection_parameter):
    """Detect cells in a Block."""

    #initialize parameter and slicings
    verbose = parameter.get('verbose', False)
    if verbose:
        prefix = 'Block %s: ' % (source.info(), )
        total_time = tmr.Timer(prefix)

    base_slicing = source.valid.base_slicing
    valid_slicing = source.valid.slicing
    valid_lower = source.valid.lower
    valid_upper = source.valid.upper
    lower = source.lower

    parameter_intensity = parameter.get('intensity_detection', None)
    measure_to_array = dict()
    if parameter_intensity:
        parameter_intensity = parameter_intensity.copy()
        measure = parameter_intensity.pop('measure', [])
        if measure is None:
            measure = []
        for m in measure:
            measure_to_array[m] = None

    if 'source' in measure_to_array:
        measure_to_array['source'] = source

    # correct illumination
    parameter_illumination = parameter.get('illumination_correction', None)
    if parameter_illumination:
        parameter_illumination = parameter_illumination.copy()
        if verbose:
            timer = tmr.Timer(prefix)
            hdict.pprint(parameter_illumination,
                         head=prefix + 'Illumination correction')
        save = parameter_illumination.pop('save', None)

        corrected = ic.correct_illumination(source, **parameter_illumination)

        if save:
            save = io.as_source(save)
            save[base_slicing] = corrected[valid_slicing]

        if verbose:
            timer.print_elapsed_time('Illumination correction')
    else:
        corrected = np.array(source.array)

    if 'illumination' in measure_to_array:
        measure_to_array['illumination'] = corrected

    #background subtraction
    parameter_background = parameter.get('background_correction', None)
    if parameter_background:
        parameter_background = parameter_background.copy()
        if verbose:
            timer = tmr.Timer(prefix)
            hdict.pprint(parameter_background,
                         head=prefix + 'Background removal')
        save = parameter_background.pop('save', None)

        background = remove_background(corrected, **parameter_background)

        if save:
            save = io.as_source(save)
            save[base_slicing] = corrected[valid_slicing]

        if verbose:
            timer.print_elapsed_time('Illumination correction')
    else:
        background = corrected

    del corrected

    if 'background' in measure_to_array:
        measure_to_array['background'] = background

    # equalize
    parameter_equalize = parameter.get('equalization', None)
    if parameter_equalize:
        parameter_equalize = parameter_equalize.copy()
        if verbose:
            timer = tmr.Timer(prefix)
            hdict.pprint(parameter_equalize, head=prefix + 'Equalization:')

        save = parameter_equalize.pop('save', None)

        equalized = equalize(background, mask=None, **parameter_equalize)

        if save:
            save = io.as_source(save)
            save[base_slicing] = equalized[valid_slicing]

        if verbose:
            timer.print_elapsed_time('Equalization')

    else:
        equalized = background

    del background

    if 'equalized' in measure_to_array:
        measure_to_array['equalized'] = equalized

    #DoG filter
    parameter_dog_filter = parameter.get('dog_filter', None)
    if parameter_dog_filter:
        parameter_dog_filter = parameter_dog_filter.copy()
        if verbose:
            timer = tmr.Timer(prefix)
            hdict.pprint(parameter_dog_filter, head=prefix + 'DoG filter:')

        save = parameter_dog_filter.pop('save', None)

        dog = dog_filter(equalized, **parameter_dog_filter)

        if save:
            save = io.as_source(save)
            save[base_slicing] = dog[valid_slicing]

        if verbose:
            timer.print_elapsed_time('DoG filter')

    else:
        dog = equalized

    del equalized

    if 'dog' in measure_to_array:
        measure_to_array['dog'] = dog

    #Maxima detection
    parameter_maxima = parameter.get('maxima_detection', None)
    parameter_shape = parameter.get('shape_detection', None)

    if parameter_shape or parameter_intensity:
        if not parameter_maxima:
            print(
                prefix +
                'Warning: maxima detection needed for shape and intensity detection!'
            )
            parameter_maxima = dict()

    if parameter_maxima:
        parameter_maxima = parameter_maxima.copy()
        if verbose:
            timer = tmr.Timer(prefix)
            hdict.pprint(parameter_maxima, head=prefix + 'Maxima detection:')

        save = parameter_maxima.pop('save', None)
        valid = parameter_maxima.pop('valid', None)

        # extended maxima
        maxima = md.find_maxima(source.array,
                                **parameter_maxima,
                                verbose=verbose)

        if save:
            save = io.as_source(save)
            save[base_slicing] = maxima[valid_slicing]

        #center of maxima
        if parameter_maxima['h_max']:
            centers = md.find_center_of_maxima(source,
                                               maxima=maxima,
                                               verbose=verbose)
        else:
            centers = ap.where(maxima).array

        if verbose:
            timer.print_elapsed_time('Maxima detection')

        #correct for valid region
        if valid:
            ids = np.ones(len(centers), dtype=bool)
            for c, l, u in zip(centers.T, valid_lower, valid_upper):
                ids = np.logical_and(ids, np.logical_and(l <= c, c < u))
            centers = centers[ids]
            del ids

    del dog, maxima

    results = (centers, )

    #cell shape detection
    if parameter_shape:
        parameter_shape = parameter_shape.copy()
        if verbose:
            timer = tmr.Timer(prefix)
            hdict.pprint(parameter_shape, head=prefix + 'Shape detection:')

        save = parameter_shape.pop('save', None)

        # shape detection
        shape = sd.detect_shape(source,
                                centers,
                                **parameter_shape,
                                verbose=verbose)

        if save:
            save = io.as_source(save)
            save[base_slicing] = shape[valid_slicing]

        #size detection
        max_label = centers.shape[0]
        sizes = sd.find_size(shape, max_label=max_label)
        valid = sizes > 0

        if verbose:
            timer.print_elapsed_time('Shape detection')

        results += (sizes, )

    else:
        valid = None
        shape = None

    #cell intensity detection
    if parameter_intensity:
        parameter_intensity = parameter_intensity.copy()
        if verbose:
            timer = tmr.Timer(prefix)
            hdict.pprint(parameter_intensity,
                         head=prefix + 'Intensity detection:')

        if not shape is None:
            r = parameter_intensity.pop('shape', 3)
            if isinstance(r, tuple):
                r = r[0]

        for m in measure:
            if shape is not None:
                intensity = sd.find_intensity(measure_to_array[m],
                                              label=shape,
                                              max_label=max_label,
                                              **parameter_intensity)
            else:
                intensity = me.measure_expression(measure_to_array[m],
                                                  centers,
                                                  search_radius=r,
                                                  **parameter_intensity,
                                                  processes=1,
                                                  verbose=False)

            results += (intensity, )

        if verbose:
            timer.print_elapsed_time('Shape detection')

    if valid is not None:
        results = tuple(r[valid] for r in results)

    #correct coordinate offsets of blocks
    results = (results[0] + lower, ) + results[1:]

    #correct shapes for merging
    results = tuple(r[:, None] if r.ndim == 1 else r for r in results)

    if verbose:
        total_time.print_elapsed_time('Cell detection')

    gc.collect()

    return results
Ejemplo n.º 26
0
def prepare_annotation_files(slicing=None,
                             orientation=None,
                             directory=None,
                             postfix=None,
                             annotation_file=None,
                             reference_file=None,
                             distance_to_surface_file=None,
                             overwrite=False,
                             verbose=False):
    """Crop the annotation, reference and distance files to match the data.
  
  Arguments
  ---------
  slicing : tuple or None
    The slice specification after reorienting.
  orientation : tuple, str or None.
    The orientation specification. Strings can be 'left' or 'right', for the
    two hemispheres.
  directory : str or None
    The target directory. If None, use ClearMap resources folder.
  postfix : str or None
    Use this postfix for the cropped annotation file. If None and automatic 
    label is choosen.
  annotation_file : str or None
    The annotation file to use.
  reference_file : str or None
    The reference file to use.
  distance_to_surface_file : str or None
    The distance file to use.
  overwrite : bool
    If True, overwrite exisitng files.
    
  Returns
  -------
  annotation_file : str
    The cropped annotation file.
  reference_file : str
    The cropped reference file.
  distance_to_surface_file : str
    The distance cropped file.
  """
    if annotation_file is None:
        annotation_file = default_annotation_file
    if reference_file is None:
        reference_file = default_reference_file
    if distance_to_surface_file is None:
        distance_to_surface_file = default_distance_to_surface_file

    files = [annotation_file, reference_file, distance_to_surface_file]

    results = []
    for f in files:
        if f is not None:
            fn = format_annotation_filename(f,
                                            orientation=orientation,
                                            slicing=slicing,
                                            postfix=postfix,
                                            directory=directory)
            if verbose:
                print('Preparing: %r' % fn)

            if not overwrite and io.is_file(fn):
                results.append(fn)
                continue

            if not io.is_file(f):
                raise ValueError('Cannot find annotation file: %s' % f)

            s = io.as_source(f)
            if verbose:
                print('Preparing: from source %r' % s)

            data = np.array(s.array)

            if not orientation is None:
                #permute
                per = res.orientation_to_permuation(orientation)
                data = data.transpose(per)

                #reverse axes
                reslice = False
                sl = [slice(None)] * data.ndim
                for d, o in enumerate(orientation):
                    if o < 0:
                        sl[d] = slice(None, None, -1)
                        reslice = True
                if reslice:
                    data = data[tuple(sl)]

            if slicing is not None:
                data = data[slicing]
            io.write(fn, data)
            results.append(fn)
        else:
            results.append(None)

    return results
Ejemplo n.º 27
0
def _test():
    import numpy as np
    import ClearMap.IO.IO as io
    import ClearMap.ParallelProcessing.BlockProcessing as bp

    source = io.as_source(np.asarray(np.random.rand(50, 100, 200), order='F'))

    blocks = bp.split_into_blocks(source,
                                  processes=10,
                                  axes=[2],
                                  size_min=30,
                                  size_max=50,
                                  overlap=20)
    print(blocks)

    b = blocks[0]
    print(b.valid.base_shape)
    print(b.valid.base_slicing)
    print(blocks[5].iteration)

    blocks = bp.split_into_blocks(source,
                                  processes=10,
                                  axes=[1, 2],
                                  size_min=30,
                                  size_max=50,
                                  overlap=20,
                                  neighbours=True)
    b = blocks[0]
    print(b.valid.base_shape)
    print(b.valid.base_slicing)

    blocks = bp.split_into_blocks(source,
                                  processes=10,
                                  axes=[1, 2],
                                  size_min='fixed',
                                  size_max=50,
                                  overlap=20,
                                  neighbours=True)
    b = blocks[0]
    print(b.valid.base_shape)
    print(b.valid.base_slicing)

    shape = (2, 3, 20)
    source = io.npy.Source(array=np.random.rand(*shape))
    sink = io.npy.Source(array=np.zeros(shape))

    def process_image(source, sink=None):
        if sink is None:
            sink = np.zeros(source.shape)
        sink[:] = 100 * source[:]
        return sink

    bp.process(process_image,
               source,
               sink,
               processes='serial',
               size_max=4,
               size_min=1,
               overlap=0,
               axes=[2],
               optimization=True,
               verbose=True)

    print(np.all(sink[:] == process_image(source)))

    bp.process(process_image,
               source,
               sink,
               processes=None,
               size_max=10,
               size_min=6,
               overlap=3,
               axes=all,
               optimization=True,
               verbose=True)

    assert (np.all(sink[:] == process_image(source)))

    result, blocks = bp.process(process_image,
                                source,
                                sink,
                                size_max=15,
                                size_min=4,
                                overlap=3,
                                axes=[2],
                                optimization=True,
                                return_blocks=True,
                                processes=None,
                                verbose=True)

    #memmaps loading
    source = io.mmp.create(location='source.npy', shape=shape)
    source[:] = np.random.rand(*shape)
    sink = io.mmp.create(location='sink.npy', shape=shape)

    bp.process(process_image,
               source,
               sink,
               size_max=10,
               size_min=6,
               overlap=3,
               axes=[2],
               optimization=True,
               as_memory=True,
               verbose=True,
               processes=None)

    assert (np.all(sink[:] == process_image(source)))

    io.delete_file(source.location)
    io.delete_file(sink.location)

    #multiple sources and sinks
    shape = (2, 50, 30)
    source1 = io.sma.Source(array=np.random.rand(*shape))
    source2 = io.sma.Source(array=np.random.rand(*shape))
    sink1 = io.sma.Source(array=np.zeros(shape))
    sink2 = io.sma.Source(array=np.zeros(shape))

    def sum_and_difference(source1, source2, sink1=None, sink2=None):
        if sink1 is None:
            sink1 = np.zeros(source1.shape)
        if sink2 is None:
            sink2 = np.zeros(source2.shape)

        sink1[:] = source1[:] + source2[:]
        sink2[:] = source1[:] - source2[:]
        return sink1, sink2

    bp.process(sum_and_difference, [source1, source2], [sink1, sink2],
               processes='!serial',
               size_max=10,
               size_min=5,
               overlap=3,
               axes=[1, 2],
               optimization=True,
               verbose=True)

    s, d = sum_and_difference(source1, source2)
    assert (np.all(sink1[:] == s))
    assert (np.all(sink2[:] == d))

    #trace backs
    shape = (3, 4)
    source = io.sma.Source(array=np.random.rand(*shape))
    sink = io.sma.Source(array=np.zeros(shape))

    def raise_error(source, sink=None):
        raise RuntimeError('test')

    bp.process(raise_error,
               source,
               sink,
               processes='!serial',
               size_max=10,
               size_min=5,
               overlap=0,
               axes=[2],
               optimization=True,
               verbose=True)
Ejemplo n.º 28
0
def postprocess(source, sink = None, postprocessing_parameter = default_postprocessing_parameter, processing_parameter = default_postprocessing_processing_parameter, processes = None, verbose = True):
  """Postprocess a binarized image.
  
  Arguments
  ---------
  source : source specification
    The binary  source.
  sink : sink specification or None
    The sink to write the postprocesses result to. 
    If None, an array is returned.
  postprocessing_parameter : dict
    Parameter for the postprocessing.
  processing_parameter : dict
    Parameter for the parallel processing.
  verbose : bool
    If True, print progress output.
  
  Returns
  -------
  sink : Source
    The result of the binarization.
    
  Notes
  -----
  * The postporcessing pipeline is composed of several steps. The parameters
    for each step are passed as sub-dictionaries to the 
    postprocessing_parameter dictionary.
  
  * If None is passed for one of the steps the step is skipped.
    
  Smoothing
  ---------
  smooth : dict or None
    Smoothing step parameter. See
    :func:`ClearMap.ImageProcessing.Binary.Smoothing.smooth_by_configuration`

    iterations : int
      Number of smoothing iterations.
      
      For the vasculature a typical value is 6.
  
  Filling
  -------
  fill : bool or None
    If True, fill holes in the binary data.
  """
  
  source = io.as_source(source);  
  sink   = ap.initialize_sink(sink, shape=source.shape, dtype=source.dtype, order=source.order, return_buffer=False);
  
  if verbose:
    timer = tmr.Timer();
    print('Binary post processing: initialized.');
  
  postprocessing_parameter = postprocessing_parameter.copy();
  parameter_smooth = postprocessing_parameter.pop('smooth', None);
  parameter_fill   = postprocessing_parameter.pop('fill', None);
  #print(parameter_smooth, parameter_fill)
  
  #smoothing
  save = None;
  if parameter_smooth:
    #intialize temporary files if needed
    if parameter_fill:
      save = parameter_smooth.pop('save', None);
      temporary_filename = save; 
      if temporary_filename is None:
        temporary_filename = postprocessing_parameter['temporary_filename'];
      if temporary_filename is None:
        temporary_filename = tmpf.mktemp(prefix='TubeMap_Vasculature_postprocessing', suffix='.npy');
      sink_smooth   = ap.initialize_sink(temporary_filename, shape=source.shape, dtype=source.dtype, order=source.order, return_buffer=False);
    else:
      sink_smooth = sink;
    
    #run smoothing
    source_fill = bs.smooth_by_configuration(source, sink=sink_smooth, processing_parameter=processing_parameter, processes=processes, verbose=verbose, **parameter_smooth);
  
  else:
    source_fill = source;
  
  if parameter_fill:
    sink = bf.fill(source_fill, sink=sink, processes=processes, verbose=verbose);
    
    if parameter_smooth and save is None:
      io.delete_file(temporary_filename);
  else:
    sink = source_fill;
  
  if verbose:
    timer.print_elapsed_time('Binary post processing');
  
  gc.collect()
  return None;
Ejemplo n.º 29
0
def binarize_block(source, sink, parameter = default_binarization_parameter):
  """Binarize a Block."""
  
  #initialize parameter and slicings
  verbose = parameter.get('verbose', False);
  if verbose:
    prefix = 'Block %s: ' % (source.info(),);
    total_time = tmr.Timer(prefix);
  
  max_bin = parameter.get('max_bin', MAX_BIN);
    
  base_slicing = sink.valid.base_slicing;
  valid_slicing = source.valid.slicing;

  #initialize binary status for inspection
  binary_status = parameter.get('binary_status', None);
  if binary_status:
    binary_status = io.as_source(binary_status);
    binary_status = binary_status[base_slicing];
  
  
  #clipping
  parameter_clip = parameter.get('clip', None);        
  if parameter_clip:
    parameter_clip = parameter_clip.copy();
    if verbose:
      timer = tmr.Timer(prefix);
      hdict.pprint(parameter_clip, head = prefix + 'Clipping:')
    parameter_clip.update(norm=max_bin, dtype=DTYPE);
    save = parameter_clip.pop('save', None);   
                          
    clipped, mask, high, low = clip(source, **parameter_clip);  
    not_low = np.logical_not(low);
    
    if save:
      save = io.as_source(save);
      save[base_slicing] = clipped[valid_slicing];
     
    if binary_status is not None:
      binary_status[high[valid_slicing]] += BINARY_STATUS['High']
    else:
      sink[valid_slicing] = high[valid_slicing]; 

    del high, low
    
    if verbose:
      timer.print_elapsed_time('Clipping');                          
  
  else:
    clipped = source
    mask = not_low = np.ones(source.shape, dtype=bool);
    #high = low = np.zeros(source.shape, dtype=bool);
    #low = np.zeros(source.shape, dtype=bool);
    #not_low = np.logical_not(low); 
  
  #active arrays: clipped, mask, not_low

                       
  #lightsheet correction
  parameter_lightsheet = parameter.get('lightsheet', None);                                
  if parameter_lightsheet:
    parameter_lightsheet = parameter_lightsheet.copy();
    if verbose:
      timer = tmr.Timer(prefix);
      hdict.pprint(parameter_lightsheet, head = prefix + 'Lightsheet:')                        
                                    
    #parameter_lightsheet.update(max_bin=max_bin);
    save = parameter_lightsheet.pop('save', None);                      
    
    corrected = lc.correct_lightsheet(clipped, mask=mask, max_bin=max_bin, **parameter_lightsheet);
           
    if save:
      save = io.as_source(save);
      save[base_slicing] = corrected[valid_slicing];
    
    if verbose:
      timer.print_elapsed_time('Lightsheet');                           
  else:
    corrected = clipped;
 
  del clipped
  #active arrays: corrected, mask, not_low
  
  #median filter
  parameter_median = parameter.get('median', None);
  if parameter_median:
    parameter_median = parameter_median.copy();
    if verbose:
      timer = tmr.Timer(prefix);
      hdict.pprint(parameter_median, head = prefix + 'Median:')    
    
    save = parameter_median.pop('save', None);      
    median = rnk.median(corrected, max_bin=max_bin, mask=not_low, **parameter_median);                              
    
    if save:
      save = io.as_source(save);
      save[base_slicing] = median[valid_slicing];
    
    if verbose:
      timer.print_elapsed_time('Median');   
    
  else:
    median = corrected;
  
  del corrected, not_low;
  #active arrays: median, mask
  
  #pseudo deconvolution
  parameter_deconvolution = parameter.get('deconvolve', None);
  if parameter_deconvolution:
    parameter_deconvolution = parameter_deconvolution.copy();
    if verbose:
      timer = tmr.Timer(prefix);
      hdict.pprint(parameter_deconvolution, head = prefix + 'Deconvolution:')
    
    save = parameter_deconvolution.pop('save', None);
    threshold = parameter_deconvolution.pop('threshold', None);  
   
    if binary_status is not None:
      binarized = binary_status > 0;
    else:
      binarized = sink[:];
    deconvolved = deconvolve(median, binarized[:], **parameter_deconvolution)
    del binarized
    
    if save:
      save = io.as_source(save);
      save[base_slicing] = deconvolved[valid_slicing];
    
    if verbose:
      timer.print_elapsed_time('Deconvolution');   
  
    if threshold:
      binary_deconvolved = deconvolved > threshold;
      
      if binary_status is not None:
        binary_status[binary_deconvolved[valid_slicing]] += BINARY_STATUS['Deconvolved'];
      else:
        sink[valid_slicing] += binary_deconvolved[valid_slicing];
    
      del binary_deconvolved
      
      if verbose:
        timer.print_elapsed_time('Deconvolution: binarization');   
  
  else:  
    deconvolved = median;
  
  #active arrays: median, mask, deconvolved
  
  #adaptive
  parameter_adaptive = parameter.get('adaptive', None);
  if parameter_adaptive:
    parameter_adaptive = parameter_adaptive.copy();
    if verbose:
      timer = tmr.Timer(prefix);
      hdict.pprint(parameter_adaptive, head = prefix + 'Adaptive:')    
    
    save = parameter_adaptive.pop('save', None);
    
    adaptive = threshold_adaptive(deconvolved, **parameter_adaptive)
    
    if save:
      save = io.as_source(save);
      save[base_slicing] = adaptive[valid_slicing];
    
    binary_adaptive = deconvolved > adaptive;
    
    if binary_status is not None:
      binary_status[binary_adaptive[valid_slicing]] += BINARY_STATUS['Adaptive'];
    else:
      sink[valid_slicing] += binary_adaptive[valid_slicing];
    
    del binary_adaptive, adaptive;
      
    if verbose:
      timer.print_elapsed_time('Adaptive');   
  
  del deconvolved
  #active arrays: median, mask
    
  # equalize 
  parameter_equalize = parameter.get('equalize', None);
  if parameter_equalize: 
    parameter_equalize = parameter_equalize.copy();
    if verbose:
      timer = tmr.Timer(prefix);
      hdict.pprint(parameter_equalize, head = prefix + 'Equalization:')    
    
    save = parameter_equalize.pop('save', None);
    threshold = parameter_equalize.pop('threshold', None);  

    equalized = equalize(median, mask=mask, **parameter_equalize);
        
    if save:
      save = io.as_source(save);
      save[base_slicing] = equalized[valid_slicing];
    
    if verbose:
      timer.print_elapsed_time('Equalization');
        
    if threshold:
      binary_equalized = equalized > threshold
      
      if binary_status is not None:
        binary_status[binary_equalized[valid_slicing]] += BINARY_STATUS['Equalized'];
      else:
        sink[valid_slicing] += binary_equalized[valid_slicing];
      
      #prepare equalized for use in vesselization
      parameter_vesselization = parameter.get('vesselize', None);
      if parameter_vesselization and parameter_vesselization.get('background', None):  
        equalized[binary_equalized] = threshold;
        equalized = float(max_bin-1) / threshold * equalized;
      
      del binary_equalized
    
      if verbose:
        timer.print_elapsed_time('Equalization: binarization');
  else:
    equalized = median;
  
  del median
  #active arrays: mask, equalized
    
  # smaller vessels /capilarries
  parameter_vesselization = parameter.get('vesselize', None);
  if parameter_vesselization:
    parameter_vesselization = parameter_vesselization.copy();
    if verbose:
      timer = tmr.Timer(prefix);
      hdict.pprint(parameter_vesselization, head = prefix + 'Vesselization:')    
    
    parameter_background = parameter_vesselization.get('background', None)
    parameter_background = parameter_background.copy();
    if parameter_background:
      save = parameter_background.pop('save', None);
      
      equalized = np.array(equalized, dtype = 'uint16');
      background = rnk.percentile(equalized, max_bin=max_bin, mask=mask, **parameter_background);
      tubeness = equalized - np.minimum(equalized, background);  
      
      del background                  
      
      if save:
        save = io.as_source(save);
        save[base_slicing] = tubeness[valid_slicing];
    
    else:
      tubeness = equalized;
    
    parameter_tubeness = parameter_vesselization.get('tubeness', {})
    tubeness = tubify(tubeness, **parameter_tubeness);
    
    save = parameter_vesselization.get('save', None);
    if save:
      save = io.as_source(save);
      save[base_slicing] = tubeness[valid_slicing];
       
    if verbose:
      timer.print_elapsed_time('Vesselization');  
      
    threshold = parameter_vesselization.get('threshold', None);
    if threshold:      
      binary_vesselized = tubeness > threshold;
      
      if binary_status is not None:
        binary_status[binary_vesselized[valid_slicing]] += BINARY_STATUS['Tube'];
      else:
        sink[valid_slicing] += binary_vesselized[valid_slicing];
      
      del binary_vesselized 
      
      if verbose:
        timer.print_elapsed_time('Vesselization: binarization');   
    
    del tubeness
  
  del equalized, mask
  #active arrays: None
  
  #fill holes  
  parameter_fill = parameter.get('fill', None);
  if parameter_fill:
    parameter_fill = parameter_fill.copy();
    if verbose:
      timer = tmr.Timer(prefix);
      #hdict.pprint(parameter_fill, head = 'Filling:')    
      
    if binary_status is not None:
      foreground = binary_status > 0;
      filled = ndi.morphology.binary_fill_holes(foreground);
      binary_status[np.logical_and(filled, np.logical_not(foreground))] += BINARY_STATUS['Fill'];
      del foreground, filled
    else:
      filled = ndi.morphology.binary_fill_holes(sink[:]);
      sink[valid_slicing] += filled[valid_slicing]; 
      del filled
    
    if verbose:
      timer.print_elapsed_time('Filling');   

  if binary_status is not None:
    sink[valid_slicing] = binary_status[valid_slicing] > 0;

  #smooth binary  
  parameter_smooth = parameter.get('smooth', None);
  if parameter_smooth:
    parameter_smooth = parameter_smooth.copy();
    if verbose:
      timer = tmr.Timer(prefix);
      hdict.pprint(parameter_smooth, head = prefix + 'Smoothing:')    
    
    smoothed = bs.smooth_by_configuration(sink, sink=None, processes=1, **parameter_smooth);
    sink[valid_slicing] = smoothed[valid_slicing]; 
    del smoothed;
      
    if verbose:
      timer.print_elapsed_time('Smoothing');  
   
  if verbose:
    total_time.print_elapsed_time('Binarization')
  
  gc.collect()
  
  return None;
Ejemplo n.º 30
0
def threshold_adaptive(source, function = threshold_isodata, selem = (100,100,3), spacing = (25,25,3), interpolate = 1, mask = None, step = None):
  source = io.as_source(source)[:];
  threshold = ls.apply_local_function(source, function=function, mask=mask, dtype=float, selem=selem, spacing=spacing, interpolate=interpolate, step = step);
  return threshold