/*
* Copyright 2004-2010 Information & Software Engineering Group (188/1)
* Institute of Software Technology and Interactive Systems
* Vienna University of Technology, Austria
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.ifs.tuwien.ac.at/dm/somtoolbox/license.html
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package at.tuwien.ifs.somtoolbox.input;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Date;
import at.tuwien.ifs.somtoolbox.SOMToolboxException;
import at.tuwien.ifs.somtoolbox.data.InputData;
import at.tuwien.ifs.somtoolbox.layers.Layer;
import at.tuwien.ifs.somtoolbox.layers.Unit;
import at.tuwien.ifs.somtoolbox.util.FileUtils;
public class InputCorrections {
/** Type how input corrections where created. */
public enum CreationType {
MANUAL, // for manually drawn corrections
COMPUTED, // computed corrections
}
private ArrayList<InputCorrection> corrections = null;
public class InputCorrection {
private Unit sourceUnit = null;
private Unit targetUnit = null;
private String label = null;
private double originalDistance;
private CreationType creationType;
public InputCorrection(Unit sourceUnit, Unit targetUnit, String label, double originalDistance,
CreationType creationType) {
this.sourceUnit = sourceUnit;
this.targetUnit = targetUnit;
this.label = label;
this.originalDistance = originalDistance;
this.creationType = creationType;
}
public Unit getSourceUnit() {
return sourceUnit;
}
public String getLabel() {
return label;
}
public Unit getTargetUnit() {
return targetUnit;
}
public double getOriginalDistance() {
return originalDistance;
}
public CreationType getCreationType() {
return creationType;
}
@Override
public String toString() {
return "Correction '" + label + "': " + sourceUnit + " -> " + targetUnit;
}
public String getPrintString() {
return label + " " + sourceUnit.getXPos() + "/" + sourceUnit.getYPos() + " " + targetUnit.getXPos() + "/"
+ targetUnit.getYPos();
}
}
public InputCorrections() {
corrections = new ArrayList<InputCorrection>();
}
public InputCorrections(String fileName, Layer layer, InputData data) throws SOMToolboxException {
this();
readFromFile(fileName, layer, data);
}
public void readFromFile(String fileName, Layer layer, InputData data) throws SOMToolboxException {
try {
BufferedReader reader = FileUtils.openFile("Input correction file", fileName);
String line = null;
while ((line = reader.readLine()) != null) {
line = line.trim();
if (line.startsWith("#")) {
continue;
}
String[] parts = line.split(" ");
String label = parts[0];
String[] sourceString = parts[1].split("/");
String[] targetString = parts[2].split("/");
Unit source = layer.getUnit(Integer.parseInt(sourceString[0]), Integer.parseInt(sourceString[1]));
Unit target = layer.getUnit(Integer.parseInt(targetString[0]), Integer.parseInt(targetString[1]));
double newDistance = data != null ? layer.getMetric().distance(target.getWeightVector(),
data.getInputDatum(label).getVector()) : 0;
corrections.add(new InputCorrection(source, target, label, source.getMappedInputDistance(label),
CreationType.MANUAL));
source.removeMappedInput(label);
target.addMappedInput(label, newDistance, true);
}
} catch (IOException e) {
throw new SOMToolboxException("Error loading input corrections file: " + e.getMessage());
}
}
public int size() {
return corrections.size();
}
public InputCorrection get(int index) {
return corrections.get(index);
}
public InputCorrection get(String label) {
for (int i = 0; i < corrections.size(); i++) {
if (label.equals(corrections.get(i).getLabel())) {
return corrections.get(i);
}
}
return null;
}
private int getIndex(String label) {
for (int i = 0; i < corrections.size(); i++) {
if (label.equals(corrections.get(i).getLabel())) {
return i;
}
}
return -1;
}
private void remove(String label) {
corrections.remove(getIndex(label));
}
public ArrayList<InputCorrection> getInputCorrections() {
return corrections;
}
public InputCorrection addComputedInputCorrection(Unit source, Unit target, String label,
InputCorrections manualCorrections) throws SOMToolboxException {
double originalDistance = manualCorrections.get(label) != null
? manualCorrections.get(label).getOriginalDistance() : source.getMappedInputDistance(label);
InputCorrection correction = new InputCorrection(source, target, label, originalDistance, CreationType.COMPUTED);
corrections.add(correction);
return correction;
}
public InputCorrection addManualInputCorrection(Unit source, Unit target, String label) throws SOMToolboxException {
// check if a correction already exists for this input
InputCorrection correction = get(label);
if (correction != null) {
// if we moved an input back to the original unit, remove that correction
if (correction.sourceUnit.equals(target)) {
remove(label);
}
correction.targetUnit = target; // and update target unit
} else { // otherwise add new
correction = new InputCorrection(source, target, label, source.getMappedInputDistance(label),
CreationType.MANUAL);
corrections.add(correction);
}
return correction;
}
@Override
public String toString() {
StringBuffer sb = new StringBuffer("Input corrections:\n");
for (InputCorrection correction : corrections) {
sb.append(correction).append("\n");
}
return sb.toString();
}
public void writeToFile(File outputFile) throws SOMToolboxException {
try {
PrintWriter out = new PrintWriter(new FileWriter(outputFile));
out.println("# Input corrections file, stored on " + new Date());
out.println("# File format: <label> <sourceX/sourceY> <targetX/targetY>");
for (InputCorrection correction : corrections) {
out.println(correction.getPrintString());
}
out.flush();
out.close();
} catch (IOException e) {
throw new SOMToolboxException("Error writing input corrections: " + e.getMessage(), e);
}
}
}