source: src/main/java/weka/gui/beans/ClassValuePicker.java @ 28

Last change on this file since 28 was 4, checked in by gnappo, 14 years ago

Import di weka.

File size: 10.1 KB
Line 
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 *    ClassValuePicker.java
19 *    Copyright (C) 2004 University of Waikato, Hamilton, New Zealand
20 *
21 */
22
23package weka.gui.beans;
24
25import weka.core.Instances;
26import weka.filters.Filter;
27import weka.filters.unsupervised.attribute.SwapValues;
28
29import java.awt.BorderLayout;
30import java.beans.EventSetDescriptor;
31import java.io.Serializable;
32import java.util.Vector;
33
34import javax.swing.JPanel;
35
36/**
37 * @author Mark Hall
38 * @version $Revision: 5731 $
39 */
40public class ClassValuePicker
41  extends JPanel
42  implements Visible, DataSourceListener, BeanCommon,
43             EventConstraints, Serializable {
44
45  /** for serialization */
46  private static final long serialVersionUID = -1196143276710882989L;
47
48  /** the class value index considered to be the positive class */
49  private int m_classValueIndex = 0;
50
51  /** format of instances for the current incoming connection (if any) */
52  private Instances m_connectedFormat;
53
54  private Object m_dataProvider;
55
56  private Vector m_dataListeners = new Vector();
57  private Vector m_dataFormatListeners = new Vector();
58
59  protected transient weka.gui.Logger m_logger = null;
60 
61  protected BeanVisual m_visual = 
62    new BeanVisual("ClassValuePicker", 
63                   BeanVisual.ICON_PATH+"ClassValuePicker.gif",
64                   BeanVisual.ICON_PATH+"ClassValuePicker_animated.gif");
65
66  /**
67   * Global info for this bean
68   *
69   * @return a <code>String</code> value
70   */
71  public String globalInfo() {
72    return "Designate which class value is to be considered the \"positive\" "
73      +"class value (useful for ROC style curves).";
74  }
75
76  public ClassValuePicker() {
77    setLayout(new BorderLayout());
78    add(m_visual, BorderLayout.CENTER);   
79  }
80
81  /**
82   * Set a custom (descriptive) name for this bean
83   *
84   * @param name the name to use
85   */
86  public void setCustomName(String name) {
87    m_visual.setText(name);
88  }
89
90  /**
91   * Get the custom (descriptive) name for this bean (if one has been set)
92   *
93   * @return the custom name (or the default name)
94   */
95  public String getCustomName() {
96    return m_visual.getText();
97  }
98
99  /**
100   * Returns the structure of the incoming instances (if any)
101   *
102   * @return an <code>Instances</code> value
103   */
104  public Instances getConnectedFormat() {
105    if (m_connectedFormat ==null) {
106      System.err.println("Is null!!!!!!");
107    }
108    return m_connectedFormat;
109  }
110
111  /**
112   * Set the class value index considered to be the "positive"
113   * class value.
114   *
115   * @param index the class value index to use
116   */
117  public void setClassValueIndex(int index) {
118    m_classValueIndex = index;
119    if (m_connectedFormat != null) {
120      notifyDataFormatListeners();
121    }
122  }
123
124  /**
125   * Gets the class value index considered to be the "positive"
126   * class value.
127   *
128   * @return the class value index
129   */
130  public int getClassValueIndex() {
131    return m_classValueIndex;
132  }
133
134  public void acceptDataSet(DataSetEvent e) {
135    if (e.isStructureOnly()) {
136      if (m_connectedFormat == null ||
137          !m_connectedFormat.equalHeaders(e.getDataSet())) { 
138        m_connectedFormat = new Instances(e.getDataSet(), 0);
139        // tell any listening customizers (or other
140        notifyDataFormatListeners();
141      }
142    }
143    Instances dataSet = e.getDataSet();
144    Instances newDataSet = assignClassValue(dataSet);
145    e = new DataSetEvent(this, newDataSet);
146    notifyDataListeners(e);
147  }
148
149  private Instances assignClassValue(Instances dataSet) {
150    if (dataSet.classIndex() < 0) {
151      if (m_logger != null) {
152        m_logger.
153          logMessage("[ClassValuePicker] " 
154              + statusMessagePrefix() 
155              + " No class attribute defined in data set.");
156        m_logger.statusMessage(statusMessagePrefix()
157            + "WARNING: No class attribute defined in data set.");
158      }
159      return dataSet;
160    }
161   
162    if (dataSet.classAttribute().isNumeric()) {
163      if (m_logger != null) {
164        m_logger.
165          logMessage("[ClassValuePicker] "
166              + statusMessagePrefix()
167              + " Class attribute must be nominal (ClassValuePicker)");
168        m_logger.statusMessage(statusMessagePrefix()
169            + "WARNING: Class attribute must be nominal.");
170      }
171      return dataSet;
172    } else {
173      if (m_logger != null) {
174        m_logger.statusMessage(statusMessagePrefix() + "remove");
175      }
176    }
177
178    if (m_classValueIndex != 0) { // nothing to do if == 0
179      // swap selected index with index 0
180      try {
181        SwapValues sv = new SwapValues();
182        sv.setAttributeIndex(""+(dataSet.classIndex()+1));
183        sv.setFirstValueIndex("first");
184        sv.setSecondValueIndex(""+(m_classValueIndex+1));
185        sv.setInputFormat(dataSet);
186        Instances newDataSet = Filter.useFilter(dataSet, sv);
187        newDataSet.setRelationName(dataSet.relationName());
188        return newDataSet;
189      } catch (Exception ex) {
190        if (m_logger != null) {
191          m_logger.
192            logMessage("[ClassValuePicker] "
193                +statusMessagePrefix()
194                + " Unable to swap class attibute values.");
195          m_logger.statusMessage(statusMessagePrefix()
196              + "ERROR (See log for details)");
197        }
198      }
199    }
200    return dataSet;
201  }
202
203  protected void notifyDataListeners(DataSetEvent tse) {
204    Vector l;
205    synchronized (this) {
206      l = (Vector)m_dataListeners.clone();
207    }
208    if (l.size() > 0) {
209      for(int i = 0; i < l.size(); i++) {
210        System.err.println("Notifying data listeners "
211                           +"(ClassValuePicker)");
212        ((DataSourceListener)l.elementAt(i)).acceptDataSet(tse);
213      }
214    }
215  }
216
217  protected void notifyDataFormatListeners() {
218    Vector l;
219    synchronized (this) {
220      l = (Vector)m_dataFormatListeners.clone();
221    }
222    if (l.size() > 0) {
223      DataSetEvent dse = new DataSetEvent(this, m_connectedFormat);
224      for(int i = 0; i < l.size(); i++) {
225        ((DataFormatListener)l.elementAt(i)).newDataFormat(dse);
226      }
227    }
228  }
229
230  public synchronized void addDataSourceListener(DataSourceListener tsl) {
231    m_dataListeners.addElement(tsl);
232  }
233
234  public synchronized void removeDataSourceListener(DataSourceListener tsl) {
235    m_dataListeners.removeElement(tsl);
236  }
237
238  public synchronized void addDataFormatListener(DataFormatListener dfl) {
239    m_dataFormatListeners.addElement(dfl);
240  }
241
242  public synchronized void removeDataFormatListener(DataFormatListener dfl) {
243    m_dataFormatListeners.removeElement(dfl);
244  }
245
246  public void setVisual(BeanVisual newVisual) {
247    m_visual = newVisual;
248  }
249
250  public BeanVisual getVisual() {
251    return m_visual;
252  }
253
254  public void useDefaultVisual() {
255    m_visual.loadIcons(BeanVisual.ICON_PATH+"ClassValuePicker.gif",
256                       BeanVisual.ICON_PATH+"ClassValuePicker_animated.gif");
257  }
258
259  /**
260   * Returns true if, at this time,
261   * the object will accept a connection according to the supplied
262   * event name
263   *
264   * @param eventName the event
265   * @return true if the object will accept a connection
266   */
267  public boolean connectionAllowed(String eventName) {
268    if (eventName.compareTo("dataSet") == 0 && 
269        (m_dataProvider != null)) { 
270      return false;
271    }
272
273    return true;
274  }
275
276  /**
277   * Returns true if, at this time,
278   * the object will accept a connection according to the supplied
279   * EventSetDescriptor
280   *
281   * @param esd the EventSetDescriptor
282   * @return true if the object will accept a connection
283   */
284  public boolean connectionAllowed(EventSetDescriptor esd) {
285    return connectionAllowed(esd.getName());
286  }
287
288  /**
289   * Notify this object that it has been registered as a listener with
290   * a source with respect to the supplied event name
291   *
292   * @param eventName the event
293   * @param source the source with which this object has been registered as
294   * a listener
295   */
296  public synchronized void connectionNotification(String eventName,
297                                                  Object source) {
298    if (connectionAllowed(eventName)) {
299      if (eventName.compareTo("dataSet") == 0) {
300        m_dataProvider = source;
301      }
302    }
303  }
304
305  /**
306   * Notify this object that it has been deregistered as a listener with
307   * a source with respect to the supplied event name
308   *
309   * @param eventName the event
310   * @param source the source with which this object has been registered as
311   * a listener
312   */
313  public synchronized void disconnectionNotification(String eventName,
314                                                     Object source) {
315
316    if (eventName.compareTo("dataSet") == 0) {
317      if (m_dataProvider == source) {
318        m_dataProvider = null;
319      }
320    }
321  }
322
323  public void setLog(weka.gui.Logger logger) {
324    m_logger = logger;
325  }
326
327  public void stop() {
328    // nothing to do
329  }
330 
331  /**
332   * Returns true if. at this time, the bean is busy with some
333   * (i.e. perhaps a worker thread is performing some calculation).
334   *
335   * @return true if the bean is busy.
336   */
337  public boolean isBusy() {
338    return false;
339  }
340
341  /**
342   * Returns true, if at the current time, the named event could
343   * be generated. Assumes that the supplied event name is
344   * an event that could be generated by this bean
345   *
346   * @param eventName the name of the event in question
347   * @return true if the named event could be generated at this point in
348   * time
349   */
350  public boolean eventGeneratable(String eventName) {
351    if (eventName.compareTo("dataSet") != 0) {
352      return false;
353    }
354
355    if (eventName.compareTo("dataSet") == 0) { 
356      if (m_dataProvider == null) {
357        m_connectedFormat = null;
358        notifyDataFormatListeners();
359        return false;
360      } else {
361        if (m_dataProvider instanceof EventConstraints) {
362          if (!((EventConstraints)m_dataProvider).
363              eventGeneratable("dataSet")) {
364            m_connectedFormat = null;
365            notifyDataFormatListeners();
366            return false;
367          }
368        }
369      }
370    }
371    return true;
372  }
373 
374  private String statusMessagePrefix() {
375    return getCustomName() + "$" + hashCode() + "|";
376  }
377}
Note: See TracBrowser for help on using the repository browser.