1 package edu.psu.geovista.symbolization;
2
3 /***
4 * Title: VisualClassifierMultiVariables
5 * Description: Viasual classifier for multi-variables, such as K-means.
6 * Copyright: Copyright (c) 2001
7 * Company: GeoVISTA
8 * @author Xiping Dai
9 * @version 1.0
10 */
11
12 import javax.swing.*;
13 import javax.swing.event.*;
14 import java.awt.*;
15 import java.awt.image.*;
16 import java.awt.geom.*;
17 import java.awt.*;
18 import java.awt.event.*;
19 import java.util.*;
20
21 import edu.psu.geovista.ui.panel.*;
22 //import edu.psu.geovista.app.spacefill.*;
23 import edu.psu.geovista.classification.*;
24 import edu.psu.geovista.symbolization.*;
25 import edu.psu.geovista.ui.event.*;
26
27 public class VisualClassifierMultiVariables extends JPanel implements ActionListener, ComponentListener, DataSetListener {
28
29 private static final int DEFAULT_CLASS_NUMBER = 5;
30 private ColorRampPicker colorPanel;
31 //XXX in future, we want to support much beyond colors.
32 private Color[] colors;
33 private Shape[] symbols;
34
35 public boolean[] anchored;
36
37 private Object[] dataObject;
38 private int[] classificationIndex;
39 private Color[] returnColors;
40
41 private int nClasses;
42 private int nSymbols;
43 private boolean update;
44 private boolean interpolate;
45 private transient boolean setupFinished;
46
47 private transient JCheckBox updateBox;
48 private transient JCheckBox interpolateBox;
49 private JPanel classPickerPanel;
50 private JPanel colorPickerPanel;
51 private JComboBox classifierBox;
52 private JTextField classNumField;
53 private JButton applyButton;
54 private JButton detailButton;
55
56 private String classifierName;
57 private ClassifierKMeans classifierKMeans;
58 private ClassifierMaximumLikelihood classifierML;
59 private int[] iniObsIdx = null;
60 private int[] selectedAttIdx;
61 private boolean visualDisplay = false;
62 private JDialog kmParameterSetupDialog;
63 private JDialog mlParameterSetupDialog;
64 private ClassifierKMParameters kMParameterSetup;
65
66 private ClassifierMLParameters mlParameterSetup;
67
68 public static final String COMMAND_COLORS_CHANGED = "colors";
69 public static final String COMMAND_BEAN_REGISTERED = "hi!";
70 private ColorSymbolizerLinear colorerLinear;
71 // private int currOrientation = this.X_AXIS;
72 // public static final int X_AXIS = 0;
73 // public static final int Y_AXIS = 1;
74
75 public VisualClassifierMultiVariables() {
76 super();
77 this.addComponentListener(this);
78 this.setupFinished = false;
79 this.nClasses = this.DEFAULT_CLASS_NUMBER;
80 this.update = true;
81 this.interpolate = true;
82 //this.colorerLinear = new ColorSymbolizerLinear();
83 this.classifierKMeans = new ClassifierKMeans();
84 this.classifierML = new ClassifierMaximumLikelihood();
85
86 //this.setLayout(new BorderLayout());
87 this.makeClassifierPanel();
88 this.makeColorPickerPanel();
89 this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
90 this.add(classPickerPanel);
91 //this.add(classificationPanel);
92 this.add(colorPickerPanel);
93 this.setupFinished = true;
94 // this.makeColors();
95 this.setPreferredSize(new Dimension(300,50));
96
97 this.revalidate();
98
99 }
100
101 public void setDataObject (Object[] dataObject){
102 this.dataObject = dataObject;
103 }
104
105 public Color[] getClassificationColors(){
106 return this.returnColors;
107 }
108
109 public int[] getClassification(){
110 return this.classificationIndex;
111 }
112
113 private void makeColorPickerPanel() {
114 //Color picker and apply button of this classificaiton
115 this.colorPickerPanel = new JPanel();
116 this.colorPickerPanel.setLayout(new BoxLayout(colorPickerPanel, BoxLayout.X_AXIS));
117 colorPanel = new ColorRampPicker();
118 this.colorPanel.setNSwatches(this.nClasses);
119 this.add(colorPanel);
120 colorPanel.addActionListener(this);
121
122 this.applyButton = new JButton ("Apply");
123 this.applyButton.addActionListener(new java.awt.event.ActionListener() {
124 public void actionPerformed(ActionEvent e) {
125 applyButton_actionPerformed(e);
126 }
127 });
128 classPickerPanel.add(applyButton);
129 }
130
131 private void makeClassifierPanel(){
132 this.classPickerPanel = new JPanel();
133 this.classPickerPanel.setLayout(new BoxLayout(classPickerPanel, BoxLayout.X_AXIS));
134 this.classifierBox = new JComboBox ();
135 this.classifierBox.addItem("Classifiers:");
136 this.classifierBox.addItem("K Means Clustering");
137 this.classifierBox.addItem("MaximumLikelihood Classifier");
138 this.classifierName = "Classifiers:";
139 this.classifierBox.setMinimumSize(new Dimension(80,20));
140 this.classifierBox.setMaximumSize(new Dimension(120,20));
141 classifierBox.addActionListener(new ActionListener() {
142 public void actionPerformed(ActionEvent e) {
143 JComboBox cb = (JComboBox)e.getSource();
144 if (cb.getItemCount() > 0) {
145 classifierName = (String)cb.getSelectedItem();
146 }//end if count > 0
147 }//end inner class
148 });//end add listener
149 //JLabel twoSpacesclassifCombo = new JLabel(" ");
150 //this.add(twoSpacesclassifCombo);
151 //this.add(classifLabel);
152 classPickerPanel.add(classifierBox);
153
154 this.classNumField = new JTextField(2);
155 this.classNumField.setMinimumSize(new Dimension(15,10));
156 this.classNumField.setMaximumSize(new Dimension(20,20));
157 this.classNumField.setText(Integer.toString(this.nClasses));
158 this.classNumField.addActionListener(new ActionListener(){
159 public void actionPerformed(ActionEvent e) {
160 JTextField classField = (JTextField)e.getSource();
161 if (Integer.parseInt(classField.getText()) != nClasses){
162 nClasses = Integer.parseInt(classField.getText());
163 makeColors();
164 }
165 }//end inner class
166 });
167 classPickerPanel.add(classNumField);
168
169 this.detailButton = new JButton ("Detail");
170 this.detailButton.addActionListener(new java.awt.event.ActionListener() {
171 public void actionPerformed(ActionEvent e) {
172 detailButton_actionPerformed(e);
173 }
174 });
175 classPickerPanel.add(detailButton);
176 }
177
178 private void makeColors(){
179 this.colorPanel.setNSwatches(this.nClasses);
180 Color[] pickerColors = this.colorPanel.getColors();
181 boolean[] pickerAnchors = this.colorPanel.getAnchored();
182 //now we interpolate...linearly
183 int nPicks = pickerColors.length;
184 double picksPerColor = (double)nPicks/(double)this.nClasses;
185 if (this.colors == null){
186 this.colors = new Color[nClasses];
187 } else if (this.colors.length != nClasses) {
188 this.colors = new Color[nClasses];
189 }
190
191 for (int i = 0; i < nClasses; i++) {
192 double whichColor = (double)i * picksPerColor;
193 int index = (int)Math.floor(whichColor);
194 //System.out.println("i = " + i + "index = " + index);
195 this.colors[i] = pickerColors[index];
196 }
197 if (this.interpolate) {
198 //for each lock in the picker, find the class that is closest.
199 double colorsPerPick = (double)(this.nClasses-1)/(double)(nPicks-1);
200 //int[] newAnchors = new int[pickerAnchors.length];
201 Vector newAnchors = new Vector();
202 for (int i = 0; i < pickerAnchors.length; i++) {
203 double whichClass = (double)i * colorsPerPick;
204 int aClass = (int)Math.round(whichClass);
205 if (pickerAnchors[i]){
206 Integer Ind = new Integer(aClass);
207 newAnchors.add(Ind);
208 }
209 }
210
211 boolean[] colorAnchors = new boolean[nClasses];
212 if (newAnchors.size() > 2) {
213 for (Enumeration e = newAnchors.elements() ; e.hasMoreElements() ;) {
214 Integer ind = (Integer)e.nextElement();
215 colorAnchors[ind.intValue()] = true;
216 }
217
218 colorAnchors[0] = true;
219 colorAnchors[colorAnchors.length -1] = true;
220 } else if (newAnchors.size() == 2) {
221 colorAnchors[0] = true;
222 colorAnchors[colorAnchors.length -1] = true;
223 } else if (newAnchors.size() == 1) {
224 colorAnchors[0] = true;
225 }
226 //now find those durn colors!
227 this.colorPanel.getRamp().rampColors(this.colors,colorAnchors);
228 }//end if interpolate
229
230 if (classificationIndex != null){
231 this.returnColors = new Color[classificationIndex.length];
232 for (int i = 0; i < classificationIndex.length; i++) {
233
234 if (classificationIndex[i] == Classifier.NULL_CLASS) {
235 returnColors[i] = ColorSymbolizer.DEFAULT_NULL_COLOR;
236 } else {
237 returnColors[i] = colors[classificationIndex[i]];
238 }
239 }
240 fireColorArrayChanged(getClassificationColors());
241 }
242 }
243
244 /*** Listens to the check boxen. */
245 class CheckBoxListener implements ItemListener {
246 public void itemStateChanged(ItemEvent e) {
247 if (e.getSource().equals(VisualClassifierMultiVariables.this.updateBox)){
248 if (e.getStateChange() == ItemEvent.SELECTED && VisualClassifierMultiVariables.this.setupFinished){
249 VisualClassifierMultiVariables.this.update = true;
250 VisualClassifierMultiVariables.this.makeColors();
251 VisualClassifierMultiVariables.this.fireActionPerformed(VisualClassifierMultiVariables.COMMAND_COLORS_CHANGED);
252 //VisualClassifierMultiVariables.this.fireColorClassifierPerformed();
253
254 } else if (e.getStateChange() == ItemEvent.DESELECTED){
255
256 VisualClassifierMultiVariables.this.update = false;
257 }
258 } else if (e.getSource().equals(VisualClassifierMultiVariables.this.interpolateBox)){
259 if (e.getStateChange() == ItemEvent.SELECTED && VisualClassifierMultiVariables.this.setupFinished){
260 VisualClassifierMultiVariables.this.interpolate = true;
261 VisualClassifierMultiVariables.this.makeColors();
262 VisualClassifierMultiVariables.this.fireActionPerformed(VisualClassifierMultiVariables.COMMAND_COLORS_CHANGED);
263 //VisualClassifierMultiVariables.this.fireColorClassifierPerformed();
264
265 } else if (e.getStateChange() == ItemEvent.DESELECTED){
266 VisualClassifierMultiVariables.this.interpolate = false;
267 VisualClassifierMultiVariables.this.makeColors();
268 VisualClassifierMultiVariables.this.fireActionPerformed(VisualClassifierMultiVariables.COMMAND_COLORS_CHANGED);
269 //VisualClassifierMultiVariables.this.fireColorClassifierPerformed();
270 }
271 }
272 }
273 }
274
275 JFrame dummyFrame;
276
277 private void detailButton_actionPerformed (ActionEvent e) {
278 //Bring up a detailed parameter setting GUI.
279 this.nClasses = Integer.parseInt(this.classNumField.getText());
280 if (dataObject == null) return;
281 if (this.classifierName.equals("Classifiers:")){
282 return;
283 }
284 if (this.classifierName.equals("K Means Clustering")&&(dataObject != null)){
285 System.out.println("Inside K means Clustering...");
286 kMParameterSetup = new ClassifierKMParameters((String[])this.dataObject[0], nClasses);
287 //kMParameterSetup.setAttributeNames((String[])this.dataObject[0]);
288 //kMParameterSetup.setClassNum(nClasses);
289 if (kmParameterSetupDialog == null){
290 if(dummyFrame == null){
291 dummyFrame = new JFrame();
292 }
293 kmParameterSetupDialog = new JDialog(dummyFrame, "Parameter Setup", true);
294 kmParameterSetupDialog.setLocation(300, 300);
295 kmParameterSetupDialog.setSize(300, 300);
296 kmParameterSetupDialog.getContentPane().setLayout(new BorderLayout());
297 kmParameterSetupDialog.getContentPane().add(kMParameterSetup, BorderLayout.CENTER);
298 kMParameterSetup.addActionListener(new ActionListener() {
299
300 /***
301 * Get event from parameter setup GUI.
302 * @param e
303 */
304 public void actionPerformed (ActionEvent e) {
305 try {
306 km_para_actionPerformed(e);
307 } catch (Exception exception) {}
308 }
309 });
310 }
311 kmParameterSetupDialog.show();
312 }
313 if (this.classifierName.equals("MaximumLikelihood Classifier")&&(dataObject != null)){
314 System.out.println("Inside MKL ...");
315 this.mlParameterSetup = new ClassifierMLParameters((String[])this.dataObject[0], nClasses);
316 if (mlParameterSetupDialog == null){
317 if(dummyFrame == null){
318 dummyFrame = new JFrame();
319 }
320 mlParameterSetupDialog = new JDialog(dummyFrame, "Parameter Setup", true);
321 mlParameterSetupDialog.setLocation(300, 300);
322 mlParameterSetupDialog.setSize(300, 300);
323 mlParameterSetupDialog.getContentPane().setLayout(new BorderLayout());
324 mlParameterSetupDialog.getContentPane().add(mlParameterSetup, BorderLayout.CENTER);
325 mlParameterSetup.addActionListener(new ActionListener() {
326
327 /***
328 * Get event from parameter setup GUI.
329 * @param e
330 */
331 public void actionPerformed (ActionEvent e) {
332 try {
333 ml_para_actionPerformed(e);
334 } catch (Exception exception) {}
335 }
336 });
337 }
338 mlParameterSetupDialog.show();
339
340 }
341 }
342
343 private void applyButton_actionPerformed (ActionEvent e) {
344 //Actually apply the parameters and do the classification, pass to other components.
345 this.nClasses = Integer.parseInt(this.classNumField.getText());
346 this.makeColors();
347 if (dataObject != null) System.out.println("data object is not null...");
348 if (this.classifierName.equals("Classifiers:")){
349 this.classifierBox.setSelectedIndex(1);
350 this.classifierKMeans.setClusterNumber(this.nClasses);
351 this.classifierKMeans.setDataObject(this.dataObject);
352 this.classificationIndex = this.classifierKMeans.getKMeansClusters();
353 }
354 if (this.classifierName.equals("K Means Clustering")&&(dataObject != null)){
355 this.classifierKMeans.setClusterNumber(this.nClasses);
356 this.classifierKMeans.setSelectedAttIdx(selectedAttIdx);
357 this.classifierKMeans.setDataObject(this.dataObject);
358 if (iniObsIdx != null){
359 this.classifierKMeans.setIniObsIdx(iniObsIdx);
360 }
361 this.classificationIndex = this.classifierKMeans.getKMeansClusters();
362 }
363 if (this.classifierName.equals("MaximumLikelihood Classifier")&&(dataObject != null)){
364 this.classifierML.setTrainingData(this.dataObject);
365 this.classifierML.setDataObject(this.dataObject);
366 this.classifierML.setVisualDisplay(this.visualDisplay);
367 this.classifierML.setClassNumber(this.nClasses);
368
369 this.classificationIndex = this.classifierML.getClassificaiton();
370 }
371
372 this.returnColors = new Color[classificationIndex.length];
373 for (int i = 0; i < classificationIndex.length; i++) {
374
375 if (classificationIndex[i] == Classifier.NULL_CLASS) {
376 returnColors[i] = ColorSymbolizer.DEFAULT_NULL_COLOR;
377 } else {
378 returnColors[i] = colors[classificationIndex[i]];
379 }
380 }
381 //fireSelectionChanged(getClassificationColors());
382 this.fireColorArrayChanged(getClassificationColors());
383 }
384
385 private void km_para_actionPerformed(ActionEvent e){
386 ClassifierKMParameters kmParameters = (ClassifierKMParameters)e.getSource();
387 this.iniObsIdx = kmParameters.getIniObsIdx();
388 this.selectedAttIdx = kmParameters.getSelectedAttIdx();
389 kmParameterSetupDialog.hide();
390 }
391
392 private void ml_para_actionPerformed(ActionEvent e){
393 ClassifierMLParameters mlParameters = (ClassifierMLParameters)e.getSource();
394 mlParameters.getIsUnBiasCov();
395 mlParameters.getDistributionType();
396 this.visualDisplay = mlParameters.getVisualDisplay();
397 this.selectedAttIdx = mlParameters.getSelectedAttIdx();
398 mlParameterSetupDialog.hide();
399 }
400
401 //start component event handling
402 //note: this class only listens to itself
403 public void componentHidden(ComponentEvent e) {}
404
405 public void componentMoved(ComponentEvent e) {}
406
407 public void componentShown(ComponentEvent e) {}
408
409 public void componentResized(ComponentEvent e) {
410 double pickPrefWidth = this.classPickerPanel.getPreferredSize().getWidth();
411 int prefWidth = (int)(pickPrefWidth * 1.5);
412 if (this.getWidth() >= prefWidth) {
413 //this.changeOrientation(this.X_AXIS);
414 } else {
415 //this.changeOrientation(this.Y_AXIS);
416 }
417 }
418
419 public void actionPerformed(ActionEvent e) {
420 String command = e.getActionCommand();
421 if (command == ColorRampPicker.COMMAND_SWATCH_COLOR_CHANGED){
422 this.makeColors();
423 this.fireActionPerformed(this.COMMAND_COLORS_CHANGED);
424 //this.fireColorClassifierPerformed();
425 } /*else if (command == this.COMMAND_CLASSES_CHANGED) {
426 this.colorPickerPanel.setNSwatches(nClasses);
427 this.nClasses = nClasses;
428 this.makeColors();
429 this.fireActionPerformed(this.COMMAND_COLORS_CHANGED);
430 //this.fireColorClassifierPerformed();
431 }*/
432 //need to pass this along, if we are a FoldupPanel
433 //super.actionPerformed(e);
434 }
435
436 /***
437 * implements ActionListener
438 */
439 public void addActionListener (ActionListener l) {
440 listenerList.add(ActionListener.class, l);
441 this.fireActionPerformed(this.COMMAND_BEAN_REGISTERED);
442 }
443
444 /***
445 * removes an ActionListener from the component
446 */
447 public void removeActionListener (ActionListener l) {
448 listenerList.remove(ActionListener.class, l);
449 }
450 /***
451 * Notify all listeners that have registered interest for
452 * notification on this event type. The event instance
453 * is lazily created using the parameters passed into
454 * the fire method.
455 * @see EventListenerList
456 */
457 private void fireActionPerformed (String command) {
458 if (update) {
459 // Guaranteed to return a non-null array
460 Object[] listeners = listenerList.getListenerList();
461 ActionEvent e = null;
462 // Process the listeners last to first, notifying
463 // those that are interested in this event
464 for (int i = listeners.length - 2; i >= 0; i -= 2) {
465 if (listeners[i] == ActionListener.class) {
466 // Lazily create the event:
467 if (e == null) {
468 e = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, command);
469 }
470 ((ActionListener)listeners[i + 1]).actionPerformed(e);
471 }
472 }//next i
473 }//end if
474 }
475
476 //Work with coordinator.
477 public void dataSetChanged(DataSetEvent e){
478 this.setDataObject(e.getDataSet());
479 }
480
481 public void selectionChanged(SelectionEvent e){
482 }
483
484 /***
485 * adds an SelectionListener
486 */
487 public void addSelectionListener (SelectionListener l) {
488 listenerList.add(SelectionListener.class, l);
489 }
490 /***
491 * removes an SelectionListener from the component
492 */
493 public void removeSelectionListener (SelectionListener l) {
494 listenerList.remove(SelectionListener.class, l);
495
496 }
497
498 private void fireSelectionChanged (Color[] newSelection) {
499
500 // Guaranteed to return a non-null array
501 Object[] listeners = listenerList.getListenerList();
502 SelectionEvent e = null;
503 // Process the listeners last to first, notifying
504 // those that are interested in this event
505 for (int i = listeners.length - 2; i >= 0; i -= 2) {
506 if (listeners[i] == SelectionListener.class) {
507 // Lazily create the event:
508 if (e == null) {
509 e = new SelectionEvent(this, newSelection);
510 }
511 ((SelectionListener)listeners[i + 1]).selectionChanged(e);
512 }
513 }//next i
514
515 }
516 /***
517 * adds an SelectionListener
518 */
519 public void addColorArrayListener (ColorArrayListener l) {
520 listenerList.add(ColorArrayListener.class, l);
521 }
522 /***
523 * removes an SelectionListener from the component
524 */
525 public void removeColorArrayListener (ColorArrayListener l) {
526 listenerList.remove(ColorArrayListener.class, l);
527
528 }
529
530 private void fireColorArrayChanged (Color[] newColorArray) {
531
532 // Guaranteed to return a non-null array
533 Object[] listeners = listenerList.getListenerList();
534 ColorArrayEvent e = null;
535 // Process the listeners last to first, notifying
536 // those that are interested in this event
537 for (int i = listeners.length - 2; i >= 0; i -= 2) {
538 if (listeners[i] == ColorArrayListener.class) {
539 // Lazily create the event:
540 if (e == null) {
541 e = new ColorArrayEvent(this, newColorArray);
542 }
543 ((ColorArrayListener)listeners[i + 1]).colorArrayChanged(e);
544 }
545 }//next i
546
547 }
548 }
This page was automatically generated by Maven