imcflibs.imagej.shading

Functions to work on shading correction / model generation.

  1"""Functions to work on shading correction / model generation."""
  2
  3import os
  4
  5import ij  # pylint: disable-msg=import-error
  6
  7from ..imagej import bioformats  # pylint: disable-msg=no-name-in-module
  8from ..imagej import misc, projections
  9from ..log import LOG as log
 10from ..pathtools import gen_name_from_orig, listdir_matching
 11
 12
 13def apply_model(imps, model, merge=True):
 14    """Apply a given shading model to a list of images / stacks.
 15
 16    The model is supposed to be a normalized 32-bit floating point 2D image that
 17    will be used as a divisor to the slices of all ImagePlus objects given.
 18
 19    WARNING: the operation happens in-place, i.e. the original "imps" images
 20    will be modified!
 21
 22    Parameters
 23    ----------
 24    imps : list(ij.ImagePlus)
 25        A list of ImagePlus objects (e.g. separate channels of a multi-channel
 26        stack image) that should be corrected for shading artefacts.
 27    model : ij.ImagePlus
 28        A 2D image with 32-bit float values normalized to 1.0 (i.e. no pixels
 29        with higher values) to be used for dividing the input images to correct
 30        for shading.
 31    merge : bool, optional
 32        Whether or not to combine the resulting ImagePlus objects into a single
 33        multi-channel stack (default=True).
 34
 35    Returns
 36    -------
 37    ij.ImagePlus or list(ij.ImagePlus)
 38        The merged ImagePlus with all channels, or the original list of stacks
 39        with the shading-corrected image planes.
 40    """
 41    log.debug("Applying shading correction...")
 42    calc = ij.plugin.ImageCalculator()
 43    for i, stack in enumerate(imps):
 44        log.debug("Processing channel %i...", i)
 45        calc.run("Divide stack", stack, model)
 46
 47    if not merge:
 48        return imps
 49
 50    log.debug("Merging shading-corrected channels...")
 51    merger = ij.plugin.RGBStackMerge()
 52    merged_imp = merger.mergeChannels(imps, False)
 53    return merged_imp
 54
 55
 56def correct_and_project(filename, path, model, proj, fmt):
 57    """Apply a shading correction to an image and create a projection.
 58
 59    In case the target file for the shading corrected image already exists,
 60    nothing is done - neither the shading correction is re-created nor any
 61    projections will be done (independent on whether the latter one already
 62    exist or not).
 63
 64    Parameters
 65    ----------
 66    filename : str
 67        The full path to a multi-channel image stack.
 68    path : str
 69        The full path to a directory for storing the results. Will be created in
 70        case it doesn't exist yet. Existing files will be overwritten.
 71    model : ij.ImagePlus or None
 72        A 32-bit floating point image to be used as the shading model. If model
 73        is None, no shading correction will be applied.
 74    proj : str
 75        A string describing the projections to be created. Use 'None' for not
 76        creating any projections, 'ALL' to do all supported ones.
 77    fmt : str
 78        The file format suffix to be used for the results and projections, e.g.
 79        '.ics' for ICS2 etc. See the Bio-Formats specification for details.
 80
 81    Returns
 82    -------
 83    (bool, bool)
 84        A tuple of booleans indicating whether a shading correction has been
 85        applied and whether projections were created. The latter depends on
 86        both, the requested projections as well as the image type (e.g. it can
 87        be False even if projections were requested, but the image)
 88    """
 89    target = gen_name_from_orig(path, filename, "", fmt)
 90    if os.path.exists(target):
 91        log.info("Found shading corrected file, not re-creating: %s", target)
 92        return False, False
 93
 94    if not os.path.exists(path):
 95        os.makedirs(path)
 96
 97    imps = bioformats.import_image(filename, split_c=True)
 98    ret_corr = False
 99    if model is not None:
100        log.debug("Applying shading correction on [%s]...", filename)
101        imp = apply_model(imps, model)
102        bioformats.export_using_orig_name(imp, path, filename, "", fmt, True)
103        # imps needs to be updated with the new (=merged) stack:
104        imps = [imp]
105        ret_corr = True
106
107    if proj == "None":
108        projs = []
109    elif proj == "ALL":
110        projs = ["Average", "Maximum"]
111    else:
112        projs = [proj]
113    for imp in imps:
114        ret_proj = projections.create_and_save(imp, projs, path, filename, fmt)
115        imp.close()
116
117    log.debug("Done processing [%s].", os.path.basename(filename))
118    return ret_corr, ret_proj
119
120
121def process_folder(path, suffix, outpath, model_file, fmt):
122    """Run shading correction and projections on an entire folder.
123
124    Parameters
125    ----------
126    path : str
127        The input folder to be scanned for images to be processed.
128    suffix : str
129        The file name suffix of the files to be processed.
130    outpath : str
131        The output folder where results will be stored. Existing files will be
132        overwritten.
133    model_file : str
134        The full path to a normalized 32-bit shading model image. If set to '-'
135        or 'NONE', no shading correction will be applied, i.e. only the
136        projection step will have an effect.
137    fmt : str
138        The file format suffix for storing the results.
139    """
140    matching_files = listdir_matching(path, suffix, fullpath=True)
141    process_files(matching_files, outpath, model_file, fmt)
142
143
144def process_files(files, outpath, model_file, fmt):
145    """Run shading correction and projections on a list of files.
146
147    Parameters
148    ----------
149    files : list(str)
150        The files to be processed, as a list of strings with the full path.
151    outpath : str
152        The output folder where results will be stored. Existing files will be
153        overwritten.
154    model_file : str
155        The full path to a normalized 32-bit shading model image. If set to '-'
156        or 'NONE', no shading correction will be applied, i.e. only the
157        projection step will have an effect.
158    fmt : str
159        The file format suffix for storing the results.
160    """
161    log.info("Running shading correction and projections on %s files...", len(files))
162
163    if model_file.upper() in ["-", "NONE"]:
164        model = None
165    else:
166        model = ij.IJ.openImage(model_file)
167        # the model needs to be shown, otherwise the IJ.run() call ignores it
168        try:
169            model.show()
170            canvas = model.getCanvas()
171            for _ in range(5):
172                # we have to show it, but we can make it smaller:
173                canvas.zoomOut(100, 100)
174        except AttributeError:
175            misc.error_exit("Opening shading model [%s] failed!" % model_file)
176
177    for in_file in files:
178        correct_and_project(in_file, outpath, model, "ALL", fmt)
179
180    if model:
181        model.close()
def apply_model(imps, model, merge=True):
14def apply_model(imps, model, merge=True):
15    """Apply a given shading model to a list of images / stacks.
16
17    The model is supposed to be a normalized 32-bit floating point 2D image that
18    will be used as a divisor to the slices of all ImagePlus objects given.
19
20    WARNING: the operation happens in-place, i.e. the original "imps" images
21    will be modified!
22
23    Parameters
24    ----------
25    imps : list(ij.ImagePlus)
26        A list of ImagePlus objects (e.g. separate channels of a multi-channel
27        stack image) that should be corrected for shading artefacts.
28    model : ij.ImagePlus
29        A 2D image with 32-bit float values normalized to 1.0 (i.e. no pixels
30        with higher values) to be used for dividing the input images to correct
31        for shading.
32    merge : bool, optional
33        Whether or not to combine the resulting ImagePlus objects into a single
34        multi-channel stack (default=True).
35
36    Returns
37    -------
38    ij.ImagePlus or list(ij.ImagePlus)
39        The merged ImagePlus with all channels, or the original list of stacks
40        with the shading-corrected image planes.
41    """
42    log.debug("Applying shading correction...")
43    calc = ij.plugin.ImageCalculator()
44    for i, stack in enumerate(imps):
45        log.debug("Processing channel %i...", i)
46        calc.run("Divide stack", stack, model)
47
48    if not merge:
49        return imps
50
51    log.debug("Merging shading-corrected channels...")
52    merger = ij.plugin.RGBStackMerge()
53    merged_imp = merger.mergeChannels(imps, False)
54    return merged_imp

Apply a given shading model to a list of images / stacks.

The model is supposed to be a normalized 32-bit floating point 2D image that will be used as a divisor to the slices of all ImagePlus objects given.

WARNING: the operation happens in-place, i.e. the original "imps" images will be modified!

Parameters
  • imps (list(ij.ImagePlus)): A list of ImagePlus objects (e.g. separate channels of a multi-channel stack image) that should be corrected for shading artefacts.
  • model (ij.ImagePlus): A 2D image with 32-bit float values normalized to 1.0 (i.e. no pixels with higher values) to be used for dividing the input images to correct for shading.
  • merge (bool, optional): Whether or not to combine the resulting ImagePlus objects into a single multi-channel stack (default=True).
Returns
  • ij.ImagePlus or list(ij.ImagePlus): The merged ImagePlus with all channels, or the original list of stacks with the shading-corrected image planes.
def correct_and_project(filename, path, model, proj, fmt):
 57def correct_and_project(filename, path, model, proj, fmt):
 58    """Apply a shading correction to an image and create a projection.
 59
 60    In case the target file for the shading corrected image already exists,
 61    nothing is done - neither the shading correction is re-created nor any
 62    projections will be done (independent on whether the latter one already
 63    exist or not).
 64
 65    Parameters
 66    ----------
 67    filename : str
 68        The full path to a multi-channel image stack.
 69    path : str
 70        The full path to a directory for storing the results. Will be created in
 71        case it doesn't exist yet. Existing files will be overwritten.
 72    model : ij.ImagePlus or None
 73        A 32-bit floating point image to be used as the shading model. If model
 74        is None, no shading correction will be applied.
 75    proj : str
 76        A string describing the projections to be created. Use 'None' for not
 77        creating any projections, 'ALL' to do all supported ones.
 78    fmt : str
 79        The file format suffix to be used for the results and projections, e.g.
 80        '.ics' for ICS2 etc. See the Bio-Formats specification for details.
 81
 82    Returns
 83    -------
 84    (bool, bool)
 85        A tuple of booleans indicating whether a shading correction has been
 86        applied and whether projections were created. The latter depends on
 87        both, the requested projections as well as the image type (e.g. it can
 88        be False even if projections were requested, but the image)
 89    """
 90    target = gen_name_from_orig(path, filename, "", fmt)
 91    if os.path.exists(target):
 92        log.info("Found shading corrected file, not re-creating: %s", target)
 93        return False, False
 94
 95    if not os.path.exists(path):
 96        os.makedirs(path)
 97
 98    imps = bioformats.import_image(filename, split_c=True)
 99    ret_corr = False
100    if model is not None:
101        log.debug("Applying shading correction on [%s]...", filename)
102        imp = apply_model(imps, model)
103        bioformats.export_using_orig_name(imp, path, filename, "", fmt, True)
104        # imps needs to be updated with the new (=merged) stack:
105        imps = [imp]
106        ret_corr = True
107
108    if proj == "None":
109        projs = []
110    elif proj == "ALL":
111        projs = ["Average", "Maximum"]
112    else:
113        projs = [proj]
114    for imp in imps:
115        ret_proj = projections.create_and_save(imp, projs, path, filename, fmt)
116        imp.close()
117
118    log.debug("Done processing [%s].", os.path.basename(filename))
119    return ret_corr, ret_proj

Apply a shading correction to an image and create a projection.

In case the target file for the shading corrected image already exists, nothing is done - neither the shading correction is re-created nor any projections will be done (independent on whether the latter one already exist or not).

Parameters
  • filename (str): The full path to a multi-channel image stack.
  • path (str): The full path to a directory for storing the results. Will be created in case it doesn't exist yet. Existing files will be overwritten.
  • model (ij.ImagePlus or None): A 32-bit floating point image to be used as the shading model. If model is None, no shading correction will be applied.
  • proj (str): A string describing the projections to be created. Use 'None' for not creating any projections, 'ALL' to do all supported ones.
  • fmt (str): The file format suffix to be used for the results and projections, e.g. '.ics' for ICS2 etc. See the Bio-Formats specification for details.
Returns
  • (bool, bool): A tuple of booleans indicating whether a shading correction has been applied and whether projections were created. The latter depends on both, the requested projections as well as the image type (e.g. it can be False even if projections were requested, but the image)
def process_folder(path, suffix, outpath, model_file, fmt):
122def process_folder(path, suffix, outpath, model_file, fmt):
123    """Run shading correction and projections on an entire folder.
124
125    Parameters
126    ----------
127    path : str
128        The input folder to be scanned for images to be processed.
129    suffix : str
130        The file name suffix of the files to be processed.
131    outpath : str
132        The output folder where results will be stored. Existing files will be
133        overwritten.
134    model_file : str
135        The full path to a normalized 32-bit shading model image. If set to '-'
136        or 'NONE', no shading correction will be applied, i.e. only the
137        projection step will have an effect.
138    fmt : str
139        The file format suffix for storing the results.
140    """
141    matching_files = listdir_matching(path, suffix, fullpath=True)
142    process_files(matching_files, outpath, model_file, fmt)

Run shading correction and projections on an entire folder.

Parameters
  • path (str): The input folder to be scanned for images to be processed.
  • suffix (str): The file name suffix of the files to be processed.
  • outpath (str): The output folder where results will be stored. Existing files will be overwritten.
  • model_file (str): The full path to a normalized 32-bit shading model image. If set to '-' or 'NONE', no shading correction will be applied, i.e. only the projection step will have an effect.
  • fmt (str): The file format suffix for storing the results.
def process_files(files, outpath, model_file, fmt):
145def process_files(files, outpath, model_file, fmt):
146    """Run shading correction and projections on a list of files.
147
148    Parameters
149    ----------
150    files : list(str)
151        The files to be processed, as a list of strings with the full path.
152    outpath : str
153        The output folder where results will be stored. Existing files will be
154        overwritten.
155    model_file : str
156        The full path to a normalized 32-bit shading model image. If set to '-'
157        or 'NONE', no shading correction will be applied, i.e. only the
158        projection step will have an effect.
159    fmt : str
160        The file format suffix for storing the results.
161    """
162    log.info("Running shading correction and projections on %s files...", len(files))
163
164    if model_file.upper() in ["-", "NONE"]:
165        model = None
166    else:
167        model = ij.IJ.openImage(model_file)
168        # the model needs to be shown, otherwise the IJ.run() call ignores it
169        try:
170            model.show()
171            canvas = model.getCanvas()
172            for _ in range(5):
173                # we have to show it, but we can make it smaller:
174                canvas.zoomOut(100, 100)
175        except AttributeError:
176            misc.error_exit("Opening shading model [%s] failed!" % model_file)
177
178    for in_file in files:
179        correct_and_project(in_file, outpath, model, "ALL", fmt)
180
181    if model:
182        model.close()

Run shading correction and projections on a list of files.

Parameters
  • files (list(str)): The files to be processed, as a list of strings with the full path.
  • outpath (str): The output folder where results will be stored. Existing files will be overwritten.
  • model_file (str): The full path to a normalized 32-bit shading model image. If set to '-' or 'NONE', no shading correction will be applied, i.e. only the projection step will have an effect.
  • fmt (str): The file format suffix for storing the results.