/**
* Copyright (C) 2010-14 diirt developers. See COPYRIGHT.TXT
* All rights reserved. Use is subject to license terms. See LICENSE.TXT
*/
package org.diirt.datasource.vtype;
import org.diirt.vtype.VStatistics;
import org.diirt.vtype.AlarmSeverity;
import org.diirt.vtype.VDouble;
import static java.lang.Math.*;
import java.util.List;
import org.diirt.datasource.Aggregator;
import org.diirt.datasource.ReadFunction;
import static org.diirt.vtype.AlarmSeverity.*;
import static org.diirt.vtype.ValueFactory.*;
/**
* Aggregates statistics out of multiple VDoubles.
* <p>
* All data with severity NONE, MINOR and MAJOR is used for calculating
* statistics. If all samples are UNDEFINED, the severity will be undefined.
* If all samples are UNDEFINED/INVALID, the severity will
* be INVALID. In all other cases, the severity will be the highest between
* NONE, MINOR and MAJOR. Only valid samples are used for computation.
* <p>
* TODO: what is the best alarm calculation?
* TODO: what should be the weight? Each sample one, or weighted by time?
* TODO: timestamp? Average? Median? Time of calculation? If weight is
* one, should be median. If weight by time, should be average.
*
* @author carcassi
*/
class StatisticsDoubleAggregator extends Aggregator<VStatistics, VDouble> {
StatisticsDoubleAggregator(ReadFunction<List<VDouble>> collector) {
super(collector);
}
private static class Stats {
double totalSum = 0;
double totalSquareSum = 0;
double min = Double.MAX_VALUE;
double max = - Double.MAX_VALUE;
int nElements = 0;
void includeValue(double value) {
totalSum += value;
totalSquareSum += value * value;
min = min(min, value);
max = max(min, value);
nElements++;
}
}
@Override
protected VStatistics calculate(List<VDouble> data) {
Stats stats = new Stats();
AlarmSeverity statSeverity = null;
for (VDouble vDouble : data) {
switch(vDouble.getAlarmSeverity()) {
case NONE:
// if severity was never MINOR or MAJOR,
// severity should be NONE
if (statSeverity != MINOR || statSeverity != MAJOR)
statSeverity = NONE;
stats.includeValue(vDouble.getValue());
break;
case MINOR:
// If severity was never MAJOR,
// set it to MINOR
if (statSeverity != MAJOR)
statSeverity = MINOR;
stats.includeValue(vDouble.getValue());
break;
case MAJOR:
statSeverity = MAJOR;
stats.includeValue(vDouble.getValue());
break;
case UNDEFINED:
if (statSeverity == null)
statSeverity = UNDEFINED;
break;
case INVALID:
if (statSeverity == null || statSeverity == UNDEFINED)
statSeverity = INVALID;
break;
default:
}
}
return newVStatistics(stats.totalSum / stats.nElements,
sqrt(stats.totalSquareSum / stats.nElements - (stats.totalSum * stats.totalSum) / (stats.nElements * stats.nElements)),
stats.min, stats.max, stats.nElements,
newAlarm(statSeverity, "NONE"), newTime(data.get(data.size() / 2).getTimestamp()), data.get(0));
}
}