public static int findFirstMinimaFollowingPeak(HistogramHolder hist, int yPeakIdx) { // TODO: could be improved to smooth over noise to find true minimum float yPeakMinimum = Float.MAX_VALUE; int yPeakMinIdx = -1; // find min within first half of histogram, after peak int n = (int) (0.5f * hist.getXHist().length); if ((n - yPeakIdx) < 3) { n = hist.getXHist().length; } for (int i = (yPeakIdx + 1); i < n; i++) { float y = hist.getYHistFloat()[i]; if (y < yPeakMinimum) { yPeakMinimum = y; yPeakMinIdx = i; } } return yPeakMinIdx; }
/** * if there is more than one peak in the histogram, reduce the histogram to only that peak, else * leave unaltered. * * @param hist * @param values * @param valueErrors * @return */ public static HistogramHolder reduceHistogramToFirstPeak( HistogramHolder hist, float[] values, float[] valueErrors) { int yPeakIdx = findFirstPeakIndex(hist); if (yPeakIdx == -1) { return hist; } int yMinPeakIdx = findFirstMinimaFollowingPeak(hist, yPeakIdx); if (yMinPeakIdx == -1) { return hist; } int n = yMinPeakIdx + 1; HistogramHolder tmp = new HistogramHolder(); tmp.setXHist(Arrays.copyOfRange(hist.getXHist(), 0, n)); tmp.setYHistFloat(Arrays.copyOfRange(hist.getYHistFloat(), 0, n)); tmp.setXErrors(Arrays.copyOfRange(hist.getXErrors(), 0, n)); tmp.setYErrors(Arrays.copyOfRange(hist.getYErrors(), 0, n)); return tmp; }
public static int findFirstPeakIndex(HistogramHolder hist) { float yPeak = Float.MIN_VALUE; int yPeakIdx = -1; // specific to use here, find max within first half of histogram for (int i = 0; i < hist.getXHist().length >> 1; i++) { float y = hist.getYHistFloat()[i]; if (y > yPeak) { yPeak = y; yPeakIdx = i; } } return yPeakIdx; }
public static float measureFWHMOfStrongestPeak(HistogramHolder hist) { if (hist == null) { throw new IllegalArgumentException("hist cannot be null"); } int yMaxIdx = MiscMath.findYMaxIndex(hist.getYHist()); return measureFWHM(hist, yMaxIdx); }
public static HistogramHolder createSimpleHistogram( final float xMin, final float xMax, int nBins, float[] values, float[] valueErrors) { if (values == null || valueErrors == null || values.length != valueErrors.length) { throw new IllegalArgumentException( "values and valueErrors cannot be null and must be the same length"); } float binWidth = calculateBinWidth(xMin, xMax, nBins); float[] xHist = new float[nBins]; int[] yHist = new int[nBins]; Histogram.createHistogram(values, nBins, xMin, xMax, xHist, yHist, binWidth); float[] yHistFloat = new float[yHist.length]; for (int i = 0; i < yHist.length; i++) { yHistFloat[i] = (float) yHist[i]; } float[] yErrors = new float[xHist.length]; float[] xErrors = new float[xHist.length]; calulateHistogramBinErrors(xHist, yHist, values, valueErrors, xErrors, yErrors); HistogramHolder histogram = new HistogramHolder(); histogram.setXHist(xHist); histogram.setYHist(yHist); histogram.setYHistFloat(yHistFloat); histogram.setYErrors(yErrors); histogram.setXErrors(xErrors); return histogram; }
public static HistogramHolder createSimpleHistogram(int binWidth, List<Integer> theValues) { if (theValues == null || theValues.isEmpty()) { throw new IllegalArgumentException( "values and valueErrors cannot be null and must be the same length"); } float[] values = new float[theValues.size()]; for (int i = 0; i < theValues.size(); ++i) { int v = theValues.get(i).intValue(); values[i] = v; } float[] valueErrors = Errors.populateYErrorsBySqrt(values); float[] minMax = MiscMath.calculateOuterRoundedMinAndMax(values); int nBins = (int) Math.ceil(((minMax[1] - minMax[0])) / binWidth); if (nBins < 0) { nBins *= -1; } float[] xHist = new float[nBins]; int[] yHist = new int[nBins]; Histogram.createHistogram(values, nBins, minMax[0], minMax[1], xHist, yHist, binWidth); float[] yHistFloat = new float[yHist.length]; for (int i = 0; i < yHist.length; i++) { yHistFloat[i] = (float) yHist[i]; } float[] yErrors = new float[xHist.length]; float[] xErrors = new float[xHist.length]; calulateHistogramBinErrors(xHist, yHist, values, valueErrors, xErrors, yErrors); HistogramHolder histogram = new HistogramHolder(); histogram.setXHist(xHist); histogram.setYHist(yHist); histogram.setYHistFloat(yHistFloat); histogram.setYErrors(yErrors); histogram.setXErrors(xErrors); return histogram; }
public static HistogramHolder createSimpleHistogram( float binWidth, float[] values, float[] valueErrors) { if (values == null || valueErrors == null || values.length != valueErrors.length) { throw new IllegalArgumentException( "values and valueErrors cannot be null and must be the same length"); } float[] minMax = MiscMath.calculateOuterRoundedMinAndMax(values); int nBins = (int) Math.ceil(((minMax[1] - minMax[0])) / binWidth); if (nBins < 0) { nBins *= -1; } float[] xHist = new float[nBins]; int[] yHist = new int[nBins]; Histogram.createHistogram(values, nBins, minMax[0], minMax[1], xHist, yHist, binWidth); float[] yHistFloat = new float[yHist.length]; for (int i = 0; i < yHist.length; i++) { yHistFloat[i] = (float) yHist[i]; } float[] yErrors = new float[xHist.length]; float[] xErrors = new float[xHist.length]; calulateHistogramBinErrors(xHist, yHist, values, valueErrors, xErrors, yErrors); HistogramHolder histogram = new HistogramHolder(); histogram.setXHist(xHist); histogram.setYHist(yHist); histogram.setYHistFloat(yHistFloat); histogram.setYErrors(yErrors); histogram.setXErrors(xErrors); return histogram; }
public static HistogramHolder calculateSturgesHistogramRemoveZeroTail( float[] values, float[] valueErrors) { if (values == null || valueErrors == null || values.length != valueErrors.length) { throw new IllegalArgumentException( "values and valueErrors cannot be null and must be the same length"); } int nIntervalsSturges = (int) Math.ceil(Math.log(values.length) / Math.log(2)); // int nItervalsRice = (int)(2*Math.pow(values.length, 0.3333)); int nBins = 25; if (values.length > 10000) { nBins = 40; } nBins = Math.max(nIntervalsSturges, nBins); float[] xHist = new float[nBins]; int[] yHist = new int[nBins]; float minx = MiscMath.findMin(values); float maxx = MiscMath.findMax(values); float binWidth = calculateBinWidth(minx, maxx, nBins); Histogram.createHistogram(values, nBins, minx, maxx, xHist, yHist, binWidth); float maxy = MiscMath.findMax(yHist); int minCountsLimit = (int) Math.max(5, 0.03f * maxy); int countsBelowMinAtTail = 0; int lastLowCountIdx = yHist.length - 1; for (int i = (yHist.length - 1); i > -1; i--) { if (yHist[i] < minCountsLimit) { countsBelowMinAtTail++; lastLowCountIdx = i; } else { break; } } if (countsBelowMinAtTail > 0) { maxx = xHist[lastLowCountIdx]; // keep nbins the same? binWidth = calculateBinWidth(minx, maxx, nBins); Histogram.createHistogram(values, nBins, minx, maxx, xHist, yHist, binWidth); if (countsBelowMinAtTail > (nBins >> 1)) { // one more round of trimming maxy = MiscMath.findMax(yHist); minCountsLimit = (int) Math.max(5, 0.03f * maxy); countsBelowMinAtTail = 0; lastLowCountIdx = yHist.length - 1; for (int i = (yHist.length - 1); i > -1; i--) { if (yHist[i] < minCountsLimit) { countsBelowMinAtTail++; lastLowCountIdx = i; } else { break; } } if (countsBelowMinAtTail > 0) { maxx = xHist[lastLowCountIdx]; binWidth = calculateBinWidth(minx, maxx, nBins); Histogram.createHistogram(values, nBins, minx, maxx, xHist, yHist, binWidth); } } } if (values.length > 100) { // if there are a large number of points, we'd like to increase the // resolution of the peak if needed int nLeftOfPeak = MiscMath.findYMaxIndex(yHist); int nIter = 0; while (nIter < 30 && nLeftOfPeak < 3 && (yHist[nLeftOfPeak] > 100)) { binWidth *= 0.8f; Histogram.createHistogram(values, nBins, minx, maxx, xHist, yHist, binWidth); nLeftOfPeak = MiscMath.findYMaxIndex(yHist); nIter++; } } float[] yHistFloat = new float[yHist.length]; for (int i = 0; i < yHist.length; i++) { yHistFloat[i] = (float) yHist[i]; } float[] yErrors = new float[xHist.length]; float[] xErrors = new float[xHist.length]; calulateHistogramBinErrors(xHist, yHist, values, valueErrors, xErrors, yErrors); HistogramHolder histogram = new HistogramHolder(); histogram.setXHist(xHist); histogram.setYHist(yHist); histogram.setYHistFloat(yHistFloat); histogram.setYErrors(yErrors); histogram.setXErrors(xErrors); return histogram; }
public static HistogramHolder createHistogramAndRemovePreAndProceedingZeros(GreyscaleImage img) { float[] values = new float[img.getNPixels()]; int count = 0; for (int i = 0; i < img.getWidth(); ++i) { for (int j = 0; j < img.getHeight(); ++j) { int v = img.getValue(i, j); values[count] = v; count++; } } float[] errors = Errors.populateYErrorsBySqrt(values); HistogramHolder hist = createSimpleHistogram(values, errors); if (hist.getXHist().length < 2) { return hist; } int n = hist.getXHist().length; // int yMax = MiscMath.findMax(hist.getYHist()); // int yMin = MiscMath.findMin(hist.getYHist()); int fIdx = 0; for (int i = 0; i < n; ++i) { fIdx = i; int y = hist.getYHist()[i]; if (y > 0) { break; } } int lIdx = (n - 1); for (int i = (n - 1); i > -1; --i) { lIdx = i; int y = hist.getYHist()[i]; if (y > 0) { break; } } if ((fIdx <= 1) && (lIdx >= (n - 2))) { return hist; } /* if there are a large number of bins, re-do the x idx limits using a lower limit larger than spurious counts... this may need revision */ // TODO: consider comparing (lIdx - fIdx) > 30 if (hist.getXHist().length > 30) { int tmp0 = fIdx; int tmp1 = lIdx; int xMaxYIdx = MiscMath.findYMaxIndex(hist.getYHist()); float limit = (int) Math.ceil(Math.sqrt(hist.getYHist()[xMaxYIdx])); fIdx = 0; for (int i = 0; i < n; ++i) { fIdx = i; int y = hist.getYHist()[i]; if (y > limit) { break; } } lIdx = (n - 1); for (int i = (n - 1); i > -1; --i) { lIdx = i; int y = hist.getYHist()[i]; if (y > limit) { break; } } int maxDiffIdx = Math.max(xMaxYIdx - fIdx, lIdx - xMaxYIdx); fIdx = xMaxYIdx - 3 * maxDiffIdx; lIdx = xMaxYIdx + 3 * maxDiffIdx; if (fIdx < 0) { fIdx = tmp0; } if (lIdx > (n - 1)) { lIdx = tmp1; } } // re-do for smaller range float xBin = hist.getXHist()[1] - hist.getXHist()[0]; float xf; if (fIdx == 0) { xf = hist.getXHist()[0] - (xBin / 2.f); } else { xf = hist.getXHist()[fIdx - 1] - (xBin / 2.f); } float xl; if (lIdx == (n - 1)) { xl = hist.getXHist()[lIdx] + (xBin / 2.f); } else { xl = hist.getXHist()[lIdx + 1] + (xBin / 2.f); } int n2 = 0; float[] values2 = new float[values.length]; float[] errors2 = new float[values2.length]; for (int i = 0; i < values2.length; ++i) { float v = values[i]; if ((v >= xf) && (v <= xl)) { values2[n2] = v; errors2[n2] = errors[n2]; n2++; } } values2 = Arrays.copyOf(values2, n2); errors2 = Arrays.copyOf(errors2, n2); hist = createSimpleHistogram(values2, errors2); return hist; }
public static float measureFWHM(HistogramHolder hist, int yPeakIndex) { if (hist == null) { throw new IllegalArgumentException("hist cannot be null"); } if ((yPeakIndex == -1) || (yPeakIndex > (hist.getXHist().length - 1))) { return 0; } float halfPeak = hist.getYHist()[yPeakIndex] / 2.f; float x0 = Float.MIN_VALUE; if (yPeakIndex == 0) { x0 = hist.getXHist()[0]; } else { for (int i = 0; i <= yPeakIndex; i++) { float y = hist.getYHistFloat()[i]; if (y == halfPeak) { x0 = hist.getXHist()[i]; } else if (y > halfPeak) { if (i == 0) { x0 = hist.getXHist()[0]; } else { // interpret between i and i-1 float dx01 = hist.getXHist()[i] - hist.getXHist()[i - 1]; float dy01 = y - hist.getYHistFloat()[i - 1]; float dy0h = y - halfPeak; float ratio = dy0h / dy01; x0 = hist.getXHist()[i] - (dx01 * ratio); } break; } } } float x1 = Float.MIN_VALUE; if (yPeakIndex == (hist.getYHist().length - 1)) { x1 = hist.getXHist()[(hist.getYHist().length - 1)]; } else { for (int i = (yPeakIndex + 1); i < hist.getYHist().length; i++) { float y = hist.getYHist()[i]; if (y == halfPeak) { x1 = hist.getXHist()[i]; } else if (y < halfPeak) { if (i == (hist.getYHist().length - 1)) { x1 = hist.getXHist()[(hist.getYHist().length - 1)]; } else { // interpret between i and i-1 float dx01 = hist.getXHist()[i] - hist.getXHist()[i - 1]; float dy01 = y - hist.getYHistFloat()[i - 1]; float dy0h = y - halfPeak; float ratio = dy0h / dy01; x1 = hist.getXHist()[i] - (dx01 * ratio); } break; } } } if ((x0 == Float.MIN_VALUE) || (x1 == Float.MIN_VALUE)) { return 0; } float fwhm = x1 - x0; return fwhm; }