/*
 * -------------------------------------------------------------------------
 *      $Id: StarCluster.java,v 1.5 2006/01/30 18:54:16 estewart Exp $
 * -------------------------------------------------------------------------
 *      Copyright (c) 1999 Visual Numerics Inc. All Rights Reserved.
 *
 *      This software is confidential information which is proprietary to
 *      and a trade secret of Visual Numerics, Inc.  Use, duplication or
 *      disclosure is subject to the terms of an appropriate license
 *      agreement.
 *
 *      VISUAL NUMERICS MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE
 *      SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING
 *      BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY,
 *      FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. VISUAL
 *      NUMERICS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
 *      AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR
 *      ITS DERIVATIVES.
 *--------------------------------------------------------------------------
 */

/*
 * StarCluster.java
 *
 * Created on August 21, 2003, 2:53 PM
 */

package com.imsl.demo.cluster;

import com.imsl.chart.*;
import com.imsl.math.*;
import com.imsl.stat.ClusterKMeans;
import com.imsl.stat.Summary;
import com.imsl.demo.gallery.Describe;

public class StarCluster extends javax.swing.JPanel {

    private final double x[] = {-0.00225554,0.192812,0.549314,0.643484,1.10088,1.16815,1.19169,1.43384,1.45402,1.50447,1.50447,1.50447,1.56165,1.52465,1.47757,1.80716,1.84752,1.74662,1.74326,1.74662,2.39909,1.51792,1.86097,1.66591,1.61209,1.49438,1.51456,1.44393,1.4742,1.49438,1.50447,1.36994,1.19505,0.962991,1.15806,1.16815,1.37667,1.43721,1.39012,1.46411,1.51792,1.57174,1.5381,1.59864,1.58519,1.58519,1.60537,1.62218,1.62555,1.64909,1.23878,1.20514,1.14124,1.12779,1.06052,0.959628,0.952901,0.825099,0.626668,0.710749,0.808283,0.791466,0.804919,0.845278,0.892363,0.946175,1.01344,1.0807,1.14797,1.16478,1.14461,1.02017,1.00335,1.0168,0.986534,0.979807,0.902453,0.932722,0.919269,0.89909,0.912543,0.744381,0.613215,0.646848,0.57622,0.455144,0.428238,0.360973,0.310525,0.169269,0.206265,0.249987,0.286982,0.374426,0.377789,0.401332,0.475323,0.502229,0.663664,0.67039,0.0885516,-0.0863363,-0.0358878,-0.190596,0.159179,0.206265,0.266803,0.266803,0.293709,0.186085,0.0515561,0.03474,-0.0695201,-0.0493407,-0.150238,-0.274677,0.139,0.159179,0.14909,0.122184,0.142363,0.152453,0.155816,0.132274,0.0851884,0.065009,0.00447091,-0.123332,-0.237682,-0.241045,-0.207412,-0.18387,-0.177143,-0.0863363,-0.0358878,0.065009,0.125547,0.0717355,0.0414664,0.0582826,0.03474,0.0246503,0.0111974,-0.0123452,-0.008982,-0.00561877,-0.0257981,-0.0493407,-0.0325246,0.00783414,-0.008982,-0.00225554,-0.0728833,-0.0930627,-0.106516,-0.0930627,-0.109879,-0.146874,-0.133421,-0.123332,-0.126695,-0.140148,0.488776,0.482049,0.468596,0.482049,0.569493,0.56613,0.704022,0.704022,0.744381,0.656937,0.673753,0.704022,0.717475,0.700659,0.693933,0.710749,0.730928,0.754471,0.754471,1.13788,1.06389,1.09416,1.07734,1.0807,1.05716,1.04707,1.0168,0.999987,0.895727,0.858731,0.848641,0.781377,0.798193,0.825099,0.804919,0.811646,0.875547,0.912543,0.862094,0.882274,0.889,1.30604,1.3094,1.32286,1.35985,1.38003,1.39685,1.41703,1.43048,1.47084,1.43048,1.4103,1.43048,1.46748,1.50447,1.47757,1.66254,1.72981,1.71972,1.69954,1.69954,1.67936,1.68609,1.65245,1.66591,1.64573,1.62891,1.61546,1.59528,1.57174,1.55492,1.5381,1.57174,1.58855,1.59528,1.60873,1.58855,1.63227,1.61209,1.61882,1.59528,1.56501,1.56837,1.5381,1.52801,1.50111,1.50783,1.52801,1.48429,1.46075,1.45066,1.45402,1.46411,1.49102,1.49102,1.49774,1.51792,1.5112,1.53138,1.5381,1.56165,1.57174,1.55828,-0.119969,-0.156964,-0.146874,-0.177143,-0.187233,-0.204049,-0.220865,-0.254498,-0.241045,-0.247771,-0.247771,-0.227592,-0.220865,-0.204049,-0.234318,-0.210776,-0.19396,-0.170417,-0.140148,-0.167054,-0.197323,-0.200686,-0.18387};
    private final double y[] = {12.0086,13.1438,14.2058,11.8621,12.9607,12.1184,11.0198,12.4114,11.5691,12.9973,12.9973,12.9973,13.2536,13.8396,13.5832,15.4508,14.279,13.51,12.9607,12.7776,12.1917,8.63956,-5.34918,-4.14073,-5.0196,-5.23932,-4.25059,-3.70129,-3.59143,-3.40833,-3.11537,-3.15199,-4.72664,-3.99425,-2.67594,-2.0534,-2.19988,-1.79706,-1.17453,-0.99143,-1.17453,-1.98016,-0.735092,-0.625233,-0.954811,-1.28439,-1.65059,-1.43087,-1.76044,-1.57735,-0.368895,-0.881571,-0.332275,-0.99143,-1.17453,-1.76044,-2.49284,-3.51819,-3.73791,-1.61397,-0.661853,-0.515374,-1.57735,-1.28439,-0.625233,-0.625233,-0.405515,0.400119,0.400119,0.729696,0.729696,0.729696,0.693077,0.876175,0.949415,0.546598,0.473358,0.32688,-0.0759374,-0.112557,3.73251,3.69589,3.40294,2.63392,2.34096,1.38885,2.63392,2.30434,2.34096,2.4142,2.19449,1.53533,1.05927,1.05927,-2.93228,-2.74918,-4.61678,-5.82523,-6.99706,-6.22805,-8.90129,-7.6196,-6.85059,-6.48439,-5.67875,-5.53228,-5.67875,-4.6534,-3.99425,-4.50692,-2.93228,-3.33509,-3.62805,-4.32382,-5.45904,-6.00833,1.68181,1.38885,1.16913,1.24237,0.766316,0.546598,0.25364,0.0339218,1.90153,1.42547,1.38885,0.21702,-5.53228,-5.16608,-5.3858,-5.05622,-4.76326,-2.56608,-1.57735,-1.02805,-0.735092,-0.185797,-0.112557,0.32688,0.436739,0.32688,0.839556,0.766316,0.473358,-0.222416,-0.332275,-0.442135,-0.918191,-1.02805,-0.771712,-0.808332,-0.844952,-0.588613,-0.698473,-1.10129,-1.06467,-1.57735,-1.46749,-1.94354,-2.09002,-2.19988,4.39167,3.91561,3.73251,3.62265,4.39167,4.57477,4.28181,4.57477,4.61139,5.0142,4.94096,5.0142,5.3804,5.30716,5.7466,5.67336,5.5635,5.70998,6.55223,7.4311,7.46772,6.99167,6.62547,6.88181,6.88181,6.40575,6.88181,6.47899,5.67336,5.45364,5.34378,5.81984,5.5635,5.7466,6.07618,5.89308,6.00294,6.47899,6.33251,6.18603,6.40575,8.38322,8.1635,8.12688,8.09026,8.3466,8.7128,8.7128,8.63956,8.74941,8.96913,9.48181,9.77477,9.33533,9.51843,9.66491,11.8987,12.0452,12.2283,12.448,12.6311,12.8508,13.0705,12.7776,12.5945,12.448,12.3381,12.448,12.3381,12.1184,11.9719,11.7522,11.5691,11.7522,11.9353,11.5325,11.3494,11.2762,11.1663,10.8367,10.9832,11.0565,11.2396,10.9832,11.2029,11.2029,10.9466,10.7269,10.7635,10.7635,10.3973,10.0677,10.1776,9.99448,10.3241,10.5072,10.141,10.4339,10.3973,10.141,10.1776,10.2508,10.3973,-3.22523,-3.92101,-3.62805,-3.48157,-3.48157,-4.14073,-4.21397,-4.28721,-4.14073,-4.03087,-3.59143,-3.51819,-3.07875,-3.18861,-2.82242,-2.82242,-2.89566,-3.00551,-2.93228,-2.71256,-2.52946,-2.30974,-2.2365};
    private double xs[], ys[], xl[], yl[];
    private double minX, minY, rangeX, rangeY;
    private java.awt.Color[] cArray;
    private AxisXY axis;
    private ClusterReport report;
    private Data wd, rg, bg, ms, msl, su;
    private final java.awt.Cursor defCursor = new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR);
    private final java.awt.Cursor waitCursor = new java.awt.Cursor(java.awt.Cursor.WAIT_CURSOR);
    private javax.swing.JFrame parentFrame;
    private JPanelChart jPanelChart;

    /** Creates new form StarCluster */
    public StarCluster(javax.swing.JFrame parent) {
        this.parentFrame = parent;

        cArray = new java.awt.Color[8];
        cArray[0] = java.awt.Color.BLUE;
        cArray[1] = java.awt.Color.GREEN;
        cArray[2] = java.awt.Color.RED;
        cArray[3] = java.awt.Color.CYAN;
        cArray[4] = java.awt.Color.MAGENTA;
        cArray[5] = java.awt.Color.YELLOW;
        cArray[6] = java.awt.Color.ORANGE;
        cArray[7] = java.awt.Color.GRAY;

        initComponents();

        report = new ClusterReport(parentFrame, "ClusterKMeans Report", viewToggleButton);
        report.setText("No analysis performed");

        computeScaledData();
        plotData();

        setPreferredSize(new java.awt.Dimension(parent.getSize().width, (int)(0.95*parent.getSize().height)));
        jPanelChart.setPreferredSize(new java.awt.Dimension(parent.getSize().width, (int)(0.75*parent.getSize().height)));
    }

    private void computeScaledData() {
        xs = new double[x.length];
        ys = new double[y.length];

        /*
        xl = new double[x.length];
        yl = new double[y.length];
        for (int i=0; i

        Summary summX = new Summary();
        Summary summY = new Summary();
        summX.update(x);
        summY.update(y);
        minX = summX.getMinimum();
        minY = summY.getMinimum();
        rangeX = summX.getMaximum() - minX;
        rangeY = summY.getMaximum() - minY;
        for (int i=0; i<x.length; i++) {
            xs[i] = (x[i]-minX)/rangeX;
            ys[i] = (y[i]-minY)/rangeY;
        }
    }

    private void runAnalysis() {
        double[][] data = new double[y.length][2];
        for (int i=0; i<x.length; i++) {
            data[i][0] = xs[i];
            data[i][1] = ys[i];
        }

        int numClusters = numSlider.getValue();
        double[][] cs = new double[numClusters][2];
        com.imsl.stat.Random r = new com.imsl.stat.Random();
        for (int i=0; i<numClusters; i++) {
            // have scaled axes to [0,1] so nextDouble is fine
            cs[i][0] = r.nextDouble();
            cs[i][1] = r.nextDouble();
        }

        try {
            ClusterKMeans kmean = new ClusterKMeans(data, cs);
            double[][] cm = kmean.compute();
            double[] wss = kmean.getClusterSSQ();
            int[] ic = kmean.getClusterMembership();
            int[] nc = kmean.getClusterCounts();

            // get cluster centers into plottable coordinates
            double[] cmx = new double[numClusters];
            double[] cmy = new double[numClusters];
            double[][] cmr = new double[numClusters][2];
            for (int i=0; i<numClusters; i++) {
                //cmx[i] = JMath.exp(minX+rangeX*(cm[i][0]));
                //cmy[i] = JMath.exp(minY+rangeY*(cm[i][1]));
                cmx[i] = minX+rangeX*(cm[i][0]);
                cmy[i] = minY+rangeY*(cm[i][1]);
                cmr[i][0] = cmx[i];
                cmr[i][1] = cmy[i];
            }

            // create the report
            java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
            java.io.PrintStream ps = new java.io.PrintStream(baos);

            ps.println("<h3><font color='blue'>Cluster Centers</font></h3>");
            PrintMatrix pm = new PrintMatrix(ps);
            PrintMatrixFormat pmf = new PrintMatrixFormat();
            java.text.NumberFormat nf = java.text.NumberFormat.getInstance();
            nf.setMinimumFractionDigits(4);
            pmf.setNumberFormat(nf);
            pmf.setColumnLabels(new String[] {"x","y"});
            pmf.setFirstRowNumber(1);
            pm.printHTML(pmf, cmr, numClusters, 2);

            ps.println("<h3><font color='blue'>Number of Observations</font></h3>");
            for (int i=0; i<numClusters; i++) {
                reportValue(ps, "Cluster "+(i+1), nc[i]);
            }
            ps.println("<h3><font color='blue'>Sum of Squares (scaled, relative)</font></h3>");
            for (int i=0; i<numClusters; i++) {
                reportValue(ps, "Cluster "+(i+1), wss[i]);
            }
            report.setText(baos.toString());

            // now update the chart
            clearChart();
            Data d = new Data(axis, x, y);
            d.setDataType(Data.DATA_TYPE_MARKER);
            d.setMarkerType(Data.MARKER_TYPE_HOLLOW_CIRCLE);
            d.setMarkerColor(java.awt.Color.DARK_GRAY);
            for (int i=0; i<numClusters; i++) {

                Data meanData = new Data(axis, new double[] {cmx[i]}, new double[] {cmy[i]});
                meanData.setDataType(Data.DATA_TYPE_MARKER);
                meanData.setMarkerType(Data.MARKER_TYPE_FILLED_TRIANGLE);
                meanData.setMarkerSize(2.0);
                meanData.setMarkerColor(cArray[i]);
                meanData.setTitle("Center "+(i+1));

                ClusterSet cset = new ClusterSet(data, ic, i+1, nc[i]);
                Data cData = new Data(axis, cset.x, cset.y);
                cData.setDataType(Data.DATA_TYPE_MARKER);
                cData.setMarkerType(Data.MARKER_TYPE_FILLED_CIRCLE);
                cData.setMarkerSize(0.7);
                cData.setMarkerColor(cArray[i]);
            }
            if (annotateToggleButton.isSelected()) {
                drawAnnotations();
            }
            repaint();

        } catch (Exception e) {
            // if it's a KMeans exception, just reseed and try again.
            if (e instanceof ClusterKMeans.NoConvergenceException ||
                e instanceof ClusterKMeans.ClusterNoPointsException) {
                System.out.println(e.getMessage());
                runAnalysis();
            } else {
                javax.swing.JOptionPane.showMessageDialog(this, e.getMessage(),
                    "Exception", javax.swing.JOptionPane.ERROR_MESSAGE);
                e.printStackTrace();
                System.exit(1);
            }
        }
    }

    private void clearChart() {
        ChartNode[] children = axis.getChildren();
        for (int i=0; i<children.length; i++) {
            if (children[i] instanceof Data) {
                children[i].remove();
            }
        }
    }

    private void drawAnnotations() {
        double wdx[] = {0.6};
        double wdy[] = {14};
        wd = new Data(axis, wdx, wdy);
        wd.setTextColor(java.awt.Color.BLACK);
        wd.setLabelType(Data.LABEL_TYPE_TITLE);
        wd.setTitle("White Dwarfs");

        double rgx[] = {1.9};
        double rgy[] = {1};
        rg = new Data(axis, rgx, rgy);
        rg.setTextColor(java.awt.Color.RED);
        rg.setLabelType(Data.LABEL_TYPE_TITLE);
        rg.setTitle("Red\nGiants");

        double bgx[] = {-0.3};
        double bgy[] = {-6.5};
        bg = new Data(axis, bgx, bgy);
        bg.setTextColor(java.awt.Color.BLUE);
        bg.setLabelType(Data.LABEL_TYPE_TITLE);
        bg.setTitle("Blue\nGiants");

        double msx[] = {0.2};
        double msy[] = {3.5};
        ms = new Data(axis, msx, msy);
        ms.setTextColor(java.awt.Color.GREEN);
        ms.setLabelType(Data.LABEL_TYPE_TITLE);
        ms.setTitle("Main\nSequence");
        ms.getTitle().setAlignment(Data.TEXT_X_RIGHT);

        double mslx[] = {-0.4, 0.0, 0.4, 0.8, 1.2, 1.6};
        double msly[] = {-5, 2.5, 4.75, 7.5, 9, 13.5};
        final com.imsl.math.CsAkima cs = new com.imsl.math.CsAkima(mslx, msly);
        ChartFunction fcn = new ChartFunction() {
            public double f(double x) {
                return cs.value(x);
            }
        };
        msl = new Data(axis, fcn, -0.4, 1.7);
        msl.setDataType(Data.DATA_TYPE_LINE);
        msl.setLineColor(java.awt.Color.GREEN);
        msl.setLineWidth(1.5);

        double sux[] = {0.6};
        double suy[] = {4.7};
        su = new Data(axis, sux, suy);
        su.setDataType(Data.DATA_TYPE_MARKER);
        su.setMarkerSize(1.5);
        su.setMarkerType(Data.MARKER_TYPE_FILLED_CIRCLE);
        su.setMarkerColor(java.awt.Color.YELLOW);
        su.setTextColor(java.awt.Color.ORANGE);
        su.setLabelType(Data.LABEL_TYPE_TITLE);
        su.setTitle("The Sun");
        su.getTitle().setAlignment(Data.TEXT_X_RIGHT | Data.TEXT_Y_TOP);
    }

    private void clearAnnotations() {
        wd.remove();
        rg.remove();
        bg.remove();
        ms.remove();
        msl.remove();
        su.remove();
    }

    private void plotData() {
        jPanelChart.setChart(new Chart());
        Chart c = jPanelChart.getChart();

        //Legend legend = c.getLegend();
        //legend.setPaint(true);
        //legend.setViewport(0.85,0.95,0.05,0.15);
        axis = new AxisXY(c);
        axis.getAxisX().setAutoscaleInput(AxisXY.AUTOSCALE_OFF);
        axis.getAxisY().setAutoscaleInput(AxisXY.AUTOSCALE_OFF);
        //axis.getAxisX().setWindow(30000.0, 3000.0);
        //axis.getAxisY().setWindow(10e-6, 10e6);
        axis.getAxisX().setWindow(-0.5, 2.5);
        axis.getAxisY().setWindow(20, -10);
        //axis.getAxisX().setTextFormat(new java.text.DecimalFormat("##,###"));
        //axis.getAxisY().setTextFormat(new java.text.DecimalFormat("00.##E0"));
        axis.getAxisX().setTextFormat(new java.text.DecimalFormat("##.#"));
        axis.getAxisY().setTextFormat(new java.text.DecimalFormat("##"));

        double yticks[] = {-10,-5,0,5,10,15,20};
        axis.getAxisY().setTicks(yticks);
        double xticks[] = {-0.5,0,0.5,1.0,1.5,2.0,2.5};
        axis.getAxisX().setTicks(xticks);

        //axis.getAxisX().setTransform(Data.TRANSFORM_LOG);
        //axis.getAxisY().setTransform(Data.TRANSFORM_LOG);
        axis.getAxisX().getAxisTitle().setTitle("B-V Color Index");
        axis.getAxisY().getAxisTitle().setTitle("Absolute V Magnitude");
        //axis.getAxisX().getAxisTitle().setTitle("Temperature, Degrees Kelvin");
        //axis.getAxisY().getAxisTitle().setTitle("Luminosity, Sun = 1");

        AxisXY axis2 = new AxisXY(c);
        axis2.getAxisX().setAutoscaleInput(AxisXY.AUTOSCALE_OFF);
        axis2.getAxisY().setAutoscaleInput(AxisXY.AUTOSCALE_OFF);
        axis2.getAxisX().setWindow(0.0, 1.0);
        axis2.getAxisY().setWindow(10e-6, 10e6);
        axis2.getAxisY().setTransform(Data.TRANSFORM_LOG);
        axis2.getAxisY().setTextFormat(new java.text.DecimalFormat("00.##E0"));
        axis2.setCross(1.0, 10e6);
        axis2.getAxisX().setType(Data.AXIS_X_TOP);
        axis2.getAxisY().setType(Data.AXIS_Y_RIGHT);
        axis2.getAxisX().setFirstTick(0.018);
        axis2.getAxisX().setTickInterval(0.162);
        String labelsx2[] = {"35,000","10,000","6,000","4,000","3,000"};
        axis2.getAxisX().getAxisLabel().setLabels(labelsx2);
        axis2.getAxisX().getAxisTitle().setTitle("Effective Temperature, K");
        axis2.getAxisY().getAxisTitle().setTitle("Luminosity, Sun = 1");

        Data d = new Data(axis, x, y);
        d.setDataType(Data.DATA_TYPE_MARKER);
        d.setMarkerType(Data.MARKER_TYPE_HOLLOW_CIRCLE);
        d.setMarkerColor(java.awt.Color.BLACK);
    }

    private void reportValue(java.io.PrintStream ps, String label, double value) {
        java.text.MessageFormat mf = new java.text.MessageFormat(label+" = <b>{0}</b>");
        Object args[] = {new Double(value)};
        ps.print(mf.format(args));
        ps.println("<br>");
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    private void initComponents() {//GEN-BEGIN:initComponents
        jPanel1 = new javax.swing.JPanel();
        jPanel2 = new javax.swing.JPanel();
        jLabel1 = new javax.swing.JLabel();
        numSlider = new javax.swing.JSlider();
        jPanel3 = new javax.swing.JPanel();
        runButton = new javax.swing.JButton();
        viewToggleButton = new javax.swing.JToggleButton();
        annotateToggleButton = new javax.swing.JToggleButton();
        jPanelChart = new com.imsl.chart.JPanelChart();

        jPanel2.setLayout(new javax.swing.BoxLayout(jPanel2, javax.swing.BoxLayout.Y_AXIS));

        jLabel1.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        jLabel1.setText("Number of Clusters");
        jPanel2.add(jLabel1);

        numSlider.setMajorTickSpacing(1);
        numSlider.setMaximum(8);
        numSlider.setMinimum(2);
        numSlider.setPaintLabels(true);
        numSlider.setPaintTicks(true);
        numSlider.setSnapToTicks(true);
        numSlider.setValue(4);
        jPanel2.add(numSlider);

        jPanel1.add(jPanel2);

        jPanel3.setLayout(new java.awt.GridLayout(3, 1));

        runButton.setForeground(new java.awt.Color(0, 153, 0));
        runButton.setText("Run Analysis");
        runButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                runButtonActionPerformed(evt);
            }
        });

        jPanel3.add(runButton);

        viewToggleButton.setText("View Report");
        viewToggleButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                viewToggleButtonActionPerformed(evt);
            }
        });

        jPanel3.add(viewToggleButton);

        annotateToggleButton.setText("Annotate Graph");
        annotateToggleButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                annotateToggleButtonActionPerformed(evt);
            }
        });

        jPanel3.add(annotateToggleButton);
        jPanel1.add(jPanel3);
        add(jPanel1, java.awt.BorderLayout.NORTH);
        add(jPanelChart);
    }//GEN-END:initComponents

    private void annotateToggleButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_annotateToggleButtonActionPerformed
        if (annotateToggleButton.isSelected()) {
            drawAnnotations();
        } else {
            clearAnnotations();
        }
        repaint();
    }//GEN-LAST:event_annotateToggleButtonActionPerformed

    private void viewToggleButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_viewToggleButtonActionPerformed
        if (viewToggleButton.isSelected()) {
            java.awt.Dimension size = parentFrame.getSize();
            java.awt.Point loc = parentFrame.getLocationOnScreen();
            report.setLocation(loc.x+size.width,loc.y);
            report.show();
        } else {
            report.setVisible(false);
        }
    }//GEN-LAST:event_viewToggleButtonActionPerformed

    private void runButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_runButtonActionPerformed
        setCursor(waitCursor);
        runAnalysis();
        setCursor(defCursor);
    }//GEN-LAST:event_runButtonActionPerformed


    private javax.swing.JLabel jLabel1;
    private javax.swing.JPanel jPanel3;
    private javax.swing.JSlider numSlider;
    private javax.swing.JToggleButton viewToggleButton;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JButton runButton;
    private javax.swing.JToggleButton annotateToggleButton;
    private javax.swing.JPanel jPanel1;
    // End of variables declaration//GEN-END:variables

    class ClusterSet {
        double[] x,y;

        ClusterSet(double[][] data, int[] member, int select, int total) {
            x = new double[total];
            y = new double[total];
            int count = 0;
            for (int i=0; i<data.length; i++) {
                if (member[i] == select) {
                    x[count] = minX+rangeX*(data[i][0]);
                    y[count] = minY+rangeY*(data[i][1]);
                    //x[count] = JMath.exp(minX+rangeX*(data[i][0]));
                    //y[count] = JMath.exp(minY+rangeY*(data[i][1]));
                    count ++;
                }
            }
        }
    }
}