Repository /Rseslib/rseslib-3.0.2.jar:rseslib.processing.classification.tree.c45.C45Vis


Back

No file description

Source code

/*
 * $RCSfile: C45Vis.java,v $
 * $Revision: 1.14 $
 * $Date: 2007/12/31 12:53:57 $
 * $Author: wojna $
 * 
 * Copyright (C) 2002 - 2007 Logic Group, Institute of Mathematics, Warsaw University
 * 
 *  This file is part of Rseslib.
 *
 *  Rseslib is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  Rseslib is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */


package rseslib.processing.classification.tree.c45;

import rseslib.processing.classification.*;
import rseslib.structure.attribute.Header;
import rseslib.structure.attribute.NominalAttribute;
import rseslib.structure.data.*;
import rseslib.structure.table.DoubleDataTable;
import rseslib.system.progress.Progress;
import rseslib.system.PropertyConfigurationException;

import javax.swing.*;
import java.awt.event.*;
import java.util.*;
import java.io.*;
import java.awt.*;

/**
 * <p>Description: Base class for visulalising C45 decision tree </p>
 * 
 * @author	Maciej Prochniak
 */

public class C45Vis
    extends C45
    implements VisualClassifier {

  /** Serialization version. */
  private static final long serialVersionUID = 1L;

	// fields describing visualizations of classifier and classifying process
  private TreePainter m_painter = null;
  private TreePainter m_classifpainter;

  // copy of decision tree containing informations about visualization
  private GraphNode m_GraphRoot = null;

  // window containing information about selected node
  private DecisionNodeInfo m_info;

  // canvas, where both visualizations are displayed
  private JPanel canvas;
  private JPanel clas_canvas;

  // constructors coming from C45
  public C45Vis(Properties prop, DoubleDataTable tab, Progress prog) throws
      InterruptedException, PropertyConfigurationException {
    super(prop, tab, prog);
  }

  /**
   * Writes this object.
   *
   * @param out			Output for writing.
   * @throws IOException	if an I/O error has occured.
   */
  private void writeObject(ObjectOutputStream out) throws IOException
  {
  }

  /**
   * Reads this object.
   *
   * @param out			Output for writing.
   * @throws IOException	if an I/O error has occured.
   */
  private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
  {
  }

  /**
   * repaint - method repaints all present components
   */

  public void repaint() {
    if (m_painter != null) {
      m_painter.repaint();
    }
    if (m_classifpainter != null) {
      m_classifpainter.repaint();
    }
  }

  /**
   * cut - method which stops visuialization of a branch, and repaints
   * both panels
   */
  public void cut() {
    makeGraphTree(m_GraphRoot.m_RealNode);
    if (m_painter != null) {
      m_painter.m_root = m_GraphRoot;
      m_painter.m_ActNode = m_GraphRoot;
    }
    if (m_classifpainter != null) {
      m_classifpainter.m_root = m_GraphRoot;
      m_classifpainter.m_ActNode = m_GraphRoot;
    }
    repaint();
  }

  /**
   * Constructs tree with visualization information from
   * original decision tree
   * @param orgNode DecisionTreeNode   root of original decision tree
   */
  private void makeGraphTree(DecisionTreeNode orgNode) {
    m_GraphRoot = new GraphNode(orgNode, 0, this);

    LinkedList<GraphNode> list_a = new LinkedList<GraphNode>();
    list_a.add(m_GraphRoot);
    LinkedList<GraphNode> list_b = new LinkedList<GraphNode>();
    GraphNode last = null;

    // iterating over levels of decision tree
    while (true) {
      if ( (list_a == null) || (list_a.isEmpty())) {
        break;
      }

      GraphNode act = (GraphNode) list_a.getFirst();
      if (last != null) {
        last.setRBrother(act);
      }
      act.setLBrother(last);

      list_b = new LinkedList<GraphNode>();
      for (int j = 0; j < act.noOfChildren(); j++) {
        list_b.add(act.getChildren()[j]);

      }
      ListIterator<GraphNode> it = list_a.listIterator();
      it.next();
      while (it.hasNext()) {
        GraphNode now = it.next();
        act.setRBrother(now);
        now.setLBrother(act);
        act = now;
        for (int j = 0; j < act.noOfChildren(); j++) {
          list_b.add(act.getChildren()[j]);
        }
      }
      last = act;
      list_a = list_b;
    }
    for (GraphNode a = m_GraphRoot; a != null; ) {
      a = a.getRightBro();

    }
    repaint();
  }

  /**
   * draws visualization of decision tree on given canvas
   * @param canv JPanel    canvas where tree is visualized
   */
  public void draw(JPanel canv) {
    if (canv.equals(canvas)) {
      return;
    }
    canvas = canv;
    makeGraphTree(m_Root);
    m_painter = new TreePainter(m_GraphRoot, false, m_Header);
    m_classifpainter = new TreePainter();
    JScrollPane scroll = new JScrollPane(m_painter);
    scroll.setVisible(true);
    canv.add(scroll);
  }

  /**
   * draws visualization of classification process, returning answer
   * @param canv JPanel         canva where classification is visualized
   * @param obj DoubleData      data being visualized
   * @return double             answer
   */

  public double drawClassify(JPanel canv, DoubleData obj) {
    if (m_GraphRoot == null) {
      return 0;
    }
    if (!canv.equals(clas_canvas)) {
      m_classifpainter = new TreePainter(m_GraphRoot, true, m_Header);
      JScrollPane scroll = new JScrollPane(m_classifpainter);
      scroll.setVisible(true);
      canv.add(scroll);
      clas_canvas = canv;
    }
    // stop classifying
    m_GraphRoot.stopClas();
    double ret = classify(obj);
    ArrayList<GraphNode> list = new ArrayList<GraphNode>();
    list.add(m_GraphRoot);
    //highlight classifying path
    for (; (!list.isEmpty()); ) {
      GraphNode act = (GraphNode) list.remove(0);
      DecisionTreeNode nod = act.m_RealNode;
      int val = 0;
      if (!nod.isLeaf()) val = nod.branch(obj);
      if (val < 0) {
        for (int i = 0; i < act.noOfChildren(); i++) {
          list.add(act.m_Children[i]);
        }
        act.setPath(2);
        continue;
      }
      act.setPath(1);
      if (nod.isLeaf()) {
        continue;
      }
      list.add(act.m_Children[val]);
    }

    m_classifpainter.validate();
    return ret;
  }

  /**
   * stops displaying current inforamtion abouyt selected node, replaces
   * with new window
   * @param nod DecisionNodeInfo
   */
  public void setInfoNode(DecisionNodeInfo nod) {
	Point p = null;
    if (m_info != null) {
      p = m_info.getLocation();
      m_info.dispose();
    }
    m_info = nod;
    if (m_info != null) {
      Dimension dlgSize = nod.getPreferredSize();
      Dimension frmSize = canvas.getSize();
      Point loc = canvas.getLocation();
      if (p!=null) nod.setLocation(p);
      else nod.setLocation( (frmSize.width - dlgSize.width) / 2 + loc.x,
                      (frmSize.height - dlgSize.height) / 2 + loc.y);
      m_info.this_componentResized(null);
      m_info.setVisible(true);
    }
  }

  /**
   * <p>Description: </p>
   * <p>Copyright: Copyright (c) 2005</p>
   * @author Maciej Prochniak
   */

  class TreePainter
      extends JComponent implements ActionListener {

    /**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	GraphNode m_root;
    GraphNode m_ActNode;
    JPanel m_canvas;
    boolean ifClas;
    Header m_hdr;

    JPopupMenu m_popmenu = new JPopupMenu();
    JMenuItem m_popCutTree = new JMenuItem("Cut...");
    JMenuItem m_expand1 = new JMenuItem("Expand/Collapse");
    JMenuItem m_stopClas = new JMenuItem("Stop classifing");
    JMenuItem m_changeDec = new JMenuItem("Change decision");

    int vertBeg = 10;
    int vertTab = 30;
    int sideTab = 10;
    int maxLev = 10;

    public TreePainter() {

    }

    public TreePainter(GraphNode mrr, boolean ifCl, Header hdr) {

      this.add(m_popmenu);

      ifClas = ifCl;
      m_ActNode = mrr;
      m_hdr = hdr;

      m_popmenu.add(m_popCutTree);
      m_popCutTree.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
          m_ActNode.cut();
          cut();
        }
      });

      m_popmenu.add(m_expand1);
      m_expand1.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
          m_ActNode.expCol();
        };
      });
      /* only when classifiable */
      if (ifClas) {
        m_popmenu.add(m_stopClas);
      }
      m_stopClas.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
          m_root.stopClas();
          m_root.m_clasif.m_classifpainter.repaint();
        }
      });

      m_popmenu.add(m_changeDec);
      m_changeDec.addActionListener(this);

      m_popmenu.setInvoker(this);
      this.addMouseListener(new ClassiVisMouseAdapter(this));

      setDoubleBuffered(true);
      setOpaque(true);
      this.setVisible(true);
      this.setSize(300, 300);
      m_root = mrr;
    }

    public void actionPerformed(ActionEvent e) {
    	NominalAttribute decAttr = m_hdr.nominalDecisionAttribute();
    	Object[] possibilities = new Object[decAttr.noOfValues()];
    	for (int v = 0; v < possibilities.length; v++)
    		possibilities[v] = NominalAttribute.stringValue(decAttr.globalValueCode(v));
        String s = (String)JOptionPane.showInputDialog(m_canvas, "Select the decision:", "",
        		JOptionPane.PLAIN_MESSAGE, null, possibilities, m_ActNode.getDecisionLabel());
        if (s!=null && s.length()>0)
        	m_ActNode.changeDecision(decAttr.globalValueCode(s));
      }

    public void paintComponent(Graphics g) {
      super.paintComponent(g);
      g.setColor(Color.white);
      g.fillRect(0, 0, getWidth(), getHeight());
      if (m_root != null) {
        drawWhole(g);
      }
    }

    public Dimension getPreferredSize() {
      return getSize();
    }

    public Dimension getMinimumSize() {
      return getPreferredSize();
    }

    public Dimension getMaximumSize() {
      return getPreferredSize();
    }

    private void drawWhole(Graphics g) {
      int i = 0;
      for (GraphNode nod = m_root; i < maxLev; i++) {
        nod = drawLevel(i, nod, vertBeg + (i * vertTab), g);
        if (nod == null) {
          return;
        }
      }
    }

    /**
     * draws one level of a tree
     *
     * @param level int              depth
     * @param startNode GraphNode    the first node on linked list of nodes
     * @param height int             distance beetween levels
     * @param g Graphics             where to draw
     * @return GraphNode             first node of next level
     */

    private GraphNode drawLevel(int level, GraphNode startNode, int height,
                                Graphics g) {

      int i = 0;
      int midTab;

      for (GraphNode a = startNode; ; ) {
        if (a == null) {
          break;
        }
        if (a.expanded()) {
            i++;
          }
        a = a.getRightBro();
        if ( (a == null) || (a.getDepth() > startNode.getDepth())) {
          break;
        }
      }
      midTab = (int) (this.getSize().getWidth() - (2 * sideTab)) / (i + 1);

      GraphNode a = startNode;
      for (i = 1; ; ) {
        if (a.expanded()) {
          a.paint(g, sideTab + (i * midTab), height, ifClas);
          i++;
        }
        if (a.getRightBro() == null) {
          a = null;
          break;
        }
        a = a.getRightBro();
        if (a.getDepth() > level) {
          break;
        }

      }
      return a;
    }

    public void m_ClassifierMousePressed(MouseEvent e) {
      int x = e.getX();
      int y = e.getY();

      if (m_root == null) {
        return;
      }

      GraphNode nod = m_root.getObject(x, y);
      if (nod == null) {
        return;
      }
      if (e.isPopupTrigger()) {
        m_ActNode = nod;
        m_popmenu.show(this, x, y);
      }
      else if (e.getButton()==MouseEvent.BUTTON1)
      {
    	  if (e.getClickCount() == 1) {
    		  //if (!m_ActNode.equals(nod))  {
    		  m_ActNode = nod;
    		  setInfoNode(new DecisionNodeInfo(nod.m_RealNode, m_Header));
    		  //}
    	  }
    	  else {
    		  nod.expColAll();
    	  }
      }
    }

    public void m_ClassifierMouseReleased(MouseEvent e) {
        int x = e.getX();
        int y = e.getY();

        if (m_root == null) {
          return;
        }

        GraphNode nod = m_root.getObject(x, y);
        if (nod == null) {
          return;
        }
        if (e.isPopupTrigger()) {
          m_ActNode = nod;
          if (m_ActNode.isLeaf()) m_changeDec.setEnabled(true);
          else m_changeDec.setEnabled(false);
          m_popmenu.show(this, x, y);
        }
      }
}

  class ClassiVisMouseAdapter
      extends MouseAdapter {
    private TreePainter what;

    public ClassiVisMouseAdapter(TreePainter wh) {
      what = wh;
    }

    public void mousePressed(MouseEvent e) {
      what.m_ClassifierMousePressed(e);
    }

    public void mouseReleased(MouseEvent e) {
        what.m_ClassifierMouseReleased(e);
      }
}

}

Copyright © 2008-2011 by TunedIT
Design by luksite