/*- * #%L * Fiji's plugin for colocalization analysis. * %% * Copyright (C) 2009 - 2017 Fiji developers. * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program. If not, see * . * #L% */ package gadgets; import algorithms.MissingPreconditionException; import java.util.Arrays; import net.imglib2.Cursor; import net.imglib2.RandomAccess; import net.imglib2.RandomAccessibleInterval; import net.imglib2.img.ImgFactory; import net.imglib2.img.array.ArrayImgFactory; import net.imglib2.type.logic.BitType; import net.imglib2.type.numeric.RealType; import net.imglib2.view.Views; public class MaskFactory { public enum CombinationMode { AND, OR, NONE } /** * Create a new mask image without any specific content, but with * a defined size. */ public static RandomAccessibleInterval createMask(long[] dim) { ImgFactory< BitType > imgFactory = new ArrayImgFactory< BitType >(); return imgFactory.create(dim, new BitType()); } /** * Create a new mask image with a defined size and preset content. */ public static RandomAccessibleInterval createMask(long[] dim, boolean val) { RandomAccessibleInterval mask = createMask(dim); for (BitType t : Views.iterable(mask)) t.set(val); return mask; } /** * Create a new mask image with a defined size and preset content. * @throws MissingPreconditionException */ public static RandomAccessibleInterval createMask(long[] dim, long[] roiOffset, long[] roiDim) throws MissingPreconditionException { if (dim.length != roiOffset.length || dim.length != roiDim.length) { throw new MissingPreconditionException("The dimensions of the mask as well as the ROIs and his offset must be the same."); } final RandomAccessibleInterval mask = createMask(dim); final int dims = mask.numDimensions(); final long[] pos = new long[dims]; // create an array with the max corner of the ROI final long[] roiOffsetMax = new long[dims]; for (int i=0; i cursor = Views.iterable(mask).localizingCursor(); while ( cursor.hasNext() ) { cursor.fwd(); cursor.localize(pos); boolean valid = true; // test if the current position is contained in the ROI for(int i=0; i= roiOffset[i] && pos[i] < roiOffsetMax[i]; cursor.get().set(valid); } return mask; } /** * Create a new mask based on a threshold condition for two images. */ public static> RandomAccessibleInterval createMask( RandomAccessibleInterval ch1, RandomAccessibleInterval ch2, T threshold1, T threshold2, ThresholdMode tMode, CombinationMode cMode) { final long[] dims = new long[ ch1.numDimensions() ]; ch1.dimensions(dims); RandomAccessibleInterval mask = createMask(dims); Cursor cursor1 = Views.iterable(ch1).cursor(); Cursor cursor2 = Views.iterable(ch2).cursor(); Cursor maskCursor = Views.iterable(mask).cursor(); while (cursor1.hasNext() && cursor2.hasNext() && maskCursor.hasNext()) { cursor1.fwd(); cursor2.fwd(); maskCursor.fwd(); boolean ch1Valid, ch2Valid; T data1 = cursor1.get(); T data2 = cursor2.get(); // get relation to threshold if (tMode == ThresholdMode.Above) { ch1Valid = data1.compareTo(threshold1) > 0; ch2Valid = data2.compareTo(threshold2) > 0; } else if (tMode == ThresholdMode.Below) { ch1Valid = data1.compareTo(threshold1) < 0; ch2Valid = data2.compareTo(threshold2) < 0; } else { throw new UnsupportedOperationException(); } BitType maskData = maskCursor.get(); // combine the results into mask if (cMode == CombinationMode.AND) { maskData.set( ch1Valid && ch2Valid ); } else if (cMode == CombinationMode.OR) { maskData.set( ch1Valid || ch2Valid ); } else if (cMode == CombinationMode.NONE) { maskData.set( !(ch1Valid || ch2Valid) ); } else { throw new UnsupportedOperationException(); } } return mask; } /** * Creates a new mask of the given dimensions, based on the image data * in the passed image. If the requested dimensionality is higher than * what is available in the data, the data gets repeated in the higher * dimensions. * * @param dim The dimensions of the new mask image * @param origMask The image from which the mask should be created from */ public static> RandomAccessibleInterval createMask( final long[] dim, final RandomAccessibleInterval origMask) { final RandomAccessibleInterval mask = createMask(dim); final long[] origDim = new long[ origMask.numDimensions() ]; origMask.dimensions(origDim); // test if original mask and new mask have same dimensions if (Arrays.equals(dim, origDim)) { // copy the input image to the mask output image Cursor origCursor = Views.iterable(origMask).localizingCursor(); RandomAccess maskCursor = mask.randomAccess(); while (origCursor.hasNext()) { origCursor.fwd(); maskCursor.setPosition(origCursor); boolean value = origCursor.get().getRealDouble() > 0.001; maskCursor.get().set(value); } } else if (dim.length > origDim.length) { // sanity check for (int i=0; i origCursor = Views.iterable(origMask).localizingCursor(); RandomAccess maskCursor = mask.randomAccess(); final long[] pos = new long[ origMask.numDimensions() ]; // iterate over the original mask while (origCursor.hasNext()) { origCursor.fwd(); origCursor.localize(pos); boolean value = origCursor.get().getRealDouble() > 0.001; // set available (lower dimensional) position information for (int i=0; i