Java tutorial
/* * 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."); } } }