Frame Generation#

Read metadata and images from microscopy files.

Frame Generator#

This module provides the gen_opener generator, which given a path a microscope file returns the frames in the image one-by-one wrapped in a MicroscopeFrame object. This contains the pixel information in the frame and the metadata of the frame such as the corresponding pixel size in the image.

Javabridge#

Opening microscopy files is surprisingly non-trivial, requiring the use of bftools [link] and python-javabridge. This introduces a great deal of complications into the software:

  • The javabridge can only be started once and care must be taken to shut it down in the case of exception, otherwise the process will hang on error.

  • Javabridge is not compatible with multiprocessing - hence why we have deal with only one file per run when getting the Fourier terms.

  • Java garbage collection spawns many threads in a high core system, such as a server and consumes arbitrary resources unless the environment variable JAVA_THREADS = 0, which is set in the multicore_saftey.py module.

  • Java logging interacts poorly with the expected python output on stdout

To deal with this we provide a @vmManager wrapper, this ensures that the javaVM is shutdown properly even if the function exits with an error (finally clause) and suppresses java logging messages below ERROR. However, we are still unable to open the javabridge a second time within the same python process!

Reading metadata#

While there is a open standard for microscopy data metadata and format, these are not strictly adhered to and so we have to handle these cases explicitly

Microscope files are surprisingly in-homogeneous, we currently support the following file types:

  • DONE: Andor: .ims, .lif, .ome.tif

  • ON-GOING: Zeiss: .czi

Outline#

Returns a generator for the frames of the image, this is designed to be called once per files. This allows better organization by tools such as snakemake. While this limits the parallelism somewhat, bioformats and javabridge handles parallelism badly.

If there are multiple Z-planes then we return these in a 3d array, then we iterate through the time steps.

Objects#

FrameGen

Generator for frames, contains metadata that is common to each file type.

MicroscopeFrame

Container for the frame image and metadata unique to that frame.

class flickerprint.common.frame_gen.MicroscopeFrame(im_data: ndarray, im_path: Path, frame_num: int, total_frames: int, timestamp: int = 0, pixel_size: float = 1.0, actual_pixel_size: bool = True, actual_timestamp: bool = False)#

Store a single image frame, along with metadata, from the microscope.

Included metadata:

  • frame_num: The index of this frame in the time series

  • total_frames: The total number of frames in the time series

  • timestamp: [Optional] The image was taken according to the microscope

  • pixel_size: [Optional] The size of the image pixel on the sample, typically measured in μm/pixel

  • actual_pixel_size: [bool] Is the pixel-size included in the metadata

  • actual_timestamp: [bool] Is the timestamp recorded from the image

property summaryRow#

Create a summary row of the data as a dictionary.

flickerprint.common.frame_gen.gen_opener(im_path)#

Return a generator based on the provided image_path.

For now we simply search for the correct extension. A generator for the MicroscopeFrames s and common metadata.