* @param database Database to use
* @param relation Relation to use
* @return Result
*/
public OutlierResult run(Database database, Relation<?> relation) {
WritableDoubleDataStore scores = DataStoreUtil.makeDoubleStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC);
Pattern colSep = Pattern.compile(AbstractParser.WHITESPACE_PATTERN);
DoubleMinMax minmax = new DoubleMinMax();
InputStream in;
try {
in = FileUtil.tryGzipInput(new FileInputStream(file));
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
for(String line; (line = reader.readLine()) != null;) {
if(line.startsWith(COMMENT)) {
continue;
}
else if(line.length() > 0) {
String[] cols = colSep.split(line);
Integer id = null;
double score = Double.NaN;
for(String str : cols) {
Matcher mi = idpattern.matcher(str);
Matcher ms = scorepattern.matcher(str);
final boolean mif = mi.find();
final boolean msf = ms.find();
if(mif && msf) {
throw new AbortException("ID pattern and score pattern both match value: " + str);
}
if(mif) {
if(id != null) {
throw new AbortException("ID pattern matched twice: previous value " + id + " second value: " + str);
}
id = Integer.parseInt(str.substring(mi.end()));
}
if(msf) {
if(!Double.isNaN(score)) {
throw new AbortException("Score pattern matched twice: previous value " + score + " second value: " + str);
}
score = Double.parseDouble(str.substring(ms.end()));
}
}
if(id != null && !Double.isNaN(score)) {
scores.putDouble(DBIDUtil.importInteger(id), score);
minmax.put(score);
}
else if(id == null && Double.isNaN(score)) {
logger.warning("Line did not match either ID nor score nor comment: " + line);
}
else {
throw new AbortException("Line matched only ID or only SCORE patterns: " + line);
}
}
}
}
catch(IOException e) {
throw new AbortException("Could not load outlier scores: " + e.getMessage() + " when loading " + file, e);
}
OutlierScoreMeta meta;
if(inverted) {
meta = new InvertedOutlierScoreMeta(minmax.getMin(), minmax.getMax());
}
else {
meta = new BasicOutlierScoreMeta(minmax.getMin(), minmax.getMax());
}
Relation<Double> scoresult = new MaterializedRelation<Double>("External Outlier", "external-outlier", TypeUtil.DOUBLE, scores, relation.getDBIDs());
OutlierResult or = new OutlierResult(meta, scoresult);
// Apply scaling
if(scaling instanceof OutlierScalingFunction) {
((OutlierScalingFunction) scaling).prepare(or);
}
DoubleMinMax mm = new DoubleMinMax();
for(DBID id : relation.iterDBIDs()) {
double val = scoresult.get(id); // scores.get(id);
val = scaling.getScaled(val);
scores.putDouble(id, val);
mm.put(val);
}
meta = new BasicOutlierScoreMeta(mm.getMin(), mm.getMax());
or = new OutlierResult(meta, scoresult);