*/
public OutlierResult run(Relation<N> nrel, Relation<? extends NumberVector<?, ?>> relation) {
final NeighborSetPredicate npred = getNeighborSetPredicateFactory().instantiate(nrel);
WritableDataStore<Double> scores = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC, Double.class);
MeanVariance mv = new MeanVariance();
for(DBID id : relation.iterDBIDs()) {
DBIDs neighbors = npred.getNeighborDBIDs(id);
final double median;
{
double[] fi = new double[neighbors.size()];
// calculate and store Median of neighborhood
int c = 0;
for(DBID n : neighbors) {
if(id.equals(n)) {
continue;
}
fi[c] = relation.get(n).doubleValue(1);
c++;
}
if(c > 0) {
// Note: only use up to c-1, since we may have used a too big array
median = QuickSelect.median(fi, 0, c - 1);
}
else {
median = relation.get(id).doubleValue(1);
}
}
double h = relation.get(id).doubleValue(1) - median;
scores.put(id, h);
mv.put(h);
}
// Normalize scores
final double mean = mv.getMean();
final double stddev = mv.getNaiveStddev();
DoubleMinMax minmax = new DoubleMinMax();
for(DBID id : relation.iterDBIDs()) {
double score = Math.abs((scores.get(id) - mean) / stddev);
minmax.put(score);
scores.put(id, score);