📄 boundarypanel.java
字号:
/*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* BoundaryPanel.java
* Copyright (C) 2002 Mark Hall
*
*/
package weka.gui.boundaryvisualizer;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.util.Random;
import java.util.Vector;
import javax.swing.JPanel;
import javax.swing.ToolTipManager;
import weka.classifiers.Classifier;
import weka.core.FastVector;
import weka.core.Instance;
import weka.core.Instances;
import weka.core.Utils;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGEncodeParam;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
/**
* BoundaryPanel. A class to handle the plotting operations
* associated with generating a 2D picture of a classifier's decision
* boundaries.
*
* @author <a href="mailto:mhall@cs.waikato.ac.nz">Mark Hall</a>
* @version $Revision$
* @since 1.0
* @see JPanel
*/
public class BoundaryPanel extends JPanel {
// default colours for classes
public static final Color [] DEFAULT_COLORS = {
Color.red,
Color.green,
Color.blue,
new Color(0, 255, 255), // cyan
new Color(255, 0, 255), // pink
new Color(255, 255, 0), // yellow
new Color(255, 255, 255), //white
new Color(0, 0, 0)};
protected FastVector m_Colors = new FastVector();
// training data
protected Instances m_trainingData;
// distribution classifier to use
protected Classifier m_classifier;
// data generator to use
protected DataGenerator m_dataGenerator;
// index of the class attribute
private int m_classIndex = -1;
// attributes for visualizing on
protected int m_xAttribute;
protected int m_yAttribute;
// min, max and ranges of these attributes
protected double m_minX;
protected double m_minY;
protected double m_maxX;
protected double m_maxY;
private double m_rangeX;
private double m_rangeY;
// pixel width and height in terms of attribute values
protected double m_pixHeight;
protected double m_pixWidth;
// used for offscreen drawing
protected Image m_osi = null;
// width and height of the display area
protected int m_panelWidth;
protected int m_panelHeight;
// number of samples to take from each region in the fixed dimensions
protected int m_numOfSamplesPerRegion = 2;
// number of samples per kernel = base ^ (# non-fixed dimensions)
protected int m_numOfSamplesPerGenerator;
protected double m_samplesBase = 2.0;
// listeners to be notified when plot is complete
private Vector m_listeners = new Vector();
// small inner class for rendering the bitmap on to
private class PlotPanel extends JPanel {
public PlotPanel() {
this.setToolTipText("");
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (m_osi != null) {
g.drawImage(m_osi,0,0,this);
}
}
public String getToolTipText(MouseEvent event) {
if (m_probabilityCache == null) {
return null;
}
if (m_probabilityCache[event.getY()][event.getX()] == null) {
return null;
}
String pVec = "(X: "
+Utils.doubleToString(convertFromPanelX((double)event.getX()), 2)
+" Y: "
+Utils.doubleToString(convertFromPanelY((double)event.getY()), 2)+") ";
// construct a string holding the probability vector
for (int i = 0; i < m_trainingData.classAttribute().numValues(); i++) {
pVec +=
Utils.
doubleToString(m_probabilityCache[event.getY()][event.getX()][i],
3)+" ";
}
return pVec;
}
}
// the actual plotting area
private PlotPanel m_plotPanel = new PlotPanel();
// thread for running the plotting operation in
private Thread m_plotThread = null;
// Stop the plotting thread
protected boolean m_stopPlotting = false;
// Stop any replotting threads
protected boolean m_stopReplotting = false;
// Used by replotting threads to pause and resume the main plot thread
private Double m_dummy = new Double(1.0);
private boolean m_pausePlotting = false;
// what size of tile is currently being plotted
private int m_size = 1;
// is the main plot thread performing the initial coarse tiling
private boolean m_initialTiling;
// A random number generator
private Random m_random = null;
// cache of probabilities for fast replotting
protected double [][][] m_probabilityCache;
// plot the training data
protected boolean m_plotTrainingData = true;
/**
* Creates a new <code>BoundaryPanel</code> instance.
*
* @param panelWidth the width in pixels of the panel
* @param panelHeight the height in pixels of the panel
*/
public BoundaryPanel(int panelWidth, int panelHeight) {
ToolTipManager.sharedInstance().setDismissDelay(Integer.MAX_VALUE);
m_panelWidth = panelWidth;
m_panelHeight = panelHeight;
setLayout(new BorderLayout());
m_plotPanel.setMinimumSize(new Dimension(m_panelWidth, m_panelHeight));
m_plotPanel.setPreferredSize(new Dimension(m_panelWidth, m_panelHeight));
m_plotPanel.setMaximumSize(new Dimension(m_panelWidth, m_panelHeight));
add(m_plotPanel, BorderLayout.CENTER);
setPreferredSize(m_plotPanel.getPreferredSize());
setMaximumSize(m_plotPanel.getMaximumSize());
setMinimumSize(m_plotPanel.getMinimumSize());
m_random = new Random(1);
for (int i = 0; i < DEFAULT_COLORS.length; i++) {
m_Colors.addElement(new Color(DEFAULT_COLORS[i].getRed(),
DEFAULT_COLORS[i].getGreen(),
DEFAULT_COLORS[i].getBlue()));
}
m_probabilityCache = new double[m_panelHeight][m_panelWidth][];
}
/**
* Set the number of points to uniformly sample from a region (fixed
* dimensions).
*
* @param num an <code>int</code> value
*/
public void setNumSamplesPerRegion(int num) {
m_numOfSamplesPerRegion = num;
}
/**
* Get the number of points to sample from a region (fixed dimensions).
*
* @return an <code>int</code> value
*/
public int getNumSamplesPerRegion() {
return m_numOfSamplesPerRegion;
}
/**
* Set the base for computing the number of samples to obtain from each
* generator. number of samples = base ^ (# non fixed dimensions)
*
* @param ksb a <code>double</code> value
*/
public void setGeneratorSamplesBase(double ksb) {
m_samplesBase = ksb;
}
/**
* Get the base used for computing the number of samples to obtain from
* each generator
*
* @return a <code>double</code> value
*/
public double getGeneratorSamplesBase() {
return m_samplesBase;
}
/**
* Set up the off screen bitmap for rendering to
*/
protected void initialize() {
int iwidth = m_plotPanel.getWidth();
int iheight = m_plotPanel.getHeight();
// System.err.println(iwidth+" "+iheight);
m_osi = m_plotPanel.createImage(iwidth, iheight);
Graphics m = m_osi.getGraphics();
m.fillRect(0,0,iwidth,iheight);
}
/**
* Stop the plotting thread
*/
public void stopPlotting() {
m_stopPlotting = true;
}
protected void computeMinMaxAtts() {
m_minX = Double.MAX_VALUE;
m_minY = Double.MAX_VALUE;
m_maxX = Double.MIN_VALUE;
m_maxY = Double.MIN_VALUE;
for (int i = 0; i < m_trainingData.numInstances(); i++) {
Instance inst = m_trainingData.instance(i);
double x = inst.value(m_xAttribute);
double y = inst.value(m_yAttribute);
if (x != Instance.missingValue()) {
if (x < m_minX) {
m_minX = x;
}
if (x > m_maxX) {
m_maxX = x;
}
}
if (y != Instance.missingValue()) {
if (y < m_minY) {
m_minY = y;
}
if (y > m_maxY) {
m_maxY = y;
}
}
}
m_rangeX = (m_maxX - m_minX);
m_rangeY = (m_maxY - m_minY);
m_pixWidth = m_rangeX / (double)m_panelWidth;
m_pixHeight = m_rangeY / (double) m_panelHeight;
}
/**
* Return a random x attribute value contained within
* the pix'th horizontal pixel
*
* @param pix the horizontal pixel number
* @return a value in attribute space
*/
private double getRandomX(int pix) {
double minPix = m_minX + (pix * m_pixWidth);
return minPix + m_random.nextDouble() * m_pixWidth;
}
/**
* Return a random y attribute value contained within
* the pix'th vertical pixel
*
* @param pix the vertical pixel number
* @return a value in attribute space
*/
private double getRandomY(int pix) {
double minPix = m_minY + (pix * m_pixHeight);
return minPix + m_random.nextDouble() * m_pixHeight;
}
/**
* Start the plotting thread
*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -