public static void main (String [] args) {
    try {
      if (args.length < 8) {
	System.err.println("Usage : BoundaryPanelDistributed <dataset> "
			   +"<class col> <xAtt> <yAtt> "
			   +"<base> <# loc/pixel> <kernel bandwidth> "
			   +"<display width> "
			   +"<display height> <classifier "
			   +"[classifier options]>");
	System.exit(1);
      }
      
      Vector hostNames = new Vector();
      // try loading hosts file
      try {
	BufferedReader br = new BufferedReader(new FileReader("hosts.vis"));
	String hostName = br.readLine();
	while (hostName != null) {
	  System.out.println("Adding host "+hostName);
	  hostNames.add(hostName);
	  hostName = br.readLine();
	}
	br.close();
      } catch (Exception ex) {
	System.err.println("No hosts.vis file - create this file in "
			   +"the current directory with one host name "
			   +"per line, or use BoundaryPanel instead.");
	System.exit(1);
      }

      final javax.swing.JFrame jf = 
	new javax.swing.JFrame("Weka classification boundary visualizer");
      jf.getContentPane().setLayout(new BorderLayout());

      System.err.println("Loading instances from : "+args[0]);
      java.io.Reader r = new java.io.BufferedReader(
			 new java.io.FileReader(args[0]));
      final Instances i = new Instances(r);
      i.setClassIndex(Integer.parseInt(args[1]));

      //      bv.setClassifier(new Logistic());
      final int xatt = Integer.parseInt(args[2]);
      final int yatt = Integer.parseInt(args[3]);
      int base = Integer.parseInt(args[4]);
      int loc = Integer.parseInt(args[5]);

      int bandWidth = Integer.parseInt(args[6]);
      int panelWidth = Integer.parseInt(args[7]);
      int panelHeight = Integer.parseInt(args[8]);

      final String classifierName = args[9];
      final BoundaryPanelDistributed bv = 
	new BoundaryPanelDistributed(panelWidth,panelHeight);
      bv.addRemoteExperimentListener(new RemoteExperimentListener() {
	  public void remoteExperimentStatus(RemoteExperimentEvent e) {
	    if (e.m_experimentFinished) {
	      String classifierNameNew = 
		classifierName.substring(classifierName.lastIndexOf('.')+1, 
					 classifierName.length());
	      bv.saveImage(classifierNameNew+"_"+i.relationName()
			   +"_X"+xatt+"_Y"+yatt+".jpg");
	    } else {
	      System.err.println(e.m_messageString);
	    }
	  }
	});
      bv.setRemoteHosts(hostNames);

      jf.getContentPane().add(bv, BorderLayout.CENTER);
      jf.setSize(bv.getMinimumSize());
      //      jf.setSize(200,200);
      jf.addWindowListener(new java.awt.event.WindowAdapter() {
	  public void windowClosing(java.awt.event.WindowEvent e) {
	    jf.dispose();
	    System.exit(0);
	  }
	});

      jf.pack();
      jf.setVisible(true);
      //      bv.initialize();
      bv.repaint();
      

      String [] argsR = null;
      if (args.length > 10) {
	argsR = new String [args.length-10];
	for (int j = 10; j < args.length; j++) {
	  argsR[j-10] = args[j];
	}
      }
      Classifier c = Classifier.forName(args[9], argsR);
      KDDataGenerator dataGen = new KDDataGenerator();
      dataGen.setKernelBandwidth(bandWidth);
      bv.setDataGenerator(dataGen);
      bv.setNumSamplesPerRegion(loc);
      bv.setGeneratorSamplesBase(base);
      bv.setClassifier(c);
      bv.setTrainingData(i);
      bv.setXAttribute(xatt);
      bv.setYAttribute(yatt);

      try {
	// try and load a color map if one exists
	FileInputStream fis = new FileInputStream("colors.ser");
	ObjectInputStream ois = new ObjectInputStream(fis);
	FastVector colors = (FastVector)ois.readObject();
	bv.setColors(colors);	
      } catch (Exception ex) {
	System.err.println("No color map file");
      }
      bv.start();
    } catch (Exception ex) {
      ex.printStackTrace();
    }
  }