package gdsc.foci;
/*-----------------------------------------------------------------------------
* 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>
* Extends the FindFociFloatProcessor to override the FindFociBaseProcessor methods with float specific processing.
*/
public class FindFociOptimisedFloatProcessor extends FindFociFloatProcessor
{
// There may be nothing to optimise.
// We would just be replacing the call to getf(i) with image[i]. All the
// processing in FindFociBaseProcessor is float specific anyway.
// So optimisation should be done by the JVM.
// For now I have just included those simple methods that use getf() for all pixels in the image.
// This means changes to the main algorithm methods will be inherited.
/*
* (non-Javadoc)
*
* @see gdsc.foci.FindFociBaseProcessor#pruneMaxima(java.lang.Object, byte[], int, double,
* gdsc.foci.FindFociStatistics, java.util.ArrayList, int[])
*/
protected void pruneMaxima(Object pixels, byte[] types, int searchMethod, double searchParameter,
FindFociStatistics stats, FindFociResult[] resultsArray, int[] maxima)
{
setPixels(pixels);
// Build an array containing the threshold for each peak.
// Note that maxima are numbered from 1
final int nMaxima = resultsArray.length;
final float[] peakThreshold = new float[nMaxima + 1];
for (int i = 1; i < peakThreshold.length; i++)
{
peakThreshold[i] = getTolerance(searchMethod, searchParameter, stats, resultsArray[i - 1].maxValue);
}
for (int i = maxima.length; i-- > 0;)
{
final int id = maxima[i];
if (id != 0)
{
if (image[i] < peakThreshold[id])
{
// Unset this pixel as part of the peak
maxima[i] = 0;
types[i] &= ~MAX_AREA;
}
}
}
}
/*
* (non-Javadoc)
*
* @see gdsc.foci.FindFociBaseProcessor#calculateInitialResults(java.lang.Object, int[], java.util.ArrayList)
*/
protected void calculateInitialResults(Object pixels, int[] maxima, FindFociResult[] resultsArray)
{
setPixels(pixels);
final int nMaxima = resultsArray.length;
// Maxima are numbered from 1
final int[] count = new int[nMaxima + 1];
final double[] intensity = new double[nMaxima + 1];
for (int i = maxima.length; i-- > 0;)
{
final int id = maxima[i];
if (id != 0)
{
count[id]++;
intensity[id] += image[i];
}
}
for (int i = 0; i < resultsArray.length; i++)
{
final FindFociResult result = resultsArray[i];
result.count = count[result.id];
result.totalIntensity = intensity[result.id];
result.averageIntensity = result.totalIntensity / result.count;
}
}
/*
* (non-Javadoc)
*
* @see gdsc.foci.FindFociBaseProcessor#calculateNativeResults(java.lang.Object, int[], java.util.ArrayList, int)
*/
protected void calculateNativeResults(Object pixels, int[] maxima, FindFociResult[] resultsArray,
int originalNumberOfPeaks)
{
setPixels(pixels);
// Maxima are numbered from 1
final double[] intensity = new double[originalNumberOfPeaks + 1];
final float[] max = new float[originalNumberOfPeaks + 1];
for (int i = maxima.length; i-- > 0;)
{
final int id = maxima[i];
if (id != 0)
{
final float v = image[i];
intensity[id] += v;
if (max[id] < v)
max[id] = v;
}
}
for (int i = 0; i < resultsArray.length; i++)
{
final FindFociResult result = resultsArray[i];
final int id = result.id;
if (intensity[id] != 0)
{
result.totalIntensity = intensity[id];
result.maxValue = max[id];
}
}
}
/**
* Compute the intensity of the peak above the saddle height.
*
* @param maxima
* the maxima
* @param peakIdMap
* the peak id map
* @param peakId
* the peak id
* @param result
* the result
* @param saddleHeight
* the saddle height
*/
protected void computeIntensityAboveSaddle(final int[] maxima, final int[] peakIdMap, final int peakId,
final FindFociResult result, final float saddleHeight)
{
int peakSize = 0;
double peakIntensity = 0;
// Search using the bounds
for (int z = result.minz; z < result.maxz; z++)
for (int y = result.miny; y < result.maxy; y++)
for (int x = result.minx, i = getIndex(result.minx, y, z); x < result.maxx; x++, i++)
{
final int id = maxima[i];
if (id != 0 && peakIdMap[id] == peakId)
{
final float v = image[i];
if (v > saddleHeight)
{
peakIntensity += v;
peakSize++;
}
}
}
result.countAboveSaddle = peakSize;
result.intensityAboveSaddle = peakIntensity;
}
/*
* (non-Javadoc)
*
* @see gdsc.foci.FindFociBaseProcessor#getIntensityAboveFloor(java.lang.Object, byte[], float)
*/
protected double getIntensityAboveFloor(Object pixels, byte[] types, final float floor)
{
setPixels(pixels);
double sum = 0;
for (int i = types.length; i-- > 0;)
{
if ((types[i] & EXCLUDED) == 0)
{
final float v = image[i];
if (v > floor)
sum += (v - floor);
}
}
return sum;
}
}