/** * Computes an alpha trimmed mean upon the current region of the current function. Note that this * method uses memory to make a copy of the input values. Larger input regions might require a lot * of memory. * * @param alpha A number between 0 and 0.5 specifying the proportion of samples to ignore on each * end. * @return The measured value */ public double alphaTrimmedMean(double alpha) { if ((alpha < 0) || (alpha >= 0.5)) throw new IllegalArgumentException("alpha value must be >= 0 and < 0.5"); T tmp = func.createOutput(); values.clear(); iter.reset(); while (iter.hasNext()) { long[] pos = iter.next(); func.compute(pos, tmp); values.add(tmp.getRealDouble()); } values.sortValues(); double tailSize = alpha * values.size(); // can we avoid interpolation? if (tailSize == Math.floor(tailSize)) { // yes, trim count is exactly an integer return calcTrimmedMean(values, (int) tailSize); } // no, trim count is a float value // calc two trimmed means and interpolate to find the value between them double mean1 = calcTrimmedMean(values, (int) Math.floor(tailSize)); double mean2 = calcTrimmedMean(values, (int) Math.ceil(tailSize)); double fraction = tailSize - Math.floor(tailSize); double interpolation = ((1 - fraction) * mean1) + (fraction * mean2); return interpolation; }
@Test public void testCrossNeighborhoodProduct() { Img<DoubleType> inputImg = makeInputImage(); /* old way DiscreteNeigh neigh = new DiscreteNeigh(new long[2], new long[]{1,1}, new long[]{1,1}); Condition<long[]> condition = new OnTheXYCrossCondition(); Function<long[],DoubleType> input = new RealImageFunction<DoubleType,DoubleType>(inputImg, new DoubleType()); Function<long[],DoubleType> one = new ConstantRealFunction<long[],DoubleType>(inputImg.firstElement(),1); Function<long[],DoubleType> conditionalFunc = new ConditionalFunction<long[],DoubleType>(condition, input, one); Function<long[],DoubleType> prodFunc = new RealProductFunction<DoubleType>(conditionalFunc); long[] index = new long[2]; DoubleType output = new DoubleType(); for (int x = 1; x < XSIZE-1; x++) { for (int y = 1; y < YSIZE-1; y++) { index[0] = x; index[1] = y; neigh.moveTo(index); prodFunc.evaluate(neigh, neigh.getKeyPoint(), output); //{ // System.out.println(" FAILURE at ("+x+","+y+"): expected (" // +expectedValue(x,y)+") actual ("+output.getRealDouble()+")"); // success = false; //} assertTrue(veryClose(output.getRealDouble(), expectedValue(x,y))); } } */ ArrayList<long[]> pts = new ArrayList<long[]>(); pts.add(new long[] {-1, -1}); pts.add(new long[] {-1, 1}); pts.add(new long[] {0, 0}); pts.add(new long[] {1, -1}); pts.add(new long[] {1, 1}); GeneralPointSet neigh = new GeneralPointSet(new long[] {0, 0}, pts); Function<long[], DoubleType> input = new RealImageFunction<DoubleType, DoubleType>(inputImg, new DoubleType()); Function<PointSet, DoubleType> prodFunc = new RealProductFunction<DoubleType>(input); HyperVolumePointSet space = new HyperVolumePointSet(new long[] {1, 1}, new long[] {XSIZE - 2, YSIZE - 2}); PointSetInputIterator iter = new PointSetInputIterator(space, neigh); DoubleType output = new DoubleType(); PointSet points = null; while (iter.hasNext()) { points = iter.next(points); prodFunc.compute(points, output); int x = (int) points.getOrigin()[0]; int y = (int) points.getOrigin()[1]; // { // System.out.println(" Point ("+x+","+y+"): expected (" // +expectedValue(x,y)+") actual ("+output.getRealDouble()+")"); // success = false; // } assertTrue(veryClose(output.getRealDouble(), expectedValue(x, y))); } }
/** * Computes the product of all the values of the current region of the current function. * * @return The measured value */ public double product() { T tmp = func.createOutput(); double prod = 1; iter.reset(); while (iter.hasNext()) { long[] pos = iter.next(); func.compute(pos, tmp); double value = tmp.getRealDouble(); prod *= value; } return prod; }
/** * Computes the minimum value upon the current region of the current function. * * @return The measured value */ public double min() { T tmp = func.createOutput(); double min = Double.POSITIVE_INFINITY; iter.reset(); while (iter.hasNext()) { long[] pos = iter.next(); func.compute(pos, tmp); double value = tmp.getRealDouble(); min = Math.min(min, value); } return min; }
/** * Computes a trimmed mean upon the current region of the current function. Note that this method * uses memory to make a copy of the input values. Larger input regions might require a lot of * memory. * * @param halfTrimSize The number of samples to ignore from each end of the data * @return The measured value */ public double trimmedMean(int halfTrimSize) { T tmp = func.createOutput(); values.clear(); iter.reset(); while (iter.hasNext()) { long[] pos = iter.next(); func.compute(pos, tmp); values.add(tmp.getRealDouble()); } values.sortValues(); return calcTrimmedMean(values, halfTrimSize); }
/** * Computes the maximum value upon the current region of the current function. * * @return The measured value */ public double max() { T tmp = func.createOutput(); double max = Double.NEGATIVE_INFINITY; iter.reset(); while (iter.hasNext()) { long[] pos = iter.next(); func.compute(pos, tmp); double value = tmp.getRealDouble(); max = Math.max(max, value); } return max; }
/** * Computes the sum of all the values of the current region of the current function. * * @return The measured value */ public double sum() { T tmp = func.createOutput(); double sum = 0; iter.reset(); while (iter.hasNext()) { long[] pos = iter.next(); func.compute(pos, tmp); double value = tmp.getRealDouble(); sum += value; } return sum; }
/** * Computes the arithmetic mean (or average) upon the current region of the current function. * * @return The measured value */ public double arithmeticMean() { T tmp = func.createOutput(); double sum = 0; long numElements = 0; iter.reset(); while (iter.hasNext()) { long[] pos = iter.next(); func.compute(pos, tmp); sum += tmp.getRealDouble(); numElements++; } return sum / numElements; }
/** * Computes the contraharmonic mean upon the current region of the current function. * * @return The measured value */ public double contraharmonicMean(double order) { T tmp = func.createOutput(); double sum1 = 0; double sum2 = 0; iter.reset(); while (iter.hasNext()) { long[] pos = iter.next(); func.compute(pos, tmp); double value = tmp.getRealDouble(); sum1 += Math.pow(value, order + 1); sum2 += Math.pow(value, order); } return sum1 / sum2; }
/** * Computes the sum of squared deviations of the values of the current region of the current * function. * * @return The measured value */ public double sumOfSquaredDeviations() { T tmp = func.createOutput(); final double xbar = arithmeticMean(); double sum = 0; iter.reset(); while (iter.hasNext()) { long[] pos = iter.next(); func.compute(pos, tmp); double value = tmp.getRealDouble(); double term = value - xbar; sum += (term * term); } return sum; }
/** * Computes the harmonic mean upon the current region of the current function. * * @return The measured value */ public double harmonicMean() { T tmp = func.createOutput(); double sum = 0; long numElements = 0; iter.reset(); while (iter.hasNext()) { long[] pos = iter.next(); func.compute(pos, tmp); double value = tmp.getRealDouble(); sum += 1 / value; numElements++; } return numElements / sum; // looks weird but it is correct }
/** * Computes a weighted sum of the current function values over the current region. The weights are * provided and there must be as many weights as there are points in the current region. * * @return The measured value */ public double weightedSum(double[] weights) { long numElements = region.size(); if (numElements != weights.length) throw new IllegalArgumentException("number of weights does not equal number of samples"); T tmp = func.createOutput(); double sum = 0; int i = 0; iter.reset(); while (iter.hasNext()) { long[] pos = iter.next(); func.compute(pos, tmp); double value = tmp.getRealDouble(); sum += weights[i++] * value; } return sum; }
/** * Computes the center of mass point of the current region of the current function. Returns it as * a pair of Doubles. The first element in the pair is the x component and the second element is * the y component. * * @return The measured point stored in a Tuple2 */ public Tuple2<Double, Double> centerOfMassXY() { T tmp = func.createOutput(); double sumV = 0; double sumX = 0; double sumY = 0; iter.reset(); while (iter.hasNext()) { long[] pos = iter.next(); func.compute(pos, tmp); double v = tmp.getRealDouble(); sumV += v; sumX += v * pos[0]; sumY += v * pos[1]; } double cx = (sumX / sumV) + 0.5; double cy = (sumY / sumV) + 0.5; return new Tuple2<Double, Double>(cx, cy); }
/** * Computes the median upon the current region of the current function. Note that this method uses * memory to make a copy of the input values. Larger input regions might require a lot of memory. * * @return The measured value */ public double median() { T tmp = func.createOutput(); values.clear(); iter.reset(); while (iter.hasNext()) { long[] pos = iter.next(); func.compute(pos, tmp); values.add(tmp.getRealDouble()); } final int numElements = values.size(); if (numElements <= 0) throw new IllegalArgumentException("number of samples must be greater than 0"); values.sortValues(); // odd number of elements if ((numElements % 2) == 1) return values.get(numElements / 2); // else an even number of elements double value1 = values.get((numElements / 2) - 1); double value2 = values.get((numElements / 2)); return (value1 + value2) / 2; }
/** * Computes the (biased) kurtosis value upon the current region of the current function. * * @return The measured value */ public double populationKurtosis() { T tmp = func.createOutput(); double xbar = arithmeticMean(); double s2 = 0; double s4 = 0; long numElements = 0; iter.reset(); while (iter.hasNext()) { long[] pos = iter.next(); func.compute(pos, tmp); double value = tmp.getRealDouble(); numElements++; double v = value - xbar; double v2 = v * v; double v4 = v2 * v2; s2 += v2; s4 += v4; } double n = numElements; double m2 = s2 / n; double m4 = s4 / n; return m4 / (m2 * m2); }
/** * Computes the (biased) skew value upon the current region of the current function. * * @return The measured value */ public double populationSkew() { T tmp = func.createOutput(); double xbar = arithmeticMean(); double s2 = 0; double s3 = 0; long numElements = 0; iter.reset(); while (iter.hasNext()) { long[] pos = iter.next(); func.compute(pos, tmp); double value = tmp.getRealDouble(); numElements++; double v = value - xbar; double v2 = v * v; double v3 = v2 * v; s2 += v2; s3 += v3; } double n = numElements; double m2 = s2 / n; double m3 = s3 / n; return m3 / Math.pow(m2, 1.5); }
private double measure(final Function<PointSet, DoubleType> func, final PointSet region) { final DoubleType output = new DoubleType(); func.compute(region, output); return output.getRealDouble(); }
@Override public DiscreteTranslationFunction<T> copy() { return new DiscreteTranslationFunction<T>(otherFunc.copy(), deltas.clone()); }
@Override public T createOutput() { return otherFunc.createOutput(); }
@Override public void compute(long[] point, T output) { for (int i = 0; i < deltas.length; i++) localPoint[i] = point[i] + deltas[i]; otherFunc.compute(localPoint, output); }