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 | * Plot2D.java |
---|
19 | * Copyright (C) 2000 University of Waikato, Hamilton, New Zealand |
---|
20 | * |
---|
21 | */ |
---|
22 | |
---|
23 | package weka.gui.visualize; |
---|
24 | |
---|
25 | import weka.core.FastVector; |
---|
26 | import weka.core.Instance; |
---|
27 | import weka.core.Instances; |
---|
28 | import weka.core.Utils; |
---|
29 | |
---|
30 | import java.awt.BorderLayout; |
---|
31 | import java.awt.Color; |
---|
32 | import java.awt.Font; |
---|
33 | import java.awt.FontMetrics; |
---|
34 | import java.awt.Graphics; |
---|
35 | import java.awt.event.InputEvent; |
---|
36 | import java.awt.event.MouseAdapter; |
---|
37 | import java.awt.event.MouseEvent; |
---|
38 | import java.awt.event.WindowAdapter; |
---|
39 | import java.awt.event.WindowEvent; |
---|
40 | import java.util.Random; |
---|
41 | import java.util.Vector; |
---|
42 | |
---|
43 | import javax.swing.JFrame; |
---|
44 | import javax.swing.JPanel; |
---|
45 | |
---|
46 | /** |
---|
47 | * This class plots datasets in two dimensions. It can also plot |
---|
48 | * classifier errors and clusterer predictions. |
---|
49 | * |
---|
50 | * @author Mark Hall (mhall@cs.waikato.ac.nz) |
---|
51 | * @version $Revision: 5987 $ |
---|
52 | */ |
---|
53 | public class Plot2D |
---|
54 | extends JPanel { |
---|
55 | |
---|
56 | /** for serialization */ |
---|
57 | private static final long serialVersionUID = -1673162410856660442L; |
---|
58 | |
---|
59 | /* constants for shape types */ |
---|
60 | public static final int MAX_SHAPES = 5; |
---|
61 | public static final int ERROR_SHAPE = 1000; |
---|
62 | public static final int MISSING_SHAPE = 2000; |
---|
63 | public static final int CONST_AUTOMATIC_SHAPE = -1; |
---|
64 | public static final int X_SHAPE = 0; |
---|
65 | public static final int PLUS_SHAPE = 1; |
---|
66 | public static final int DIAMOND_SHAPE = 2; |
---|
67 | public static final int TRIANGLEUP_SHAPE = 3; |
---|
68 | public static final int TRIANGLEDOWN_SHAPE = 4; |
---|
69 | public static final int DEFAULT_SHAPE_SIZE = 2; |
---|
70 | |
---|
71 | /** Default colour for the axis */ |
---|
72 | protected Color m_axisColour = Color.green; |
---|
73 | |
---|
74 | /** Default colour for the plot background */ |
---|
75 | protected Color m_backgroundColour = Color.black; |
---|
76 | |
---|
77 | /** The plots to display */ |
---|
78 | protected FastVector m_plots = new FastVector(); |
---|
79 | |
---|
80 | /** The master plot */ |
---|
81 | protected PlotData2D m_masterPlot = null; |
---|
82 | |
---|
83 | /** The name of the master plot */ |
---|
84 | protected String m_masterName = "master plot"; |
---|
85 | |
---|
86 | /** The instances to be plotted */ |
---|
87 | protected Instances m_plotInstances=null; |
---|
88 | |
---|
89 | /** An optional "compainion" of the panel. If specified, this |
---|
90 | class will get to do its thing with our graphics context |
---|
91 | before we do any drawing. Eg. the visualize panel may need |
---|
92 | to draw polygons etc. before we draw plot axis and data points */ |
---|
93 | protected Plot2DCompanion m_plotCompanion=null; |
---|
94 | |
---|
95 | /** the class for displaying instance info. */ |
---|
96 | protected Class m_InstanceInfoFrameClass = null; |
---|
97 | |
---|
98 | /** For popping up text info on data points */ |
---|
99 | protected JFrame m_InstanceInfo = null; |
---|
100 | |
---|
101 | /** The list of the colors used */ |
---|
102 | protected FastVector m_colorList; |
---|
103 | |
---|
104 | /** default colours for colouring discrete class */ |
---|
105 | protected Color [] m_DefaultColors = {Color.blue, |
---|
106 | Color.red, |
---|
107 | Color.green, |
---|
108 | Color.cyan, |
---|
109 | Color.pink, |
---|
110 | new Color(255, 0, 255), |
---|
111 | Color.orange, |
---|
112 | new Color(255, 0, 0), |
---|
113 | new Color(0, 255, 0), |
---|
114 | Color.white}; |
---|
115 | |
---|
116 | /** Indexes of the attributes to go on the x and y axis and the attribute |
---|
117 | to use for colouring and the current shape for drawing */ |
---|
118 | protected int m_xIndex=0; |
---|
119 | protected int m_yIndex=0; |
---|
120 | protected int m_cIndex=0; |
---|
121 | protected int m_sIndex=0; |
---|
122 | |
---|
123 | /** Holds the min and max values of the x, y and colouring attributes |
---|
124 | over all plots */ |
---|
125 | protected double m_maxX; |
---|
126 | protected double m_minX; |
---|
127 | protected double m_maxY; |
---|
128 | protected double m_minY; |
---|
129 | protected double m_maxC; |
---|
130 | protected double m_minC; |
---|
131 | |
---|
132 | /** Axis padding */ |
---|
133 | protected final int m_axisPad = 5; |
---|
134 | |
---|
135 | /** Tick size */ |
---|
136 | protected final int m_tickSize = 5; |
---|
137 | |
---|
138 | /**the offsets of the axes once label metrics are calculated */ |
---|
139 | protected int m_XaxisStart=0; |
---|
140 | protected int m_YaxisStart=0; |
---|
141 | protected int m_XaxisEnd=0; |
---|
142 | protected int m_YaxisEnd=0; |
---|
143 | |
---|
144 | /** if the user resizes the window, or the attributes selected for |
---|
145 | the attributes change, then the lookup table for points needs |
---|
146 | to be recalculated */ |
---|
147 | protected boolean m_plotResize = true; |
---|
148 | |
---|
149 | /** if the user changes attribute assigned to an axis */ |
---|
150 | protected boolean m_axisChanged = false; |
---|
151 | |
---|
152 | /** An array used to show if a point is hidden or not. |
---|
153 | * This is used for speeding up the drawing of the plot panel |
---|
154 | * although I am not sure how much performance this grants over |
---|
155 | * not having it. |
---|
156 | */ |
---|
157 | protected int[][] m_drawnPoints; |
---|
158 | |
---|
159 | /** Font for labels */ |
---|
160 | protected Font m_labelFont; |
---|
161 | protected FontMetrics m_labelMetrics=null; |
---|
162 | |
---|
163 | /** the level of jitter */ |
---|
164 | protected int m_JitterVal=0; |
---|
165 | |
---|
166 | /** random values for perterbing the data points */ |
---|
167 | protected Random m_JRand = new Random(0); |
---|
168 | |
---|
169 | /** lookup table for plotted points */ |
---|
170 | protected double [][] m_pointLookup=null; |
---|
171 | |
---|
172 | /** Constructor */ |
---|
173 | public Plot2D() { |
---|
174 | super(); |
---|
175 | setProperties(); |
---|
176 | this.setBackground(m_backgroundColour); |
---|
177 | |
---|
178 | m_drawnPoints = new int[this.getWidth()][this.getHeight()]; |
---|
179 | |
---|
180 | /** Set up some default colours */ |
---|
181 | m_colorList = new FastVector(10); |
---|
182 | for (int noa = m_colorList.size(); noa < 10; noa++) { |
---|
183 | Color pc = m_DefaultColors[noa % 10]; |
---|
184 | int ija = noa / 10; |
---|
185 | ija *= 2; |
---|
186 | for (int j=0;j<ija;j++) { |
---|
187 | pc = pc.darker(); |
---|
188 | } |
---|
189 | |
---|
190 | m_colorList.addElement(pc); |
---|
191 | } |
---|
192 | } |
---|
193 | |
---|
194 | /** |
---|
195 | * Set the properties for Plot2D |
---|
196 | */ |
---|
197 | private void setProperties() { |
---|
198 | if (VisualizeUtils.VISUALIZE_PROPERTIES != null) { |
---|
199 | String thisClass = this.getClass().getName(); |
---|
200 | String axisKey = thisClass+".axisColour"; |
---|
201 | String backgroundKey = thisClass+".backgroundColour"; |
---|
202 | |
---|
203 | String axisColour = VisualizeUtils.VISUALIZE_PROPERTIES. |
---|
204 | getProperty(axisKey); |
---|
205 | if (axisColour == null) { |
---|
206 | /* |
---|
207 | System.err.println("Warning: no configuration property found in " |
---|
208 | +VisualizeUtils.PROPERTY_FILE |
---|
209 | +" for "+axisKey);*/ |
---|
210 | } else { |
---|
211 | //System.err.println("Setting axis colour to: "+axisColour); |
---|
212 | m_axisColour = VisualizeUtils.processColour(axisColour, m_axisColour); |
---|
213 | } |
---|
214 | |
---|
215 | String backgroundColour = |
---|
216 | VisualizeUtils.VISUALIZE_PROPERTIES.getProperty(backgroundKey); |
---|
217 | if (backgroundColour == null) { |
---|
218 | /* |
---|
219 | System.err.println("Warning: no configuration property found in " |
---|
220 | +VisualizeUtils.PROPERTY_FILE |
---|
221 | +" for "+backgroundKey);*/ |
---|
222 | } else { |
---|
223 | //System.err.println("Setting background colour to: "+backgroundColour); |
---|
224 | m_backgroundColour = VisualizeUtils.processColour(backgroundColour, |
---|
225 | m_backgroundColour); |
---|
226 | } |
---|
227 | |
---|
228 | try { |
---|
229 | m_InstanceInfoFrameClass = Class.forName(VisualizeUtils.VISUALIZE_PROPERTIES.getProperty(thisClass + ".instanceInfoFrame", "weka.gui.visualize.InstanceInfoFrame")); |
---|
230 | } |
---|
231 | catch (Exception e) { |
---|
232 | e.printStackTrace(); |
---|
233 | m_InstanceInfoFrameClass = InstanceInfoFrame.class; |
---|
234 | } |
---|
235 | } |
---|
236 | } |
---|
237 | |
---|
238 | /** |
---|
239 | * This will check the values of the screen points passed and make sure |
---|
240 | * that they land on the screen |
---|
241 | * @param x1 The x coord. |
---|
242 | * @param y1 The y coord. |
---|
243 | */ |
---|
244 | private boolean checkPoints(double x1, double y1) { |
---|
245 | if (x1 < 0 || x1 > this.getSize().width || y1 < 0 |
---|
246 | || y1 > this.getSize().height) { |
---|
247 | return false; |
---|
248 | } |
---|
249 | return true; |
---|
250 | } |
---|
251 | |
---|
252 | /** |
---|
253 | * Set a companion class. This is a class that might want |
---|
254 | * to render something on the plot before we do our thing. Eg, |
---|
255 | * Malcolm's shape drawing stuff needs to happen before we plot |
---|
256 | * axis and points |
---|
257 | * @param p a companion class |
---|
258 | */ |
---|
259 | public void setPlotCompanion(Plot2DCompanion p) { |
---|
260 | m_plotCompanion = p; |
---|
261 | } |
---|
262 | |
---|
263 | /** |
---|
264 | * Set level of jitter and repaint the plot using the new jitter value |
---|
265 | * @param j the level of jitter |
---|
266 | */ |
---|
267 | public void setJitter(int j) { |
---|
268 | if (m_plotInstances.numAttributes() > 0 |
---|
269 | && m_plotInstances.numInstances() > 0) { |
---|
270 | if (j >= 0) { |
---|
271 | m_JitterVal = j; |
---|
272 | m_JRand = new Random(m_JitterVal); |
---|
273 | // if (m_pointLookup != null) { |
---|
274 | m_drawnPoints = new int[m_XaxisEnd - m_XaxisStart + 1] |
---|
275 | [m_YaxisEnd - m_YaxisStart + 1]; |
---|
276 | updatePturb(); |
---|
277 | // } |
---|
278 | this.repaint(); |
---|
279 | } |
---|
280 | } |
---|
281 | } |
---|
282 | |
---|
283 | /** |
---|
284 | * Set a list of colours to use when colouring points according |
---|
285 | * to class values or cluster numbers |
---|
286 | * @param cols the list of colours to use |
---|
287 | */ |
---|
288 | public void setColours (FastVector cols) { |
---|
289 | m_colorList = cols; |
---|
290 | } |
---|
291 | |
---|
292 | /** |
---|
293 | * Set the index of the attribute to go on the x axis |
---|
294 | * @param x the index of the attribute to use on the x axis |
---|
295 | */ |
---|
296 | public void setXindex(int x) { |
---|
297 | m_xIndex = x; |
---|
298 | for (int i=0;i<m_plots.size();i++) { |
---|
299 | ((PlotData2D)m_plots.elementAt(i)).setXindex(m_xIndex); |
---|
300 | } |
---|
301 | determineBounds(); |
---|
302 | if (m_JitterVal != 0) { |
---|
303 | updatePturb(); |
---|
304 | } |
---|
305 | m_axisChanged = true; |
---|
306 | this.repaint(); |
---|
307 | } |
---|
308 | |
---|
309 | /** |
---|
310 | * Set the index of the attribute to go on the y axis |
---|
311 | * @param y the index of the attribute to use on the y axis |
---|
312 | */ |
---|
313 | public void setYindex(int y) { |
---|
314 | m_yIndex = y; |
---|
315 | for (int i=0;i<m_plots.size();i++) { |
---|
316 | ((PlotData2D)m_plots.elementAt(i)).setYindex(m_yIndex); |
---|
317 | } |
---|
318 | determineBounds(); |
---|
319 | if (m_JitterVal != 0) { |
---|
320 | updatePturb(); |
---|
321 | } |
---|
322 | m_axisChanged = true; |
---|
323 | this.repaint(); |
---|
324 | } |
---|
325 | |
---|
326 | /** |
---|
327 | * Set the index of the attribute to use for colouring |
---|
328 | * @param c the index of the attribute to use for colouring |
---|
329 | */ |
---|
330 | public void setCindex(int c) { |
---|
331 | m_cIndex = c; |
---|
332 | for (int i=0;i<m_plots.size();i++) { |
---|
333 | ((PlotData2D)m_plots.elementAt(i)).setCindex(m_cIndex); |
---|
334 | } |
---|
335 | determineBounds(); |
---|
336 | m_axisChanged = true; |
---|
337 | this.repaint(); |
---|
338 | } |
---|
339 | |
---|
340 | /** |
---|
341 | * Return the list of plots |
---|
342 | * @return the list of plots |
---|
343 | */ |
---|
344 | public FastVector getPlots() { |
---|
345 | return m_plots; |
---|
346 | } |
---|
347 | |
---|
348 | /** |
---|
349 | * Get the master plot |
---|
350 | * @return the master plot |
---|
351 | */ |
---|
352 | public PlotData2D getMasterPlot() { |
---|
353 | return m_masterPlot; |
---|
354 | } |
---|
355 | |
---|
356 | /** |
---|
357 | * Return the current max value of the attribute plotted on the x axis |
---|
358 | * @return the max x value |
---|
359 | */ |
---|
360 | public double getMaxX() { |
---|
361 | return m_maxX; |
---|
362 | } |
---|
363 | |
---|
364 | /** |
---|
365 | * Return the current max value of the attribute plotted on the y axis |
---|
366 | * @return the max y value |
---|
367 | */ |
---|
368 | public double getMaxY() { |
---|
369 | return m_maxY; |
---|
370 | } |
---|
371 | |
---|
372 | /** |
---|
373 | * Return the current min value of the attribute plotted on the x axis |
---|
374 | * @return the min x value |
---|
375 | */ |
---|
376 | public double getMinX() { |
---|
377 | return m_minX; |
---|
378 | } |
---|
379 | |
---|
380 | /** |
---|
381 | * Return the current min value of the attribute plotted on the y axis |
---|
382 | * @return the min y value |
---|
383 | */ |
---|
384 | public double getMinY() { |
---|
385 | return m_minY; |
---|
386 | } |
---|
387 | |
---|
388 | /** |
---|
389 | * Return the current max value of the colouring attribute |
---|
390 | * @return the max colour value |
---|
391 | */ |
---|
392 | public double getMaxC() { |
---|
393 | return m_maxC; |
---|
394 | } |
---|
395 | |
---|
396 | /** |
---|
397 | * Return the current min value of the colouring attribute |
---|
398 | * @return the min colour value |
---|
399 | */ |
---|
400 | public double getMinC() { |
---|
401 | return m_minC; |
---|
402 | } |
---|
403 | |
---|
404 | /** |
---|
405 | * Sets the master plot from a set of instances |
---|
406 | * @param inst the instances |
---|
407 | * @exception Exception if instances could not be set |
---|
408 | */ |
---|
409 | public void setInstances(Instances inst) throws Exception { |
---|
410 | //System.err.println("Setting Instances"); |
---|
411 | PlotData2D tempPlot = new PlotData2D(inst); |
---|
412 | tempPlot.setPlotName("master plot"); |
---|
413 | setMasterPlot(tempPlot); |
---|
414 | } |
---|
415 | |
---|
416 | /** |
---|
417 | * Set the master plot. |
---|
418 | * @param master the plot to make the master plot |
---|
419 | * @exception Exception if the plot could not be set. |
---|
420 | */ |
---|
421 | public void setMasterPlot(PlotData2D master) throws Exception { |
---|
422 | if (master.m_plotInstances == null) { |
---|
423 | throw new Exception("No instances in plot data!"); |
---|
424 | } |
---|
425 | removeAllPlots(); |
---|
426 | m_masterPlot = master; |
---|
427 | m_plots.addElement(m_masterPlot); |
---|
428 | m_plotInstances = m_masterPlot.m_plotInstances; |
---|
429 | |
---|
430 | m_xIndex=0; |
---|
431 | m_yIndex=0; |
---|
432 | m_cIndex=0; |
---|
433 | |
---|
434 | determineBounds(); |
---|
435 | } |
---|
436 | |
---|
437 | /** |
---|
438 | * Clears all plots |
---|
439 | */ |
---|
440 | public void removeAllPlots() { |
---|
441 | m_masterPlot = null; |
---|
442 | m_plotInstances = null; |
---|
443 | m_plots = new FastVector(); |
---|
444 | m_xIndex = 0; m_yIndex = 0; m_cIndex = 0; |
---|
445 | } |
---|
446 | |
---|
447 | /** |
---|
448 | * Add a plot to the list of plots to display |
---|
449 | * @param newPlot the new plot to add |
---|
450 | * @exception Exception if the plot could not be added |
---|
451 | */ |
---|
452 | public void addPlot(PlotData2D newPlot) throws Exception { |
---|
453 | if (newPlot.m_plotInstances == null) { |
---|
454 | throw new Exception("No instances in plot data!"); |
---|
455 | } |
---|
456 | |
---|
457 | if (m_masterPlot != null) { |
---|
458 | if (m_masterPlot.m_plotInstances. |
---|
459 | equalHeaders(newPlot.m_plotInstances) == false) { |
---|
460 | throw new Exception("Plot2D :Plot data's instances are incompatable " |
---|
461 | +" with master plot"); |
---|
462 | } |
---|
463 | } else { |
---|
464 | m_masterPlot = newPlot; |
---|
465 | m_plotInstances = m_masterPlot.m_plotInstances; |
---|
466 | } |
---|
467 | m_plots.addElement(newPlot); |
---|
468 | setXindex(m_xIndex); |
---|
469 | setYindex(m_yIndex); |
---|
470 | setCindex(m_cIndex); |
---|
471 | } |
---|
472 | |
---|
473 | /** |
---|
474 | * Set up fonts and font metrics |
---|
475 | * @param gx the graphics context |
---|
476 | */ |
---|
477 | private void setFonts(Graphics gx) { |
---|
478 | if (m_labelMetrics == null) { |
---|
479 | m_labelFont = new Font("Monospaced", Font.PLAIN, 12); |
---|
480 | m_labelMetrics = gx.getFontMetrics(m_labelFont); |
---|
481 | } |
---|
482 | gx.setFont(m_labelFont); |
---|
483 | } |
---|
484 | |
---|
485 | /** |
---|
486 | * Pops up a window displaying attribute information on any instances |
---|
487 | * at a point+-plotting_point_size (in panel coordinates) |
---|
488 | * |
---|
489 | * @param x the x value of the clicked point |
---|
490 | * @param y the y value of the clicked point |
---|
491 | * @param newFrame true if instance info is to be displayed in a |
---|
492 | * new frame. |
---|
493 | */ |
---|
494 | public void searchPoints(int x, int y, final boolean newFrame) { |
---|
495 | if (m_masterPlot.m_plotInstances != null) { |
---|
496 | int longest=0; |
---|
497 | for (int j=0;j<m_masterPlot.m_plotInstances.numAttributes();j++) { |
---|
498 | if (m_masterPlot.m_plotInstances.attribute(j).name().length() > |
---|
499 | longest) { |
---|
500 | longest = m_masterPlot.m_plotInstances.attribute(j).name().length(); |
---|
501 | } |
---|
502 | } |
---|
503 | |
---|
504 | StringBuffer insts = new StringBuffer(); |
---|
505 | Vector<Instances> data = new Vector<Instances>(); |
---|
506 | for (int jj=0;jj<m_plots.size();jj++) { |
---|
507 | PlotData2D temp_plot = (PlotData2D)(m_plots.elementAt(jj)); |
---|
508 | data.add(new Instances(temp_plot.m_plotInstances, 0)); |
---|
509 | |
---|
510 | for (int i=0;i<temp_plot.m_plotInstances.numInstances();i++) { |
---|
511 | if (temp_plot.m_pointLookup[i][0] != Double.NEGATIVE_INFINITY) { |
---|
512 | double px = temp_plot.m_pointLookup[i][0] + |
---|
513 | temp_plot.m_pointLookup[i][2]; |
---|
514 | double py = temp_plot.m_pointLookup[i][1] + |
---|
515 | temp_plot.m_pointLookup[i][3]; |
---|
516 | // double size = temp_plot.m_pointLookup[i][2]; |
---|
517 | double size = temp_plot.m_shapeSize[i]; |
---|
518 | if ((x >= px-size) && (x <= px+size) && |
---|
519 | (y >= py-size) && (y <= py+size)) { |
---|
520 | { |
---|
521 | data.get(jj).add((Instance)temp_plot.m_plotInstances.instance(i).copy()); |
---|
522 | insts.append("\nPlot : "+temp_plot.m_plotName |
---|
523 | + "\nInstance: " + (i + 1 ) + "\n"); |
---|
524 | for (int j=0;j<temp_plot.m_plotInstances.numAttributes();j++) { |
---|
525 | for (int k = 0;k < |
---|
526 | (longest-temp_plot.m_plotInstances. |
---|
527 | attribute(j).name().length()); k++) { |
---|
528 | insts.append(" "); |
---|
529 | } |
---|
530 | insts.append(temp_plot.m_plotInstances.attribute(j).name()); |
---|
531 | insts.append(" : "); |
---|
532 | |
---|
533 | if (temp_plot.m_plotInstances.instance(i).isMissing(j)) { |
---|
534 | insts.append("Missing"); |
---|
535 | } else if (temp_plot.m_plotInstances.attribute(j). |
---|
536 | isNominal()) { |
---|
537 | insts.append(temp_plot.m_plotInstances. |
---|
538 | attribute(j). |
---|
539 | value((int)temp_plot.m_plotInstances. |
---|
540 | instance(i).value(j))); |
---|
541 | } else { |
---|
542 | insts.append(temp_plot.m_plotInstances. |
---|
543 | instance(i).value(j)); |
---|
544 | } |
---|
545 | insts.append("\n"); |
---|
546 | } |
---|
547 | } |
---|
548 | } |
---|
549 | } |
---|
550 | } |
---|
551 | } |
---|
552 | // remove datasets that contain no instances |
---|
553 | int i = 0; |
---|
554 | while (data.size() > i) { |
---|
555 | if (data.get(i).numInstances() == 0) |
---|
556 | data.remove(i); |
---|
557 | else |
---|
558 | i++; |
---|
559 | } |
---|
560 | |
---|
561 | if (insts.length() > 0) { |
---|
562 | // Pop up a new frame |
---|
563 | if (newFrame || m_InstanceInfo == null) { |
---|
564 | try { |
---|
565 | final JFrame jf = (JFrame) m_InstanceInfoFrameClass.newInstance(); |
---|
566 | ((InstanceInfo) jf).setInfoText(insts.toString()); |
---|
567 | ((InstanceInfo) jf).setInfoData(data); |
---|
568 | final JFrame testf = m_InstanceInfo; |
---|
569 | jf.addWindowListener(new WindowAdapter() { |
---|
570 | public void windowClosing(WindowEvent e) { |
---|
571 | if (!newFrame || testf == null) { |
---|
572 | m_InstanceInfo = null; |
---|
573 | } |
---|
574 | jf.dispose(); |
---|
575 | } |
---|
576 | }); |
---|
577 | jf.setVisible(true); |
---|
578 | if (m_InstanceInfo == null) |
---|
579 | m_InstanceInfo = jf; |
---|
580 | } |
---|
581 | catch (Exception e) { |
---|
582 | e.printStackTrace(); |
---|
583 | } |
---|
584 | } |
---|
585 | else { |
---|
586 | // Overwrite info in existing frame |
---|
587 | ((InstanceInfo) m_InstanceInfo).setInfoText(insts.toString()); |
---|
588 | ((InstanceInfo) m_InstanceInfo).setInfoData(data); |
---|
589 | } |
---|
590 | } |
---|
591 | } |
---|
592 | } |
---|
593 | |
---|
594 | |
---|
595 | /** |
---|
596 | * Determine the min and max values for axis and colouring attributes |
---|
597 | */ |
---|
598 | public void determineBounds() { |
---|
599 | double value,min,max; |
---|
600 | |
---|
601 | // find maximums minimums over all plots |
---|
602 | m_minX = ((PlotData2D)m_plots.elementAt(0)).m_minX; |
---|
603 | m_maxX = ((PlotData2D)m_plots.elementAt(0)).m_maxX; |
---|
604 | m_minY = ((PlotData2D)m_plots.elementAt(0)).m_minY; |
---|
605 | m_maxY = ((PlotData2D)m_plots.elementAt(0)).m_maxY; |
---|
606 | m_minC = ((PlotData2D)m_plots.elementAt(0)).m_minC; |
---|
607 | m_maxC = ((PlotData2D)m_plots.elementAt(0)).m_maxC; |
---|
608 | for (int i=1;i<m_plots.size();i++) { |
---|
609 | value = ((PlotData2D)m_plots.elementAt(i)).m_minX; |
---|
610 | if (value < m_minX) { |
---|
611 | m_minX = value; |
---|
612 | } |
---|
613 | value = ((PlotData2D)m_plots.elementAt(i)).m_maxX; |
---|
614 | if (value > m_maxX) { |
---|
615 | m_maxX = value; |
---|
616 | } |
---|
617 | value = ((PlotData2D)m_plots.elementAt(i)).m_minY; |
---|
618 | if (value < m_minY) { |
---|
619 | m_minY= value; |
---|
620 | } |
---|
621 | value = ((PlotData2D)m_plots.elementAt(i)).m_maxY; |
---|
622 | if (value > m_maxY) { |
---|
623 | m_maxY = value; |
---|
624 | } |
---|
625 | value = ((PlotData2D)m_plots.elementAt(i)).m_minC; |
---|
626 | if (value < m_minC) { |
---|
627 | m_minC = value; |
---|
628 | } |
---|
629 | value = ((PlotData2D)m_plots.elementAt(i)).m_maxC; |
---|
630 | if (value > m_maxC) { |
---|
631 | m_maxC = value; |
---|
632 | } |
---|
633 | } |
---|
634 | |
---|
635 | fillLookup(); |
---|
636 | this.repaint(); |
---|
637 | } |
---|
638 | |
---|
639 | |
---|
640 | //to convert screen coords to attrib values |
---|
641 | // note that I use a double to avoid accuracy |
---|
642 | //headaches with ints |
---|
643 | /** |
---|
644 | * convert a Panel x coordinate to a raw x value. |
---|
645 | * @param scx The Panel x coordinate |
---|
646 | * @return A raw x value. |
---|
647 | */ |
---|
648 | public double convertToAttribX(double scx) { |
---|
649 | double temp = m_XaxisEnd - m_XaxisStart; |
---|
650 | double temp2 = ((scx - m_XaxisStart) * (m_maxX - m_minX)) / temp; |
---|
651 | |
---|
652 | temp2 = temp2 + m_minX; |
---|
653 | |
---|
654 | return temp2; |
---|
655 | } |
---|
656 | |
---|
657 | /** |
---|
658 | * convert a Panel y coordinate to a raw y value. |
---|
659 | * @param scy The Panel y coordinate |
---|
660 | * @return A raw y value. |
---|
661 | */ |
---|
662 | public double convertToAttribY(double scy) { |
---|
663 | double temp = m_YaxisEnd - m_YaxisStart; |
---|
664 | double temp2 = ((scy - m_YaxisEnd) * (m_maxY - m_minY)) / temp; |
---|
665 | |
---|
666 | temp2 = -(temp2 - m_minY); |
---|
667 | |
---|
668 | return temp2; |
---|
669 | } |
---|
670 | ////// |
---|
671 | |
---|
672 | /** |
---|
673 | * returns a value by which an x value can be peturbed. Makes sure |
---|
674 | * that the x value+pturb stays within the plot bounds |
---|
675 | * @param xvalP the x coordinate to be peturbed |
---|
676 | * @param xj a random number to use in calculating a peturb value |
---|
677 | * @return a peturb value |
---|
678 | */ |
---|
679 | int pturbX(double xvalP, double xj) { |
---|
680 | int xpturb = 0; |
---|
681 | if (m_JitterVal > 0) { |
---|
682 | xpturb = (int)((double)m_JitterVal * (xj / 2.0)); |
---|
683 | if (((xvalP + xpturb) < m_XaxisStart) || |
---|
684 | ((xvalP + xpturb) > m_XaxisEnd)) { |
---|
685 | xpturb *= -1; |
---|
686 | } |
---|
687 | } |
---|
688 | return xpturb; |
---|
689 | } |
---|
690 | |
---|
691 | /** |
---|
692 | * Convert an raw x value to Panel x coordinate. |
---|
693 | * @param xval the raw x value |
---|
694 | * @return an x value for plotting in the panel. |
---|
695 | */ |
---|
696 | public double convertToPanelX(double xval) { |
---|
697 | double temp = (xval - m_minX)/(m_maxX - m_minX); |
---|
698 | double temp2 = temp * (m_XaxisEnd - m_XaxisStart); |
---|
699 | |
---|
700 | temp2 = temp2 + m_XaxisStart; |
---|
701 | |
---|
702 | return temp2; |
---|
703 | } |
---|
704 | |
---|
705 | /** |
---|
706 | * returns a value by which a y value can be peturbed. Makes sure |
---|
707 | * that the y value+pturb stays within the plot bounds |
---|
708 | * @param yvalP the y coordinate to be peturbed |
---|
709 | * @param yj a random number to use in calculating a peturb value |
---|
710 | * @return a peturb value |
---|
711 | */ |
---|
712 | int pturbY(double yvalP, double yj) { |
---|
713 | int ypturb = 0; |
---|
714 | if (m_JitterVal > 0) { |
---|
715 | ypturb = (int)((double)m_JitterVal * (yj / 2.0)); |
---|
716 | if (((yvalP + ypturb) < m_YaxisStart) || |
---|
717 | ((yvalP + ypturb) > m_YaxisEnd)) { |
---|
718 | ypturb *= -1; |
---|
719 | } |
---|
720 | } |
---|
721 | return ypturb; |
---|
722 | } |
---|
723 | |
---|
724 | /** |
---|
725 | * Convert an raw y value to Panel y coordinate. |
---|
726 | * @param yval the raw y value |
---|
727 | * @return an y value for plotting in the panel. |
---|
728 | */ |
---|
729 | public double convertToPanelY(double yval) { |
---|
730 | double temp = (yval - m_minY)/(m_maxY - m_minY); |
---|
731 | double temp2 = temp * (m_YaxisEnd - m_YaxisStart); |
---|
732 | |
---|
733 | temp2 = m_YaxisEnd - temp2; |
---|
734 | |
---|
735 | return temp2; |
---|
736 | } |
---|
737 | |
---|
738 | /** |
---|
739 | * Draws an X. |
---|
740 | * @param gx the graphics context |
---|
741 | * @param x the x coord |
---|
742 | * @param y the y coord |
---|
743 | * @param size the size of the shape |
---|
744 | */ |
---|
745 | private static void drawX(Graphics gx, double x, double y, int size) { |
---|
746 | gx.drawLine((int)(x-size),(int)(y-size), |
---|
747 | (int)(x+size),(int)(y+size)); |
---|
748 | |
---|
749 | gx.drawLine((int)(x+size),(int)(y-size), |
---|
750 | (int)(x-size),(int)(y+size)); |
---|
751 | } |
---|
752 | |
---|
753 | /** |
---|
754 | * Draws a plus. |
---|
755 | * @param gx the graphics context |
---|
756 | * @param x the x coord |
---|
757 | * @param y the y coord |
---|
758 | * @param size the size of the shape |
---|
759 | */ |
---|
760 | private static void drawPlus(Graphics gx, double x, double y, int size) { |
---|
761 | gx.drawLine((int)(x-size),(int)(y), |
---|
762 | (int)(x+size),(int)(y)); |
---|
763 | |
---|
764 | gx.drawLine((int)(x),(int)(y-size), |
---|
765 | (int)(x),(int)(y+size)); |
---|
766 | } |
---|
767 | |
---|
768 | /** |
---|
769 | * Draws a diamond. |
---|
770 | * @param gx the graphics context |
---|
771 | * @param x the x coord |
---|
772 | * @param y the y coord |
---|
773 | * @param size the size of the shape |
---|
774 | */ |
---|
775 | private static void drawDiamond(Graphics gx, double x, double y, int size) { |
---|
776 | gx.drawLine((int)(x-size),(int)(y), |
---|
777 | (int)(x),(int)(y-size)); |
---|
778 | |
---|
779 | gx.drawLine((int)(x),(int)(y-size), |
---|
780 | (int)(x+size),(int)(y)); |
---|
781 | |
---|
782 | gx.drawLine((int)(x+size),(int)(y), |
---|
783 | (int)(x),(int)(y+size)); |
---|
784 | |
---|
785 | gx.drawLine((int)(x),(int)(y+size), |
---|
786 | (int)(x-size),(int)(y)); |
---|
787 | } |
---|
788 | |
---|
789 | /** |
---|
790 | * Draws an triangle (point at top). |
---|
791 | * @param gx the graphics context |
---|
792 | * @param x the x coord |
---|
793 | * @param y the y coord |
---|
794 | * @param size the size of the shape |
---|
795 | */ |
---|
796 | private static void drawTriangleUp(Graphics gx, double x, |
---|
797 | double y, int size) { |
---|
798 | gx.drawLine((int)(x),(int)(y-size), |
---|
799 | (int)(x-size),(int)(y+size)); |
---|
800 | |
---|
801 | gx.drawLine((int)(x-size),(int)(y+size), |
---|
802 | (int)(x+size),(int)(y+size)); |
---|
803 | |
---|
804 | gx.drawLine((int)(x+size),(int)(y+size), |
---|
805 | (int)(x),(int)(y-size)); |
---|
806 | |
---|
807 | } |
---|
808 | |
---|
809 | /** |
---|
810 | * Draws an triangle (point at bottom). |
---|
811 | * @param gx the graphics context |
---|
812 | * @param x the x coord |
---|
813 | * @param y the y coord |
---|
814 | * @param size the size of the shape |
---|
815 | */ |
---|
816 | private static void drawTriangleDown(Graphics gx, double x, |
---|
817 | double y, int size) { |
---|
818 | gx.drawLine((int)(x),(int)(y+size), |
---|
819 | (int)(x-size),(int)(y-size)); |
---|
820 | |
---|
821 | gx.drawLine((int)(x-size),(int)(y-size), |
---|
822 | (int)(x+size),(int)(y-size)); |
---|
823 | |
---|
824 | gx.drawLine((int)(x+size),(int)(y-size), |
---|
825 | (int)(x),(int)(y+size)); |
---|
826 | |
---|
827 | } |
---|
828 | |
---|
829 | /** |
---|
830 | * Draws a data point at a given set of panel coordinates at a given |
---|
831 | * size and connects a line to the previous point. |
---|
832 | * @param x the x coord |
---|
833 | * @param y the y coord |
---|
834 | * @param xprev the x coord of the previous point |
---|
835 | * @param yprev the y coord of the previous point |
---|
836 | * @param size the size of the point |
---|
837 | * @param shape the shape of the data point (square is reserved for nominal |
---|
838 | * error data points). Shapes: 0=x, 1=plus, 2=diamond, 3=triangle(up), |
---|
839 | * 4 = triangle (down). |
---|
840 | * @param gx the graphics context |
---|
841 | */ |
---|
842 | protected static void drawDataPoint(double x, |
---|
843 | double y, |
---|
844 | double xprev, |
---|
845 | double yprev, |
---|
846 | int size, |
---|
847 | int shape, |
---|
848 | Graphics gx) { |
---|
849 | |
---|
850 | drawDataPoint(x,y,size,shape,gx); |
---|
851 | |
---|
852 | // connect a line to the previous point |
---|
853 | gx.drawLine((int)x, (int)y, (int)xprev, (int)yprev); |
---|
854 | } |
---|
855 | |
---|
856 | /** |
---|
857 | * Draws a data point at a given set of panel coordinates at a given |
---|
858 | * size. |
---|
859 | * @param x the x coord |
---|
860 | * @param y the y coord |
---|
861 | * @param size the size of the point |
---|
862 | * @param shape the shape of the data point (square is reserved for nominal |
---|
863 | * error data points). Shapes: 0=x, 1=plus, 2=diamond, 3=triangle(up), |
---|
864 | * 4 = triangle (down). |
---|
865 | * @param gx the graphics context |
---|
866 | */ |
---|
867 | protected static void drawDataPoint(double x, |
---|
868 | double y, |
---|
869 | int size, |
---|
870 | int shape, |
---|
871 | Graphics gx) { |
---|
872 | |
---|
873 | Font lf = new Font("Monospaced", Font.PLAIN, 12); |
---|
874 | FontMetrics fm = gx.getFontMetrics(lf); |
---|
875 | |
---|
876 | if (size == 0) { |
---|
877 | size = 1; |
---|
878 | } |
---|
879 | |
---|
880 | if (shape != ERROR_SHAPE && shape != MISSING_SHAPE) { |
---|
881 | shape = shape % 5; |
---|
882 | } |
---|
883 | |
---|
884 | switch (shape) { |
---|
885 | case X_SHAPE: |
---|
886 | drawX(gx, x, y, size); |
---|
887 | break; |
---|
888 | case PLUS_SHAPE: |
---|
889 | drawPlus(gx, x, y, size); |
---|
890 | break; |
---|
891 | case DIAMOND_SHAPE: |
---|
892 | drawDiamond(gx, x, y, size); |
---|
893 | break; |
---|
894 | case TRIANGLEUP_SHAPE: |
---|
895 | drawTriangleUp(gx, x, y, size); |
---|
896 | break; |
---|
897 | case TRIANGLEDOWN_SHAPE: |
---|
898 | drawTriangleDown(gx, x, y, size); |
---|
899 | break; |
---|
900 | case ERROR_SHAPE: // draws the nominal error shape |
---|
901 | gx.drawRect((int)(x-size),(int)(y-size),(size*2),(size*2)); |
---|
902 | break; |
---|
903 | case MISSING_SHAPE: |
---|
904 | int hf = fm.getAscent(); |
---|
905 | int width = fm.stringWidth("M"); |
---|
906 | gx.drawString("M",(int)(x-(width / 2)), (int)(y+(hf / 2))); |
---|
907 | break; |
---|
908 | } |
---|
909 | } |
---|
910 | |
---|
911 | /** |
---|
912 | * Updates the perturbed values for the plots when the jitter value is |
---|
913 | * changed |
---|
914 | */ |
---|
915 | private void updatePturb() { |
---|
916 | double xj=0; |
---|
917 | double yj=0; |
---|
918 | for (int j=0;j<m_plots.size();j++) { |
---|
919 | PlotData2D temp_plot = (PlotData2D)(m_plots.elementAt(j)); |
---|
920 | for (int i=0;i<temp_plot.m_plotInstances.numInstances();i++) { |
---|
921 | if (temp_plot.m_plotInstances.instance(i).isMissing(m_xIndex) || |
---|
922 | temp_plot.m_plotInstances.instance(i).isMissing(m_yIndex)) { |
---|
923 | } else { |
---|
924 | if (m_JitterVal > 0) { |
---|
925 | xj = m_JRand.nextGaussian(); |
---|
926 | yj = m_JRand.nextGaussian(); |
---|
927 | } |
---|
928 | temp_plot.m_pointLookup[i][2] = |
---|
929 | pturbX(temp_plot.m_pointLookup[i][0],xj); |
---|
930 | temp_plot.m_pointLookup[i][3] = |
---|
931 | pturbY(temp_plot.m_pointLookup[i][1],yj); |
---|
932 | } |
---|
933 | } |
---|
934 | } |
---|
935 | } |
---|
936 | |
---|
937 | /** |
---|
938 | * Fills the lookup caches for the plots. Also calculates errors for |
---|
939 | * numeric predictions (if any) in plots |
---|
940 | */ |
---|
941 | private void fillLookup() { |
---|
942 | |
---|
943 | for (int j=0;j<m_plots.size();j++) { |
---|
944 | PlotData2D temp_plot = (PlotData2D)(m_plots.elementAt(j)); |
---|
945 | |
---|
946 | if (temp_plot.m_plotInstances.numInstances() > 0 && |
---|
947 | temp_plot.m_plotInstances.numAttributes() > 0) { |
---|
948 | for (int i=0;i<temp_plot.m_plotInstances.numInstances();i++) { |
---|
949 | if (temp_plot.m_plotInstances.instance(i).isMissing(m_xIndex) || |
---|
950 | temp_plot.m_plotInstances.instance(i).isMissing(m_yIndex)) { |
---|
951 | temp_plot.m_pointLookup[i][0] = Double.NEGATIVE_INFINITY; |
---|
952 | temp_plot.m_pointLookup[i][1] = Double.NEGATIVE_INFINITY; |
---|
953 | } else { |
---|
954 | double x = convertToPanelX(temp_plot.m_plotInstances. |
---|
955 | instance(i).value(m_xIndex)); |
---|
956 | double y = convertToPanelY(temp_plot.m_plotInstances. |
---|
957 | instance(i).value(m_yIndex)); |
---|
958 | temp_plot.m_pointLookup[i][0] = x; |
---|
959 | temp_plot.m_pointLookup[i][1] = y; |
---|
960 | } |
---|
961 | } |
---|
962 | } |
---|
963 | } |
---|
964 | } |
---|
965 | |
---|
966 | /** |
---|
967 | * Draws the data points and predictions (if provided). |
---|
968 | * @param gx the graphics context |
---|
969 | */ |
---|
970 | private void paintData(Graphics gx) { |
---|
971 | |
---|
972 | for (int j=0;j<m_plots.size();j++) { |
---|
973 | PlotData2D temp_plot = (PlotData2D)(m_plots.elementAt(j)); |
---|
974 | |
---|
975 | for (int i=0;i<temp_plot.m_plotInstances.numInstances();i++) { |
---|
976 | if (temp_plot.m_plotInstances.instance(i).isMissing(m_xIndex) || |
---|
977 | temp_plot.m_plotInstances.instance(i).isMissing(m_yIndex)) { |
---|
978 | } else { |
---|
979 | double x = (temp_plot.m_pointLookup[i][0] + |
---|
980 | temp_plot.m_pointLookup[i][2]); |
---|
981 | double y = (temp_plot.m_pointLookup[i][1] + |
---|
982 | temp_plot.m_pointLookup[i][3]); |
---|
983 | |
---|
984 | double prevx = 0; |
---|
985 | double prevy = 0; |
---|
986 | if (i > 0) { |
---|
987 | prevx = (temp_plot.m_pointLookup[i - 1][0] + |
---|
988 | temp_plot.m_pointLookup[i - 1][2]); |
---|
989 | prevy = (temp_plot.m_pointLookup[i - 1][1] + |
---|
990 | temp_plot.m_pointLookup[i - 1][3]); |
---|
991 | } |
---|
992 | |
---|
993 | int x_range = (int)x - m_XaxisStart; |
---|
994 | int y_range = (int)y - m_YaxisStart; |
---|
995 | |
---|
996 | if (x_range >= 0 && y_range >= 0) { |
---|
997 | if (m_drawnPoints[x_range][y_range] == i |
---|
998 | || m_drawnPoints[x_range][y_range] == 0 |
---|
999 | || temp_plot.m_shapeSize[i] == temp_plot.m_alwaysDisplayPointsOfThisSize |
---|
1000 | || temp_plot.m_displayAllPoints == true) { |
---|
1001 | m_drawnPoints[x_range][y_range] = i; |
---|
1002 | if (temp_plot.m_plotInstances.attribute(m_cIndex).isNominal()) { |
---|
1003 | if (temp_plot.m_plotInstances.attribute(m_cIndex).numValues() > |
---|
1004 | m_colorList.size() && |
---|
1005 | !temp_plot.m_useCustomColour) { |
---|
1006 | extendColourMap(temp_plot.m_plotInstances. |
---|
1007 | attribute(m_cIndex).numValues()); |
---|
1008 | } |
---|
1009 | |
---|
1010 | Color ci; |
---|
1011 | if (temp_plot.m_plotInstances.instance(i). |
---|
1012 | isMissing(m_cIndex)) { |
---|
1013 | ci = Color.gray; |
---|
1014 | } else { |
---|
1015 | int ind = (int)temp_plot.m_plotInstances.instance(i). |
---|
1016 | value(m_cIndex); |
---|
1017 | ci = (Color)m_colorList.elementAt(ind); |
---|
1018 | } |
---|
1019 | |
---|
1020 | if (!temp_plot.m_useCustomColour) { |
---|
1021 | gx.setColor(ci); |
---|
1022 | } else { |
---|
1023 | gx.setColor(temp_plot.m_customColour); |
---|
1024 | } |
---|
1025 | |
---|
1026 | if (temp_plot.m_plotInstances.instance(i). |
---|
1027 | isMissing(m_cIndex)) { |
---|
1028 | if (temp_plot.m_connectPoints[i] == true) { |
---|
1029 | drawDataPoint(x,y,prevx,prevy,temp_plot.m_shapeSize[i], |
---|
1030 | MISSING_SHAPE,gx); |
---|
1031 | } else { |
---|
1032 | drawDataPoint(x,y,temp_plot.m_shapeSize[i], |
---|
1033 | MISSING_SHAPE,gx); |
---|
1034 | } |
---|
1035 | } else { |
---|
1036 | if (temp_plot.m_shapeType[i] == CONST_AUTOMATIC_SHAPE) { |
---|
1037 | if (temp_plot.m_connectPoints[i] == true) { |
---|
1038 | drawDataPoint(x,y,prevx,prevy, |
---|
1039 | temp_plot.m_shapeSize[i],j,gx); |
---|
1040 | } else { |
---|
1041 | drawDataPoint(x,y,temp_plot.m_shapeSize[i],j,gx); |
---|
1042 | } |
---|
1043 | } else { |
---|
1044 | if (temp_plot.m_connectPoints[i] == true) { |
---|
1045 | drawDataPoint(x,y,prevx,prevy,temp_plot.m_shapeSize[i], |
---|
1046 | temp_plot.m_shapeType[i],gx); |
---|
1047 | } else { |
---|
1048 | drawDataPoint(x,y,temp_plot.m_shapeSize[i], |
---|
1049 | temp_plot.m_shapeType[i],gx); |
---|
1050 | } |
---|
1051 | } |
---|
1052 | } |
---|
1053 | } else { |
---|
1054 | double r; |
---|
1055 | Color ci = null; |
---|
1056 | if (!temp_plot.m_plotInstances.instance(i). |
---|
1057 | isMissing(m_cIndex)) { |
---|
1058 | r = (temp_plot.m_plotInstances.instance(i). |
---|
1059 | value(m_cIndex) - m_minC) / (m_maxC - m_minC); |
---|
1060 | r = (r * 240) + 15; |
---|
1061 | ci = new Color((int)r,150,(int)(255-r)); |
---|
1062 | } else { |
---|
1063 | ci = Color.gray; |
---|
1064 | } |
---|
1065 | if (!temp_plot.m_useCustomColour) { |
---|
1066 | gx.setColor(ci); |
---|
1067 | } else { |
---|
1068 | gx.setColor(temp_plot.m_customColour); |
---|
1069 | } |
---|
1070 | if (temp_plot.m_plotInstances.instance(i). |
---|
1071 | isMissing(m_cIndex)) { |
---|
1072 | if (temp_plot.m_connectPoints[i] == true) { |
---|
1073 | drawDataPoint(x,y,prevx,prevy,temp_plot.m_shapeSize[i], |
---|
1074 | MISSING_SHAPE,gx); |
---|
1075 | } else { |
---|
1076 | drawDataPoint(x,y,temp_plot.m_shapeSize[i], |
---|
1077 | MISSING_SHAPE,gx); |
---|
1078 | } |
---|
1079 | } else { |
---|
1080 | if (temp_plot.m_shapeType[i] == CONST_AUTOMATIC_SHAPE) { |
---|
1081 | if (temp_plot.m_connectPoints[i] == true) { |
---|
1082 | drawDataPoint(x,y,prevx,prevy, |
---|
1083 | temp_plot.m_shapeSize[i],j,gx); |
---|
1084 | } else { |
---|
1085 | drawDataPoint(x,y,temp_plot.m_shapeSize[i],j,gx); |
---|
1086 | } |
---|
1087 | } else { |
---|
1088 | if (temp_plot.m_connectPoints[i] == true) { |
---|
1089 | drawDataPoint(x,y,prevx,prevy,temp_plot.m_shapeSize[i], |
---|
1090 | temp_plot.m_shapeType[i],gx); |
---|
1091 | } else { |
---|
1092 | drawDataPoint(x,y,temp_plot.m_shapeSize[i], |
---|
1093 | temp_plot.m_shapeType[i],gx); |
---|
1094 | } |
---|
1095 | } |
---|
1096 | } |
---|
1097 | } |
---|
1098 | } |
---|
1099 | } |
---|
1100 | } |
---|
1101 | } |
---|
1102 | } |
---|
1103 | } |
---|
1104 | |
---|
1105 | /* |
---|
1106 | public void determineAxisPositions(Graphics gx) { |
---|
1107 | setFonts(gx); |
---|
1108 | int mxs = m_XaxisStart; |
---|
1109 | int mxe = m_XaxisEnd; |
---|
1110 | int mys = m_YaxisStart; |
---|
1111 | int mye = m_YaxisEnd; |
---|
1112 | m_axisChanged = false; |
---|
1113 | |
---|
1114 | int h = this.getHeight(); |
---|
1115 | int w = this.getWidth(); |
---|
1116 | int hf = m_labelMetrics.getAscent(); |
---|
1117 | int mswx=0; |
---|
1118 | int mswy=0; |
---|
1119 | |
---|
1120 | // determineBounds(); |
---|
1121 | int fieldWidthX = (int)((Math.log(m_maxX)/Math.log(10)))+1; |
---|
1122 | int precisionX = 1; |
---|
1123 | if ((Math.abs(m_maxX-m_minX) < 1) && ((m_maxY-m_minX) != 0)) { |
---|
1124 | precisionX = (int)Math.abs(((Math.log(Math.abs(m_maxX-m_minX)) / |
---|
1125 | Math.log(10))))+1; |
---|
1126 | } |
---|
1127 | String maxStringX = Utils.doubleToString(m_maxX, |
---|
1128 | fieldWidthX+1+precisionX |
---|
1129 | ,precisionX); |
---|
1130 | mswx = m_labelMetrics.stringWidth(maxStringX); |
---|
1131 | int fieldWidthY = (int)((Math.log(m_maxY)/Math.log(10)))+1; |
---|
1132 | int precisionY = 1; |
---|
1133 | if (Math.abs((m_maxY-m_minY)) < 1 && ((m_maxY-m_minY) != 0)) { |
---|
1134 | precisionY = (int)Math.abs(((Math.log(Math.abs(m_maxY-m_minY)) / |
---|
1135 | Math.log(10))))+1; |
---|
1136 | } |
---|
1137 | String maxStringY = Utils.doubleToString(m_maxY, |
---|
1138 | fieldWidthY+1+precisionY |
---|
1139 | ,precisionY); |
---|
1140 | String minStringY = Utils.doubleToString(m_minY, |
---|
1141 | fieldWidthY+1+precisionY |
---|
1142 | ,precisionY); |
---|
1143 | |
---|
1144 | if (m_plotInstances.attribute(m_yIndex).isNumeric()) { |
---|
1145 | mswy = (m_labelMetrics.stringWidth(maxStringY) > |
---|
1146 | m_labelMetrics.stringWidth(minStringY)) |
---|
1147 | ? m_labelMetrics.stringWidth(maxStringY) |
---|
1148 | : m_labelMetrics.stringWidth(minStringY); |
---|
1149 | } else { |
---|
1150 | mswy = m_labelMetrics.stringWidth("MM"); |
---|
1151 | } |
---|
1152 | |
---|
1153 | m_YaxisStart = m_axisPad; |
---|
1154 | m_XaxisStart = 0+m_axisPad+m_tickSize+mswy; |
---|
1155 | |
---|
1156 | m_XaxisEnd = w-m_axisPad-(mswx/2); |
---|
1157 | |
---|
1158 | m_YaxisEnd = h-m_axisPad-(2 * hf)-m_tickSize; |
---|
1159 | } */ |
---|
1160 | |
---|
1161 | /** |
---|
1162 | * Draws the axis and a spectrum if the colouring attribute is numeric |
---|
1163 | * @param gx the graphics context |
---|
1164 | */ |
---|
1165 | private void paintAxis(Graphics gx) { |
---|
1166 | setFonts(gx); |
---|
1167 | int mxs = m_XaxisStart; |
---|
1168 | int mxe = m_XaxisEnd; |
---|
1169 | int mys = m_YaxisStart; |
---|
1170 | int mye = m_YaxisEnd; |
---|
1171 | m_plotResize = false; |
---|
1172 | |
---|
1173 | int h = this.getHeight(); |
---|
1174 | int w = this.getWidth(); |
---|
1175 | int hf = m_labelMetrics.getAscent(); |
---|
1176 | int mswx=0; |
---|
1177 | int mswy=0; |
---|
1178 | |
---|
1179 | // determineBounds(); |
---|
1180 | int precisionXmax = 1; |
---|
1181 | int precisionXmin = 1; |
---|
1182 | int precisionXmid = 1; |
---|
1183 | /*if ((Math.abs(m_maxX-m_minX) < 1) && ((m_maxY-m_minX) != 0)) { |
---|
1184 | precisionX = (int)Math.abs(((Math.log(Math.abs(m_maxX-m_minX)) / |
---|
1185 | Math.log(10))))+1; |
---|
1186 | } */ |
---|
1187 | int whole = (int)Math.abs(m_maxX); |
---|
1188 | double decimal = Math.abs(m_maxX) - whole; |
---|
1189 | int nondecimal; |
---|
1190 | nondecimal = (whole > 0) |
---|
1191 | ? (int)(Math.log(whole) / Math.log(10)) |
---|
1192 | : 1; |
---|
1193 | |
---|
1194 | precisionXmax = (decimal > 0) |
---|
1195 | ? (int)Math.abs(((Math.log(Math.abs(m_maxX)) / |
---|
1196 | Math.log(10))))+2 |
---|
1197 | : 1; |
---|
1198 | if (precisionXmax > VisualizeUtils.MAX_PRECISION) { |
---|
1199 | precisionXmax = 1; |
---|
1200 | } |
---|
1201 | |
---|
1202 | String maxStringX = Utils.doubleToString(m_maxX, |
---|
1203 | nondecimal+1+precisionXmax |
---|
1204 | ,precisionXmax); |
---|
1205 | |
---|
1206 | whole = (int)Math.abs(m_minX); |
---|
1207 | decimal = Math.abs(m_minX) - whole; |
---|
1208 | nondecimal = (whole > 0) |
---|
1209 | ? (int)(Math.log(whole) / Math.log(10)) |
---|
1210 | : 1; |
---|
1211 | precisionXmin = (decimal > 0) |
---|
1212 | ? (int)Math.abs(((Math.log(Math.abs(m_minX)) / |
---|
1213 | Math.log(10))))+2 |
---|
1214 | : 1; |
---|
1215 | if (precisionXmin > VisualizeUtils.MAX_PRECISION) { |
---|
1216 | precisionXmin = 1; |
---|
1217 | } |
---|
1218 | |
---|
1219 | String minStringX = Utils.doubleToString(m_minX, |
---|
1220 | nondecimal+1+precisionXmin, |
---|
1221 | precisionXmin); |
---|
1222 | |
---|
1223 | mswx = m_labelMetrics.stringWidth(maxStringX); |
---|
1224 | |
---|
1225 | int precisionYmax = 1; |
---|
1226 | int precisionYmin = 1; |
---|
1227 | int precisionYmid = 1; |
---|
1228 | whole = (int)Math.abs(m_maxY); |
---|
1229 | decimal = Math.abs(m_maxY) - whole; |
---|
1230 | nondecimal = (whole > 0) |
---|
1231 | ? (int)(Math.log(whole) / Math.log(10)) |
---|
1232 | : 1; |
---|
1233 | precisionYmax = (decimal > 0) |
---|
1234 | ? (int)Math.abs(((Math.log(Math.abs(m_maxY)) / |
---|
1235 | Math.log(10))))+2 |
---|
1236 | : 1; |
---|
1237 | if (precisionYmax > VisualizeUtils.MAX_PRECISION) { |
---|
1238 | precisionYmax = 1; |
---|
1239 | } |
---|
1240 | |
---|
1241 | String maxStringY = Utils.doubleToString(m_maxY, |
---|
1242 | nondecimal+1+precisionYmax |
---|
1243 | ,precisionYmax); |
---|
1244 | |
---|
1245 | |
---|
1246 | whole = (int)Math.abs(m_minY); |
---|
1247 | decimal = Math.abs(m_minY) - whole; |
---|
1248 | nondecimal = (whole > 0) |
---|
1249 | ? (int)(Math.log(whole) / Math.log(10)) |
---|
1250 | : 1; |
---|
1251 | precisionYmin = (decimal > 0) |
---|
1252 | ? (int)Math.abs(((Math.log(Math.abs(m_minY)) / |
---|
1253 | Math.log(10))))+2 |
---|
1254 | : 1; |
---|
1255 | if (precisionYmin > VisualizeUtils.MAX_PRECISION) { |
---|
1256 | precisionYmin = 1; |
---|
1257 | } |
---|
1258 | |
---|
1259 | String minStringY = Utils.doubleToString(m_minY, |
---|
1260 | nondecimal+1+precisionYmin |
---|
1261 | ,precisionYmin); |
---|
1262 | |
---|
1263 | if (m_plotInstances.attribute(m_yIndex).isNumeric()) { |
---|
1264 | mswy = (m_labelMetrics.stringWidth(maxStringY) > |
---|
1265 | m_labelMetrics.stringWidth(minStringY)) |
---|
1266 | ? m_labelMetrics.stringWidth(maxStringY) |
---|
1267 | : m_labelMetrics.stringWidth(minStringY); |
---|
1268 | mswy += m_labelMetrics.stringWidth("M"); |
---|
1269 | } else { |
---|
1270 | mswy = m_labelMetrics.stringWidth("MM"); |
---|
1271 | } |
---|
1272 | |
---|
1273 | m_YaxisStart = m_axisPad; |
---|
1274 | m_XaxisStart = 0+m_axisPad+m_tickSize+mswy; |
---|
1275 | |
---|
1276 | m_XaxisEnd = w-m_axisPad-(mswx/2); |
---|
1277 | |
---|
1278 | m_YaxisEnd = h-m_axisPad-(2 * hf)-m_tickSize; |
---|
1279 | |
---|
1280 | // draw axis |
---|
1281 | gx.setColor(m_axisColour); |
---|
1282 | if (m_plotInstances.attribute(m_xIndex).isNumeric()) { |
---|
1283 | if (w > (2 * mswx)) { |
---|
1284 | |
---|
1285 | gx.drawString(maxStringX, |
---|
1286 | m_XaxisEnd-(mswx/2), |
---|
1287 | m_YaxisEnd+hf+m_tickSize); |
---|
1288 | |
---|
1289 | mswx = m_labelMetrics.stringWidth(minStringX); |
---|
1290 | gx.drawString(minStringX, |
---|
1291 | (m_XaxisStart-(mswx/2)), |
---|
1292 | m_YaxisEnd+hf+m_tickSize); |
---|
1293 | |
---|
1294 | // draw the middle value |
---|
1295 | if (w > (3 * mswx) && |
---|
1296 | (m_plotInstances.attribute(m_xIndex).isNumeric())) { |
---|
1297 | double mid = m_minX+((m_maxX-m_minX)/2.0); |
---|
1298 | whole = (int)Math.abs(mid); |
---|
1299 | decimal = Math.abs(mid) - whole; |
---|
1300 | nondecimal = (whole > 0) |
---|
1301 | ? (int)(Math.log(whole) / Math.log(10)) |
---|
1302 | : 1; |
---|
1303 | precisionXmid = (decimal > 0) |
---|
1304 | ? (int)Math.abs(((Math.log(Math.abs(mid)) / |
---|
1305 | Math.log(10))))+2 |
---|
1306 | : 1; |
---|
1307 | if (precisionXmid > VisualizeUtils.MAX_PRECISION) { |
---|
1308 | precisionXmid = 1; |
---|
1309 | } |
---|
1310 | |
---|
1311 | String maxString = Utils.doubleToString(mid, |
---|
1312 | nondecimal+1+precisionXmid, |
---|
1313 | precisionXmid); |
---|
1314 | int sw = m_labelMetrics.stringWidth(maxString); |
---|
1315 | double mx = m_XaxisStart+((double)(m_XaxisEnd-m_XaxisStart)/2.0); |
---|
1316 | gx.drawString(maxString, |
---|
1317 | (int)(mx-(((double)sw)/2.0)), |
---|
1318 | m_YaxisEnd+hf+m_tickSize); |
---|
1319 | gx.drawLine((int)mx,m_YaxisEnd,(int)mx,m_YaxisEnd+m_tickSize); |
---|
1320 | } |
---|
1321 | } |
---|
1322 | } else { |
---|
1323 | int numValues = m_plotInstances.attribute(m_xIndex).numValues(); |
---|
1324 | int div = (numValues % 2 > 0) ? (numValues/2)+1 : (numValues/2); |
---|
1325 | int maxXStringWidth = (m_XaxisEnd - m_XaxisStart) / numValues; |
---|
1326 | |
---|
1327 | for (int i=0;i<numValues;i++) { |
---|
1328 | String val = m_plotInstances.attribute(m_xIndex).value(i); |
---|
1329 | int sw = m_labelMetrics.stringWidth(val); |
---|
1330 | int rm; |
---|
1331 | // truncate string if necessary |
---|
1332 | if (sw > maxXStringWidth) { |
---|
1333 | int incr = (sw / val.length()); |
---|
1334 | rm = (sw - maxXStringWidth) / incr; |
---|
1335 | if (rm == 0) { |
---|
1336 | rm = 1; |
---|
1337 | } |
---|
1338 | val = val.substring(0,val.length()-rm); |
---|
1339 | sw = m_labelMetrics.stringWidth(val); |
---|
1340 | } |
---|
1341 | if (i == 0) { |
---|
1342 | gx.drawString(val,(int)convertToPanelX(i), |
---|
1343 | m_YaxisEnd+hf+m_tickSize); |
---|
1344 | } else if (i == numValues -1) { |
---|
1345 | if ((i % 2) == 0) { |
---|
1346 | gx.drawString(val, |
---|
1347 | m_XaxisEnd-sw, |
---|
1348 | m_YaxisEnd+hf+m_tickSize); |
---|
1349 | } else { |
---|
1350 | gx.drawString(val, |
---|
1351 | m_XaxisEnd-sw, |
---|
1352 | m_YaxisEnd+(2*hf)+m_tickSize); |
---|
1353 | } |
---|
1354 | } else { |
---|
1355 | if ((i % 2) == 0) { |
---|
1356 | gx.drawString(val, |
---|
1357 | (int)convertToPanelX(i)-(sw/2), |
---|
1358 | m_YaxisEnd+hf+m_tickSize); |
---|
1359 | } else { |
---|
1360 | gx.drawString(val, |
---|
1361 | (int)convertToPanelX(i)-(sw/2), |
---|
1362 | m_YaxisEnd+(2*hf)+m_tickSize); |
---|
1363 | } |
---|
1364 | } |
---|
1365 | gx.drawLine((int)convertToPanelX(i), |
---|
1366 | m_YaxisEnd, |
---|
1367 | (int)convertToPanelX(i), |
---|
1368 | m_YaxisEnd+m_tickSize); |
---|
1369 | } |
---|
1370 | |
---|
1371 | } |
---|
1372 | |
---|
1373 | // draw the y axis |
---|
1374 | if (m_plotInstances.attribute(m_yIndex).isNumeric()) { |
---|
1375 | if (h > (2 * hf)) { |
---|
1376 | gx.drawString(maxStringY, |
---|
1377 | m_XaxisStart-mswy-m_tickSize, |
---|
1378 | m_YaxisStart+(hf)); |
---|
1379 | |
---|
1380 | gx.drawString(minStringY, |
---|
1381 | (m_XaxisStart-mswy-m_tickSize), |
---|
1382 | m_YaxisEnd); |
---|
1383 | |
---|
1384 | // draw the middle value |
---|
1385 | if (w > (3 * hf) && |
---|
1386 | (m_plotInstances.attribute(m_yIndex).isNumeric())) { |
---|
1387 | double mid = m_minY+((m_maxY-m_minY)/2.0); |
---|
1388 | whole = (int)Math.abs(mid); |
---|
1389 | decimal = Math.abs(mid) - whole; |
---|
1390 | nondecimal = (whole > 0) |
---|
1391 | ? (int)(Math.log(whole) / Math.log(10)) |
---|
1392 | : 1; |
---|
1393 | precisionYmid = (decimal > 0) |
---|
1394 | ? (int)Math.abs(((Math.log(Math.abs(mid)) / |
---|
1395 | Math.log(10))))+2 |
---|
1396 | : 1; |
---|
1397 | if (precisionYmid > VisualizeUtils.MAX_PRECISION) { |
---|
1398 | precisionYmid = 1; |
---|
1399 | } |
---|
1400 | |
---|
1401 | String maxString = Utils.doubleToString(mid, |
---|
1402 | nondecimal+1+precisionYmid, |
---|
1403 | precisionYmid); |
---|
1404 | int sw = m_labelMetrics.stringWidth(maxString); |
---|
1405 | double mx = m_YaxisStart+((double)(m_YaxisEnd-m_YaxisStart)/2.0); |
---|
1406 | gx.drawString(maxString, |
---|
1407 | m_XaxisStart-sw-m_tickSize-1, |
---|
1408 | (int)(mx+(((double)hf)/2.0))); |
---|
1409 | gx.drawLine(m_XaxisStart-m_tickSize,(int)mx,m_XaxisStart,(int)mx); |
---|
1410 | } |
---|
1411 | } |
---|
1412 | } else { |
---|
1413 | int numValues = m_plotInstances.attribute(m_yIndex).numValues(); |
---|
1414 | int div = ((numValues % 2) == 0) ? (numValues/2) : (numValues/2+1); |
---|
1415 | int maxYStringHeight = (m_YaxisEnd - m_XaxisStart) / div; |
---|
1416 | int sw = m_labelMetrics.stringWidth("M"); |
---|
1417 | for (int i=0;i<numValues;i++) { |
---|
1418 | // can we at least print 2 characters |
---|
1419 | if (maxYStringHeight >= (2*hf)) { |
---|
1420 | String val = m_plotInstances.attribute(m_yIndex).value(i); |
---|
1421 | int numPrint = ((maxYStringHeight/hf) > val.length()) ? |
---|
1422 | val.length() : |
---|
1423 | (maxYStringHeight/hf); |
---|
1424 | |
---|
1425 | for (int j=0;j<numPrint;j++) { |
---|
1426 | String ll = val.substring(j,j+1); |
---|
1427 | if (val.charAt(j) == '_' || val.charAt(j) == '-') { |
---|
1428 | ll = "|"; |
---|
1429 | } |
---|
1430 | if (i == 0) { |
---|
1431 | gx.drawString(ll,m_XaxisStart-sw-m_tickSize-1, |
---|
1432 | (int)convertToPanelY(i) |
---|
1433 | -((numPrint-1)*hf) |
---|
1434 | +(j*hf) |
---|
1435 | +(hf/2)); |
---|
1436 | } else if (i == (numValues-1)) { |
---|
1437 | if ((i % 2) == 0) { |
---|
1438 | gx.drawString(ll,m_XaxisStart-sw-m_tickSize-1, |
---|
1439 | (int)convertToPanelY(i) |
---|
1440 | +(j*hf) |
---|
1441 | +(hf/2)); |
---|
1442 | } else { |
---|
1443 | gx.drawString(ll,m_XaxisStart-(2*sw)-m_tickSize-1, |
---|
1444 | (int)convertToPanelY(i) |
---|
1445 | +(j*hf) |
---|
1446 | +(hf/2)); |
---|
1447 | } |
---|
1448 | } else { |
---|
1449 | if ((i % 2) == 0) { |
---|
1450 | gx.drawString(ll,m_XaxisStart-sw-m_tickSize-1, |
---|
1451 | (int)convertToPanelY(i) |
---|
1452 | -(((numPrint-1)*hf)/2) |
---|
1453 | +(j*hf) |
---|
1454 | +(hf/2)); |
---|
1455 | } else { |
---|
1456 | gx.drawString(ll,m_XaxisStart-(2*sw)-m_tickSize-1, |
---|
1457 | (int)convertToPanelY(i) |
---|
1458 | -(((numPrint-1)*hf)/2) |
---|
1459 | +(j*hf) |
---|
1460 | +(hf/2)); |
---|
1461 | } |
---|
1462 | } |
---|
1463 | } |
---|
1464 | } |
---|
1465 | gx.drawLine(m_XaxisStart-m_tickSize, |
---|
1466 | (int)convertToPanelY(i), |
---|
1467 | m_XaxisStart, |
---|
1468 | (int)convertToPanelY(i)); |
---|
1469 | } |
---|
1470 | } |
---|
1471 | |
---|
1472 | gx.drawLine(m_XaxisStart, |
---|
1473 | m_YaxisStart, |
---|
1474 | m_XaxisStart, |
---|
1475 | m_YaxisEnd); |
---|
1476 | gx.drawLine(m_XaxisStart, |
---|
1477 | m_YaxisEnd, |
---|
1478 | m_XaxisEnd, |
---|
1479 | m_YaxisEnd); |
---|
1480 | |
---|
1481 | if (m_XaxisStart != mxs || m_XaxisEnd != mxe || |
---|
1482 | m_YaxisStart != mys || m_YaxisEnd != mye) { |
---|
1483 | m_plotResize = true; |
---|
1484 | } |
---|
1485 | } |
---|
1486 | |
---|
1487 | /** |
---|
1488 | * Add more colours to the colour map |
---|
1489 | */ |
---|
1490 | private void extendColourMap(int highest) { |
---|
1491 | //System.err.println("Extending colour map"); |
---|
1492 | for (int i = m_colorList.size(); i < highest; i++) { |
---|
1493 | Color pc = m_DefaultColors[i % 10]; |
---|
1494 | int ija = i / 10; |
---|
1495 | ija *= 2; |
---|
1496 | for (int j=0;j<ija;j++) { |
---|
1497 | pc = pc.brighter(); |
---|
1498 | } |
---|
1499 | |
---|
1500 | m_colorList.addElement(pc); |
---|
1501 | } |
---|
1502 | } |
---|
1503 | |
---|
1504 | /** |
---|
1505 | * Renders this component |
---|
1506 | * @param gx the graphics context |
---|
1507 | */ |
---|
1508 | public void paintComponent(Graphics gx) { |
---|
1509 | super.paintComponent(gx); |
---|
1510 | if (m_plotInstances != null |
---|
1511 | && m_plotInstances.numInstances() > 0 |
---|
1512 | && m_plotInstances.numAttributes() > 0) { |
---|
1513 | if (m_plotCompanion != null) { |
---|
1514 | m_plotCompanion.prePlot(gx); |
---|
1515 | } |
---|
1516 | |
---|
1517 | m_JRand = new Random(m_JitterVal); |
---|
1518 | paintAxis(gx); |
---|
1519 | if (m_axisChanged || m_plotResize) { |
---|
1520 | int x_range = m_XaxisEnd - m_XaxisStart; |
---|
1521 | int y_range = m_YaxisEnd - m_YaxisStart; |
---|
1522 | if (x_range < 10) { |
---|
1523 | x_range = 10; |
---|
1524 | } |
---|
1525 | if (y_range < 10) { |
---|
1526 | y_range = 10; |
---|
1527 | } |
---|
1528 | |
---|
1529 | m_drawnPoints = new int[x_range + 1][y_range + 1]; |
---|
1530 | fillLookup(); |
---|
1531 | m_plotResize = false; |
---|
1532 | m_axisChanged = false; |
---|
1533 | } |
---|
1534 | paintData(gx); |
---|
1535 | } |
---|
1536 | } |
---|
1537 | |
---|
1538 | protected static Color checkAgainstBackground(Color c, Color background) { |
---|
1539 | if (background == null) { |
---|
1540 | return c; |
---|
1541 | } |
---|
1542 | |
---|
1543 | if (c.equals(background)) { |
---|
1544 | int red = c.getRed(); |
---|
1545 | int blue = c.getBlue(); |
---|
1546 | int green = c.getGreen(); |
---|
1547 | red += (red < 128) ? (255 - red) / 2 : -(red / 2); |
---|
1548 | blue += (blue < 128) ? (blue - red) / 2 : -(blue / 2); |
---|
1549 | green += (green< 128) ? (255 - green) / 2 : -(green / 2); |
---|
1550 | c = new Color(red, green, blue); |
---|
1551 | } |
---|
1552 | return c; |
---|
1553 | } |
---|
1554 | |
---|
1555 | /** |
---|
1556 | * Main method for testing this class |
---|
1557 | * @param args arguments |
---|
1558 | */ |
---|
1559 | public static void main(String [] args) { |
---|
1560 | try { |
---|
1561 | if (args.length < 1) { |
---|
1562 | System.err.println("Usage : weka.gui.visualize.Plot2D " |
---|
1563 | +"<dataset> [<dataset> <dataset>...]"); |
---|
1564 | System.exit(1); |
---|
1565 | } |
---|
1566 | |
---|
1567 | final javax.swing.JFrame jf = |
---|
1568 | new javax.swing.JFrame("Weka Explorer: Visualize"); |
---|
1569 | jf.setSize(500,400); |
---|
1570 | jf.getContentPane().setLayout(new BorderLayout()); |
---|
1571 | final Plot2D p2 = new Plot2D(); |
---|
1572 | jf.getContentPane().add(p2, BorderLayout.CENTER); |
---|
1573 | jf.addWindowListener(new java.awt.event.WindowAdapter() { |
---|
1574 | public void windowClosing(java.awt.event.WindowEvent e) { |
---|
1575 | jf.dispose(); |
---|
1576 | System.exit(0); |
---|
1577 | } |
---|
1578 | }); |
---|
1579 | |
---|
1580 | p2.addMouseListener(new MouseAdapter() { |
---|
1581 | public void mouseClicked(MouseEvent e) { |
---|
1582 | if ((e.getModifiers() & InputEvent.BUTTON1_MASK) == |
---|
1583 | InputEvent.BUTTON1_MASK) { |
---|
1584 | p2.searchPoints(e.getX(), e.getY(), false); |
---|
1585 | } else { |
---|
1586 | p2.searchPoints(e.getX(), e.getY(), true); |
---|
1587 | } |
---|
1588 | } |
---|
1589 | }); |
---|
1590 | |
---|
1591 | jf.setVisible(true); |
---|
1592 | if (args.length >= 1) { |
---|
1593 | for (int j = 0; j < args.length; j++) { |
---|
1594 | System.err.println("Loading instances from " + args[j]); |
---|
1595 | java.io.Reader r = new java.io.BufferedReader( |
---|
1596 | new java.io.FileReader(args[j])); |
---|
1597 | Instances i = new Instances(r); |
---|
1598 | i.setClassIndex(i.numAttributes()-1); |
---|
1599 | PlotData2D pd1 = new PlotData2D(i); |
---|
1600 | |
---|
1601 | if (j == 0) { |
---|
1602 | pd1.setPlotName("Master plot"); |
---|
1603 | p2.setMasterPlot(pd1); |
---|
1604 | p2.setXindex(2); |
---|
1605 | p2.setYindex(3); |
---|
1606 | p2.setCindex(i.classIndex()); |
---|
1607 | } else { |
---|
1608 | pd1.setPlotName("Plot "+(j+1)); |
---|
1609 | pd1.m_useCustomColour = true; |
---|
1610 | pd1.m_customColour = (j % 2 == 0) ? Color.red : Color.blue; |
---|
1611 | p2.addPlot(pd1); |
---|
1612 | } |
---|
1613 | } |
---|
1614 | } |
---|
1615 | } catch (Exception ex) { |
---|
1616 | ex.printStackTrace(); |
---|
1617 | System.err.println(ex.getMessage()); |
---|
1618 | } |
---|
1619 | } |
---|
1620 | } |
---|