📄 visualtreepanel.java
字号:
// Modify the current menu text.
if( m_resultToShow == TRAINING ) {
m_showExampleResult.setText( SHOW_TESTING_RESULT );
VisualTreeNode.showTrainingPerformance();
if( m_chart != null )
m_chart.showTrainingPerformance();
}
else {
m_showExampleResult.setText( SHOW_TRAINING_RESULT );
VisualTreeNode.showTestingPerformance();
if( m_chart != null )
m_chart.showTestingPerformance();
}
refresh();
}
/**
* Handles node click detection. If a user clicks
* on an existing node in the panel, statistics
* about the node are displayed in the status bar.
* If the user clicks on a 'vacant' node, a pop-up
* menu appears - the menu contains a selection
* of attributes available for splitting at the node.
*
* @return true if a vacant node was clicked on,
* or false otherwise.
*/
private boolean handleNodeClickDetect( int x, int y )
{
m_tempNode = null;
for( int i = 0; i < m_nodes.size(); i++ ) {
AbstractTreeNode temp = null;
// Run through the list of internal nodes,
// looking for a collision.
if( (temp = ((AbstractTreeNode)
m_nodes.elementAt( i )).withinBoundingBox( x, y )) != null ) {
m_tempNode = temp;
break;
}
}
if( m_tempNode != null ) {
// If we found a collision, perform the appropriate action.
if( m_tempNode instanceof VisualTreeNode &&
m_manager.getStatusBar() != null ) {
DecisionTreeNode DTNode =
((VisualTreeNode)m_tempNode).getDecisionTreeNode();
// Assemble a text string with info about the node.
StringBuffer msg = new StringBuffer( "<html><font size=\"-1\">" );
if( DTNode.isLeaf() )
msg.append( "Leaf " );
else
msg.append( "Internal " );
msg.append( "node <font color=\"yellow\">" +
DTNode.getLabel() + "</font> " );
if( m_resultToShow == TRAINING )
msg.append( "has a training classification accuracy of " +
DTNode.getTrainingEgsCorrectClassUsingBestTrainingIndex() +
" / " + DTNode.getTrainingEgsAtNode() + "." );
else
msg.append( "has a testing classification accuracy of " +
DTNode.getTestingEgsCorrectClassUsingBestTrainingIndex() +
" / " + DTNode.getTestingEgsAtNode() + "." );
m_manager.getStatusBar().postMessage( msg.toString() );
if( !isEnabled() )
return false;
else {
m_tempParent = (VisualTreeNode)m_tempNode.getParent();
m_tempArcNum = m_tempNode.getArcNum();
}
}
else if( m_tempNode instanceof VacantTreeNode && isEnabled() ) {
// We have a 'vacant' node, so we figure
// out who it's parent is, and then ask
// for a list of available attributes.
// Save the parent and arc number - if
// user clicks on an item from the
// popup menu, we'll need to know about this.
m_tempParent = (VisualTreeNode)m_tempNode.getParent();
m_tempArcNum = m_tempNode.getArcNum();
}
else {
if( m_manager.getStatusBar() != null ) {
String msg =
new String( "<html><font size=\"-1\">" +
"You must 'Cancel' the algorithm " +
"before you can manually build the decision tree." );
m_manager.getStatusBar().postMessage( msg.toString() );
}
return false;
}
}
else if( m_nodes.size() != 0 ) {
return false;
}
Dataset dataset = m_manager.getAlgorithm().getDataset();
if( m_tempNode != null && m_tempNode.getParent() != null ) {
DecisionTreeNode dtNode = m_tempParent.getDecisionTreeNode();
m_tempMask = new AttributeMask( dtNode.getMask() );
try {
m_tempMask.mask( dataset.getAttributePosition( dtNode.getLabel() ),
m_tempArcNum );
}
catch( NonexistentAttributeException e ) {
}
}
else if( m_nodes.size() == 0 || m_tempNode.getParent() == null ) {
m_tempParent = null;
m_tempMask = new AttributeMask( dataset.getNumAttributes() );
}
// Now we have a mask that indicates where we are
// in the tree, and what attributes are available
// at that point - so we build a popup menu that
// contains the list.
m_tempConcl = new int[ 8 ];
m_tempTrainingCounts =
new int[ dataset.getTargetAttribute().getNumValues() ];
m_tempTestingCounts =
new int[ dataset.getTargetAttribute().getNumValues() ];
int[] nodeStats = new int[ dataset.getTargetAttribute().getNumValues() ];
boolean[] reachedHere = new boolean[ dataset.getNumTrainingExamples() ];
int result =
m_manager.getAlgorithm().classifyExamples(
m_tempMask,
m_tempConcl,
m_tempTrainingCounts,
m_tempTestingCounts,
reachedHere );
// First, we clear out any old items that
// might still be in the menu.
m_attMenu = new JPopupMenu();
Vector availableAtts =
m_manager.getAlgorithm().generateStats( m_tempMask, nodeStats );
Vector attResults = new Vector();
// Choose an attribute, but discard the result...we're
// only interested in filling attResults.
m_manager.getAlgorithm().chooseAttribute(
availableAtts, nodeStats, attResults );
generateAttributesPopup( availableAtts, attResults );
// Highlight rows in the table
if( m_manager.getDatasetPanel() != null )
m_manager.getDatasetPanel().setSelectedRows( reachedHere );
return true;
}
/**
* Builds a popup attribute menu that contains a list
* of all the attributes available for splitting at
* a specific position in the tree.
*
* @param attributes A Vector that contains all of the
* available attributes at the current tree position.
*
* @param results A parallel Vector of splitting function
* results for each attribute in the attribute
* vector. This vector can be empty (if the splitting
* function used did not generate numerical results).
*/
private void generateAttributesPopup( Vector attributes, Vector results )
{
// If there are more than 10 attributes
// available, we split the menu into multiple
// submenus - each with 10 elements.
int numToAdd = attributes.size() < 10 ? attributes.size() : 10;
// No matter what, we can ALWAYS add or change
// the leaf node at the current position in
// the tree - we add the names of the target classes
// as AttributeValueMenuItems - and this is how we
// distinguish between attributes and target attribute values.
Attribute targetAtt =
m_manager.getAlgorithm().getDataset().getTargetAttribute();
for( int i = 0; i < targetAtt.getNumValues(); i++ ) {
try {
AttributeValueMenuItem item =
new AttributeValueMenuItem(
targetAtt.getAttributeValueByNum( i ),
m_tempConcl[1],
i,
m_tempTrainingCounts[i],
m_tempTestingCounts[i],
m_tempConcl[5],
m_tempConcl[4],
m_tempConcl[6],
m_tempConcl[7] );
item.addActionListener( this );
m_attMenu.add( item );
}
catch( NonexistentAttributeValueException e ) {
}
}
if( attributes.size() > 0 )
m_attMenu.addSeparator();
// Add the first bunch to the popup menu.
for( int i = 0; i < numToAdd; i++ ) {
AttributeMenuItem item = null;
if( results.size() - 1 < i )
item = new AttributeMenuItem(
(Attribute)attributes.elementAt( i ), null, null );
else
item = new AttributeMenuItem(
(Attribute)attributes.elementAt( i ),
m_manager.getAlgorithm().getSplittingFunction(),
(Double)results.elementAt( i ) );
item.addActionListener( this );
m_attMenu.add( item );
}
// If necessary, add additional menus.
if( attributes.size() <= 10 ) return;
JMenu subMenu = null;
JMenu prevMenu = null;
int numItemsRemaining = attributes.size() - 10;
int pos = 10;
while( numItemsRemaining > 0 ) {
prevMenu = subMenu;
subMenu = new JMenu( "More..." );
numToAdd = numItemsRemaining < 10 ? numItemsRemaining : 10;
for( int j = 0; j < numToAdd; j++ ) {
AttributeMenuItem item = null;
if( results.size() - 1 < pos )
item = new AttributeMenuItem(
(Attribute)attributes.elementAt( pos ), null, null );
else
item = new AttributeMenuItem(
(Attribute)attributes.elementAt( pos ),
m_manager.getAlgorithm().getSplittingFunction(),
(Double)results.elementAt( pos ) );
item.addActionListener( this );
subMenu.add( item );
pos++;
}
numItemsRemaining -= numToAdd;
if( prevMenu == null )
m_attMenu.add( subMenu );
else
prevMenu.add( subMenu );
}
}
/**
* Handles attribute or attribute value selection
* from a popup menu. A new internal or leaf node is
* added to the tree, with with attribute's or value's
* label text.
*
* @param menuItem The selected AttributeMenuItem or
* AttributeValueMenuItem.
*/
private void
handleAttributeOrValueSelected( JMenuItem menuItem )
{
DecisionTreeNode parent = null;
// Find out where we clicked.
if( m_tempParent != null )
parent = m_tempParent.getDecisionTreeNode();
// If we're replacing a pre-existing node,
// prune the subtree below it.
if( m_tempNode != null && m_tempNode instanceof VisualTreeNode ) {
// Each node removed from the backend decision tree will
// trigger a call to notifyNodeRemoved(), which will
// remove the corresponding visual node.
DecisionTreeNode pruneRoot =
((VisualTreeNode)m_tempNode).getDecisionTreeNode();
m_manager.getAlgorithm().getTree().pruneSubtree( pruneRoot );
}
if( menuItem instanceof AttributeMenuItem ) {
try {
Attribute att = ((AttributeMenuItem)menuItem).getAttribute();
int pos = m_manager.getAlgorithm()
.getDataset().getAttributePosition( att.getName() );
m_manager.getAlgorithm().getTree().addInternalNode(
parent,
m_tempArcNum,
pos,
att,
m_tempMask,
m_tempConcl[1],
m_tempConcl[0],
m_tempConcl[2],
m_tempConcl[3],
m_tempConcl[5],
m_tempConcl[4],
m_tempConcl[6],
m_tempConcl[7] );
}
catch( NonexistentAttributeException e ) {
}
if( m_manager.getAlgorithmMenu() != null )
m_manager.getAlgorithmMenu()
.setMenuState( AlgorithmMenu.INITIAL_STATE );
}
else {
AttributeValueMenuItem item = (AttributeValueMenuItem)menuItem;
String valName = item.getAttributeValue();
Attribute targetAtt =
m_manager.getAlgorithm().getDataset().getTargetAttribute();
m_manager.getAlgorithm().getTree().addLeafNode(
parent,
m_tempArcNum,
valName,
m_tempMask,
item.getTrainingEgsAtNode(),
item.getTrainingBestTarget(),
item.getTrainingEgsCorrectClassUsingBestTrainingIndex(),
item.getTestingEgsCorrectClassUsingBestTrainingIndex(),
item.getTestingEgsAtNode(),
item.getTestingBestTarget(),
item.getTestingEgsCorrectClassUsingBestTestingIndex(),
item.getTrainingEgsCorrectClassUsingBestTestingIndex() );
if( m_manager.getAlgorithmMenu() != null )
m_manager.getAlgorithmMenu()
.setMenuState( AlgorithmMenu.INITIAL_STATE );
}
}
/**
* Builds and arranges the various GUI components
* for this panel.
*/
private void buildPanel()
{
// Build the view menu.
m_showExampleResult = new JMenuItem( SHOW_TESTING_RESULT );
m_showExampleResult.addActionListener( this );
m_infoOn = new JCheckBoxMenuItem( "Display Tree Statistics Icons" );
m_infoOn.setSelected( true );
m_infoOn.addActionListener( this );
m_fullSizeView = new JCheckBoxMenuItem( "Full Panel Tree View" );
m_fullSizeView.setSelected( false );
m_fullSizeView.addActionListener( this );
m_zoom100 = new JRadioButtonMenuItem( "Zoom Level 100%", true );
m_zoom100.addActionListener( this );
m_zoom75 = new JRadioButtonMenuItem( "Zoom Level 75%", false );
m_zoom75.addActionListener( this );
m_zoom50 = new JRadioButtonMenuItem( "Zoom Level 50%", false );
m_zoom50.addActionListener( this );
m_zoom25 = new JRadioButtonMenuItem( "Zoom Level 25%", false );
m_zoom25.addActionListener( this );
ButtonGroup zoomGroup = new ButtonGroup();
zoomGroup.add( m_zoom100 );
zoomGroup.add( m_zoom75 );
zoomGroup.add( m_zoom50 );
zoomGroup.add( m_zoom25 );
m_viewMenu = new JPopupMenu();
addMouseListener( this );
m_viewMenu.add( m_showExampleResult );
m_viewMenu.addSeparator();
m_viewMenu.add( m_infoOn );
m_viewMenu.add( m_fullSizeView );
m_viewMenu.addSeparator();
m_viewMenu.add( m_zoom100 );
m_viewMenu.add( m_zoom75 );
m_viewMenu.add( m_zoom50 );
m_viewMenu.add( m_zoom25 );
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -