All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.github.mianalysis.mia.module.inputoutput.ImageLoader Maven / Gradle / Ivy

Go to download

ModularImageAnalysis (MIA) is an ImageJ plugin which provides a modular framework for assembling image and object analysis workflows. Detected objects can be transformed, filtered, measured and related. Analysis workflows are batch-enabled by default, allowing easy processing of high-content datasets.

There is a newer version: 1.7.0
Show newest version
package io.github.mianalysis.mia.module.inputoutput;

import java.awt.Rectangle;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.io.FilenameUtils;
import org.scijava.Priority;
import org.scijava.plugin.Plugin;

import com.drew.lang.annotations.NotNull;
import com.drew.lang.annotations.Nullable;

import ij.CompositeImage;
import ij.IJ;
import ij.ImagePlus;
import ij.ImageStack;
import ij.gui.Roi;
import ij.measure.Calibration;
import ij.plugin.CanvasResizer;
import ij.plugin.CompositeConverter;
import ij.process.ImageProcessor;
import ij.process.LUT;
import io.github.mianalysis.mia.MIA;
import io.github.mianalysis.mia.module.Categories;
import io.github.mianalysis.mia.module.Category;
import io.github.mianalysis.mia.module.Module;
import io.github.mianalysis.mia.module.Modules;
import io.github.mianalysis.mia.module.core.InputControl;
import io.github.mianalysis.mia.object.Measurement;
import io.github.mianalysis.mia.object.Objs;
import io.github.mianalysis.mia.object.Workspace;
import io.github.mianalysis.mia.object.image.Image;
import io.github.mianalysis.mia.object.image.ImageFactory;
import io.github.mianalysis.mia.object.metadata.CV7000FilenameExtractor;
import io.github.mianalysis.mia.object.metadata.IncuCyteShortFilenameExtractor;
import io.github.mianalysis.mia.object.metadata.Metadata;
import io.github.mianalysis.mia.object.metadata.NameExtractor;
import io.github.mianalysis.mia.object.parameters.BooleanP;
import io.github.mianalysis.mia.object.parameters.ChoiceP;
import io.github.mianalysis.mia.object.parameters.FilePathP;
import io.github.mianalysis.mia.object.parameters.InputImageP;
import io.github.mianalysis.mia.object.parameters.InputObjectsP;
import io.github.mianalysis.mia.object.parameters.OutputImageP;
import io.github.mianalysis.mia.object.parameters.ParameterState;
import io.github.mianalysis.mia.object.parameters.Parameters;
import io.github.mianalysis.mia.object.parameters.SeparatorP;
import io.github.mianalysis.mia.object.parameters.text.DoubleP;
import io.github.mianalysis.mia.object.parameters.text.IntegerP;
import io.github.mianalysis.mia.object.parameters.text.MessageP;
import io.github.mianalysis.mia.object.parameters.text.StringP;
import io.github.mianalysis.mia.object.refs.collections.ImageMeasurementRefs;
import io.github.mianalysis.mia.object.refs.collections.MetadataRefs;
import io.github.mianalysis.mia.object.refs.collections.ObjMeasurementRefs;
import io.github.mianalysis.mia.object.refs.collections.ObjMetadataRefs;
import io.github.mianalysis.mia.object.refs.collections.ParentChildRefs;
import io.github.mianalysis.mia.object.refs.collections.PartnerRefs;
import io.github.mianalysis.mia.object.system.Status;
import io.github.mianalysis.mia.object.units.SpatialUnit;
import io.github.mianalysis.mia.object.units.TemporalUnit;
import io.github.mianalysis.mia.process.string.CommaSeparatedStringInterpreter;
import io.github.mianalysis.mia.process.system.FileCrawler;
import io.github.mianalysis.mia.process.system.FileTools;
import loci.common.DebugTools;
import loci.common.services.DependencyException;
import loci.common.services.ServiceException;
import loci.common.services.ServiceFactory;
import loci.formats.ChannelSeparator;
import loci.formats.FormatException;
import loci.formats.IFormatReader;
import loci.formats.Memoizer;
import loci.formats.meta.MetadataStore;
import loci.formats.services.OMEXMLService;
import loci.plugins.util.ImageProcessorReader;
import loci.plugins.util.LociPrefs;
import net.imglib2.type.NativeType;
import net.imglib2.type.numeric.RealType;
import ome.units.UNITS;
import ome.units.quantity.Length;
import ome.units.quantity.Time;
import ome.units.unit.Unit;
import ome.xml.meta.IMetadata;
import ome.xml.model.primitives.Color;

/**
 * Created by Stephen on 15/05/2017.
 */

/**
 * Load image into MIA workspace. This module can be configured to import images
 * from a variety of locations (selected using the "Import mode" control).
 */
@Plugin(type = Module.class, priority = Priority.LOW, visible = true)
public class ImageLoader & NativeType> extends Module {

    /**
    * 
    */
    public static final String LOADER_SEPARATOR = "Core image loading controls";

    /**
     * Name assigned to the image.
     */
    public static final String OUTPUT_IMAGE = "Output image";

    /**
     * Controls where the image will be loaded from:
*
    *
  • "Current file" (default option) will import the current root-file for the * workspace (this is the file specified in the "Input control" module).
  • *
  • "From ImageJ" will load the active image fromm ImageJ.
  • *
  • "Image sequence (alphabetical)" will load a series of images matching a * specified name format in alphabetical order. The format of the names to be * loaded is specified by the "Sequence root name" parameter.
  • *
  • "Image sequence (zero-based)" will load a series of images with numbered * elements. The format of the names to be loaded is specified by the "Sequence * root name" parameter.
  • *
  • "Matching format" will load the image matching a filename based on the * root-file for the workspace and a series of rules.
  • *
  • "Specific file" will load the image at the location specified by "File * path".
  • *
*/ public static final String IMPORT_MODE = "Import mode"; /** * Set the reader for importing the image:
*
    *
  • "Bio-Formats" will use the Bio-Formats plugin. This is best for most * cases (especially proprietary formats).
  • *
  • "ImageJ" will use the stock ImageJ file reader.
  • *
*/ public static final String READER = "Reader"; /** * Template filename for loading multiple image sequence files (those with names * in the format "image0001.tif", "image0002.tif", "image0003.tif",etc.). * Template filenames are constructed in a generic manner, whereby metadata * values stored in the workspace can be inserted into the name using the * notation "M{name}". This allows names to be created dynamically for each * analysis run. The location in the filenam of the variable image number is * specified using the "Z{0000}" notation, where the number of "0" characters * specifies the number of digits. It is also necessary to specify the filepath * (input file filepath stored as metadata value "M{Filepath}".
*
* For example, loading the sequence "image0001.tif", etc. from the same folder * as the input file would require the format "M{Filepath}\\imageZ{0000}.tif". * Note: Backslash characters specifying the folder path need to be double typed * (standard Java formatting). */ public static final String SEQUENCE_ROOT_NAME = "Sequence root name"; /** * Method to use for generation of the input filename:
*
    *
  • "Generic (from metadata)" (default) will generate a name from metadata * values stored in the current workspace.
  • *
  • "Huygens" will generate a name matching the SVI Huygens format, where * channel numbers are specified as "ch00", "ch01", etc.
  • *
  • "Incucyte short filename" will generate a name matching the short * Incucyte Zoom format. The root name is specified as the parameter * "Comment".
  • *
  • "Yokogowa" will generate a name matching the Yokogawa high content * microscope name format.
  • *
*/ public static final String NAME_FORMAT = "Name format"; /** * Root name for generation of Incucyte Zoom filenames. This will be added * before the standard well and field values. */ public static final String COMMENT = "Comment"; /** * Extension for the generated filename. */ public static final String EXTENSION = "Extension"; /** * Format for a generic filename. Plain text can be mixed with global variables * or metadata values currently stored in the workspace. Global variables are * specified using the "V{name}" notation, where "name" is the name of the * variable to insert. Similarly, metadata values are specified with the * "M{name}" notation. */ public static final String GENERIC_FORMAT = "Generic format"; /** * Channel to load when constructing a "Yokogawa" format name. */ public static final String CHANNEL = "Channel"; /** * List of the currently-available metadata values for this workspace. These can * be used when compiling a generic filename. */ public static final String AVAILABLE_METADATA_FIELDS = "Available metadata fields"; /** * Option to include the current series number when compiling filenames. This * may be necessary when working with multi-series files, as there will be * multiple analyses completed for the same root file. */ public static final String INCLUDE_SERIES_NUMBER = "Include series number"; /** * Path to file to be loaded. */ public static final String FILE_PATH = "File path"; /** * Controls which series should be loaded for multiseries files (e.g. Leica LIF * files):
*
    *
  • "Current series" will load the same series as the current root file (i.e. * that selected via "Input control").
  • *
  • "Specific series" will load a specific series specified by the "Series * number"parameter.
  • *
*/ public static final String SERIES_MODE = "Series mode"; /** * If a specific series is being loaded ("Series mode" set to "Specific * series"), this is the series that will be used. */ public static final String SERIES_NUMBER = "Series number"; /** * */ public static final String RANGE_SEPARATOR = "Dimension ranges"; /** * Range of channels to be loaded for the current file. These can be specified * as a comma-separated list, using a range (e.g. "4-7" will load channels 4,5,6 * and 7) or as a range loading every nth channel (e.g. "4-10-2" will load * channels 4,6,8 and 10). The "end" keyword will be converted to the total * number of available channels at runtime. */ public static final String CHANNELS = "Channels"; /** * Range of slices to be loaded for the current file. These can be specified as * a comma-separated list, using a range (e.g. "4-7" will load slices 4,5,6 and * 7) or as a range loading every nth slice (e.g. "4-10-2" will load slices * 4,6,8 and 10). The "end" keyword will be converted to the total number of * available slices at runtime. */ public static final String SLICES = "Slices"; /** * Range of frames to be loaded for the current file. These can be specified as * a comma-separated list, using a range (e.g. "4-7" will load frames 4,5,6 and * 7) or as a range loading every nth frame (e.g. "4-10-2" will load frames * 4,6,8 and 10). The "end" keyword will be converted to the total number of * available frames at runtime. */ public static final String FRAMES = "Frames"; /** * */ public static final String CROP_SEPARATOR = "Image cropping"; /** * Choice of loading the entire image, or cropping in XY:
*
    *
  • "None" (default) will load the entire image in XY.
  • *
  • "Fixed" will apply a pre-defined crop to the input image based on the * parameters "Left", "Top","Width" and "Height".
  • *
  • "From reference" will display a specified image and ask the user to * select a region to crop the input image to.
  • *
  • "Object collection limits" will crop to the limits of the objects in the * collection specified by "Objects for limits".
  • *
*/ public static final String CROP_MODE = "Crop mode"; /** * The image to be displayed for selection of the cropping region if the * cropping mode is set to "From reference". */ public static final String REFERENCE_IMAGE = "Reference image"; /** * Left coordinate limit for image cropping (specified in pixel units). */ public static final String LEFT = "Left coordinate"; /** * Top coordinate limit for image cropping (specified in pixel units). */ public static final String TOP = "Top coordinate"; /** * Width of the final cropped region (specified in pixel units). */ public static final String WIDTH = "Width"; /** * Height of the final cropped region (specified in pixel units). */ public static final String HEIGHT = "Height"; /** * If "Crop mode" is set to "Object collection limits", this is the object * collection that will define the limits of the cropped region. */ public static final String OBJECTS_FOR_LIMITS = "Objects for limits"; /** * */ public static final String SCALE_SEPARATOR = "Image scaling"; /** * Controls if the input image is scaled upon importing. This only works for * scaling in X and Y (magnitudes determined by the "X scale factor" and "Y * scale factor" parameters):
*
    *
  • "Scaling (bicubic)" Scales the input images using a bicubic filter. This * leads to smooth intensity transitions between interpolated pixels.
  • *
  • "Scaling (bilinear)" Scales the input images using a bilinear filter. * This leads to smooth intensity transitions between interpolated pixels.
  • *
  • "No scaling" (default) Input images are not scaled. They are loaded into * the workspace at their native resolutions.
  • *
  • "Scaling (no interpolation)" Scales the input images using a * nearest-neighbour approach. This leads to a "blocky" apppearance to scaled * images.
  • *
*/ public static final String SCALE_MODE = "Scale mode"; /** * Scale factor applied to X-axis of input images (if "Scale mode" is in an * image scaling mode). Values less than 1 will reduce image width, while values * greater than 1 will increase it. */ public static final String SCALE_FACTOR_X = "X scale factor"; /** * Scale factor applied to Y-axis of input images (if "Scale mode" is in an * image scaling mode). Values less than 1 will reduce image height, while * values greater than 1 will increase it. */ public static final String SCALE_FACTOR_Y = "Y scale factor"; /** * If loading an image sequence from separate files, this parameter controls how * dimensions mismatches between images are handled:
*
    *
  • "Crop (centred)" The images will be centred-aligned and cropped to the * smallest image dimensions. This prevents empty borders around some images, * but means information is lost from larger images.
  • *
  • "Pad (centred)" The images will be centre-aligned and padded to the * largest image dimensions. This prevents any image infomation being lost at * edges, but means smaller images will have borders.
  • *
  • "Disallow (fail upon mismatch)" All images must have exactly the same * dimensions. If a dimension mismatch is detected, the image loading process * will fail.
  • *
*/ public static final String DIMENSION_MISMATCH_MODE = "Dimension mismatch mode"; /** * If loading an image series from separate files and "Dimension mismatch mode" * is set to "Pad (centred)" this parameter will control the intensity of the * padding border around images smaller than the largest loaded image. */ public static final String PAD_INTENSITY_MODE = "Pad intensity mode"; /** * */ public static final String CALIBRATION_SEPARATOR = "Spatial and intensity calibration"; /** * Option to use the automatically-applied spatial calibration or manually * specify these values. */ public static final String SET_SPATIAL_CAL = "Set manual spatial calibration"; public static final String XY_CAL = "XY calibration (dist/px)"; public static final String Z_CAL = "Z calibration (dist/px)"; /** * Option to use the automatically-applied temporal calibration or manually * specify this value. */ public static final String SET_TEMPORAL_CAL = "Set manual temporal calibration"; public static final String FRAME_INTERVAL = "Frame interval (time/frame)"; /** * Enable to force the output image to adopt a specific bit-depth. */ public static final String FORCE_BIT_DEPTH = "Force bit depth"; /** * Output bit depth of the loaded image. */ public static final String OUTPUT_BIT_DEPTH = "Output bit depth"; /** * Minimum intensity in the input image when in the native bit depth. This is * used for scaling intensities to the desired bit depth. */ public static final String MIN_INPUT_INTENSITY = "Minimum input intensity"; /** * Maximum intensity in the input image when in the native bit depth. This is * used for scaling intensities to the desired bit depth. */ public static final String MAX_INPUT_INTENSITY = "Maximum input intensity"; public ImageLoader(Modules modules) { super("Load image", modules); } public interface ImportModes { String ALL_IN_FOLDER = "All in current folder"; String CURRENT_FILE = "Current file"; String IMAGEJ = "From ImageJ"; String IMAGE_SEQUENCE_ALPHABETICAL = "Image sequence (alphabetical)"; String IMAGE_SEQUENCE_ZEROS = "Image sequence (zero-based)"; String MATCHING_FORMAT = "Matching format"; String SPECIFIC_FILE = "Specific file"; String[] ALL = new String[] { ALL_IN_FOLDER, CURRENT_FILE, IMAGEJ, IMAGE_SEQUENCE_ALPHABETICAL, IMAGE_SEQUENCE_ZEROS, MATCHING_FORMAT, SPECIFIC_FILE }; } public interface Readers { String BIOFORMATS = "Bio-Formats"; String IMAGEJ = "ImageJ"; String[] ALL = new String[] { BIOFORMATS, IMAGEJ }; } public interface SeriesModes { String CURRENT_SERIES = "Current series"; String SPECIFIC_SERIES = "Specific series"; String[] ALL = new String[] { CURRENT_SERIES, SPECIFIC_SERIES }; } public interface NameFormats { String GENERIC = "Generic (from metadata)"; String HUYGENS = "Huygens"; String INCUCYTE_SHORT = "Incucyte short filename"; String YOKOGAWA = "Yokogowa"; String[] ALL = new String[] { GENERIC, HUYGENS, INCUCYTE_SHORT, YOKOGAWA }; } public interface CropModes { String NONE = "None"; String FIXED = "Fixed"; String FROM_REFERENCE = "From reference"; String OBJECT_COLLECTION_LIMITS = "Object collection limits"; String[] ALL = new String[] { NONE, FIXED, FROM_REFERENCE, OBJECT_COLLECTION_LIMITS }; } public interface ScaleModes { String NONE = "No scaling"; String NO_INTERPOLATION = "Scaling (no interpolation)"; String BILINEAR = "Scaling (bilinear)"; String BICUBIC = "Scaling (bicubic)"; String[] ALL = new String[] { NONE, NO_INTERPOLATION, BILINEAR, BICUBIC }; } public interface DimensionMismatchModes { String DISALLOW = "Disallow (fail upon mismatch)"; String CENTRE_CROP = "Crop (centred)"; String CENTRE_PAD = "Pad (centred)"; String[] ALL = new String[] { DISALLOW, CENTRE_CROP, CENTRE_PAD }; } public interface PadIntensityModes { String BLACK = "Black (0)"; String WHITE = "White (bit-depth max)"; String[] ALL = new String[] { BLACK, WHITE }; } public interface OutputBitDepths { String EIGHT = "8"; String SIXTEEN = "16"; String THIRTY_TWO = "32"; String[] ALL = new String[] { EIGHT, SIXTEEN, THIRTY_TWO }; } public interface Measurements { String ROI_LEFT = "IMAGE_LOADING // ROI_LEFT (PX)"; String ROI_TOP = "IMAGE_LOADING // ROI_TOP (PX)"; String ROI_WIDTH = "IMAGE_LOADING // ROI_WIDTH (PX)"; String ROI_HEIGHT = "IMAGE_LOADING // ROI_HEIGHT (PX)"; } protected static int checkBitDepth(int bitDepth) { // Ensure bit depth is 8, 16 or 32 if (bitDepth < 8) bitDepth = 8; else if (bitDepth > 8 && bitDepth < 16) bitDepth = 16; else if (bitDepth > 16 && bitDepth < 32) bitDepth = 32; else if (bitDepth > 32) { MIA.log.writeError("Input image bit depth exceeds maximum supported (32 bit)."); return -1; } return bitDepth; } public HashMap getLUTs(IMetadata meta, int series) { HashMap luts = new HashMap<>(); for (int c = 0; c < meta.getChannelCount(series); c++) { Color color = meta.getChannelColor(series, c); if (color == null) { luts.put(c, null); } else { int red = color.getRed(); int green = color.getGreen(); int blue = color.getBlue(); LUT lut = LUT.createLutFromColor(new java.awt.Color(red, green, blue)); luts.put(c, lut); } } return luts; } public static int[] getCropROI(Image referenceImage) { int[] crop = null; // Displaying the image ImagePlus referenceIpl = referenceImage.getImagePlus().duplicate(); referenceIpl.show(); // Asking the user to draw a rectangular ROI IJ.runMacro("waitForUser(getArgument())", "Click \"OK\" once ROI selected"); // Getting the ROI Roi roi = referenceIpl.getRoi(); Rectangle bounds = roi.getBounds(); crop = new int[] { bounds.x, bounds.y, bounds.width, bounds.height }; // Closing the reference image referenceIpl.close(); return crop; } public ImagePlus getBFImage(String path, int seriesNumber, @NotNull String[] dimRanges, @Nullable int[] crop, double[] scaleFactors, String scaleMode, @Nullable double[] intRange, boolean[] manualCal, boolean localVerbose) throws ServiceException, DependencyException, IOException, FormatException { DebugTools.enableLogging("off"); DebugTools.setRootLevel("off"); // Setting spatial calibration ServiceFactory factory = new ServiceFactory(); OMEXMLService service = factory.getInstance(OMEXMLService.class); IMetadata meta = service.createOMEXMLMetadata(); IFormatReader reader = MIA.getPreferences() .getReader(new ImageProcessorReader(new ChannelSeparator(LociPrefs.makeImageReader()))); reader.setMetadataStore((MetadataStore) meta); reader.setGroupFiles(false); reader.setId(path); reader.setSeries(seriesNumber - 1); int left = 0; int top = 0; int width = reader.getSizeX(); int height = reader.getSizeY(); int sizeC = reader.getSizeC(); int sizeT = reader.getSizeT(); int sizeZ = reader.getSizeZ(); int bitDepth = reader.getBitsPerPixel(); // If a specific bit depth is to be used if (intRange != null) bitDepth = (int) intRange[0]; bitDepth = checkBitDepth(bitDepth); if (bitDepth == -1) return null; if (crop != null) { left = crop[0]; top = crop[1]; width = crop[2]; height = crop[3]; } int[] channelsList = CommaSeparatedStringInterpreter.interpretIntegers(dimRanges[0], true, sizeC); int[] slicesList = CommaSeparatedStringInterpreter.interpretIntegers(dimRanges[1], true, sizeZ); int[] framesList = CommaSeparatedStringInterpreter.interpretIntegers(dimRanges[2], true, sizeT); int nC = channelsList.length; int nZ = slicesList.length; int nT = framesList.length; int widthOut = width; int heightOut = height; // Applying scaling switch (scaleMode) { case ScaleModes.NONE: scaleFactors[0] = 1; scaleFactors[1] = 1; break; case ScaleModes.NO_INTERPOLATION: case ScaleModes.BILINEAR: case ScaleModes.BICUBIC: widthOut = (int) Math.round(width * scaleFactors[0]); heightOut = (int) Math.round(height * scaleFactors[1]); break; } // Creating the new ImagePlus ImagePlus ipl = IJ.createHyperStack("Image", widthOut, heightOut, nC, nZ, nT, bitDepth); // Iterating over all images in the stack, adding them to the output ImagePlus int nTotal = nC * nT * nZ; int count = 0; int countZ = 1; for (int z : slicesList) { int countC = 1; for (int c : channelsList) { int countT = 1; for (int t : framesList) { int idx; try { idx = reader.getIndex(z - 1, c - 1, t - 1); } catch (IllegalArgumentException e) { MIA.log.writeWarning("Indices out of range for image \"" + path + "\" at c=" + (c - 1) + ", z=" + (z - 1) + ", t=" + (t - 1)); return null; } ImageProcessor ip = null; if (reader instanceof Memoizer) ip = ((ImageProcessorReader) ((Memoizer) reader).getReader()).openProcessors(idx, left, top, width, height)[0]; else ip = ((ImageProcessorReader) reader).openProcessors(idx, left, top, width, height)[0]; // If forcing bit depth if (intRange != null) { ip.setMinAndMax(intRange[1], intRange[2]); switch (bitDepth) { case 8: ip = ip.convertToByte(true); break; case 16: ip = ip.convertToShort(true); break; case 32: ip = ip.convertToFloat(); break; } } // Applying scaling switch (scaleMode) { case ScaleModes.NO_INTERPOLATION: ip.setInterpolationMethod(ImageProcessor.NONE); ip = ip.resize(widthOut, heightOut); break; case ScaleModes.BILINEAR: ip.setInterpolationMethod(ImageProcessor.BILINEAR); ip = ip.resize(widthOut, heightOut); break; case ScaleModes.BICUBIC: ip.setInterpolationMethod(ImageProcessor.BICUBIC); ip = ip.resize(widthOut, heightOut); break; } ipl.setPosition(countC, countZ, countT); ipl.setProcessor(ip); if (localVerbose) writeProgressStatus(++count, nTotal, "images"); countT++; } countC++; } countZ++; } ipl.setPosition(1, 1, 1); ipl.updateAndDraw(); // Applying LUTs HashMap luts = getLUTs(meta, seriesNumber - 1); for (int i = 0; i < channelsList.length; i++) { int c = channelsList[i]; LUT lut = luts.get(c - 1); if (lut == null) continue; if (ipl.isComposite()) { ((CompositeImage) ipl).setChannelLut(lut, i + 1); } else { ipl.setLut(lut); } } ipl.setPosition(1, 1, 1); ipl.updateAndDraw(); // Adding spatial calibration if (!manualCal[0]) { if (!setSpatialCalibrationBF(ipl, meta, seriesNumber, scaleFactors) && ipl.getCalibration().getUnit().equals("pixel")) { MIA.log.writeWarning("Can't apply spatial units for file \"" + new File(path).getName() + "\". Spatially calibrated values will be unavailable."); setDummySpatialCalibration(ipl); } } // Adding temporal calibration if (!manualCal[1]) { if (!setTemporalCalibrationBF(ipl, meta, seriesNumber)) { // Only display a warning if there's more than 1 frame. Otherwise this should't // be a problem. if (ipl.getNFrames() != 1) MIA.log.writeWarning("Can't apply temporal units for file \"" + new File(path).getName() + "\". Temporally calibrated values will be unavailable."); // Either way, remove the temporal calibration setDummyTemporalCalibration(ipl); } } ipl.setPosition(1, 1, 1); ipl.updateAndDraw(); reader.close(); return ipl; } boolean setSpatialCalibrationBF(ImagePlus ipl, IMetadata meta, int seriesNumber, double[] scaleFactors) { // Add spatial calibration Unit spatialUnits = SpatialUnit.getOMEUnit(); if (spatialUnits == null) return false; Calibration cal = ipl.getCalibration(); cal.setXUnit(spatialUnits.getSymbol()); cal.setYUnit(spatialUnits.getSymbol()); cal.setZUnit(spatialUnits.getSymbol()); if (meta == null) return false; if (meta.getPixelsPhysicalSizeX(seriesNumber - 1) == null) { return false; } else { Length physicalSizeX = meta.getPixelsPhysicalSizeX(seriesNumber - 1); if (physicalSizeX == null || physicalSizeX.value(spatialUnits) == null) return false; cal.pixelWidth = (double) physicalSizeX.value(spatialUnits) / scaleFactors[0]; } if (meta.getPixelsPhysicalSizeY(seriesNumber - 1) == null) { return false; } else { Length physicalSizeY = meta.getPixelsPhysicalSizeY(seriesNumber - 1); if (physicalSizeY == null || physicalSizeY.value(spatialUnits) == null) return false; cal.pixelHeight = (double) physicalSizeY.value(spatialUnits) / scaleFactors[1]; } if (ipl.getNSlices() > 1) { if (meta.getPixelsPhysicalSizeZ(seriesNumber - 1) == null) { return false; } else { Length physicalSizeZ = meta.getPixelsPhysicalSizeZ(seriesNumber - 1); if (physicalSizeZ == null || physicalSizeZ.value(spatialUnits) == null) return false; cal.pixelDepth = (double) physicalSizeZ.value(spatialUnits); } } return true; } boolean setTemporalCalibrationBF(ImagePlus ipl, IMetadata meta, int seriesNumber) { // Add spatial calibration Unit




© 2015 - 2025 Weber Informatics LLC | Privacy Policy