package org.kairosdb.core.aggregator;
import com.google.inject.Inject;
import org.apache.commons.math3.stat.regression.SimpleRegression;
import org.kairosdb.core.DataPoint;
import org.kairosdb.core.aggregator.annotation.AggregatorName;
import org.kairosdb.core.aggregator.annotation.AggregatorProperty;
import org.kairosdb.core.datapoints.DoubleDataPointFactory;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
Created with IntelliJ IDEA.
User: bhawkins
Date: 5/29/13
Time: 3:10 PM
To change this template use File | Settings | File Templates.
*/
@AggregatorName(
name = "least_squares",
description = "Returns a best fit line through the datapoints using the least squares algorithm.",
properties = {
@AggregatorProperty(name = "sampling", type = "duration"),
@AggregatorProperty(name="align_start_time", type="boolean")
}
)
public class LeastSquaresAggregator extends RangeAggregator
{
private DoubleDataPointFactory m_dataPointFactory;
@Inject
public LeastSquaresAggregator(DoubleDataPointFactory dataPointFactory)
{
m_dataPointFactory = dataPointFactory;
}
@Override
public boolean canAggregate(String groupType)
{
return DataPoint.GROUP_NUMBER.equals(groupType);
}
@Override
public String getAggregatedGroupType(String groupType)
{
return m_dataPointFactory.getGroupType();
}
@Override
protected RangeSubAggregator getSubAggregator()
{
return new LeastSquaresDataPointAggregator();
}
private class LeastSquaresDataPointAggregator implements RangeSubAggregator
{
public LeastSquaresDataPointAggregator()
{
}
@Override
public Iterable<DataPoint> getNextDataPoints(long returnTime, Iterator<DataPoint> dataPointRange)
{
long start = -1L;
long stop = -1L;
DataPoint first = null;
DataPoint second = null;
int count = 0;
SimpleRegression simpleRegression = new SimpleRegression(true);
while (dataPointRange.hasNext())
{
count ++;
DataPoint dp = dataPointRange.next();
if (second == null)
{
if (first == null)
first = dp;
else
second = dp;
}
stop = dp.getTimestamp();
if (start == -1L)
start = dp.getTimestamp();
simpleRegression.addData(dp.getTimestamp(), dp.getDoubleValue());
}
List<DataPoint> ret = new ArrayList<DataPoint>();
if (count == 1)
{
ret.add(first);
}
else if (count == 2)
{
ret.add(first);
ret.add(second);
}
else if (count != 0)
{
ret.add(m_dataPointFactory.createDataPoint(start, simpleRegression.predict(start)));
ret.add(m_dataPointFactory.createDataPoint(stop, simpleRegression.predict(stop)));
}
return (ret);
}
}
}