~ubuntu-branches/ubuntu/precise/weka/precise

« back to all changes in this revision

Viewing changes to weka/gui/visualize/PlotData2D.java

  • Committer: Bazaar Package Importer
  • Author(s): Soeren Sonnenburg
  • Date: 2008-02-24 09:18:45 UTC
  • Revision ID: james.westby@ubuntu.com-20080224091845-1l8zy6fm6xipbzsr
Tags: upstream-3.5.7+tut1
ImportĀ upstreamĀ versionĀ 3.5.7+tut1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
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.
 
6
 *
 
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.
 
11
 *
 
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.
 
15
 */
 
16
 
 
17
/*
 
18
 *    PlotData2D.java
 
19
 *    Copyright (C) 2000 University of Waikato, Hamilton, New Zealand
 
20
 *
 
21
 */
 
22
 
 
23
 
 
24
package weka.gui.visualize;
 
25
 
 
26
import weka.core.FastVector;
 
27
import weka.core.Instances;
 
28
import weka.filters.Filter;
 
29
import weka.filters.unsupervised.attribute.Add;
 
30
 
 
31
import java.awt.Color;
 
32
 
 
33
/**
 
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.
 
37
 *
 
38
 * @author Mark Hall (mhall@cs.waikato.ac.nz)
 
39
 * @version $Revision: 1.18 $
 
40
 */
 
41
public class PlotData2D {
 
42
 
 
43
  /** The instances */
 
44
  protected Instances m_plotInstances = null;
 
45
 
 
46
  /** The name of this plot */
 
47
  protected String m_plotName = "new plot";
 
48
 
 
49
  /** Custom colour for this plot */
 
50
  public boolean m_useCustomColour = false;
 
51
  public Color m_customColour = null;
 
52
 
 
53
  /** Display all points (ie. those that map to the same display coords) */
 
54
  public boolean m_displayAllPoints = false;
 
55
 
 
56
  /** Panel coordinate cache for data points */
 
57
  protected double [][] m_pointLookup;
 
58
 
 
59
  /** Additional optional information to control the size of points.
 
60
      The default is shape size 2  */
 
61
  protected int [] m_shapeSize;
 
62
 
 
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;
 
67
 
 
68
  /**
 
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.
 
73
   */
 
74
  protected boolean [] m_connectPoints;
 
75
 
 
76
  /** These are used to determine bounds */
 
77
 
 
78
  /** The x index */
 
79
  private int m_xIndex;
 
80
 
 
81
  /** The y index */
 
82
  private int m_yIndex;
 
83
 
 
84
  /** The colouring index */
 
85
  private int m_cIndex;
 
86
 
 
87
  /** Holds the min and max values of the x, y and colouring attributes 
 
88
   for this plot */
 
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;
 
95
 
 
96
  /**
 
97
   * Construct a new PlotData2D using the supplied instances
 
98
   * @param insts the instances to use.
 
99
   */
 
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)
 
110
    }
 
111
    determineBounds();
 
112
  }
 
113
 
 
114
  /**
 
115
   * Adds an instance number attribute to the plottable instances,
 
116
   */
 
117
  public void addInstanceNumberAttribute() {
 
118
    String originalRelationName = m_plotInstances.relationName();
 
119
    try {
 
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);
 
128
      }
 
129
      m_plotInstances.setRelationName(originalRelationName);
 
130
    } catch (Exception ex) {
 
131
      ex.printStackTrace();
 
132
    }
 
133
  }
 
134
 
 
135
  /**
 
136
   * Returns the instances for this plot
 
137
   * @return the instances for this plot
 
138
   */
 
139
  public Instances getPlotInstances() {
 
140
    return new Instances(m_plotInstances);
 
141
  }
 
142
 
 
143
  /**
 
144
   * Set the name of this plot
 
145
   * @param name the name for this plot
 
146
   */
 
147
  public void setPlotName(String name) {
 
148
    m_plotName = name;
 
149
  }
 
150
 
 
151
  /**
 
152
   * Get the name of this plot
 
153
   * @return the name of this plot
 
154
   */
 
155
  public String getPlotName() {
 
156
    return m_plotName;
 
157
  }
 
158
 
 
159
  /**
 
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)
 
163
   */
 
164
  public void setShapeType(int [] st) throws Exception {
 
165
    m_shapeType = st;
 
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!");
 
169
    }
 
170
    for (int i = 0; i < st.length; i++) {
 
171
      if (m_shapeType[i] == Plot2D.ERROR_SHAPE) {
 
172
        m_shapeSize[i] = 3;
 
173
      }
 
174
    }
 
175
  }
 
176
 
 
177
  /**
 
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)
 
181
   */
 
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!");
 
186
    }
 
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) {
 
191
        m_shapeSize[i] = 3;
 
192
      }
 
193
    }
 
194
  }
 
195
 
 
196
  /**
 
197
   * Set the shape sizes for the plot data
 
198
   * @param ss an array of integers specifying the size of data points
 
199
   */
 
200
  public void setShapeSize(int [] ss) throws Exception {
 
201
    m_shapeSize = ss;
 
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!");
 
205
    }
 
206
  }
 
207
  
 
208
  /**
 
209
   * Set the shape sizes for the plot data
 
210
   * @param ss a FastVector of integers specifying the size of data points
 
211
   */
 
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!");
 
216
    }
 
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();
 
221
    }
 
222
  }
 
223
 
 
224
  /**
 
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.
 
228
   */
 
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!");
 
234
    }
 
235
    m_connectPoints[0] = false;
 
236
  }
 
237
  
 
238
  /**
 
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.
 
242
   */
 
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!");
 
247
    }
 
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();
 
252
    }
 
253
    m_connectPoints[0] = false;
 
254
  }
 
255
 
 
256
  /**
 
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
 
261
   * colouring).
 
262
   */
 
263
  public void setCustomColour(Color c) {
 
264
    m_customColour = c;
 
265
    if (c != null) {
 
266
      m_useCustomColour = true;
 
267
    } else {
 
268
      m_useCustomColour = false;
 
269
    }
 
270
  }
 
271
 
 
272
  /**
 
273
   * Set the x index of the data.
 
274
   * @param x the x index
 
275
   */
 
276
  public void setXindex(int x) {
 
277
    m_xIndex = x;
 
278
    determineBounds();
 
279
  }
 
280
 
 
281
  /**
 
282
   * Set the y index of the data
 
283
   * @param y the y index
 
284
   */
 
285
  public void setYindex(int y) {
 
286
    m_yIndex = y;
 
287
    determineBounds();
 
288
  }
 
289
 
 
290
  /**
 
291
   * Set the colouring index of the data
 
292
   * @param c the colouring index
 
293
   */
 
294
  public void setCindex(int c) {
 
295
    m_cIndex = c;
 
296
    determineBounds();
 
297
  }
 
298
 
 
299
  /**
 
300
   * Get the currently set x index of the data
 
301
   * @return the current x index
 
302
   */
 
303
  public int getXindex() {
 
304
    return m_xIndex;
 
305
  }
 
306
 
 
307
  /**
 
308
   * Get the currently set y index of the data
 
309
   * @return the current y index
 
310
   */
 
311
  public int getYindex() {
 
312
    return m_yIndex;
 
313
  }
 
314
 
 
315
  /**
 
316
   * Get the currently set colouring index of the data
 
317
   * @return the current colouring index
 
318
   */
 
319
  public int getCindex() {
 
320
    return m_cIndex;
 
321
  }
 
322
 
 
323
  /**
 
324
   * Determine bounds for the current x,y and colouring indexes
 
325
   */
 
326
  private void determineBounds() {
 
327
     double value,min,max;
 
328
    
 
329
    if (m_plotInstances != null && 
 
330
        m_plotInstances.numAttributes() > 0 &&
 
331
        m_plotInstances.numInstances() > 0) {
 
332
      // x bounds
 
333
      min=Double.POSITIVE_INFINITY;
 
334
      max=Double.NEGATIVE_INFINITY;
 
335
      if (m_plotInstances.attribute(m_xIndex).isNominal()) {
 
336
        m_minX = 0;
 
337
        m_maxX = m_plotInstances.attribute(m_xIndex).numValues()-1;
 
338
      } else {
 
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);
 
342
            if (value < min) {
 
343
              min = value;
 
344
            }
 
345
            if (value > max) {
 
346
              max = value;
 
347
            }
 
348
          }
 
349
        }
 
350
        
 
351
        // handle case where all values are missing
 
352
        if (min == Double.POSITIVE_INFINITY) min = max = 0.0;
 
353
        
 
354
        m_minX = min; m_maxX = max;
 
355
        if (min == max) {
 
356
          m_maxX += 0.05;
 
357
          m_minX -= 0.05;
 
358
        }
 
359
      }
 
360
 
 
361
      // y bounds
 
362
      min=Double.POSITIVE_INFINITY;
 
363
      max=Double.NEGATIVE_INFINITY;
 
364
      if (m_plotInstances.attribute(m_yIndex).isNominal()) {
 
365
        m_minY = 0;
 
366
        m_maxY = m_plotInstances.attribute(m_yIndex).numValues()-1;
 
367
      } else {
 
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);
 
371
            if (value < min) {
 
372
              min = value;
 
373
            }
 
374
            if (value > max) {
 
375
              max = value;
 
376
            }
 
377
          }
 
378
        }
 
379
        
 
380
        // handle case where all values are missing
 
381
        if (min == Double.POSITIVE_INFINITY) min = max = 0.0;
 
382
 
 
383
        m_minY = min; m_maxY = max;
 
384
        if (min == max) {
 
385
          m_maxY += 0.05;
 
386
          m_minY -= 0.05;
 
387
        }
 
388
      }
 
389
      
 
390
      // colour bounds
 
391
      min=Double.POSITIVE_INFINITY;
 
392
      max=Double.NEGATIVE_INFINITY;
 
393
 
 
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);
 
397
          if (value < min) {
 
398
            min = value;
 
399
          }
 
400
          if (value > max) {
 
401
            max = value;
 
402
          }
 
403
        }
 
404
      }
 
405
 
 
406
      // handle case where all values are missing
 
407
      if (min == Double.POSITIVE_INFINITY) min = max = 0.0;
 
408
 
 
409
      m_minC = min; m_maxC = max;
 
410
    }
 
411
  }
 
412
}