License Type Branch status Build Status Code Coverage Code Health

Image Pipe

Pipeline building solution for 4D biological microscopy

Description:

This project is still in development. Initially started as a tool for Ruan, Zhou et al, Nature 2017, this pipeline has since grown to allow arbitrary pipeline construction based on a set of primitive functions and abstractions (pipe, tiling, per-segment processing, etc…).

This project is currently in alpha development, hence poorly documented, sparsely tested and prone to rapid changes.

Basic installation:

> pip install imagepipe

or:

> pip install git+https://github.com/chiffa/Image_pipe.git

The documentation is available on readthedocs.

Project is housed at GitHub. For any issues please refer to GitHub issue tracker.

Usage Guides:

Installation and requirements:

script:

> pip install imagepipe

Pipeline and functions overview:

Basic usage:

Dev log:

This is a general library for image processing

Logic in the

Logic layers: 1. Traversal 2. Matching of the images to different channels 3. Segmentation of a. Mitochondria b. Cells 4. Retrieval of descriptors each surface/volume 5. Classification of a surface/volume a. with respect to the signal intensity => Cell death b. with respect to the geometry i. Area, skeleton, => fragmented mitochondria or not 6. Re-hashing of the file names in order to extract time-stamp 7. Perform time-line tracing and statistics calculation

DEBUG: output the graphical representation of what has been done by different cell

Desired code:

# Attach the debuger
set.debugger(dump_location = "./verification/", layers={"layer1":12, })

# point to the source folder
set.source_folder("xxxx")

# map a pattern in the name to a color channel
input.images = set.color_pattern({"_1465":"green", "_2660":"red"})

intermediate.cells = pipeline.step.add(segment.cells(input.images["green"], binary=True), debugger=layer1)
intermediate.cells = pipeline.step.add(remove outliers(intermediate.cells, "green"), debugger=layer2)
intermediate.cells = pipeline.step.add(remove outliers(intermediate.cells, "red"), debugger=layer2)
intermediate.granules = pipeline.step.add(segment.granules(intermediate.cells, "green"), debugger=layer3)
intermediate.mitochondriae = pipeline.step.add(segment.threshold(intermediate.cells, "red"), debugger=layer3)

colocalization = pipeline.step.add(colocalization.first_in_second(granules, mitochondriae), debugger=layer3)
anti_colocalization = pipeline.step.add(colocalization.first_in_second(granules, not(mitochondriae)), debugger=layer3)

pipeline.save.pattern(input.image.shorcode, colocalization, anti_colocalization)

save.location("final_table.csv")

pipeline.run()

Remarks:

In fact, we don’t really need an explicit pipeline class to assem ble the pipeline. We use intermediate variables within the user class in order `to stitch the pipeline and store the intermediate processes. We can as well plug the debug process to get the function debug output as it goes.

Unless we are using yield statements, in which case the pipeline would be performing processing ticks.

Idea - separate the namespaces that are logical in the context of the analysis

In order to avoid the generator once-consumed property, use multiple pass-through objects in dicts. That will also make it for an easy debugging in the end

Formalism:

Can we replace the in_channel, out_channel, log_channel with actual bindings to the variables? Right now, we are using an explicit dict for scope passing - could we rather use the function names?

What I am trying is basically to make flow control explicit by using an assembly-line model. The sort-coming is that I am using words, so I am using a lot Python interpreter errors and IDEs power.

A way around it is to hack the pipeline in the same manner as the guy who wrote hy (py-lisp)

Sub-segmentation

As of now, the mechanics of our method are operation only on the full image frames. If we want to segment the image for the analysis any further, for instance in order to perform cell-specific processing, would need to: - have a sencond generator wrapping / unwrapping routine - second-level dictionary store in the dict. Basically a

The second generator is basically a wrapper around the generator wrapper to execute the same instruction over a generator of generators, where the inner generator is processed by the generator wrapper logic, whereas the outer is processed by the second layer of wrapping

=> That’s basically a double generator_wrapper, but that cannot support the expected dims because a dict is being passed. => We actually just need the outer wrapper, the inner can be just the generator wrapper

Registering Run:

As of now, it is pretty trivial to get the current revision from git and the source/dump locations of all the elements. to get the replicability within the pipeline.

Possible usages:

  • Assembly of generator-based sub-pipes
  • Assembly of input-output chains and then wrapping them into pipe

Organization:

  • Core functions => Non-wrapped, testable
  • Pipeline logic => Generator-wrapped, ready for assembly; wrappers
  • Pre-assembled filters
  • It is all to be imported into the actual field and

From the usage

  • we definitely need a pipeline assembly - it is too easy to forget the pipe redirections between the generators
  • it is a bit frustrating to be unable to add elementary modifications to channels when they are injected
  • protection against dims mismatch is good and saves some time
  • the fact that stack trace returns nothing informative is definitely a minus

Reformulation

A pretty clear way of dealing with it is to re-write to get rid of the wrappers and reduce it all to a main for loop with embedded for sub-loops. Nitty-gritty details: - splitter needs to be a generator, returning values we want to use in the end - secondary namespace - point/tile/summarize

Audit:

  • Word audit trail explaining what function does?
  • Image binding into the final rendering frame?

API documentation:

imagepipe package

Subpackages

imagepipe.tools package

Submodules
imagepipe.tools.helpers module
exception imagepipe.tools.helpers.PipeArgError

Bases: exceptions.ValueError

imagepipe.tools.helpers.list_not_string(argument)

function that checks if a list is not a string

credits: http://stackoverflow.com/questions/1055360/how-to-tell-a-variable-is-iterable-but-not-a-string

Parameters:argument
Returns:
imagepipe.tools.helpers.safe_dir_create(path)
imagepipe.tools.helpers.tiff_stack_2_np_arr(tiff_location)

Loads the image from the tiff stack to a 3D numpy array

Parameters:tiff_location
Returns:
Module contents

Submodules

imagepipe.core_functions module

imagepipe.core_functions.doublewrap(f)

a decorator decorator, allowing the decorator to be used as: @decorator(with, arguments, and=kwargs) or @decorator

credits: http://stackoverflow.com/questions/653368/how-to-create-a-python-decorator-that-can-be-used-either-with-or-without-paramet

imagepipe.core_functions.for_each(outer_generator, embedded_transformer, inside, **kwargs)
imagepipe.core_functions.generator_wrapper(*args, **kwargs)
imagepipe.core_functions.pad_skipping_iterator(secondary_namespace)
imagepipe.core_functions.paint_from_mask(outer_generator, based_on, in_anchor, out_channel=None)
imagepipe.core_functions.splitter(outer_generator, to, sources, mask)

Creates a secondary namespace by using mask as a pad to conserve only certain segments in sources

Parameters:
  • outer_generator
  • to
  • sources
  • mask
Returns:

imagepipe.core_functions.tile_from_mask(outer_generator, based_on, in_anchor, out_channel=None)

imagepipe.debug_renders module

imagepipe.density_plot module

imagepipe.density_plot.better2D_desisty_plot(xdat, ydat, thresh=3, bins=(100, 100))

imagepipe.iterate_and_check_img_files module

imagepipe.iterate_and_check_img_files.iterate_and_check_img(filename)

imagepipe.raw_functions module

This module contains raw function definitions that can be either used directly or wrapped and then assembled in pipelines

imagepipe.raw_functions.agreeing_skeletons(float_surface, mito_labels)

Calculates agreeing skeletonization by both median and morphological skeletons

Parameters:
  • float_surface – float volume on which we need to calculate the values
  • mito_labels – labels that will be skeletonized
Returns:

imagepipe.raw_functions.average_qualifying_value_per_region(region_labels, image_2d, qualifying_mask)

Calculates average qualifying value per region of interest

Parameters:
  • region_labels
  • image_2d
  • qualifying_mask
Returns:

np.array list of average values, 2d pad of average values

imagepipe.raw_functions.binarize_2d(float_surface, cutoff_type='static', mcc_cutoff=None)

Performs a 2d binarization based on several possible methods

Parameters:
  • float_surface
  • cutoff_type – [‘otsu’, ‘local_otsu’, ‘static’, ‘log-otsu”]. Local Otsu is done with 5px mask
  • mcc_cutoff – is cutoff_type is ‘static’, this will be the cutoff threshold
Returns:

binary labels

imagepipe.raw_functions.binarize_3d(floats_volume, cutoff)

Performs a 3d binarization

Parameters:
  • floats_volume
  • cutoff
Returns:

imagepipe.raw_functions.classify_fragmentation_for_mitochondria(label_mask, skeletons)

Performs mitochondria fragmentation based off the labels mask and skeletons mask

Parameters:
  • label_mask
  • skeletons
Returns:

imagepipe.raw_functions.clear_based_on_2d_mask(stack, mask)

Sets to 0 in 3d everything covered by the mask along the z axis

Parameters:
  • stack – 3d image stack
  • mask
Returns:

imagepipe.raw_functions.detect_upper_outliers(value_list)

Performs upper outlier detection based on the extreme value distribution intuition. Works best with over 15 data elements

Parameters:value_list
Returns:positions of non-outliers, baseline curve of sorted averages, error margins
imagepipe.raw_functions.exclude_region(exclusion_mask, base_image, _dilation=5)

Excludes the region where exclusion_mask is true from the base image.

Parameters:
  • exclusion_mask
  • base_image
  • _dilation – if set to anything other than 0, would perform a morphological dilation using this parameter value as size on the exclusion mask
Returns:

imagepipe.raw_functions.f_2d_stack_2d_filter(_2d_stack, _2d_filter)

helper function to apply the 2d filter to a 2d image while creating an image copy

Parameters:
  • _2d_stack
  • _2d_filter
Returns:

imagepipe.raw_functions.f_3d_stack_2d_filter(_3d_stack, _2d_filter)

helper function to apply 2d filter to a 3d image along the z axis

Parameters:
  • _3d_stack
  • _2d_filter
Returns:

imagepipe.raw_functions.filter_labels(labels, binary_mask, min_feature_size=10)

Applies the binary mask to labels, than filters out all the labels with feature size less than min_feature_size

Parameters:
  • labels
  • binary_mask
  • min_feature_size
Returns:

imagepipe.raw_functions.gamma_stabilize(image, alpha_clean=5, floor_method='min')

Normalizes the luma curve. floor intensity becomes 0 and max allowed by the bit number - 1

Parameters:
  • image
  • alpha_clean – size of features that would be removed if surrounded by a majority of
  • floor_method – [‘min’, ‘1q’, ‘5p’, ‘median’] method of setting the floor intensity. 1q is first quartile, 1p is the first percentile
Returns:

imagepipe.raw_functions.improved_watershed(binary_base, intensity, expected_separation=10)

Improved watershed method that takes in account minimum intensity as well as minimal size of separation between the elements

Parameters:
  • binary_base – support for watershedding
  • intensity – intensity value used to exclude watershed points with too low of intensity
  • expected_separation – expected minimal separation (in pixels) between watershed centers
Returns:

imagepipe.raw_functions.in_contact(mask1, mask2, distance=10)

Finds if two binary masks are in contact or proximity. distance of detection is defined by the distance parameter

Parameters:
  • mask1
  • mask2
  • distance
Returns:

two arrays of the same shape as masks, each with ones for labels that overlap.

imagepipe.raw_functions.label_and_correct(binary_channel, value_channel, min_px_radius=3, min_intensity=0, mean_diff=10)
Labelling of a binary image, with constraints on minimal feature size, minimal intensity of area
covered by a binary label or minimal mean difference from background
Parameters:
  • binary_channel
  • value_channel – used to compute total intensity
  • min_px_radius – minimal feature size
  • min_intensity – minimal total intensity
  • mean_diff – minimal (multiplicative) difference from the background
Returns:

imagepipe.raw_functions.label_based_aq(labels, field_of_interest)

Calculates average qualifying intensity of field of interest based on the labels mask

Parameters:
  • labels
  • field_of_interest
Returns:

list of averages, pad of averages

imagepipe.raw_functions.locally_normalize(channel, local_xy_pool=5, local_z_pool=2)

Performs a per- zslice local normalization of a 3d channel

Parameters:
  • channel
  • local_xy_pool – size of the neighborhood to be considered for normalization
  • local_z_pool – placeholder, currently unused
Returns:

normalized 3d channel

imagepipe.raw_functions.mask_filter_2d(base, _filter)

Applies a filter a base mask in 2d

Parameters:
  • base
  • _filter
Returns:

imagepipe.raw_functions.max_projection(current_image)

Max projection along z axis

Parameters:current_image
Returns:
imagepipe.raw_functions.otsu_tresholding(shape_base)

perofrms an otsu thresholding based of the shape_base

Parameters:shape_base
Returns:
imagepipe.raw_functions.paint_mask(label_masks, labels_to_paint)

Paints a labeled mask based off a numpy list of values assigned to labels to paint.

Parameters:
  • label_masks
  • labels_to_paint – 1d numpy array with values that need to be painted on the labels.
Returns:

imagepipe.raw_functions.qualifying_gfp(max_sum_projection)

Creates a binary mask for qualifying gfp

Parameters:max_sum_projection
Returns:binary mask
imagepipe.raw_functions.random_walker_binarize(base_image, _dilation=0)

Improved random walker binarization based on the the scikits image library

Parameters:
  • base_image
  • _dilation – if set to anything other than 0, would perform a morphological dilation using this parameter value as size
Returns:

binary labels

imagepipe.raw_functions.robust_binarize(base_image, _dilation=0, heterogeity_size=10, feature_size=50)

Robust binarization algorithm based off random walker clustering

Parameters:
  • base_image
  • _dilation – if set to anything other than 0, would perform a morphological dilation using this parameter value as size
  • heterogeity_size – size of the feature (px) that the method will try to eliminate by smoothing
  • feature_size – size of the feature (px) that the method will try to segment out
Returns:

binary_labels

imagepipe.raw_functions.smooth(image, smoothing_px=1.5)

Gaussian smoothing of the image

Parameters:
  • image
  • smoothing_px
Returns:

imagepipe.raw_functions.smooth_2d(image, smoothing_px=1.5)

Gaussian smoothing of a 2d image

Parameters:
  • image
  • smoothing_px
Returns:

imagepipe.raw_functions.split_and_trim(path_prefix, main_root)

helper function for OS Path trimming routine that accounts for the trailing separator

Parameters:
  • path_prefix – [str]
  • main_root – [str]

:return:[list]

imagepipe.raw_functions.sum_projection(image)

Sum projection along z axis

Parameters:image
Returns:
imagepipe.raw_functions.volume_aqvi(float_volume, binary_volume)

Calculates the average of the float volume after filtering it through the binary volume

Parameters:
  • float_volume
  • binary_volume
Returns:

imagepipe.raw_functions.volume_mqvi(float_volume, binary_volume)

Calculates the median of the float volume after filtering it through the binary volume

Parameters:
  • float_volume
  • binary_volume
Returns:

imagepipe.raw_functions.voronoi_segment_labels(binary_labels)

Performs a Voronoi segmentation on binary labels (assuming background is set to 0)

Parameters:binary_labels
Returns:pad with labels of segmentation of the same size as binary_labels

imagepipe.traversals module

imagepipe.traversals.color_based_traversal(main_root, coding_separator='.', group_anchor=1)

Traverses the main root directory pulling the data from the images. different layers are assumed to be different colors, images are assumed to be 2D.

Parameters:
  • main_root
  • coding_separator – character used to derived codename of the image
  • group_anchor – position where the group information is stored
Returns:

imagepipe.traversals.name_channels(stack_group_generator, channel_names)

Assigns names to the channel for the future processing and bundles them together

Parameters:
  • stack_group_generator – generator returning image stack,
  • channel_names
Returns:

imagepipe.traversals.z_stack_based_traversal(main_root, matching_rule='c', matching_map=None)

Traverses the main_root directory, looking for all the ‘.tif/.TIF’ files, performs name matching then iterates through the resulting matched dictironary.

Matching assumption is that except for the matching keys, the names are identical

Parameters:
  • main_root – folder from which will be traversed in depth
  • matching_rule – name modification to type mapping. Currently ‘’ for no matching, ‘color’ for colors
  • matching_map – {‘pattern in the file name’: color channel number}
Returns:

imagepipe.wrapped_functions module

This module essentially wraps the functions to be compatible with the usage inside the pipelines

Module contents

Indices and tables