at.tuwien.ifs.somtoolbox.apps.viewer.controls.DendogramView.java Source code

Java tutorial

Introduction

Here is the source code for at.tuwien.ifs.somtoolbox.apps.viewer.controls.DendogramView.java

Source

/*
 * Copyright 2004-2010 Institute of Software Technology and Interactive Systems, Vienna University of Technology
 *
 * 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.viewer.controls;

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Paint;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.Stroke;
import java.util.logging.Logger;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import org.apache.commons.collections15.Transformer;

import edu.uci.ics.jung.algorithms.layout.Layout;
import edu.uci.ics.jung.algorithms.layout.TreeLayout;
import edu.uci.ics.jung.graph.DelegateTree;
import edu.uci.ics.jung.graph.Graph;
import edu.uci.ics.jung.graph.util.Context;
import edu.uci.ics.jung.visualization.RenderContext;
import edu.uci.ics.jung.visualization.VisualizationViewer;
import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse;
import edu.uci.ics.jung.visualization.control.ModalGraphMouse;

import at.tuwien.ifs.somtoolbox.util.UiUtils;
import at.tuwien.ifs.somtoolbox.visualization.Palette;
import at.tuwien.ifs.somtoolbox.visualization.Palettes;
import at.tuwien.ifs.somtoolbox.visualization.clustering.ClusterNode;
import at.tuwien.ifs.somtoolbox.visualization.clustering.ClusteringTree;

/**
 * @author tomas
 * @version $Id: $
 */
public class DendogramView {

    private static final Logger log = Logger.getLogger(DendogramView.class.getName());

    protected Palette palette = Palettes.getPaletteByName(getPreferredPaletteName());

    private static final float MAX_STROKE_WIDTH = 1;

    private static final float DEFAULT_STROKE_WIDTH = 0.1f;

    private JFrame frame;

    private JLabel lblNewLabel;

    private int nodeId = 0;

    private Double mMergeCostMax = null;

    private Double mMergeCostMin = null;

    private Double mMergeCostSumMax = null;

    private Double mMergeCostSumMin = null;

    private JSpinner mMainSpinnerCluster = null;

    private JSpinner spinnerCluster;

    private JPanel clusterPanel;

    private int maxCluster = 0;

    /**
     * Create the application.
     */
    public DendogramView() {
        initialize();
    }

    /**
     * Create the application.
     */
    public DendogramView(int maxCluster, JSpinner _cs) {
        initialize();
        this.maxCluster = maxCluster;
        this.mMainSpinnerCluster = _cs;
    }

    /**
     * Initialize the contents of the frame.
     */
    private void initialize() {
        frame = new JFrame();
        frame.setBounds(100, 100, 578, 414);
        frame.setAlwaysOnTop(true);
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

    }

    /**
     * @param t
     * @param numClusters2
     */
    public void update(ClusteringTree t, int numClusters) {

        frame.setVisible(true);

        frame.getContentPane().removeAll();
        try {
            // create spinner-panel
            clusterPanel = UiUtils.makeBorderedPanel(new FlowLayout(FlowLayout.LEFT, 10, 0), "Clusters");
            spinnerCluster = new JSpinner(new SpinnerNumberModel(1, 1, maxCluster, 1));
            spinnerCluster.setValue(numClusters);
            spinnerCluster.addChangeListener(new ChangeListener() {
                @Override
                public void stateChanged(ChangeEvent e) {
                    if (mMainSpinnerCluster != null) {
                        mMainSpinnerCluster.setValue(((JSpinner) e.getSource()).getValue());
                    }
                }
            });
            UiUtils.fillPanel(clusterPanel, new JLabel("#"), spinnerCluster);
            frame.getContentPane().add(clusterPanel, BorderLayout.NORTH);
            // create graph
            VisualizationViewer g = generateGraph(t, numClusters);
            frame.getContentPane().add(g, BorderLayout.CENTER);
            frame.setSize(frame.getWidth() + 1, frame.getHeight() + 1);
            frame.setSize(frame.getWidth() - 1, frame.getHeight() - 1);

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * @param t
     * @param numClusters
     * @return
     */
    private VisualizationViewer generateGraph(ClusteringTree t, final int numClusters) {

        DelegateTree<ChildDG, EdgeDG> g = new DelegateTree<ChildDG, EdgeDG>();

        ClusterNode root = t.findNode(1);

        mMergeCostMax = null;
        mMergeCostMin = null;
        mMergeCostSumMax = null;
        mMergeCostSumMin = null;

        calcMergeCostSum(root, root.getMergeCost(), numClusters);

        findMinMaxMergeCost(root, true, numClusters);

        nodeId = 0;
        ChildDG rc = new ChildDG(root);

        addChildren(root, g, rc, numClusters);
        Layout<ChildDG, EdgeDG> layout = new TreeLayout<ChildDG, EdgeDG>(g);

        VisualizationViewer<ChildDG, EdgeDG> graphComponent = new VisualizationViewer<ChildDG, EdgeDG>(layout);
        DefaultModalGraphMouse gm = new DefaultModalGraphMouse();
        gm.setMode(ModalGraphMouse.Mode.TRANSFORMING);
        graphComponent.setGraphMouse(gm);

        graphComponent.enableInputMethods(true);

        RenderContext<ChildDG, EdgeDG> c = graphComponent.getRenderContext();
        graphComponent.setVertexToolTipTransformer(new Transformer<ChildDG, String>() {

            @Override
            public String transform(ChildDG c) {
                if (c.getNode().getMergeCost() == null) {
                    return "count:" + c.getNode().getNodes().length + " " + c.getTooltip();
                } else {
                    return "merge cotst:" + c.getNode().getMergeCost() + " count:" + c.getNode().getNodes().length
                            + " " + c.getTooltip();
                }
            }
        });

        graphComponent.setSize(frame.getContentPane().getWidth(),
                frame.getContentPane().getHeight() - clusterPanel.getHeight());

        // change edge-stroke-thickness
        c.setEdgeStrokeTransformer(new Transformer<EdgeDG, Stroke>() {

            @Override
            public Stroke transform(EdgeDG _arg0) {
                return new BasicStroke(_arg0.getMergeCost().floatValue() * MAX_STROKE_WIDTH);
            }
        });
        final Rectangle fake = new Rectangle(1, 1);
        c.setEdgeArrowTransformer(new Transformer<Context<Graph<ChildDG, EdgeDG>, EdgeDG>, Shape>() {

            @Override
            public Shape transform(Context<Graph<ChildDG, EdgeDG>, EdgeDG> _arg0) {
                return fake;
            }
        });
        // change vertex-fill-color
        c.setVertexFillPaintTransformer(new Transformer<ChildDG, Paint>() {

            @Override
            public Paint transform(ChildDG _arg0) {
                if (_arg0.getPaint() == null) {
                    if (_arg0.getMergeCostSum() != null) {
                        double normalized = getNormalizedValue(_arg0.getMergeCostSum(), mMergeCostSumMax,
                                mMergeCostSumMin, _arg0.getMergeCostSum());
                        int cc = (int) Math.round(normalized * (palette.getColors().length - 1));
                        return palette.getColor(cc);
                    } else {
                        return palette.getColor(palette.getColors().length - 1);
                    }
                } else {
                    return _arg0.getPaint();
                }
            }
        });

        return graphComponent;
    }

    /**
     * @param root
     * @param g
     * @param numClusters
     * @param parrent
     */
    private void addChildren(ClusterNode n, DelegateTree<ChildDG, EdgeDG> g, ChildDG parent, int numClusters) {
        nodeId++;

        if (g.getVertexCount() == 0) {
            g.setRoot(parent);
            if (n.getLevel() < numClusters) {

                if (n.getChild1() != null) {
                    addChildren(n.getChild1(), g, parent, numClusters);
                }
                if (n.getChild2() != null) {

                    addChildren(n.getChild2(), g, parent, numClusters);
                }

            }
            return;
        }
        ChildDG child = new ChildDG(n);
        double mergecost = n.getMergeCost() != null ? n.getMergeCost() : 1.0;

        g.addChild(
                new EdgeDG(nodeId,
                        getNormalizedValue(mergecost, mMergeCostMax, mMergeCostMin, DEFAULT_STROKE_WIDTH)),
                parent, child);
        if (n.getLevel() < numClusters) {

            if (n.getChild1() != null) {
                addChildren(n.getChild1(), g, child, numClusters);
            }
            if (n.getChild2() != null) {
                addChildren(n.getChild2(), g, child, numClusters);
            }
        }
    }

    private void findMinMaxMergeCost(ClusterNode root, boolean isRoot, int numClusters) {
        if (root != null) {
            Double m = root.getMergeCost();
            Double mSum = root.getMergeCostSum();
            if (m != null) {
                if (!isRoot) {
                    if (mSum != null) {
                        if (mMergeCostSumMin != null) {
                            mMergeCostSumMax = mMergeCostSumMax == null || mSum > mMergeCostSumMax ? mSum
                                    : mMergeCostSumMax;
                        }
                        mMergeCostSumMin = mMergeCostSumMin == null || mSum < mMergeCostSumMin ? mSum
                                : mMergeCostSumMin;
                    }
                    mMergeCostMax = mMergeCostMax == null || m > mMergeCostMax ? m : mMergeCostMax;
                    mMergeCostMin = mMergeCostMin == null || m < mMergeCostMin ? m : mMergeCostMin;
                }

                findMinMaxMergeCost(root.getChild1(), false, numClusters);
                findMinMaxMergeCost(root.getChild2(), false, numClusters);
            }
        }
    }

    private Double getNormalizedValue(double value, Double max, Double min, double default_val) {
        if (max != null) {
            return (value - min) / (max - min);
        }
        return default_val;
    }

    private void calcMergeCostSum(ClusterNode root, Double mergeCostParent, int numClusters) {
        if (root != null && mergeCostParent != null) {

            ClusterNode c1 = root.getChild1();

            if (c1 != null) {
                if (c1.getMergeCost() != null) {
                    c1.setMergeCostSum(mergeCostParent + c1.getMergeCost());
                } else {
                    c1.setMergeCostSum(mergeCostParent);
                }
                if (c1.getLevel() <= numClusters) {
                    calcMergeCostSum(c1, c1.getMergeCostSum(), numClusters);
                }
            }

            ClusterNode c2 = root.getChild2();

            if (c2 != null) {
                if (c2.getMergeCost() != null) {
                    c2.setMergeCostSum(mergeCostParent + c2.getMergeCost());
                } else {
                    c2.setMergeCostSum(mergeCostParent);
                }
                if (c2.getLevel() <= numClusters) {
                    calcMergeCostSum(c2, c2.getMergeCostSum(), numClusters);
                }
            }
        }
    }

    public String getPreferredPaletteName() {
        return Palettes.getDefaultPalette().getName();
    }
}