2
* This program is free software; you can redistribute it and/or modify
3
* it under the terms of the GNU General Public License as published by
4
* the Free Software Foundation; either version 2 of the License, or
5
* (at your option) any later version.
7
* This program is distributed in the hope that it will be useful,
8
* but WITHOUT ANY WARRANTY; without even the implied warranty of
9
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
* GNU General Public License for more details.
12
* You should have received a copy of the GNU General Public License
13
* along with this program; if not, write to the Free Software
14
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
* Copyright (C) 2000 University of Waikato, Hamilton, New Zealand
24
package weka.gui.visualize;
26
import weka.core.FastVector;
27
import weka.core.Instances;
28
import weka.filters.Filter;
29
import weka.filters.unsupervised.attribute.Add;
31
import java.awt.Color;
34
* This class is a container for plottable data. Instances form the
35
* primary data. An optional array of classifier/clusterer predictions
36
* (associated 1 for 1 with the instances) can also be provided.
38
* @author Mark Hall (mhall@cs.waikato.ac.nz)
39
* @version $Revision: 1.18 $
41
public class PlotData2D {
44
protected Instances m_plotInstances = null;
46
/** The name of this plot */
47
protected String m_plotName = "new plot";
49
/** Custom colour for this plot */
50
public boolean m_useCustomColour = false;
51
public Color m_customColour = null;
53
/** Display all points (ie. those that map to the same display coords) */
54
public boolean m_displayAllPoints = false;
56
/** Panel coordinate cache for data points */
57
protected double [][] m_pointLookup;
59
/** Additional optional information to control the size of points.
60
The default is shape size 2 */
61
protected int [] m_shapeSize;
63
/** Additional optional information to control the point shape for this
64
data. Default is to allow automatic assigning of point shape on the
65
basis of plot number */
66
protected int [] m_shapeType;
69
* Additional optional information to control the drawing of lines
70
* between consecutive points. Setting an entry in the array to true
71
* indicates that the associated point should have a line connecting
72
* it to the previous point.
74
protected boolean [] m_connectPoints;
76
/** These are used to determine bounds */
84
/** The colouring index */
87
/** Holds the min and max values of the x, y and colouring attributes
89
protected double m_maxX;
90
protected double m_minX;
91
protected double m_maxY;
92
protected double m_minY;
93
protected double m_maxC;
94
protected double m_minC;
97
* Construct a new PlotData2D using the supplied instances
98
* @param insts the instances to use.
100
public PlotData2D(Instances insts) {
101
m_plotInstances = insts;
102
m_xIndex = m_yIndex = m_cIndex = 0;
103
m_pointLookup = new double [m_plotInstances.numInstances()][4];
104
m_shapeSize = new int [m_plotInstances.numInstances()];
105
m_shapeType = new int [m_plotInstances.numInstances()];
106
m_connectPoints = new boolean [m_plotInstances.numInstances()];
107
for (int i = 0; i < m_plotInstances.numInstances(); i++) {
108
m_shapeSize[i] = Plot2D.DEFAULT_SHAPE_SIZE; //default shape size
109
m_shapeType[i] = Plot2D.CONST_AUTOMATIC_SHAPE; // default (automatic shape assignment)
115
* Adds an instance number attribute to the plottable instances,
117
public void addInstanceNumberAttribute() {
118
String originalRelationName = m_plotInstances.relationName();
120
Add addF = new Add();
121
addF.setAttributeName("Instance_number");
122
addF.setAttributeIndex("first");
123
addF.setInputFormat(m_plotInstances);
124
m_plotInstances = Filter.useFilter(m_plotInstances, addF);
125
m_plotInstances.setClassIndex(m_plotInstances.numAttributes()-1);
126
for (int i = 0; i < m_plotInstances.numInstances(); i++) {
127
m_plotInstances.instance(i).setValue(0,(double)i);
129
m_plotInstances.setRelationName(originalRelationName);
130
} catch (Exception ex) {
131
ex.printStackTrace();
136
* Returns the instances for this plot
137
* @return the instances for this plot
139
public Instances getPlotInstances() {
140
return new Instances(m_plotInstances);
144
* Set the name of this plot
145
* @param name the name for this plot
147
public void setPlotName(String name) {
152
* Get the name of this plot
153
* @return the name of this plot
155
public String getPlotName() {
160
* Set the shape type for the plot data
161
* @param st an array of integers corresponding to shape types (see
162
* constants defined in Plot2D)
164
public void setShapeType(int [] st) throws Exception {
166
if (m_shapeType.length != m_plotInstances.numInstances()) {
167
throw new Exception("PlotData2D: Shape type array must have the same "
168
+"number of entries as number of data points!");
170
for (int i = 0; i < st.length; i++) {
171
if (m_shapeType[i] == Plot2D.ERROR_SHAPE) {
178
* Set the shape type for the plot data
179
* @param st a FastVector of integers corresponding to shape types (see
180
* constants defined in Plot2D)
182
public void setShapeType(FastVector st) throws Exception {
183
if (st.size() != m_plotInstances.numInstances()) {
184
throw new Exception("PlotData2D: Shape type vector must have the same "
185
+"number of entries as number of data points!");
187
m_shapeType = new int [st.size()];
188
for (int i = 0; i < st.size(); i++) {
189
m_shapeType[i] = ((Integer)st.elementAt(i)).intValue();
190
if (m_shapeType[i] == Plot2D.ERROR_SHAPE) {
197
* Set the shape sizes for the plot data
198
* @param ss an array of integers specifying the size of data points
200
public void setShapeSize(int [] ss) throws Exception {
202
if (m_shapeType.length != m_plotInstances.numInstances()) {
203
throw new Exception("PlotData2D: Shape size array must have the same "
204
+"number of entries as number of data points!");
209
* Set the shape sizes for the plot data
210
* @param ss a FastVector of integers specifying the size of data points
212
public void setShapeSize(FastVector ss) throws Exception {
213
if (ss.size() != m_plotInstances.numInstances()) {
214
throw new Exception("PlotData2D: Shape size vector must have the same "
215
+"number of entries as number of data points!");
217
//System.err.println("Setting connect points ");
218
m_shapeSize = new int [ss.size()];
219
for (int i = 0; i < ss.size(); i++) {
220
m_shapeSize[i] = ((Integer)ss.elementAt(i)).intValue();
225
* Set whether consecutive points should be connected by lines
226
* @param cp an array of boolean specifying which points should be
227
* connected to their preceeding neighbour.
229
public void setConnectPoints(boolean [] cp) throws Exception {
230
m_connectPoints = cp;
231
if (m_connectPoints.length != m_plotInstances.numInstances()) {
232
throw new Exception("PlotData2D: connect points array must have the "
233
+"same number of entries as number of data points!");
235
m_connectPoints[0] = false;
239
* Set whether consecutive points should be connected by lines
240
* @param cp a FastVector of boolean specifying which points should be
241
* connected to their preceeding neighbour.
243
public void setConnectPoints(FastVector cp) throws Exception {
244
if (cp.size() != m_plotInstances.numInstances()) {
245
throw new Exception("PlotData2D: connect points array must have the "
246
+"same number of entries as number of data points!");
248
//System.err.println("Setting connect points ");
249
m_shapeSize = new int [cp.size()];
250
for (int i = 0; i < cp.size(); i++) {
251
m_connectPoints[i] = ((Boolean)cp.elementAt(i)).booleanValue();
253
m_connectPoints[0] = false;
257
* Set a custom colour to use for this plot. This overides any
258
* data index to use for colouring. If null, then will revert back
259
* to the default (no custom colouring).
260
* @param c a custom colour to use for this plot or null (default---no
263
public void setCustomColour(Color c) {
266
m_useCustomColour = true;
268
m_useCustomColour = false;
273
* Set the x index of the data.
274
* @param x the x index
276
public void setXindex(int x) {
282
* Set the y index of the data
283
* @param y the y index
285
public void setYindex(int y) {
291
* Set the colouring index of the data
292
* @param c the colouring index
294
public void setCindex(int c) {
300
* Get the currently set x index of the data
301
* @return the current x index
303
public int getXindex() {
308
* Get the currently set y index of the data
309
* @return the current y index
311
public int getYindex() {
316
* Get the currently set colouring index of the data
317
* @return the current colouring index
319
public int getCindex() {
324
* Determine bounds for the current x,y and colouring indexes
326
private void determineBounds() {
327
double value,min,max;
329
if (m_plotInstances != null &&
330
m_plotInstances.numAttributes() > 0 &&
331
m_plotInstances.numInstances() > 0) {
333
min=Double.POSITIVE_INFINITY;
334
max=Double.NEGATIVE_INFINITY;
335
if (m_plotInstances.attribute(m_xIndex).isNominal()) {
337
m_maxX = m_plotInstances.attribute(m_xIndex).numValues()-1;
339
for (int i=0;i<m_plotInstances.numInstances();i++) {
340
if (!m_plotInstances.instance(i).isMissing(m_xIndex)) {
341
value = m_plotInstances.instance(i).value(m_xIndex);
351
// handle case where all values are missing
352
if (min == Double.POSITIVE_INFINITY) min = max = 0.0;
354
m_minX = min; m_maxX = max;
362
min=Double.POSITIVE_INFINITY;
363
max=Double.NEGATIVE_INFINITY;
364
if (m_plotInstances.attribute(m_yIndex).isNominal()) {
366
m_maxY = m_plotInstances.attribute(m_yIndex).numValues()-1;
368
for (int i=0;i<m_plotInstances.numInstances();i++) {
369
if (!m_plotInstances.instance(i).isMissing(m_yIndex)) {
370
value = m_plotInstances.instance(i).value(m_yIndex);
380
// handle case where all values are missing
381
if (min == Double.POSITIVE_INFINITY) min = max = 0.0;
383
m_minY = min; m_maxY = max;
391
min=Double.POSITIVE_INFINITY;
392
max=Double.NEGATIVE_INFINITY;
394
for (int i=0;i<m_plotInstances.numInstances();i++) {
395
if (!m_plotInstances.instance(i).isMissing(m_cIndex)) {
396
value = m_plotInstances.instance(i).value(m_cIndex);
406
// handle case where all values are missing
407
if (min == Double.POSITIVE_INFINITY) min = max = 0.0;
409
m_minC = min; m_maxC = max;