pixelMidY = getMidY(m_panelHeight-i-1);
  public void start() throws Exception {    if (m_trainingData == null) {      throw new Exception("No training data set (BoundaryPanel)");    }    if (m_classifier == null) {      throw new Exception("No classifier set (BoundaryPanel)");    }    if (m_dataGenerator == null) {      throw new Exception("No data generator set (BoundaryPanel)");    }    if (m_trainingData.attribute(m_xAttribute).isNominal() || 	m_trainingData.attribute(m_yAttribute).isNominal()) {      throw new Exception("Visualization dimensions must be numeric "			  +"(BoundaryPanel)");    }        computeMinMaxAtts();    if (m_plotThread == null) {      m_plotThread = new Thread() {	  public void run() {	    m_stopPlotting = false;	    try {	      /*  if (m_osi == null) {		initialize();		repaint();		} */	      initialize();	      repaint();	      // train the classifier	      //	      System.err.println("Building classifier...");	      m_classifier.buildClassifier(m_trainingData);	      // make a copy of the training data minus the class	      Remove rmF = new Remove();	      rmF.setAttributeIndices(""+(m_classIndex+1));	      rmF.setInvertSelection(false);	      rmF.setInputFormat(m_trainingData);	      rmF.setAttributeIndices(""+(m_classIndex+1));	      Instances trainNoClass = Filter.useFilter(m_trainingData, rmF);	      Instances trainNoClassHeader = new Instances(trainNoClass,0);	      	      // build DataGenerator	      //	      System.err.println("Building data generator...");	      boolean [] attsToWeightOn = 		new boolean[trainNoClass.numAttributes()];	      attsToWeightOn[m_xAttribute] = true;	      attsToWeightOn[m_yAttribute] = true;	      m_dataGenerator.setWeightingDimensions(attsToWeightOn);	      m_dataGenerator.buildGenerator(trainNoClass);	      int samplesPerPixel = 		m_numberOfSamplesFromEachGeneratingModel * 		m_dataGenerator.getNumGeneratingModels();	      	      // generate samples	      Add addF = new Add();	      addF.setInputFormat(trainNoClass);	      addF.setAttributeIndex(m_classIndex);	      double pixelMidX = 0;	      double pixelMidY = 0;	      double [] dist;	      double [] weightingAttsValues = 		new double [attsToWeightOn.length];	      double [] vals = new double[m_trainingData.numAttributes()];	      Instance predInst = new Instance(1.0, vals);	      predInst.setDataset(m_trainingData);	      abortPlot: for (int i = 0; i < m_panelHeight; i++) {		pixelMidY = getMidY(m_panelHeight-i-1);		for (int j = 0; j < m_panelWidth; j++) {		  if (m_stopPlotting) {		    break abortPlot;		  }		  pixelMidX = getMidX(j);		  double sumOfWeights = 0;		  double [] sumOfProbs = 		    new double [m_trainingData.classAttribute().numValues()];		  for (int z = 0; z < samplesPerPixel; z++) {		    weightingAttsValues[m_xAttribute] = pixelMidX;		    weightingAttsValues[m_yAttribute] = pixelMidY;		    m_dataGenerator.setWeightingValues(weightingAttsValues);		    Instance newInst = 		      m_dataGenerator.generateInstanceFast();		    sumOfWeights += newInst.weight();		    int index = 0;		    for (int k = 0; k < predInst.numAttributes(); k++) {		      if (k != m_trainingData.classIndex()) {			vals[k] = newInst.value(index);			index++;		      }		    }		    // classify the instance		    dist = m_classifier.distributionForInstance(predInst);		    for (int k = 0; k < sumOfProbs.length; k++) {		      sumOfProbs[k] += (dist[k] * newInst.weight()); 		    }		  }		  // average		  Utils.normalize(sumOfProbs, sumOfWeights);		  // plot the point		  Graphics osg = m_osi.getGraphics();		  Graphics g = m_plotPanel.getGraphics();		  float [] colVal = new float[3];		  for (int k = 0; k < 3; k++) {		    if (k < sumOfProbs.length) {		      if (m_rgbClassValues[k] != -1) {			colVal[k] = 			  (float)sumOfProbs[m_rgbClassValues[k]];		      }		    }		    if (colVal[k] < 0) {		      colVal[k] = 0;		    }		    if (colVal[k] > 1) {		      colVal[k] = 1;		    }		  }		  osg.setColor(new Color(colVal[0], 					 colVal[1], 					 colVal[2]));		  osg.drawLine(j,i,j,i);		  if (j == 0) {		    g.drawImage(m_osi,0,0,m_plotPanel);		  }		}	      }	    } catch (Exception ex) {	      ex.printStackTrace();	    } finally {	      m_plotThread = null;	      // notify any listeners that we are finished	      Vector l;	      ActionEvent e = new ActionEvent(this, 0, "");	      synchronized(this) {		l = (Vector)m_listeners.clone();	      }	      for (int i = 0; i < l.size(); i++) {		ActionListener al = (ActionListener)l.elementAt(i);		al.actionPerformed(e);	      }	    }	  }	};      m_plotThread.setPriority(Thread.MIN_PRIORITY);      m_plotThread.start();    }  }