#!/usr/bin/env python
# -*- coding: utf-8 -*-
# ------------------------------------------------------------------------------
# Copyright (c) 2022 Univ. Lyon, ENS de Lyon, UCB Lyon 1, CNRS, INRAe, Inria
# All rights reserved.
# This file is part of the TimageTK library, and is released under the "GPLv3"
# license. Please see the LICENSE.md file that should have been included as
# part of this package.
# ------------------------------------------------------------------------------
"""This module contains tools to generate 2D intensity projections for a time series of grayscale images."""
from os import sep
from imageio import imwrite as io_imwrite
from imageio import mimsave as gif_writer
from timagetk.algorithms.resample import resample
from timagetk.algorithms.trsf import apply_trsf
from timagetk.bin.logger import get_logger
from timagetk.tasks.registration import sequence_registration
from timagetk.visu.projection import projection
log = get_logger(__name__)
[docs]
def sequence_projections(list_img, method='contour', register=False, export_png=False, **kwargs):
"""Get the list of Max Intensity Projections from list of images.
Parameters
----------
list_img : list of SpatialImage
List of 3D image to project.
method : str, optional
Method to use for projection, see ``PROJECTION_METHODS`` for available methods.
register : bool, optional
If ``True``, default is ``False``, performs a rigid sequence registration before generating MIPs.
export_png : bool, optional
If ``True``, default is ``False``, export the individual MIPs as PNG files.
Other Parameters
----------------
axis : {'x', 'y', 'z'}
Axis to use for projection.
invert_axis : bool
If ``True``, revert the selected axis before projection.
threshold : int
Threshold to use with the 'contour' method.
Returns
-------
list
2D SpatialImage
See Also
--------
timagetk.visu.projection.PROJECTION_METHODS
Examples
--------
>>> from timagetk.io import imread
>>> from timagetk.io.util import shared_dataset
>>> from timagetk.tasks.registration import sequence_registration
>>> from timagetk.visu.temporal_projection import sequence_projections
>>> from timagetk.visu.mplt import grayscale_imshow
>>> times = shared_dataset("p58", "time-points")
>>> list_fnames = shared_dataset("p58", "intensity")
>>> list_images = [imread(fname) for fname in list_fnames]
>>> # Generates the max intensity projections:
>>> mips = sequence_projections(list_images, method='maximum')
>>> grayscale_imshow(mips)
>>> # Generates & save the max intensity projections as PNGs:
>>> mips = sequence_projections(list_images, threshold=45, export_png=True)
>>> # Register image list then generates & save the max intensity projections as PNGs:
>>> mips = sequence_projections(list_images, threshold=45, register=True, export_png=True)
"""
if register:
list_trsf = sequence_registration(list_img, method='rigid')
ref_img = list_img[-1]
for n, trsf in enumerate(list_trsf):
float_img = list_img[n]
list_img[n] = apply_trsf(float_img, trsf, template_img=ref_img)
mips = []
for img in list_img:
mip = projection(img, method=method, **kwargs)
mips.append(mip)
if export_png:
fp, fn = img.filepath, img.filename
path = fp if fp != '' else img.metadata['filepath']
name = fn if fn != '' else img.metadata['filename']
# Defines the PNG filename:
png_name = path + sep + name + '_mip.png'
log.info(f"Saving MIP: {png_name}")
io_imwrite(png_name, mip.get_array(), format='png', dpi=mip.voxelsize * 100)
log.info("Done.\n")
return mips
[docs]
def mips2gif(mips, gif_fname, fps=1., reshape=None):
"""Write an animated GIF file from the sequence of mips.
Parameters
----------
mips : list(SpatialImages)
List of MIPs, *i.e.* 2D projections of images
gif_fname : str
Name of the gif file to write
fps : float, optional
Frame per second, default is 1.
reshape : list, optional
The shape of the GIF image to return, *e.g.* [256, 256]
Notes
-----
If your images have different shapes, you should register them over the
temporal sequence or specify a shape to apply to all images so they all fit
in the GIF.
Examples
--------
>>> from timagetk.io import imread
>>> from timagetk.io.util import shared_dataset
>>> from timagetk.visu.temporal_projection import sequence_projections
>>> from timagetk.visu.temporal_projection import mips2gif
>>> times = shared_dataset("p58", "time-points")
>>> list_fnames = shared_dataset("p58", "intensity")
>>> list_images = [imread(fname) for fname in list_fnames]
>>> # Register image list then generates the max intensity projections:
>>> mips = sequence_projections(list_images, threshold_value=45, register=True)
>>> # Example #1 - Generate GIF animation:
>>> from timagetk.io.util import shared_data
>>> mips2gif(mips, shared_data("p58_TimeLapse.gif", "p58"))
>>> # Example #2 - Generate GIF animation and control the final size to 265x256:
>>> mips2gif(mips, shared_data("p58_TimeLapse.gif", "p58"), reshape=[256, 256])
"""
if reshape is not None:
for n, img in enumerate(mips):
mips[n] = resample(img, shape=reshape)
gif_writer(gif_fname, [m.get_array() for m in mips], format='gif', fps=fps)
return "Saved GIF under: '{}'".format(gif_fname)