com.itemanalysis.jmetrik.graph.density.DensityAnalysis.java Source code

Java tutorial

Introduction

Here is the source code for com.itemanalysis.jmetrik.graph.density.DensityAnalysis.java

Source

/*
 * Copyright (c) 2012 Patrick Meyer
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.itemanalysis.jmetrik.graph.density;

import com.itemanalysis.jmetrik.dao.DatabaseAccessObject;
import com.itemanalysis.jmetrik.dao.DatabaseType;
import com.itemanalysis.jmetrik.dao.JmetrikDatabaseFactory;
import com.itemanalysis.jmetrik.sql.DataTableName;
import com.itemanalysis.jmetrik.sql.VariableTableName;
import com.itemanalysis.jmetrik.workspace.JmetrikPreferencesManager;
import com.itemanalysis.jmetrik.workspace.VariableChangeEvent;
import com.itemanalysis.jmetrik.workspace.VariableChangeListener;
import com.itemanalysis.psychometrics.data.VariableAttributes;
import com.itemanalysis.psychometrics.distribution.UniformDistributionApproximation;
import com.itemanalysis.psychometrics.kernel.*;
import com.itemanalysis.psychometrics.tools.StopWatch;
import com.itemanalysis.squiggle.base.SelectQuery;
import com.itemanalysis.squiggle.base.Table;
import org.apache.commons.math3.stat.descriptive.rank.Max;
import org.apache.commons.math3.stat.descriptive.rank.Min;
import org.apache.commons.math3.util.ResizableDoubleArray;
import org.apache.log4j.Logger;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;

import javax.swing.*;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.TreeMap;

public class DensityAnalysis extends SwingWorker<DensityPanel, Void> {

    private DensityCommand command = null;
    private DensityPanel densityPanel = null;
    private Throwable theException = null;
    private Connection conn = null;
    private static int KERNEL_POINTS = 500;
    public StopWatch sw = null;
    static Logger logger = Logger.getLogger("jmetrik-logger");
    static Logger scriptLogger = Logger.getLogger("jmetrik-script-logger");
    public boolean hasGroupingVariable = false;
    private VariableAttributes variable = null;
    private VariableAttributes groupVar = null;
    private DataTableName tableName = null;
    private int progressValue = 0;
    private int lineNumber = 0;
    private double maxProgress = 0.0;
    private DatabaseAccessObject dao = null;
    private ArrayList<VariableChangeListener> variableChangeListeners = null;

    public DensityAnalysis(Connection conn, DatabaseAccessObject dao, DensityCommand command,
            DensityPanel densityPanel) {
        this.conn = conn;
        this.dao = dao;
        this.command = command;
        this.densityPanel = densityPanel;
        variableChangeListeners = new ArrayList<VariableChangeListener>();
    }

    private void updateProgress() {
        progressValue = (int) ((100 * ((double) lineNumber + 1.0)) / maxProgress);
        setProgress(Math.max(0, Math.min(100, progressValue)));
        lineNumber++;
    }

    public XYSeriesCollection summarize() throws SQLException, IllegalArgumentException {
        Statement stmt = null;
        ResultSet rs = null;
        TreeMap<String, ResizableDoubleArray> data = new TreeMap<String, ResizableDoubleArray>();

        //set progress bar information
        int nrow = 0;
        JmetrikPreferencesManager pref = new JmetrikPreferencesManager();
        String dbType = pref.getDatabaseType();
        if (DatabaseType.APACHE_DERBY.toString().equals(dbType)) {
            JmetrikDatabaseFactory dbFactory = new JmetrikDatabaseFactory(DatabaseType.APACHE_DERBY);
            nrow = dao.getRowCount(conn, tableName);
        } else {
            //add other databases here when functionality is added
        }
        maxProgress = (double) nrow;

        Table sqlTable = new Table(tableName.getNameForDatabase());
        SelectQuery select = new SelectQuery();
        select.addColumn(sqlTable, variable.getName().nameForDatabase());
        if (hasGroupingVariable)
            select.addColumn(sqlTable, groupVar.getName().nameForDatabase());
        stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        rs = stmt.executeQuery(select.toString());

        String conditionalName = "";
        ResizableDoubleArray cData = null;
        double value = Double.NaN;

        while (rs.next()) {
            if (groupVar != null) {
                String groupName = rs.getString(groupVar.getName().nameForDatabase());
                if (rs.wasNull()) {
                    groupName = "";
                }
                conditionalName = groupName;
            } else {
                conditionalName = "Series 1";
            }

            cData = data.get(conditionalName);
            if (cData == null) {
                cData = new ResizableDoubleArray((int) maxProgress);
                data.put(conditionalName, cData);
            }
            value = rs.getDouble(variable.getName().nameForDatabase());
            if (!rs.wasNull()) {
                cData.addElement(value);
            }
            updateProgress();
        }
        rs.close();
        stmt.close();

        String kType = command.getSelectOneOption("kernel").getSelectedArgument();
        double adjustment = command.getFreeOption("adjust").getDouble();
        KernelFactory kernelFactory = new KernelFactory(kType);

        KernelFunction kernelFunction = kernelFactory.getKernelFunction();
        Bandwidth bandwidth = null;
        KernelDensity density = null;
        UniformDistributionApproximation uniform = null;
        Min min = new Min();
        Max max = new Max();
        double[] x = null;

        this.firePropertyChange("progress-ind-on", null, null);

        XYSeriesCollection seriesCollection = new XYSeriesCollection();
        XYSeries series = null;
        for (String s : data.keySet()) {
            series = new XYSeries(s);
            x = data.get(s).getElements();
            bandwidth = new ScottsBandwidth(x, adjustment);
            uniform = new UniformDistributionApproximation(min.evaluate(x), max.evaluate(x), KERNEL_POINTS);
            density = new KernelDensity(kernelFunction, bandwidth, uniform);

            double[] dens = density.evaluate(x);
            double[] points = density.getPoints();
            for (int i = 0; i < dens.length; i++) {
                series.add(points[i], dens[i]);
            }
            seriesCollection.addSeries(series);
        }
        return seriesCollection;

    }

    protected DensityPanel doInBackground() {
        sw = new StopWatch();
        this.firePropertyChange("status", "", "Running Density Analysis...");
        this.firePropertyChange("progress-on", null, null);
        try {
            //get variable info from db
            tableName = new DataTableName(command.getPairedOptionList("data").getStringAt("table"));
            String selectVariable = command.getFreeOption("variable").getString();
            variable = dao.getVariableAttributes(conn, new VariableTableName(tableName.toString()), selectVariable);
            if (command.getFreeOption("groupvar").hasValue()) {
                String groupByName = command.getFreeOption("groupvar").getString();
                groupVar = dao.getVariableAttributes(conn, new VariableTableName(tableName.toString()),
                        groupByName);
                hasGroupingVariable = true;
            }

            densityPanel.updateDataset(summarize());
            firePropertyChange("status", "", "Done: " + sw.getElapsedTime());
            firePropertyChange("progress-off", null, null); //make statusbar progress not visible
        } catch (Throwable t) {
            logger.fatal(t.getMessage(), t);
            theException = t;
        }

        return densityPanel;
    }

    //===============================================================================================================
    //Handle variable changes here
    //===============================================================================================================
    public synchronized void addVariableChangeListener(VariableChangeListener l) {
        variableChangeListeners.add(l);
    }

    public synchronized void removeVariableChangeListener(VariableChangeListener l) {
        variableChangeListeners.remove(l);
    }

    public synchronized void removeAllVariableChangeListeners() {
        variableChangeListeners.clear();
    }

    public void fireVariableChanged(VariableChangeEvent event) {
        System.out
                .println("TestSclingAnalysis: firing variable changed=" + event.getVariable().getName().toString());
        for (VariableChangeListener l : variableChangeListeners) {
            l.variableChanged(event);
        }
    }
    //===============================================================================================================

    @Override
    protected void done() {
        try {
            if (theException != null) {
                logger.fatal(theException.getMessage(), theException);
                firePropertyChange("error", "", "Error - Check log for details.");
            }
            scriptLogger.info(command.paste());
        } catch (Exception ex) {
            logger.fatal(theException.getMessage(), theException);
            firePropertyChange("error", "", "Error - Check log for details.");
        }
    }

}