implements OutlierAlgorithm {
/**
* The logger for this class.
*/
private static final Logging LOG = Logging.getLogger(RescaleMetaOutlierAlgorithm.class);
/**
* Parameter to specify a scaling function to use.
*
* Key: {@code -comphist.scaling}
*
*/
public static final OptionID SCALING_ID = new OptionID("metaoutlier.scaling", "Class to use as scaling function.");
/**
* Holds the algorithm to run.
*/
private Algorithm algorithm;
/**
* Scaling function to use
*/
private ScalingFunction scaling;
/**
* Constructor.
*
* @param algorithm Inner algorithm
* @param scaling Scaling to apply.
*/
public RescaleMetaOutlierAlgorithm(Algorithm algorithm, ScalingFunction scaling) {
super();
this.algorithm = algorithm;
this.scaling = scaling;
}
@Override
public OutlierResult run(Database database) {
Result innerresult = algorithm.run(database);
OutlierResult or = getOutlierResult(innerresult);
final Relation scores = or.getScores();
if(scaling instanceof OutlierScalingFunction) {
((OutlierScalingFunction) scaling).prepare(or);
}
WritableDoubleDataStore scaledscores = DataStoreUtil.makeDoubleStorage(scores.getDBIDs(), DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_STATIC);
DoubleMinMax minmax = new DoubleMinMax();
for(DBIDIter iditer = scores.iterDBIDs(); iditer.valid(); iditer.advance()) {
double val = scaling.getScaled(scores.get(iditer));
scaledscores.putDouble(iditer, val);
minmax.put(val);
}
OutlierScoreMeta meta = new BasicOutlierScoreMeta(minmax.getMin(), minmax.getMax(), scaling.getMin(), scaling.getMax());
Relation scoresult = new MaterializedRelation("Scaled Outlier", "scaled-outlier", TypeUtil.DOUBLE, scaledscores, scores.getDBIDs());
OutlierResult result = new OutlierResult(meta, scoresult);
result.addChildResult(innerresult);
return result;
}
/**
* Find an OutlierResult to work with.
*
* @param result Result object
* @return Iterator to work with
*/
private OutlierResult getOutlierResult(Result result) {
List ors = ResultUtil.filterResults(result, OutlierResult.class);
if(ors.size() > 0) {
return ors.get(0);
}
throw new IllegalStateException("Comparison algorithm expected at least one outlier result.");
}
@Override
protected Logging getLogger() {
return LOG;
}
@Override
public TypeInformation[] getInputTypeRestriction() {
return algorithm.getInputTypeRestriction();
}
/**
* Parameterization class
*
* @author Erich Schubert
*
* @apiviz.exclude
*/
public static class Parameterizer extends AbstractParameterizer {
/**
* Holds the algorithm to run.
*/
private Algorithm algorithm;
/**
* Scaling function to use
*/
private ScalingFunction scaling;
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
ObjectParameter algP = new ObjectParameter(OptionID.ALGORITHM, OutlierAlgorithm.class);
if(config.grab(algP)) {
algorithm = algP.instantiateClass(config);
}
ObjectParameter scalingP = new ObjectParameter(SCALING_ID, ScalingFunction.class);
if(config.grab(scalingP)) {
scaling = scalingP.instantiateClass(config);
}
}
@Override
protected RescaleMetaOutlierAlgorithm makeInstance() {
return new RescaleMetaOutlierAlgorithm(algorithm, scaling);
}
}
}