/*
 * DescriptiveStatisticsDialog.java
 *
 * Created on March 18, 2008, 9:09 AM
 */

package org.statcato.dialogs.stat.basicstats;

import org.statcato.*;
import org.statcato.spreadsheet.*;
import org.statcato.statistics.*;
import org.statcato.utils.HelperFunctions;
import java.util.*;
import javax.swing.ButtonGroup;

/**
 * A dialog for computing descriptive statistics of a set of columns/
 * data variables.  Descriptive statistics include
 * mean, SE of mean, standard deviation, variance, coefficient of variation,
 * first quartile, median, third quartile, interquartile range, mode, 
 * trimmed mean, sum, minimum, maximum, range, sum of squares, skewness, kurtosis,
 * MSSD, N nonmissing, N missing, N total, cumulative N, percent, and
 * cumulative percentage.
 * 
 * @author  Margaret Yau
 * @version %I%, %G%
 * @see org.statcato.statistics.BasicStatistics
 * @since 1.0
 */
public class DescriptiveStatisticsDialog extends StatcatoDialog {
    private String header1 = "", header2 = "", header3 = "", header4 = "", 
            header5 = "", header6 = "";
    boolean hasHeader1 = false, hasHeader2 = false, hasHeader3 = false,
            hasHeader4 = false, hasHeader5 = false, hasHeader6 = false;
    
    /** Creates new form DescriptiveStatisticsDialog */
    public DescriptiveStatisticsDialog(java.awt.Frame parent, boolean modal, 
            Statcato mTab) {
        super(parent, modal);
        app = mTab;
        ParentSpreadsheet = app.getSpreadsheet();        
        initComponents();

        ParentSpreadsheet.populateComboBox(ByVarComboBox);
        
        ButtonGroup group1 = new ButtonGroup();
        group1.add(SkewnessBiasedRadioButton);
        group1.add(SkewnessUnbiasedRadioButton);
        
        ButtonGroup group2 = new ButtonGroup();
        group2.add(KurtosisBiasedRadioButton);
        group2.add(KurtosisUnbiasedRadioButton);
        
        ButtonGroup group3 = new ButtonGroup();
        group3.add(KurtosisC3RadioButton);
        group3.add(KurtosisC0RadioButton);
        
        SkewnessPanel.setVisible(false);
        KurtosisPanel.setVisible(false);
        
        getRootPane().setDefaultButton(OKButton);
        setHelpFile("stat-basic-descriptive");
        name = "Descriptive Statistics";
        description = "For computing descriptive statistics for a set " +
                "of input column variables or for groups of data within a " +
                "set of input column variables. ";
        helpStrings.add("Specify the names of the input columns. " +
                "(optional) Select the variable that will be used to " +
                "group data values in each column.");
        helpStrings.add("Select the descriptive statistics to be" +
                " computed by checking their corresponding check boxes.");
        helpStrings.add("Check the Store Results in New Datasheet box " +
                "if you would like to store the statistics in new datasheet(s). " +
                "Statistics for each input variable will be stored in separate datasheet.");
    }

    /**
     * Updates elements on the dialog so that they have the most
     * current values.  Called by {@link #setVisible} to make
     * sure the dialog displays current values when made visible again.
     * 
     * @see #setVisible(boolean)
     */
    @Override
    public void updateElements() {
        updateComboBox(ByVarComboBox);     
    }
    
    /** 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.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        OKButton = new javax.swing.JButton();
        CancelButton = new javax.swing.JButton();
        jPanel1 = new javax.swing.JPanel();
        ByVarComboBox = new javax.swing.JComboBox();
        jLabel4 = new javax.swing.JLabel();
        jLabel1 = new javax.swing.JLabel();
        InputTextField = new javax.swing.JTextField();
        jLabel8 = new javax.swing.JLabel();
        jPanel2 = new javax.swing.JPanel();
        StoreResultCheckBox = new javax.swing.JCheckBox();
        jLabel3 = new javax.swing.JLabel();
        jPanel3 = new javax.swing.JPanel();
        SelectAllCheckBox = new javax.swing.JCheckBox();
        jPanel4 = new javax.swing.JPanel();
        VarianceCheckBox = new javax.swing.JCheckBox();
        StdevCheckBox = new javax.swing.JCheckBox();
        SEMeanCheckBox = new javax.swing.JCheckBox();
        MeanCheckBox = new javax.swing.JCheckBox();
        CoeffVarCheckBox = new javax.swing.JCheckBox();
        jPanel5 = new javax.swing.JPanel();
        InterquartileRangeCheckBox = new javax.swing.JCheckBox();
        ModeCheckBox = new javax.swing.JCheckBox();
        ThirdQuartileCheckBox = new javax.swing.JCheckBox();
        MedianCheckBox = new javax.swing.JCheckBox();
        FirstQuartileCheckBox = new javax.swing.JCheckBox();
        jPanel6 = new javax.swing.JPanel();
        jLabel5 = new javax.swing.JLabel();
        TrimmedPercentTextField = new javax.swing.JTextField();
        MinCheckBox = new javax.swing.JCheckBox();
        SumCheckBox = new javax.swing.JCheckBox();
        RangeCheckBox = new javax.swing.JCheckBox();
        jLabel6 = new javax.swing.JLabel();
        TrimmedMeanCheckBox = new javax.swing.JCheckBox();
        MaxCheckBox = new javax.swing.JCheckBox();
        jPanel7 = new javax.swing.JPanel();
        NmissingCheckBox = new javax.swing.JCheckBox();
        CumulativeNCheckBox = new javax.swing.JCheckBox();
        NnonmissingCheckBox = new javax.swing.JCheckBox();
        NtotalCheckBox = new javax.swing.JCheckBox();
        CumulativePercentCheckBox = new javax.swing.JCheckBox();
        PercentCheckBox = new javax.swing.JCheckBox();
        jPanel8 = new javax.swing.JPanel();
        SkewnessCheckBox = new javax.swing.JCheckBox();
        SumOfSqCheckBox = new javax.swing.JCheckBox();
        KurtosisCheckBox = new javax.swing.JCheckBox();
        MSSDCheckBox = new javax.swing.JCheckBox();
        SkewnessPanel = new javax.swing.JPanel();
        SkewnessBiasedRadioButton = new javax.swing.JRadioButton();
        SkewnessUnbiasedRadioButton = new javax.swing.JRadioButton();
        KurtosisPanel = new javax.swing.JPanel();
        KurtosisC0RadioButton = new javax.swing.JRadioButton();
        KurtosisC3RadioButton = new javax.swing.JRadioButton();
        KurtosisUnbiasedRadioButton = new javax.swing.JRadioButton();
        KurtosisBiasedRadioButton = new javax.swing.JRadioButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setTitle("Descriptive Statistics");

        OKButton.setText("OK");
        OKButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                OKButtonActionPerformed(evt);
            }
        });

        CancelButton.setText("Cancel");
        CancelButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                CancelButtonActionPerformed(evt);
            }
        });

        jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder("Inputs"));

        ByVarComboBox.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                ByVarComboBoxActionPerformed(evt);
            }
        });

        jLabel4.setFont(new java.awt.Font("Tahoma", 1, 11));
        jLabel4.setText("By Variable (optional):");
        jLabel4.setToolTipText("By Variable");

        jLabel1.setFont(new java.awt.Font("Tahoma", 1, 11));
        jLabel1.setText("Input Variable(s):");
        jLabel1.setToolTipText("Input variables");

        jLabel8.setText("<html>\nEnter valid column names <br>separated by space.<br>\nFor a continuous range of <br>columns,\nseparate using <br>dash (e.g. C1-C30).<br>\n</html>\n");

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addComponent(jLabel1)
                        .addContainerGap(151, Short.MAX_VALUE))
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addComponent(InputTextField, javax.swing.GroupLayout.DEFAULT_SIZE, 240, Short.MAX_VALUE)
                        .addContainerGap())
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addComponent(ByVarComboBox, 0, 214, Short.MAX_VALUE)
                        .addGap(36, 36, 36))
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addComponent(jLabel4, javax.swing.GroupLayout.DEFAULT_SIZE, 240, Short.MAX_VALUE)
                        .addContainerGap())
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addComponent(jLabel8, javax.swing.GroupLayout.DEFAULT_SIZE, 240, Short.MAX_VALUE)
                        .addContainerGap())))
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jLabel1)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(InputTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(18, 18, 18)
                .addComponent(jLabel8)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 71, Short.MAX_VALUE)
                .addComponent(jLabel4)
                .addGap(18, 18, 18)
                .addComponent(ByVarComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(63, 63, 63))
        );

        jPanel2.setBorder(javax.swing.BorderFactory.createTitledBorder("Results"));

        StoreResultCheckBox.setText("New worksheet");

        jLabel3.setFont(new java.awt.Font("Tahoma", 1, 11));
        jLabel3.setText("Store Results in:");

        javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
        jPanel2.setLayout(jPanel2Layout);
        jPanel2Layout.setHorizontalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel2Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(StoreResultCheckBox)
                    .addComponent(jLabel3))
                .addContainerGap(151, Short.MAX_VALUE))
        );
        jPanel2Layout.setVerticalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel2Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jLabel3)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(StoreResultCheckBox)
                .addContainerGap(92, Short.MAX_VALUE))
        );

        jPanel3.setBorder(javax.swing.BorderFactory.createTitledBorder("Statistics"));

        SelectAllCheckBox.setText("Select all statistics");
        SelectAllCheckBox.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                SelectAllCheckBoxActionPerformed(evt);
            }
        });

        VarianceCheckBox.setText("Variance");
        VarianceCheckBox.setToolTipText("Variance");

        StdevCheckBox.setText("Standard deviation");
        StdevCheckBox.setToolTipText("Standard deviation");

        SEMeanCheckBox.setText("SE of mean");
        SEMeanCheckBox.setToolTipText("Standard error of the mean");

        MeanCheckBox.setText("Mean");
        MeanCheckBox.setToolTipText("Arithmetic mean");

        CoeffVarCheckBox.setText("Coefficient of variation");
        CoeffVarCheckBox.setToolTipText("Coefficient of variation");

        javax.swing.GroupLayout jPanel4Layout = new javax.swing.GroupLayout(jPanel4);
        jPanel4.setLayout(jPanel4Layout);
        jPanel4Layout.setHorizontalGroup(
            jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel4Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(MeanCheckBox)
                    .addComponent(SEMeanCheckBox)
                    .addComponent(StdevCheckBox)
                    .addComponent(VarianceCheckBox)
                    .addComponent(CoeffVarCheckBox))
                .addContainerGap())
        );

        jPanel4Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {CoeffVarCheckBox, MeanCheckBox, SEMeanCheckBox, StdevCheckBox, VarianceCheckBox});

        jPanel4Layout.setVerticalGroup(
            jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel4Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(MeanCheckBox)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(SEMeanCheckBox)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(StdevCheckBox)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(VarianceCheckBox)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(CoeffVarCheckBox)
                .addContainerGap())
        );

        jPanel4Layout.linkSize(javax.swing.SwingConstants.VERTICAL, new java.awt.Component[] {CoeffVarCheckBox, MeanCheckBox, SEMeanCheckBox, StdevCheckBox, VarianceCheckBox});

        InterquartileRangeCheckBox.setText("Interquartile range");
        InterquartileRangeCheckBox.setToolTipText("Interquartile range: the difference between the first and third quartiles");

        ModeCheckBox.setText("Mode");
        ModeCheckBox.setToolTipText("Mode");

        ThirdQuartileCheckBox.setText("Third quartile");
        ThirdQuartileCheckBox.setToolTipText("Third quartile");

        MedianCheckBox.setText("Median");
        MedianCheckBox.setToolTipText("Median");

        FirstQuartileCheckBox.setText("First quartile");
        FirstQuartileCheckBox.setToolTipText("First quartile");

        javax.swing.GroupLayout jPanel5Layout = new javax.swing.GroupLayout(jPanel5);
        jPanel5.setLayout(jPanel5Layout);
        jPanel5Layout.setHorizontalGroup(
            jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel5Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(FirstQuartileCheckBox)
                    .addComponent(MedianCheckBox)
                    .addComponent(ThirdQuartileCheckBox)
                    .addComponent(InterquartileRangeCheckBox)
                    .addComponent(ModeCheckBox))
                .addContainerGap())
        );
        jPanel5Layout.setVerticalGroup(
            jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel5Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(FirstQuartileCheckBox)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(MedianCheckBox)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(ThirdQuartileCheckBox)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(InterquartileRangeCheckBox)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(ModeCheckBox)
                .addContainerGap())
        );

        jLabel5.setText("(between 0 and 100)");

        TrimmedPercentTextField.setEnabled(false);

        MinCheckBox.setText("Minimum");
        MinCheckBox.setToolTipText("Minimum");

        SumCheckBox.setText("Sum");
        SumCheckBox.setToolTipText("Sum");

        RangeCheckBox.setText("Range");
        RangeCheckBox.setToolTipText("Range");

        jLabel6.setText("% of values to be trimmed");

        TrimmedMeanCheckBox.setText("Trimmed mean: cutoff %");
        TrimmedMeanCheckBox.setToolTipText("Trimmed mean");
        TrimmedMeanCheckBox.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                TrimmedMeanCheckBoxActionPerformed(evt);
            }
        });

        MaxCheckBox.setText("Maximum");
        MaxCheckBox.setToolTipText("Maximum");

        javax.swing.GroupLayout jPanel6Layout = new javax.swing.GroupLayout(jPanel6);
        jPanel6.setLayout(jPanel6Layout);
        jPanel6Layout.setHorizontalGroup(
            jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel6Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(jPanel6Layout.createSequentialGroup()
                        .addGroup(jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(jPanel6Layout.createSequentialGroup()
                                .addComponent(TrimmedMeanCheckBox)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(TrimmedPercentTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 79, javax.swing.GroupLayout.PREFERRED_SIZE))
                            .addComponent(SumCheckBox))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jLabel5)
                            .addComponent(jLabel6)))
                    .addComponent(MinCheckBox)
                    .addComponent(MaxCheckBox)
                    .addComponent(RangeCheckBox))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        jPanel6Layout.setVerticalGroup(
            jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel6Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(jPanel6Layout.createSequentialGroup()
                        .addGap(9, 9, 9)
                        .addGroup(jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(TrimmedMeanCheckBox)
                            .addComponent(TrimmedPercentTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(SumCheckBox)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(MinCheckBox)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(MaxCheckBox)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addComponent(RangeCheckBox))
                    .addGroup(jPanel6Layout.createSequentialGroup()
                        .addComponent(jLabel6)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jLabel5)))
                .addContainerGap())
        );

        NmissingCheckBox.setText("N missing");
        NmissingCheckBox.setToolTipText("number of missing column entries");

        CumulativeNCheckBox.setText("Cumulative N");
        CumulativeNCheckBox.setToolTipText("Cumulative N");

        NnonmissingCheckBox.setText("N nonmissing");
        NnonmissingCheckBox.setToolTipText("number of nonmissing column entries");

        NtotalCheckBox.setText("N total");
        NtotalCheckBox.setToolTipText(" total (nonmissing and missing) number of column entries");

        CumulativePercentCheckBox.setText("Cumulative Percent");
        CumulativePercentCheckBox.setToolTipText("Cumulative Percent");

        PercentCheckBox.setText("Percent");
        PercentCheckBox.setToolTipText("Percent");

        javax.swing.GroupLayout jPanel7Layout = new javax.swing.GroupLayout(jPanel7);
        jPanel7.setLayout(jPanel7Layout);
        jPanel7Layout.setHorizontalGroup(
            jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel7Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(PercentCheckBox)
                    .addComponent(CumulativeNCheckBox)
                    .addComponent(NtotalCheckBox)
                    .addComponent(NmissingCheckBox)
                    .addComponent(NnonmissingCheckBox)
                    .addComponent(CumulativePercentCheckBox))
                .addContainerGap())
        );
        jPanel7Layout.setVerticalGroup(
            jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel7Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(jPanel7Layout.createSequentialGroup()
                        .addComponent(NnonmissingCheckBox)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(NmissingCheckBox))
                    .addGroup(jPanel7Layout.createSequentialGroup()
                        .addGap(46, 46, 46)
                        .addComponent(NtotalCheckBox)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(CumulativeNCheckBox)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(PercentCheckBox)))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(CumulativePercentCheckBox)
                .addContainerGap())
        );

        SkewnessCheckBox.setText("Skewness");
        SkewnessCheckBox.setToolTipText("Skewness");
        SkewnessCheckBox.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                SkewnessCheckBoxStateChanged(evt);
            }
        });

        SumOfSqCheckBox.setText("Sum of squares");
        SumOfSqCheckBox.setToolTipText("sum of the squared data values");

        KurtosisCheckBox.setText("Kurtosis");
        KurtosisCheckBox.setToolTipText("Kurtosis");
        KurtosisCheckBox.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                KurtosisCheckBoxStateChanged(evt);
            }
        });

        MSSDCheckBox.setText("MSSD");
        MSSDCheckBox.setToolTipText("Mean of Successive Squared Differences");

        SkewnessBiasedRadioButton.setSelected(true);
        SkewnessBiasedRadioButton.setText("Biased");

        SkewnessUnbiasedRadioButton.setText("Unbiased");

        javax.swing.GroupLayout SkewnessPanelLayout = new javax.swing.GroupLayout(SkewnessPanel);
        SkewnessPanel.setLayout(SkewnessPanelLayout);
        SkewnessPanelLayout.setHorizontalGroup(
            SkewnessPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(SkewnessPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(SkewnessPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(SkewnessUnbiasedRadioButton)
                    .addComponent(SkewnessBiasedRadioButton))
                .addContainerGap())
        );
        SkewnessPanelLayout.setVerticalGroup(
            SkewnessPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(SkewnessPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(SkewnessBiasedRadioButton)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(SkewnessUnbiasedRadioButton)
                .addContainerGap())
        );

        KurtosisC0RadioButton.setText("Center at 0");

        KurtosisC3RadioButton.setSelected(true);
        KurtosisC3RadioButton.setText("Centered at 3");

        KurtosisUnbiasedRadioButton.setText("Unbiased");

        KurtosisBiasedRadioButton.setSelected(true);
        KurtosisBiasedRadioButton.setText("Biased");

        javax.swing.GroupLayout KurtosisPanelLayout = new javax.swing.GroupLayout(KurtosisPanel);
        KurtosisPanel.setLayout(KurtosisPanelLayout);
        KurtosisPanelLayout.setHorizontalGroup(
            KurtosisPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(KurtosisPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(KurtosisPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(KurtosisUnbiasedRadioButton)
                    .addComponent(KurtosisBiasedRadioButton))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(KurtosisPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(KurtosisC3RadioButton)
                    .addComponent(KurtosisC0RadioButton))
                .addContainerGap())
        );
        KurtosisPanelLayout.setVerticalGroup(
            KurtosisPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(KurtosisPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(KurtosisPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(KurtosisBiasedRadioButton)
                    .addComponent(KurtosisC3RadioButton))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(KurtosisPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(KurtosisUnbiasedRadioButton)
                    .addComponent(KurtosisC0RadioButton))
                .addContainerGap())
        );

        javax.swing.GroupLayout jPanel8Layout = new javax.swing.GroupLayout(jPanel8);
        jPanel8.setLayout(jPanel8Layout);
        jPanel8Layout.setHorizontalGroup(
            jPanel8Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel8Layout.createSequentialGroup()
                .addGroup(jPanel8Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(jPanel8Layout.createSequentialGroup()
                        .addContainerGap()
                        .addGroup(jPanel8Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(SumOfSqCheckBox)
                            .addComponent(MSSDCheckBox)
                            .addComponent(SkewnessCheckBox)
                            .addComponent(KurtosisCheckBox)))
                    .addGroup(jPanel8Layout.createSequentialGroup()
                        .addGap(27, 27, 27)
                        .addComponent(SkewnessPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addGroup(jPanel8Layout.createSequentialGroup()
                        .addGap(27, 27, 27)
                        .addComponent(KurtosisPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
                .addContainerGap(144, Short.MAX_VALUE))
        );
        jPanel8Layout.setVerticalGroup(
            jPanel8Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel8Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(SumOfSqCheckBox)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(SkewnessCheckBox)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(SkewnessPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(KurtosisCheckBox)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(KurtosisPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(MSSDCheckBox)
                .addGap(19, 19, 19))
        );

        javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3);
        jPanel3.setLayout(jPanel3Layout);
        jPanel3Layout.setHorizontalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel3Layout.createSequentialGroup()
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(jPanel3Layout.createSequentialGroup()
                        .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jPanel4, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(jPanel5, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(jPanel7, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addGap(35, 35, 35)
                        .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jPanel8, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(jPanel6, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
                    .addComponent(SelectAllCheckBox)))
        );
        jPanel3Layout.setVerticalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel3Layout.createSequentialGroup()
                .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(jPanel3Layout.createSequentialGroup()
                        .addGap(187, 187, 187)
                        .addComponent(jPanel5, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jPanel7, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addGroup(jPanel3Layout.createSequentialGroup()
                        .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                            .addGroup(jPanel3Layout.createSequentialGroup()
                                .addComponent(SelectAllCheckBox)
                                .addGap(24, 24, 24)
                                .addComponent(jPanel4, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                            .addComponent(jPanel6, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(jPanel8, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
                .addContainerGap(28, Short.MAX_VALUE))
        );

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jPanel3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
            .addGroup(layout.createSequentialGroup()
                .addGap(294, 294, 294)
                .addComponent(OKButton, javax.swing.GroupLayout.PREFERRED_SIZE, 60, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(CancelButton)
                .addContainerGap(448, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(5, 5, 5)
                        .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                    .addComponent(jPanel3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addGap(46, 46, 46)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(CancelButton)
                    .addComponent(OKButton))
                .addGap(25, 25, 25))
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void OKButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_OKButtonActionPerformed
        app.compoundEdit = new DialogEdit("descriptive statistics");
        
        // get selected input variables
        int[] columnNumbers = ParentSpreadsheet.getColumnNumbersArrayFromString(InputTextField.getText());    
        
        // check that at least one input variable is selected
        if (columnNumbers.length == 0) {
            app.showErrorDialog("Select at least one input variable.");
            return;
        }
        // check if a BY variable is specified
        String byVarLabel = ByVarComboBox.getSelectedItem().toString();
        int byVarColNum = -1;   // BY variable column number
        Vector<Cell> byVarColVector = null;   // BY variable column vector
        boolean hasByVar = false;
        TreeSet groupSet = new TreeSet();
        
        if (!byVarLabel.equals("")) { // has BY variable
            hasByVar = true;
            byVarColNum = ParentSpreadsheet.parseColumnNumber(byVarLabel);
            byVarColVector = ParentSpreadsheet.getColumn(byVarColNum); 
            
            // create hashset of group names
            for (Enumeration e = byVarColVector.elements(); e.hasMoreElements();) {
                Cell next = (Cell) e.nextElement();
                if (!next.getContents().equals(""))
                    groupSet.add(next.getContents());
            }
        }
        
        Vector<Cell> StrColumnVector;
        Vector<String> varNameVector = new Vector<String>(0);
        Vector<Vector<String>> ResultVectors = new Vector<Vector<String>>(0);
        Object[] conversions;
        Vector<Double> ColumnVector;
        Vector<String> ResultVector;
        String columnLabel;
        
        // ------------- setup table headers -----------------------
        header1 = "<tr><th align='left'>Variable</th>";
        if (hasByVar) {
            header1 += "<th align='left'>Group</th>";
            varNameVector.addElement("group");
        }
        if (MeanCheckBox.isSelected()) {    // mean
            header1 += "<th align='right'>Mean</th>";
            hasHeader1 = true;
            varNameVector.addElement("mean");
        }
        if (SEMeanCheckBox.isSelected()) {
            header1 += "<th align='right'>SE Mean</th>";
            hasHeader1 = true;
            varNameVector.addElement("SEMean");
        }
        if (StdevCheckBox.isSelected()) {
            header1 += "<th align='right'>Standard<br>Deviation</th>";
            hasHeader1 = true;
            varNameVector.addElement("stdev");
        }
        if (VarianceCheckBox.isSelected()) {
            header1 += "<th align='right'>Variance</th>";
            hasHeader1 = true;
            varNameVector.addElement("variance");
        }
        if (CoeffVarCheckBox.isSelected()) {
            header1 += "<th align='right'>Coefficient<br>of Variation</th>";
            hasHeader1 = true;
            varNameVector.addElement("coeffVar");
        }
        header1 += "</tr>";
        header2 = "<tr><th align='left'>Variable</th>";
        if (hasByVar) {
            header2 += "<th align='left'>Group</th>";
        }        
        if (FirstQuartileCheckBox.isSelected()) {
            header2 += "<th align='right'>Q1</th>";
            hasHeader2 = true;
            varNameVector.addElement("Q1");
        }
        if (MedianCheckBox.isSelected()) {
            header2 += "<th align='right'>Median</th>";
            hasHeader2 = true;
            varNameVector.addElement("median");
        }
        if (ThirdQuartileCheckBox.isSelected()) {
            header2 += "<th align='right'>Q3</th>";
            hasHeader2 = true;
            varNameVector.addElement("Q3");
        }            
        if (InterquartileRangeCheckBox.isSelected()) {
            header2 += "<th align='right'>IQR</th>";
            hasHeader2 = true;
            varNameVector.addElement("IQR");
        }
        if (ModeCheckBox.isSelected()) {
            header2 += "<th align='right'>Mode</th>";
            header2 += "<th align='right'>N for mode</th>";
            hasHeader2 = true;
            varNameVector.addElement("mode");
        }
        header2 += "</tr>";
        header3 = "<tr><th align='left'>Variable</th>";
        if (hasByVar) {
            header3 += "<th align='left'>Group</th>";
        }
        if (TrimmedMeanCheckBox.isSelected()) {
            header3 += "<th align='right'>Trimmed<br>Mean</th>";
            hasHeader3 = true;
            varNameVector.addElement("trMean");
        }
        if (SumCheckBox.isSelected()) {
            header3 += "<th align='right'>Sum</th>";
            hasHeader3 = true;
            varNameVector.addElement("sum");
        }        
        if (MinCheckBox.isSelected()) {
            header3 += "<th align='right'>Min</th>";
            hasHeader3 = true;
            varNameVector.addElement("min");
        }        
        if (MaxCheckBox.isSelected()) {
            header3 += "<th align='right'>Max</th>";
            hasHeader3 = true;
            varNameVector.addElement("max");
        }        
        if (RangeCheckBox.isSelected()) {
            header3 += "<th align='right'>Range</th>";
            hasHeader3 = true;
            varNameVector.addElement("range");
        }        
        header3 += "</tr>";
        header4 = "<tr><th align='left'>Variable</th>";
        if (hasByVar) {
            header4 += "<th align='left'>Group</th>";
        }        
        if (SumOfSqCheckBox.isSelected()) {
            header4 += "<th align='right'>Sum of<br>Squares</th>";
            hasHeader4 = true;
            varNameVector.addElement("sumOfSq");
        }
        if (SkewnessCheckBox.isSelected()) {
            if (SkewnessBiasedRadioButton.isSelected())
                header4 += "<th align='right'>Skewness (biased)</th>";
            else
                header4 += "<th align='right'>Skewness (unbiased)</th>";
            hasHeader4 = true;
            varNameVector.addElement("skewness");
        }        
        if (KurtosisCheckBox.isSelected()) {
            if (KurtosisBiasedRadioButton.isSelected()) {
                if (KurtosisC0RadioButton.isSelected())
                    header4 += "<th align='right'>Kurtosis(biased, centered at 0)</th>";
                else
                    header4 += "<th align='right'>Kurtosis(biased, centered at 3)</th>";
            }
            else {
               if (KurtosisC0RadioButton.isSelected()) 
                    header4 += "<th align='right'>Kurtosis(unbiased, centered at 0)</th>";
                else
                    header4 += "<th align='right'>Kurtosis(unbiased, centered at 3)</th>";
            }
            hasHeader4 = true;
            varNameVector.addElement("kurtosis");
        }          
        if (MSSDCheckBox.isSelected()) {
            header4 += "<th align='right'>MSSD</th>";
            hasHeader4 = true;
            varNameVector.addElement("MSSD");
        }                
        header4 += "</tr>";
        header5 = "<tr><th align='left'>Variable</th>";
        if (hasByVar) {
            header5 += "<th align='left'>Group</th>";
        }        
        if (NnonmissingCheckBox.isSelected()) {
            header5 += "<th align='right'>N<br>nonmissing</th>";
            hasHeader5 = true;
            varNameVector.addElement("Nnonmissing");
        }           
        if (NmissingCheckBox.isSelected()) {
            header5 += "<th align='right'>N<br>missing</th>";
            hasHeader5 = true;
            varNameVector.addElement("Nmissing");
        }     
        if (NtotalCheckBox.isSelected()) {
            header5 += "<th align='right'>N<br>total</th>";
            hasHeader5 = true;
            varNameVector.addElement("Ntotal");
        }               
        header5 += "</tr>";
        header6 = "<tr><th align='left'>Variable</th>";
        if (hasByVar) {
            header6 += "<th align='left'>Group</th>";
        }
        if (CumulativeNCheckBox.isSelected()) {
            header6 += "<th align='right'>Cumulative<br>N</th>";
            hasHeader6 = true;
            varNameVector.addElement("cumN");
        }         
        if (PercentCheckBox.isSelected()) {
            header6 += "<th align='right'>Percent</th>";
            hasHeader6 = true;
            varNameVector.addElement("percent");
        }         
        if (CumulativePercentCheckBox.isSelected()) {
            header6 += "<th align='right'>Cumulative<br>Percent</th>";
            hasHeader6 = true;
            varNameVector.addElement("cumPercent");
        }
        header6 += "</tr>";
        
        // check if text field for trimmed mean is valid
        if (TrimmedMeanCheckBox.isSelected()) {
            double percent;
            try {
                percent = Double.parseDouble(TrimmedPercentTextField.getText());
            }
            catch (NumberFormatException exception) {
                app.showErrorDialog("Enter a valid cutoff percent to compute trimmed mean.");
                return;
            }
        
            if (percent < 0 || percent > 100) {
                app.showErrorDialog("Cutoff percent for trimmed mean must be between 0 and 1.");
                return;
            }      
        }
        
        String result1 = "", result2 = "", result3 = "", result4 = "", 
                result5 = "", result6 = "";
     
        int nonmissing, total, cumTotal, numGroups;
        // for storing the number of nonmissing elements in each group
        int[] nonmissingArray = new int[groupSet.size()];
        
        
        // ----------- for each variable, calculate statistics  -------------
        for (int i = 0; i < columnNumbers.length; ++i) {
            StrColumnVector = ParentSpreadsheet.getColumn(columnNumbers[i]);

            columnLabel = SpreadsheetModel.getColumnLabel(columnNumbers[i]);
           
            if (hasByVar) { // has BY variable    
                ResultVectors = new Vector<Vector<String>>(0);
                cumTotal = 0;
                numGroups = 0;
                for (Iterator iter = groupSet.iterator(); iter.hasNext();) {
                    numGroups++;
                    String groupName = (String) iter.next();
                    // build a vector of doubles just for this group
                    Vector<Cell> subVector = new Vector<Cell>(0);
                    for (int j = 0; j < StrColumnVector.size(); ++j) {
                        String label = byVarColVector.elementAt(j).getContents();
                        if (label.equals(groupName))
                            subVector.addElement(StrColumnVector.elementAt(j));
                    }
                    
                    Object[] values = computeGroupStatistics(subVector, 
                            columnLabel, groupName);
                    if (values == null)
                        return;
                                        
                    ResultVector = (Vector<String>) values[0];
                    ResultVector.insertElementAt(groupName, 0);
                    ResultVectors.addElement(ResultVector);
                    result1 += (String) values[1];
                    result2 += (String) values[2];
                    result3 += (String) values[3];
                    result4 += (String) values[4];
                    result5 += (String) values[5];
                    nonmissing = ((Integer)values[6]).intValue();
                    total = ((Integer)values[7]).intValue();
                    nonmissingArray[numGroups - 1] = nonmissing;
                    cumTotal += total;                  
                }                    
                
                int subtotal = 0;
                double cumPercent = 0;
                numGroups = 0;
                for (Iterator iter = groupSet.iterator(); iter.hasNext();) {
                    String groupName = (String) iter.next();
                    result6 += "<tr><th align='left'>" + columnLabel + "</th>";
                    if (!groupName.equals(""))
                        result6 += "<td align='left'>" + groupName + "</td>"; 
                    subtotal += nonmissingArray[numGroups];
                    double percent = (double) nonmissingArray[numGroups] 
                                / cumTotal * 100;
                    cumPercent += percent;
                    
                    Vector<String> vec = (Vector<String>) ResultVectors.elementAt(numGroups);
                    if (CumulativeNCheckBox.isSelected()) {
                         result6 += "<td align='right'>" + subtotal + "</td>";
                         vec.addElement(subtotal + "");
                    }
                    if (PercentCheckBox.isSelected()) {    
                        result6 += "<td align='right'>" 
                                + HelperFunctions.formatFloat(percent) 
                                + "</td>";
                        vec.addElement(percent + "");
                    }
                    if (CumulativePercentCheckBox.isSelected()) {
                        result6 += "<td align='right'>" 
                                + HelperFunctions.formatFloat(cumPercent) 
                                + "</td>";
                        vec.addElement(cumPercent + "");
                    }
                    result6 += "</tr>";
                    numGroups++;
                }
            }
            else {
                Object[] values = computeGroupStatistics(StrColumnVector, 
                        columnLabel, "");
                if (values == null)
                    return;
                ResultVectors = new Vector<Vector<String>>(0);
                ResultVector = (Vector<String>) values[0];
                result1 += (String) values[1];
                result2 += (String) values[2];
                result3 += (String) values[3];
                result4 += (String) values[4];
                result5 += (String) values[5];
                nonmissing = ((Integer)values[6]).intValue();
                total = ((Integer)values[7]).intValue();
                double percent = (double) nonmissing / total;
                result6 += "<tr><th align='left'>" + columnLabel + "</th>";
                if (CumulativeNCheckBox.isSelected()) {
                    ResultVector.addElement(nonmissing + "");
                    result6 += "<td align='right'>" + nonmissing + "</td>";
                }
                if (PercentCheckBox.isSelected()) {
                    ResultVector.addElement(percent + "");
                    result6 += "<td align='right'>" 
                                + HelperFunctions.formatFloat(percent) 
                                + "</td>";
                }
                if (CumulativePercentCheckBox.isSelected()) {
                    ResultVector.addElement(percent + "");
                    result6 += "<td align='right'>" 
                                + HelperFunctions.formatFloat(percent) 
                                + "</td>";
                }                                
                result6 += "</tr>";
                // add this result vector to the vector of result vectors
                ResultVectors.addElement(ResultVector);                               
            }
            // add space between rows for different variables
            /*
            if (i < columnNumbers.length - 1) {
                result1 += "<tr></tr>";
                result2 += "<tr></tr>";
                result3 += "<tr></tr>";
                result4 += "<tr></tr>";
                result5 += "<tr></tr>";
                result6 += "<tr></tr>";
            }*/
            
            // store results in new spreadsheet
            if (StoreResultCheckBox.isSelected()) {
                Spreadsheet ThisSpreadsheet = new Spreadsheet(app);
                app.getDatasheetTabbedPane().addDatasheet(ThisSpreadsheet);
                ThisSpreadsheet.setData(ResultVectors);
                ThisSpreadsheet.setVariablesRow(varNameVector);
                app.getDatasheetTabbedPane().setCurrentTabTitle("DS: "+columnLabel+"*");
            }            
        }
        
        // print results
        app.addLogHeading("Descriptive Statistics");
        if (hasHeader1)
            app.addLogText("<table border='1' cellpadding='3'>" + header1 + result1 + "</table><br>");
        if (hasHeader2)
            app.addLogText("<table border='1' cellpadding='3'>" + header2 + result2 + "</table><br>");
        if (hasHeader3)
            app.addLogText("<table border='1' cellpadding='3'>" + header3 + result3 + "</table><br>");
        if (hasHeader4)
            app.addLogText("<table border='1' cellpadding='3'>" + header4 + result4 + "</table><br>");
        if (hasHeader5)
            app.addLogText("<table border='1' cellpadding='3'>" + header5 + result5 + "</table><br>");
        if (hasHeader6)
            app.addLogText("<table border='1' cellpadding='3'>" + header6 + result6 + "</table><br>");        
        
        
        app.compoundEdit.end();
        app.addCompoundEdit(app.compoundEdit);
        
        // close dialog
        setVisible(false);
    }//GEN-LAST:event_OKButtonActionPerformed

    // compute descriptive statistics of a group of values
    // given a vector of Cell values, and the label of the group
    // returns an object array containing
    // [Vector<String> resultVector, String result1, String result2, 
    //  String result3, String result4, String result5,
    // int nonmissingCount, int totalCount
    private Object[] computeGroupStatistics(Vector<Cell> StrColumnVector, 
            String columnLabel, String groupLabel) {
        Vector<Double> ColumnVector;
        Vector<String> ResultVector;
        int missing, nonmissing, total;
        
        String result1 = "", result2 = "", result3 = "", result4 = "", result5 = "";

        
        ColumnVector = HelperFunctions.ConvertInputVectorToDoubles(StrColumnVector);
        //System.out.println(HelperFunctions.ConvertDoubleVectorToString(ColumnVector));

        if (ColumnVector == null) {
            app.showErrorDialog("Invalid input column " + columnLabel +
                    ": all data must be numbers.");
            return null;            
        }        

        nonmissing = BasicStatistics.Nnonmissing(ColumnVector);
        if (groupLabel.equals("")) {
            missing = BasicStatistics.Nmissing(ColumnVector);
            total = BasicStatistics.Ntotal(ColumnVector);
        }
        else { // for a group
            total = ColumnVector.size(); // don't ignore null values in total size
            missing = total - nonmissing;
        }
            
        ResultVector = new Vector<String>(0);   
        
        result1 += "<tr><th align='left'>" + columnLabel + "</th>";
        if (!groupLabel.equals(""))
            result1 += "<td align='left'>" + groupLabel + "</td>";
        
        // compute statistics
        if (MeanCheckBox.isSelected()) {    // mean
            Double mean = BasicStatistics.mean(ColumnVector);
            String mea;
            if (mean == null)
                mea = "*";
            else
                mea = HelperFunctions.formatFloat(mean);
            ResultVector.addElement(mea);
            result1 += "<td align='right'>" + mea + "</td>";
        }
        if (SEMeanCheckBox.isSelected()) {
            Double SEmean = BasicStatistics.SEmean(ColumnVector);
            String q;
            if (SEmean == null)
                q = "*";
            else
                q = HelperFunctions.formatFloat(SEmean);
            ResultVector.addElement(q);
            result1 += "<td align='right'>" + q + "</td>";
        }
        if (StdevCheckBox.isSelected()) {
            Double stdev = BasicStatistics.stdev(ColumnVector);
            String q;
            if (stdev == null)
                q = "*";
            else
                q = HelperFunctions.formatFloat(stdev);
            ResultVector.addElement(q);
            result1 += "<td align='right'>" + q + "</td>";
        }
        if (VarianceCheckBox.isSelected()) {
            Double variance = BasicStatistics.variance(ColumnVector);
            String q;
            if (variance == null)
                q = "*";
            else
                q = HelperFunctions.formatFloat(variance);
            ResultVector.addElement(q);
            result1 += "<td align='right'>" + q + "</td>";
        }
        if (CoeffVarCheckBox.isSelected()) {
            Double coeffVar = BasicStatistics.coefficientOfVariance(ColumnVector);
            String q;
            if (coeffVar == null)
                q = "*";
            else
                q = HelperFunctions.formatFloat(coeffVar);
            ResultVector.addElement(q);
            result1 += "<td align='right'>" + q + "</td>";
        }
        
        result1 += "</tr>";
        result2 += "<tr><th align='left'>" + columnLabel + "</th>";
        if (!groupLabel.equals(""))
            result2 += "<td align='left'>" + groupLabel + "</td>";
        
        if (FirstQuartileCheckBox.isSelected()) {
            Double quartile1 = BasicStatistics.firstQuartile(ColumnVector);
            String q1;
            if (quartile1 == null)
                q1 = "*";
            else
                q1 = HelperFunctions.formatFloat(quartile1);
            ResultVector.addElement(q1 + "");
            result2 += "<td align='right'>" + q1 + "</td>";
        }
        if (MedianCheckBox.isSelected()) {
            Double median = BasicStatistics.median(ColumnVector);
            String med;
            if (median == null)
                med = "*";
            else
                med = HelperFunctions.formatFloat(median);
            ResultVector.addElement(med + "");
            result2 += "<td align='right'>" + med + "</td>";
        }
        if (ThirdQuartileCheckBox.isSelected()) {
            Double quartile = BasicStatistics.thirdQuartile(ColumnVector);
            String q;
            if (quartile == null)
                q = "*";
            else
                q = HelperFunctions.formatFloat(quartile);
            ResultVector.addElement(q + "");
            result2 += "<td align='right'>" + q + "</td>";
        }
        if (InterquartileRangeCheckBox.isSelected()) {
            Double IRQ = BasicStatistics.interquartileRange(ColumnVector);
            String q;
            if (IRQ == null)
                q = "*";
            else
                q = HelperFunctions.formatFloat(IRQ);
            ResultVector.addElement(q + "");
            result2 += "<td align='right'>" + q + "</td>";
        }
        if (ModeCheckBox.isSelected()) {
            Object[] results = BasicStatistics.mode(ColumnVector);
            Vector<Double> modes = (Vector<Double>)results[0];
            int numOcc = ((Integer)results[1]).intValue();
            String modesStr;
            
            if (modes.size() == 0)
                modesStr = "*";
            else {
                // put modes in one string
                modesStr = "";
                for (Enumeration e = modes.elements(); e.hasMoreElements();) {
                    double num = ((Double)e.nextElement()).doubleValue();
                    if (!modesStr.equals(""))
                        modesStr += ", ";
                    modesStr += num;
                }
            }
            ResultVector.addElement(modesStr);
            result2 += "<td align='right'>" + modesStr + "</td>";
            result2 += "<td align='right'>" + numOcc + "</td>";
        }
        
        result2 += "</tr>";        
        result3 += "<tr><th align='left'>" + columnLabel + "</th>";
        if (!groupLabel.equals(""))
            result3 += "<td align='left'>" + groupLabel + "</td>";        
        
        if (TrimmedMeanCheckBox.isSelected()) {    // trimmed mean
            try {
                double tpercent = Double.parseDouble(TrimmedPercentTextField.getText());
                if (tpercent < 0 || tpercent > 100) {
                    app.showErrorDialog("Enter a valid percent for trimmed mean");
                    return null;
                }
                Double TrMean = BasicStatistics.trimmedMean(ColumnVector, tpercent);
                String q;
                if (TrMean == null)
                    q = "*";
                else
                    q = HelperFunctions.formatFloat(TrMean);
                ResultVector.addElement(q + "");
                result3 += "<td align='right'>" + q + "</td>";
            }
            catch (NumberFormatException e) {
                app.showErrorDialog("Enter a valid percent for trimmed mean");
                return null;
            }
        }
        if (SumCheckBox.isSelected()) {
            double sum = BasicStatistics.sum(ColumnVector);
            ResultVector.addElement(sum + "");
            result3 += "<td align='right'>" + HelperFunctions.formatFloat(sum) + "</td>";
        }
        if (MinCheckBox.isSelected()) {
            Double min = BasicStatistics.min(ColumnVector);
            String m;
            if (min == null)
                m = "*";
            else 
                m = HelperFunctions.formatFloat(min);
            ResultVector.addElement(m);
            result3 += "<td align='right'>" + m + "</td>";
        }
        if (MaxCheckBox.isSelected()) {
            Double max = BasicStatistics.max(ColumnVector);
            String m;
            if (max == null)
                m = "*";
            else
                m = HelperFunctions.formatFloat(max);
            ResultVector.addElement(m);
            result3 += "<td align='right'>" + m + "</td>";
        }
        if (RangeCheckBox.isSelected()) {
            Double range = BasicStatistics.range(ColumnVector);
            String r;
            if (range == null)
                r = "*";
            else 
                r = HelperFunctions.formatFloat(range);
            ResultVector.addElement(r);
            result3 += "<td align='right'>" + r + "</td>";
        }
        
        result3 += "</tr>";      
        result4 += "<tr><th align='left'>" + columnLabel + "</th>";
        if (!groupLabel.equals(""))
            result4 += "<td align='left'>" + groupLabel + "</td>";
        
        if (SumOfSqCheckBox.isSelected()) {
            double sumOfSq = BasicStatistics.sumOfSquares(ColumnVector);
            ResultVector.addElement(sumOfSq + "");
            result4 += "<td align='right'>" + HelperFunctions.formatFloat(sumOfSq) + "</td>";
        }
        if (SkewnessCheckBox.isSelected()) {
            Double skew;
            if (SkewnessBiasedRadioButton.isSelected())
                skew = BasicStatistics.skewnessBiased(ColumnVector);
            else // unbiased
                skew = BasicStatistics.skewness(ColumnVector);
            String q;
            if (skew == null)
                q = "*";
            else
                q = HelperFunctions.formatFloat(skew);
            ResultVector.addElement(q);
            result4 += "<td align='right'>" + q + "</td>";
        }
        if (KurtosisCheckBox.isSelected()) {
            Double kurtosis;
            if (KurtosisBiasedRadioButton.isSelected()) {
                if (KurtosisC0RadioButton.isSelected())
                    kurtosis = BasicStatistics.kurtosisBiased(ColumnVector);
                else
                    kurtosis = BasicStatistics.kurtosisBiasedCentered3(ColumnVector);
            }
            else { // unbiased
                if (KurtosisC0RadioButton.isSelected())
                    kurtosis = BasicStatistics.kurtosis(ColumnVector);
                else
                    kurtosis = BasicStatistics.kurtosisCentered3(ColumnVector);
            }
            
            String q;
            if (kurtosis == null)
                q = "*";
            else
                q = HelperFunctions.formatFloat(kurtosis);
            ResultVector.addElement(q);
            result4 += "<td align='right'>" + q + "</td>";
        }
        if (MSSDCheckBox.isSelected()) {
            Double sum = BasicStatistics.MSSD(ColumnVector);
            String q;
            if (sum == null)
                q = "*";
            else
                q = HelperFunctions.formatFloat(sum);
            ResultVector.addElement(q);
            result4 += "<td align='right'>" + q + "</td>";
        }
        
        result4 += "</tr>";
        result5 += "<tr><th align='left'>" + columnLabel + "</th>";
        if (!groupLabel.equals(""))
            result5 += "<td align='left'>" + groupLabel + "</td>";        
        
        if (NnonmissingCheckBox.isSelected()) {
            ResultVector.addElement(nonmissing + "");
            result5 += "<td align='right'>" + nonmissing + "</td>";
        }
        if (NmissingCheckBox.isSelected()) {
            ResultVector.addElement(missing + "");
            result5 += "<td align='right'>" + missing + "</td>";
        }
        if (NtotalCheckBox.isSelected()) {
            ResultVector.addElement(total + "");
            result5 += "<td align='right'>" + total + "</td>";
        }

        result5 += "</tr>";
        
        Object[] returnValues = new Object[8];
        returnValues[0] = ResultVector;
        returnValues[1] = result1;
        returnValues[2] = result2;
        returnValues[3] = result3;
        returnValues[4] = result4;
        returnValues[5] = result5;
        returnValues[6] = new Integer(nonmissing);
        returnValues[7] = new Integer(total);
        
        return returnValues;
    }
    
    private void CancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_CancelButtonActionPerformed
        // close dialog
        setVisible(false);      
    }//GEN-LAST:event_CancelButtonActionPerformed

    private void TrimmedMeanCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_TrimmedMeanCheckBoxActionPerformed
        // enable trimmed mean percentage text field
        if (TrimmedMeanCheckBox.isSelected())
            TrimmedPercentTextField.setEnabled(true);
        else
            TrimmedPercentTextField.setEnabled(false);
    }//GEN-LAST:event_TrimmedMeanCheckBoxActionPerformed

    private void ByVarComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_ByVarComboBoxActionPerformed
        /*
        String byVarLabel = ByVarComboBox.getSelectedItem().toString();
        if (byVarLabel.equals("")) // no BY var
            StoreResultCheckBox.setEnabled(true);
        else
            StoreResultCheckBox.setEnabled(false);
         * */
    }//GEN-LAST:event_ByVarComboBoxActionPerformed

    private void SelectAllCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_SelectAllCheckBoxActionPerformed
        if (SelectAllCheckBox.isSelected())
            toggleAllCheckBoxes(true);
        else
            toggleAllCheckBoxes(false);
        TrimmedPercentTextField.setEnabled(true);
}//GEN-LAST:event_SelectAllCheckBoxActionPerformed

    private void SkewnessCheckBoxStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_SkewnessCheckBoxStateChanged
        if (SkewnessCheckBox.isSelected()) {
            SkewnessPanel.setVisible(true);
        }
        else {
            SkewnessPanel.setVisible(false);
        }
    }//GEN-LAST:event_SkewnessCheckBoxStateChanged

    private void KurtosisCheckBoxStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_KurtosisCheckBoxStateChanged
        if (KurtosisCheckBox.isSelected()) {
            KurtosisPanel.setVisible(true);
        }
        else {
            KurtosisPanel.setVisible(false);
        }
    }//GEN-LAST:event_KurtosisCheckBoxStateChanged
 
    // set all the check boxes to the given states
    private void toggleAllCheckBoxes(boolean state) {
        CoeffVarCheckBox.setSelected(state);
        CumulativeNCheckBox.setSelected(state);
        CumulativePercentCheckBox.setSelected(state);
        FirstQuartileCheckBox.setSelected(state);
        InterquartileRangeCheckBox.setSelected(state);
        KurtosisCheckBox.setSelected(state);
        MSSDCheckBox.setSelected(state);
        MaxCheckBox.setSelected(state);
        MeanCheckBox.setSelected(state);
        MedianCheckBox.setSelected(state);
        MinCheckBox.setSelected(state);
        ModeCheckBox.setSelected(state);
        NmissingCheckBox.setSelected(state);
        NnonmissingCheckBox.setSelected(state);
        NtotalCheckBox.setSelected(state);
        PercentCheckBox.setSelected(state);
        RangeCheckBox.setSelected(state);
        SEMeanCheckBox.setSelected(state);
        SkewnessCheckBox.setSelected(state);
        StdevCheckBox.setSelected(state);
        SumCheckBox.setSelected(state);
        SumOfSqCheckBox.setSelected(state);
        ThirdQuartileCheckBox.setSelected(state);
        TrimmedMeanCheckBox.setSelected(state);
        VarianceCheckBox.setSelected(state);
    }
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JComboBox ByVarComboBox;
    private javax.swing.JButton CancelButton;
    private javax.swing.JCheckBox CoeffVarCheckBox;
    private javax.swing.JCheckBox CumulativeNCheckBox;
    private javax.swing.JCheckBox CumulativePercentCheckBox;
    private javax.swing.JCheckBox FirstQuartileCheckBox;
    private javax.swing.JTextField InputTextField;
    private javax.swing.JCheckBox InterquartileRangeCheckBox;
    private javax.swing.JRadioButton KurtosisBiasedRadioButton;
    private javax.swing.JRadioButton KurtosisC0RadioButton;
    private javax.swing.JRadioButton KurtosisC3RadioButton;
    private javax.swing.JCheckBox KurtosisCheckBox;
    private javax.swing.JPanel KurtosisPanel;
    private javax.swing.JRadioButton KurtosisUnbiasedRadioButton;
    private javax.swing.JCheckBox MSSDCheckBox;
    private javax.swing.JCheckBox MaxCheckBox;
    private javax.swing.JCheckBox MeanCheckBox;
    private javax.swing.JCheckBox MedianCheckBox;
    private javax.swing.JCheckBox MinCheckBox;
    private javax.swing.JCheckBox ModeCheckBox;
    private javax.swing.JCheckBox NmissingCheckBox;
    private javax.swing.JCheckBox NnonmissingCheckBox;
    private javax.swing.JCheckBox NtotalCheckBox;
    private javax.swing.JButton OKButton;
    private javax.swing.JCheckBox PercentCheckBox;
    private javax.swing.JCheckBox RangeCheckBox;
    private javax.swing.JCheckBox SEMeanCheckBox;
    private javax.swing.JCheckBox SelectAllCheckBox;
    private javax.swing.JRadioButton SkewnessBiasedRadioButton;
    private javax.swing.JCheckBox SkewnessCheckBox;
    private javax.swing.JPanel SkewnessPanel;
    private javax.swing.JRadioButton SkewnessUnbiasedRadioButton;
    private javax.swing.JCheckBox StdevCheckBox;
    private javax.swing.JCheckBox StoreResultCheckBox;
    private javax.swing.JCheckBox SumCheckBox;
    private javax.swing.JCheckBox SumOfSqCheckBox;
    private javax.swing.JCheckBox ThirdQuartileCheckBox;
    private javax.swing.JCheckBox TrimmedMeanCheckBox;
    private javax.swing.JTextField TrimmedPercentTextField;
    private javax.swing.JCheckBox VarianceCheckBox;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JLabel jLabel6;
    private javax.swing.JLabel jLabel8;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JPanel jPanel3;
    private javax.swing.JPanel jPanel4;
    private javax.swing.JPanel jPanel5;
    private javax.swing.JPanel jPanel6;
    private javax.swing.JPanel jPanel7;
    private javax.swing.JPanel jPanel8;
    // End of variables declaration//GEN-END:variables
    
}
