PointListProcessor.java
package com.github.celldynamics.quimp.geom.filters;
import java.awt.geom.Point2D;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import org.scijava.vecmath.Point2d;
import org.scijava.vecmath.Tuple2d;
import com.github.celldynamics.quimp.plugin.utils.IPadArray;
import com.github.celldynamics.quimp.plugin.utils.QuimpDataConverter;
/**
* Perform filtering on basic list of coordinates.
*
* @author p.baniukiewicz
* @see OutlineProcessor
*/
public class PointListProcessor {
private QuimpDataConverter dt;
/**
* Initialize object with list of points.
*
* @param list to process
*/
public PointListProcessor(List<? extends Tuple2d> list) {
dt = new QuimpDataConverter(list);
}
/**
* Initialize object with list of points.
*
* @param list to process
*/
public PointListProcessor(Collection<? extends Point2D> list) {
dt = new QuimpDataConverter(list);
}
/**
* Apply mean filter to list.
*
* @param window size of mean window
* @param iters number of iterations
* @return Reference to this object
*/
public PointListProcessor smoothMean(int window, int iters) {
double[] x = dt.getX();
double[] y = dt.getY();
for (int i = 0; i < iters; i++) {
y = runningMean(y, window);
x = runningMean(x, window);
}
dt = new QuimpDataConverter(x, y);
return this;
}
/**
* Apply median filter to list.
*
* @param window size of median window
* @param iters number of iterations
* @return Reference to this object
*/
public PointListProcessor smoothMedian(int window, int iters) {
double[] x = dt.getX();
double[] y = dt.getY();
for (int i = 0; i < iters; i++) {
y = runningMedian(y, window);
x = runningMedian(x, window);
}
dt = new QuimpDataConverter(x, y);
return this;
}
/**
* Return modified list.
*
* @return list after processing
*/
public List<Point2d> getList() {
return dt.getList();
}
/**
* Return modified awt double list.
*
* @return list after processing (doubles)
*/
public List<Point2D> getListAwtDouble() {
return dt.getListofDoublePoints();
}
/**
* Return modified awt int list.
*
* @return list after processing (integers)
*/
public List<Point2D> getListAwtInt() {
return dt.getListofIntPoints();
}
/**
* Return underlying DataConverter instance.
*
* @return DataConverter
*/
public QuimpDataConverter getDataConverterInstance() {
return dt;
}
/**
* Running mean on input array.
*
* @param data data to filter, can be empty
* @param windowSize odd window size
* @return Filtered array
*/
public static double[] runningMean(double[] data, int windowSize) {
if (windowSize % 2 == 0) {
throw new IllegalArgumentException("Window must be odd");
}
double[] ret = new double[data.length];
int cp = windowSize / 2; // left and right range of window
for (int c = 0; c < data.length; c++) { // for every point in data
double mean = 0;
for (int cc = c - cp; cc <= c + cp; cc++) { // points in range c-2 - c+2 (for window=5)
int indexTmp = IPadArray.getIndex(data.length, cc, IPadArray.CIRCULARPAD);
mean += data[indexTmp];
}
mean = mean / windowSize;
ret[c] = mean; // remember result
}
return ret;
}
/**
* Running median on input array.
*
* @param data data to filter, can be empty
* @param windowSize odd window size
* @return Filtered array
*/
public static double[] runningMedian(double[] data, int windowSize) {
if (windowSize % 2 == 0) {
throw new IllegalArgumentException("Window must be odd");
}
double[] ret = new double[data.length];
int cp = windowSize / 2; // left and right range of window
double[] xs = new double[windowSize]; // window point
int l = 0;
for (int c = 0; c < data.length; c++) { // for every point in data
l = 0;
for (int cc = c - cp; cc <= c + cp; cc++) { // collect points in range c-2 c-1 c-0 c+1 c+2
int indexTmp = IPadArray.getIndex(data.length, cc, IPadArray.CIRCULARPAD);
xs[l] = data[indexTmp];
l++;
}
// get median
Arrays.sort(xs);
ret[c] = xs[cp];
}
return ret;
}
}