/*
* 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.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import cern.colt.matrix.DoubleMatrix2D;
import cern.jet.math.Functions;
import at.tuwien.ifs.somtoolbox.SOMToolboxException;
import at.tuwien.ifs.somtoolbox.models.GrowingSOM;
import at.tuwien.ifs.somtoolbox.util.ImageUtils;
import at.tuwien.ifs.somtoolbox.util.VisualisationUtils;
/**
* A hit-histogram visualiser, with three different modes of the hit count:
* <ul>
* <li>Colour-coding the values</li>
* <li>Size and colour-encoding of the values</li>
* <li>Textually displaying the numeric values</li>
* </ul>
*
* @author Rudolf Mayer
* @version $Id: HitHistogramVisualizer.java 3642 2010-07-12 09:30:53Z mayer $
*/
public class HitHistogramVisualizer extends AbstractMatrixVisualizer implements BackgroundImageVisualizer {
public HitHistogramVisualizer() {
NUM_VISUALIZATIONS = 3;
VISUALIZATION_NAMES = new String[] { "Hit Histogram - Colour Coding", "Hit Histogram - Size & Colour Coding",
"Hit Histogram - Textual Values" };
VISUALIZATION_SHORT_NAMES = new String[] { "HitHistogramColour", "HitHistogramSize", "HitHistogramNumeric" };
VISUALIZATION_DESCRIPTIONS = new String[] { "A simple Hit Histogram with colour coding",
"Hit Histogram with size and colour coding", "Hit Histogram with textual display of the numeric values" };
setInterpolate(false);
}
@Override
public BufferedImage createVisualization(int variantIndex, GrowingSOM gsom, int width, int height)
throws SOMToolboxException {
checkVariantIndex(variantIndex, getClass());
DoubleMatrix2D matrix = computeHitHistogram(gsom);
if (variantIndex == 0) { // simple colour coding - just user the super-class method
matrix.assign(Functions.div(maximumMatrixValue));
return super.createImage(gsom, matrix, width, height, interpolate);
} else if (variantIndex == 1) { // size coding
matrix.assign(Functions.div(maximumMatrixValue));
BufferedImage res = ImageUtils.createEmptyImage(width, height);
Graphics2D g = (Graphics2D) res.getGraphics();
double unitWidth = (double) width / gsom.getLayer().getXSize();
double unitHeight = (double) height / gsom.getLayer().getYSize();
int ci = 0;
double totalArea = unitWidth * unitHeight;
double aspectRatio = unitWidth / unitHeight;
for (int y = 0; y < matrix.rows(); y++) {
for (int x = 0; x < matrix.columns(); x++) {
// determine relative size of the area & sides
double relativeSize = matrix.get(y, x);
double relativeArea = totalArea * relativeSize;
int relativeWidth = (int) Math.round(Math.sqrt(relativeArea * aspectRatio));
int relativeHeight = (int) Math.round(Math.sqrt(relativeArea * aspectRatio) * 1 / aspectRatio);
ci = (int) Math.round(relativeSize * palette.maxColourIndex());
g.setPaint(palette.getColor(ci));
g.fill(new Rectangle((int) (x * unitWidth + (unitWidth - relativeWidth) / 2),//
(int) (y * unitHeight + (unitHeight - relativeHeight) / 2), //
relativeWidth, relativeHeight));
}
}
return res;
} else if (variantIndex == 2) { // textual display of numeric values
BufferedImage res = ImageUtils.createEmptyImage(width, height);
Graphics2D g = (Graphics2D) res.getGraphics();
g.setColor(Color.BLACK);
double unitWidth = (double) width / gsom.getLayer().getXSize();
double unitHeight = (double) height / gsom.getLayer().getYSize();
g.setFont(new Font("sansserif", Font.BOLD, 32));
FontMetrics metrics = g.getFontMetrics();
for (int y = 0; y < matrix.rows(); y++) {
for (int x = 0; x < matrix.columns(); x++) {
Point unitCentre = VisualisationUtils.getUnitCentreLocation(x, y, unitWidth, unitHeight);
int count = (int) matrix.get(y, x);
if (count > 0) {
String str = String.valueOf(count);
int stringWidth = metrics.stringWidth(str);
g.drawString(str, unitCentre.x - stringWidth / 2, unitCentre.y
+ (metrics.getAscent() - metrics.getDescent()) / 2);
}
}
}
return res;
} else {
throw getVariantException(variantIndex, getClass());
}
}
@Override
public int getPreferredScaleFactor() {
return 1;
}
@Override
public String getPreferredPaletteName() {
return "Redscale32";
}
}