/*
* 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.apps;
import java.io.IOException;
import java.util.ArrayList;
import java.util.logging.Logger;
import com.martiansoftware.jsap.JSAPResult;
import com.martiansoftware.jsap.Parameter;
import at.tuwien.ifs.somtoolbox.SOMToolboxException;
import at.tuwien.ifs.somtoolbox.apps.config.OptionFactory;
import at.tuwien.ifs.somtoolbox.apps.helper.SOMMerger;
import at.tuwien.ifs.somtoolbox.data.InputData;
import at.tuwien.ifs.somtoolbox.data.InputDatum;
import at.tuwien.ifs.somtoolbox.data.SOMLibSparseInputData;
import at.tuwien.ifs.somtoolbox.input.SOMLibFormatInputReader;
import at.tuwien.ifs.somtoolbox.layers.GrowingLayer;
import at.tuwien.ifs.somtoolbox.layers.Unit;
import at.tuwien.ifs.somtoolbox.models.GrowingSOM;
import at.tuwien.ifs.somtoolbox.output.SOMLibMapOutputter;
import at.tuwien.ifs.somtoolbox.util.FileUtils;
/**
* Maps inputs on a merged SOM. The merged SOM is trained from the weight vectors of two or more initial SOMs, e.g. by
* using {@link SOMMerger}. The input vectors mapped to the initial SOMs will be put on the units in the merged SOM on
* which the weight-vector initially representing them is merged.
*
* @author Rudolf Mayer
* @version $Id: MergedSOMDataMapper.java 3589 2010-05-21 10:42:01Z mayer $
*/
public class MergedSOMDataMapper {
private static final Logger logger = Logger.getLogger("at.tuwien.ifs.somtoolbox");
public static void main(String[] args) throws IOException, SOMToolboxException {
new MergedSOMDataMapper(args);
}
public MergedSOMDataMapper(String[] args) throws IOException, SOMToolboxException {
// register and parse all options
// Labelling is an optional step, and requires input and template vectors
JSAPResult config = OptionFactory.parseResults(args, new Parameter[] {
OptionFactory.getOptWeightVectorFile(true), OptionFactory.getOptUnitDescriptionFile(true),
OptionFactory.getOptInputVectorFile(false), OptionFactory.getOptNumberWinners(false),
OptionFactory.getSwitchSkipDataWinnerMapping(), OptionFactory.getOptClassInformationFile(false),
OptionFactory.getOptProperties(true), OptionFactory.getOptSOMLibMaps(true) });
String unitDescFileName = config.getString("unitDescriptionFile");
String weightVectorFileName = config.getString("weightVectorFile");
String classInformationFile = config.getString("classInformationFile");
String[] originalMaps = config.getStringArray("maps");
boolean skipDataWinnerMapping = config.getBoolean("skipDataWinnerMapping", false);
int numDataWinners = config.getInt("numberWinners");
GrowingSOM som = null;
/* restore SOM */
try {
som = new GrowingSOM(new SOMLibFormatInputReader(weightVectorFileName, unitDescFileName, null));
} catch (Exception e) {
logger.severe(e.getMessage() + " Aborting.");
e.printStackTrace();
System.exit(-1);
}
ArrayList<String> originalMappedUnitvectorNames = som.getLayer().getAllMappedDataNamesAsList();
for (String originalMap2 : originalMaps) {
String orignalMapPrefix = FileUtils.extractSOMLibInputPrefix(FileUtils.stripPathPrefix(originalMap2));
GrowingSOM originalSOM = new GrowingSOM(new SOMLibFormatInputReader(null, originalMap2, null));
final GrowingLayer originalMap = originalSOM.getLayer();
for (Unit originalMapUnit : originalMap.getAllUnits()) {
// find the unit where this weight vector is mapped to
final String unitInputName = orignalMapPrefix + "_" + originalMapUnit.printCoordinates();
final Unit unitForDatum = som.getLayer().getUnitForDatum(unitInputName);
// replace the mapping of the unit's weight vector with the inputs it represents
if (originalMapUnit.getNumberOfMappedInputs() > 0) {
for (String string : originalMapUnit.getMappedInputNames()) {
unitForDatum.addMappedInput(new InputDatum(string, new double[som.getLayer().getDim()]), false);
}
}
// remove this weight vector from the mapped unit files
unitForDatum.removeMappedInput(unitInputName);
}
}
ArrayList<String> finalMappedVectorNames = som.getLayer().getAllMappedDataNamesAsList();
originalMappedUnitvectorNames.retainAll(finalMappedVectorNames);
logger.info("New unit file contains " + finalMappedVectorNames.size() + " vectors.");
if (originalMappedUnitvectorNames.size() > 0) {
logger.warning("Could not replace " + originalMappedUnitvectorNames.size() + " unit weight vectors: "
+ originalMappedUnitvectorNames);
}
final String outfilePrefix = FileUtils.extractSOMLibInputPrefix(FileUtils.stripPathPrefix(weightVectorFileName))
+ ".mergeMapped";
try {
SOMLibMapOutputter.writeUnitDescriptionFile(som, "", outfilePrefix, true);
} catch (IOException e) { // TODO: create new exception type
logger.severe("Could not open or write to output file " + outfilePrefix + ": " + e.getMessage());
e.printStackTrace();
System.exit(-1);
}
if (!skipDataWinnerMapping) {
int numWinners = Math.min(numDataWinners, som.getLayer().getXSize() * som.getLayer().getYSize());
try {
InputData data = new SOMLibSparseInputData(config.getString("inputVectorFile"));
SOMLibMapOutputter.writeDataWinnerMappingFile(som, data, numWinners, "", outfilePrefix, true);
} catch (IOException e) {
logger.severe("Could not open or write to output file " + outfilePrefix + ": " + e.getMessage());
System.exit(-1);
}
} else {
logger.info("Skipping writing data winner mapping file");
}
// just copy along the class information file, so we have a copy with the same name-prefix, eases SOMViewer
// starting..
if (classInformationFile != null) {
String classInfoDestination = outfilePrefix + ".cls" + (classInformationFile.endsWith(".gz") ? ".gz" : "");
FileUtils.copyFile(classInformationFile, classInfoDestination);
}
}
}