/*
* 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.visualization;
import java.awt.image.BufferedImage;
import java.util.logging.Logger;
import cern.colt.matrix.DoubleFactory2D;
import cern.colt.matrix.DoubleMatrix2D;
import at.tuwien.ifs.somtoolbox.SOMToolboxException;
import at.tuwien.ifs.somtoolbox.layers.GrowingLayer;
import at.tuwien.ifs.somtoolbox.layers.LayerAccessException;
import at.tuwien.ifs.somtoolbox.layers.metrics.DistanceMetric;
import at.tuwien.ifs.somtoolbox.layers.metrics.MetricException;
import at.tuwien.ifs.somtoolbox.models.GrowingSOM;
import at.tuwien.ifs.somtoolbox.util.VectorTools;
/**
* This Visualizer provides two variants of the U-Matrix.
* <ol>
* <li>Implementation of the classic U-Matrix as described in <i><b>Ultsch, A., and Siemon, H.P.</b> Kohonen's Self
* Organizing Feature Maps for Exploratory Data Analysis. In Proc. Intern. Neural Networks, 1990, pp. 305-308, Kluwer
* Academic Press, Paris, France.</i>.</li>
* <li>Same as 1., but D-Matrix Values only.</li>
* </ol>
*
* @author Michael Dittenbach
* @author Rudolf Mayer
* @version $Id: UMatrix.java 3852 2010-10-12 13:32:25Z mayer $
*/
public class UMatrix extends AbstractMatrixVisualizer implements BackgroundImageVisualizer {
public static final String[] UMATRIX_SHORT_NAMES = new String[] { "UMatrix", "DMatrix" };
public UMatrix() {
NUM_VISUALIZATIONS = 2;
VISUALIZATION_NAMES = new String[] { "U-Matrix", "D-Matrix", };
VISUALIZATION_SHORT_NAMES = UMATRIX_SHORT_NAMES;
VISUALIZATION_DESCRIPTIONS = new String[] {
"Implementation of the classic U-Matrix as described in \"Ultsch, A., and Siemon, H.P.\n"
+ "Kohonen's Self Organizing Feature Maps for Exploratory Data Analysis.\n"
+ "In Proc.Intern. Neural Networks, 1990, pp. 305-308, Kluwer Academic Press, Paris, France.\"",//
"D-Matrix Values only", };
setInterpolate(false); // by default, the U-Matrix is not interpolated
}
@Override
public BufferedImage createVisualization(int index, GrowingSOM gsom, int width, int height)
throws SOMToolboxException {
checkVariantIndex(index, getClass());
if (index == 0) {
return createOriginalUMatrix(gsom, width, height);
} else {
return createOriginalDMatrix(gsom, width, height);
}
}
/**
* Creates an image of the D-Matrix visualisation.
*
* @param gsom the GrowingSOM to generate the visualisation for
* @param width the desired width of the image, in pixels
* @param height the desired height of the image, in pixels.
* @return an image for this visualisation.
*/
private BufferedImage createOriginalDMatrix(GrowingSOM gsom, int width, int height) throws SOMToolboxException {
DoubleMatrix2D dmatrix = createUMatrix(gsom).viewStrides(2, 2);
// System.out.println(new cern.colt.matrix.doublealgo.Formatter("%1.4f").toString(dmatrix));
VectorTools.normalise(dmatrix);
return createImage(gsom, dmatrix, width, height, interpolate);
}
/**
* Creates an image of the U-Matrix visualisation.
*
* @param gsom the GrowingSOM to generate the visualisation for
* @param width the desired width of the image, in pixels
* @param height the desired height of the image, in pixels.
* @return an image for this visualisation.
*/
private BufferedImage createOriginalUMatrix(GrowingSOM gsom, int width, int height) throws SOMToolboxException {
DoubleMatrix2D umatrix = createUMatrix(gsom);
// System.out.println(new cern.colt.matrix.doublealgo.Formatter("%1.4f").toString(umatrix));
VectorTools.normalise(umatrix);
return createImage(gsom, umatrix, width, height, interpolate);
}
/**
* Creates the height matrix.
*
* @param gsom the GrowingSOM to generate the visualisation for
* @return a matrix containing heights for each coordinate.
*/
public DoubleMatrix2D createUMatrix(GrowingSOM gsom) {
GrowingLayer layer = gsom.getLayer();
DistanceMetric metric = layer.getMetric();
int umatW = layer.getXSize() * 2 - 1;
int umatH = layer.getYSize() * 2 - 1;
DoubleMatrix2D umatrix = DoubleFactory2D.dense.make(umatH, umatW, -1);
// calc horizontal, vertical and diagonal distances between units
for (int row = 0; row < umatH; row++) {
for (int col = 0; col < umatW; col++) {
try {
if (col % 2 != 0 && row % 2 == 0) { // horizontal
umatrix.set(row, col, metric.distance(layer.getUnit((col - 1) / 2, row / 2).getWeightVector(),
layer.getUnit((col - 1) / 2 + 1, row / 2).getWeightVector()));
} else if (col % 2 == 0 && row % 2 != 0) { // vertical
umatrix.set(row, col, metric.distance(layer.getUnit(col / 2, (row - 1) / 2).getWeightVector(),
layer.getUnit(col / 2, (row - 1) / 2 + 1).getWeightVector()));
} else if (col % 2 != 0 && row % 2 != 0) { // diagonal
double d1 = metric.distance(layer.getUnit((col - 1) / 2, (row - 1) / 2).getWeightVector(),
layer.getUnit((col - 1) / 2 + 1, (row - 1) / 2 + 1).getWeightVector());
double d2 = metric.distance(layer.getUnit((col - 1) / 2, (row - 1) / 2 + 1).getWeightVector(),
layer.getUnit((col - 1) / 2 + 1, (row - 1) / 2).getWeightVector());
umatrix.set(row, col, (d1 + d2) / (2 * Math.sqrt(2)));
}
} catch (MetricException me) {
Logger.getLogger("at.tuwien.ifs.somtoolbox").severe(me.getMessage());
System.exit(-1);
} catch (LayerAccessException lae) {
Logger.getLogger("at.tuwien.ifs.somtoolbox").severe(lae.getMessage());
System.exit(-1);
}
}
}
// interpolate based on surrounding distances between units (median)
for (int row = 0; row < umatH; row += 2) {
for (int col = 0; col < umatW; col += 2) {
if (row == 0 && col == 0) { // upper left unit
umatrix.set(row, col, VectorTools.median(umatrix.get(row + 1, col), umatrix.get(row, col + 1)));
} else if (col == umatW - 1 && row == 0) { // upper right unit
umatrix.set(row, col, VectorTools.median(umatrix.get(row, col - 1), umatrix.get(row + 1, col)));
} else if (col == 0 && row == umatH - 1) { // lower left unit
umatrix.set(row, col, VectorTools.median(umatrix.get(row, col + 1), umatrix.get(row - 1, col)));
} else if (col == umatW - 1 && row == umatH - 1) { // lower right unit
umatrix.set(row, col, VectorTools.median(umatrix.get(row, col - 1), umatrix.get(row - 1, col)));
} else if (col == 0) { // left border
umatrix.set(row, col, VectorTools.median(umatrix.get(row - 1, col), umatrix.get(row + 1, col),
umatrix.get(row, col + 1)));
} else if (col == umatW - 1) { // right border
umatrix.set(row, col, VectorTools.median(umatrix.get(row - 1, col), umatrix.get(row + 1, col),
umatrix.get(row, col - 1)));
} else if (row == 0) { // top border
umatrix.set(row, col, VectorTools.median(umatrix.get(row, col - 1), umatrix.get(row, col + 1),
umatrix.get(row + 1, col)));
} else if (row == umatH - 1) { // bottom border
umatrix.set(row, col, VectorTools.median(umatrix.get(row, col - 1), umatrix.get(row, col + 1),
umatrix.get(row - 1, col)));
} else { // middle unit
umatrix.set(row, col, VectorTools.median(umatrix.get(row, col - 1), umatrix.get(row, col + 1),
umatrix.get(row - 1, col), umatrix.get(row + 1, col)));
}
}
}
return umatrix;
}
@Override
public String getPreferredPaletteName() {
return "Matlab SOMToolbox UMatrix";
}
}