package org.epics.archiverappliance.retrieval.postprocessors; import java.sql.Timestamp; import java.util.LinkedList; import org.apache.commons.math3.analysis.interpolation.LinearInterpolator; import org.apache.commons.math3.analysis.polynomials.PolynomialSplineFunction; import org.apache.log4j.Logger; import org.epics.archiverappliance.Event; /** * Implements the arithmetic mean across an interval * @author mshankar * */ public class LinearInterpolation extends SummaryStatsPostProcessor implements PostProcessor { private static Logger logger = Logger.getLogger(LinearInterpolation.class.getName()); static final String IDENTITY = "linear"; private class InterpolationValues { double x; double y; public InterpolationValues(double x, double y) { this.x = x; this.y = y; } } @Override public String getIdentity() { return IDENTITY; } @Override public SummaryStatsCollector getCollector() { return new SummaryStatsCollector() { long binNum; int intervalSecs; LinkedList<InterpolationValues> vals = new LinkedList<InterpolationValues>(); @Override public void setBinParams(int intervalSecs, long binNum) { this.intervalSecs = intervalSecs; this.binNum = binNum; } @Override public boolean haveEventsBeenAdded() { return vals.size() > 0; } @Override public double getStat() { int size = vals.size(); double[] xa = new double[size]; double[] ya = new double[size]; for(int i = 0; i < size; i++) { InterpolationValues iv = vals.get(i); xa[i] = iv.x; ya[i] = iv.y; } try { PolynomialSplineFunction fn = new LinearInterpolator().interpolate(xa, ya); return fn.value(binNum*intervalSecs + intervalSecs/2); } catch(Exception ex) { logger.debug("Exception when computing value; note that this may be perfectly acceptable; so we return the first value ", ex); return ya[0]; } } @Override public void addEvent(Event e) { Timestamp ts = e.getEventTimeStamp(); double time = e.getEpochSeconds() + ts.getNanos()/1000000000.0; vals.add(new InterpolationValues(time, e.getSampleValue().getValue().doubleValue())); } }; } }