Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
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.
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