package gdsc.foci; import gdsc.core.threshold.Histogram; import ij.ImagePlus; import ij.ImageStack; import ij.process.ImageProcessor; /*----------------------------------------------------------------------------- * GDSC Plugins for ImageJ * * Copyright (C) 2016 Alex Herbert * Genome Damage and Stability Centre * University of Sussex, UK * * 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 2 of the License, or * (at your option) any later version. *---------------------------------------------------------------------------*/ /** * Find the peak intensity regions of an image. * * <P> * All local maxima above threshold are identified. For all other pixels the direction to the highest neighbour pixel is * stored (steepest gradient). In order of highest local maxima, regions are only grown down the steepest gradient to a * lower pixel. Provides many configuration options for regions growing thresholds. * * <P> * This plugin was based on {@link ij.plugin.filter.MaximumFinder}. Options have been changed to only support greyscale * 2D images and 3D stacks and to perform region growing using configurable thresholds. Support for Watershed, * Previewing, and Euclidian Distance Map (EDM) have been removed. * * <P> * Stopping criteria for region growing routines are partly based on the options in PRIISM * (http://www.msg.ucsf.edu/IVE/index.html). * * <p> * Supports 8- or 16-bit images */ public class FindFociIntProcessor extends FindFociBaseProcessor { protected int[] image; protected Object extractImage(ImagePlus imp) { if (imp.getBitDepth() != 8 && imp.getBitDepth() != 16) throw new RuntimeException("Bit-depth not supported: " + imp.getBitDepth()); final ImageStack stack = imp.getStack(); final int[] image = new int[maxx_maxy_maxz]; final int c = imp.getChannel(); final int f = imp.getFrame(); for (int slice = 1, i = 0; slice <= maxz; slice++) { final int stackIndex = imp.getStackIndex(c, slice, f); final ImageProcessor ip = stack.getProcessor(stackIndex); for (int index = 0; index < ip.getPixelCount(); index++) { image[i++] = ip.get(index); } } return image; } protected byte[] createTypesArray(Object pixels) { return new byte[maxx_maxy_maxz]; } protected float getImageMin(Object pixels, byte[] types) { final int[] image = (int[]) pixels; int min = Integer.MAX_VALUE; for (int i = image.length; i-- > 0;) { if ((types[i] & EXCLUDED) == 0) { if (min > image[i]) min = image[i]; } } return min; } protected Histogram buildHistogram(int bitDepth, Object pixels, byte[] types, int statsMode) { final int[] image = (int[]) pixels; final int size = (int) Math.pow(2, bitDepth); final int[] data = new int[size]; if (statsMode == OPTION_STATS_INSIDE) { for (int i = image.length; i-- > 0;) { if ((types[i] & EXCLUDED) == 0) { data[image[i]]++; } } } else { for (int i = image.length; i-- > 0;) { if ((types[i] & EXCLUDED) != 0) { data[image[i]]++; } } } return new Histogram(data); } protected Histogram buildHistogram(int bitDepth, Object pixels) { final int[] image = ((int[]) pixels); final int size = (int) Math.pow(2, bitDepth); final int[] data = new int[size]; for (int i = image.length; i-- > 0;) { data[image[i]]++; } return new Histogram(data); } protected Histogram buildHistogram(Object pixels, int[] maxima, int peakValue, float maxValue) { final int[] image = (int[]) pixels; final int[] histogram = new int[(int) maxValue + 1]; for (int i = image.length; i-- > 0;) { if (maxima[i] == peakValue) { histogram[image[i]]++; } } return new Histogram(histogram); } protected float getSearchThreshold(int backgroundMethod, double backgroundParameter, FindFociStatistics stats) { switch (backgroundMethod) { case BACKGROUND_ABSOLUTE: // Ensure all points above the threshold parameter are found return round((backgroundParameter >= 0) ? backgroundParameter : 0); case BACKGROUND_AUTO_THRESHOLD: return round(stats.background); case BACKGROUND_MEAN: return round(stats.backgroundRegionAverage); case BACKGROUND_STD_DEV_ABOVE_MEAN: return round(stats.backgroundRegionAverage + ((backgroundParameter >= 0) ? backgroundParameter * stats.backgroundRegionStdDev : 0)); case BACKGROUND_MIN_ROI: return round(stats.regionMinimum); case BACKGROUND_NONE: default: // Ensure all the maxima are found return 0; } } protected void setPixels(Object pixels) { this.image = (int[]) pixels; } protected float getf(int i) { return image[i]; } protected int getBackgroundBin(Histogram histogram, float background) { return round(background); } protected int getBin(Histogram histogram, int i) { return image[i]; } protected float getTolerance(int searchMethod, double searchParameter, FindFociStatistics stats, float v0) { switch (searchMethod) { case SEARCH_ABOVE_BACKGROUND: return round(stats.background); case SEARCH_FRACTION_OF_PEAK_MINUS_BACKGROUND: if (searchParameter < 0) searchParameter = 0; return round(stats.background + searchParameter * (v0 - stats.background)); case SEARCH_HALF_PEAK_VALUE: return round(stats.background + 0.5 * (v0 - stats.background)); } return 0; } protected double getPeakHeight(int peakMethod, double peakParameter, FindFociStatistics stats, float v0) { int height = 1; if (peakParameter < 0) peakParameter = 0; switch (peakMethod) { case PEAK_ABSOLUTE: height = round(peakParameter); break; case PEAK_RELATIVE: height = round(v0 * peakParameter); break; case PEAK_RELATIVE_ABOVE_BACKGROUND: height = round((v0 - stats.background) * peakParameter); break; } if (height < 1) height = 1; // It should be a peak return height; } @Override public boolean isFloatProcessor() { return false; } }