/*
* 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.stats.irt.rasch;
import java.sql.*;
import java.util.ArrayList;
import com.itemanalysis.jmetrik.dao.DatabaseAccessObject;
import com.itemanalysis.jmetrik.sql.DataTableName;
import com.itemanalysis.jmetrik.sql.VariableTableName;
import com.itemanalysis.psychometrics.data.DataType;
import com.itemanalysis.psychometrics.data.ItemType;
import com.itemanalysis.psychometrics.data.VariableAttributes;
import com.itemanalysis.psychometrics.data.VariableName;
import com.itemanalysis.psychometrics.irt.estimation.IrtEstimation;
import com.itemanalysis.psychometrics.irt.estimation.ItemResponseVector;
import com.itemanalysis.psychometrics.irt.estimation.JointMaximumLikelihoodEstimation;
import com.itemanalysis.psychometrics.irt.model.ItemResponseModel;
import org.apache.log4j.Logger;
/**
*
* Creates a database table that contains the residuals values from a set of item response models.
*
* @author J. Patrick Meyer
*/
public class IrtResidualOut {
private JointMaximumLikelihoodEstimation jmle = null;
private ArrayList<VariableAttributes> variables = null;
private Connection conn = null;
private DatabaseAccessObject dao = null;
private DataTableName tableName = null;
private DataTableName newTableName = null;
static Logger logger = Logger.getLogger("jmetrik-logger");
private ItemResponseVector[] itemResponseVector = null;
private ItemResponseModel[] irm = null;
private double[] theta = null;
private int numberOfPeople = 0;
private int numberOfItems = 0;
private boolean usingJmle = true;
/**
* Use this constructor when saving a residual table from JointMaximumLikelihoodEstimation.java.
* @param conn
* @param dao
* @param jmle
* @param tableName
* @param newTableName
*/
public IrtResidualOut(Connection conn, DatabaseAccessObject dao, JointMaximumLikelihoodEstimation jmle, DataTableName tableName, DataTableName newTableName){
this.conn = conn;
this.dao = dao;
this.jmle = jmle;
this.tableName = tableName;
this.newTableName = newTableName;
this.irm = jmle.getItems();
numberOfPeople = jmle.getNumberOfPeople();
numberOfItems = irm.length;
usingJmle = true;
createVariables();
}
/**
* Use this constructor for saving a residual table from MarginalMaximumLikelihoodEstimation.java.
*
* @param conn
* @param dao
* @param itemResponseVector
* @param theta
* @param irm
* @param tableName
* @param newTableName
*/
public IrtResidualOut(Connection conn, DatabaseAccessObject dao, ItemResponseVector[] itemResponseVector, double[] theta, ItemResponseModel[] irm, DataTableName tableName, DataTableName newTableName){
this.conn = conn;
this.dao = dao;
this.tableName = tableName;
this.newTableName = newTableName;
this.itemResponseVector = itemResponseVector;
this.theta = theta;
this.irm = irm;
numberOfPeople = itemResponseVector.length;//NOTE: assumes one response vector per examinee.
numberOfItems = irm.length;
usingJmle = false;
createVariables();
}
private void createVariables(){
int column = 0;
variables = new ArrayList<VariableAttributes>();
VariableAttributes vInfo = null;
String name = "";
for(int j=0;j<numberOfItems;j++){
name = irm[j].getName().toString();
vInfo = new VariableAttributes(name, (name + " residual"), ItemType.NOT_ITEM, DataType.DOUBLE, ++column, "");
variables.add(vInfo);
}
}
public void outputToDb()throws SQLException{
PreparedStatement pstmt = null;
try{
//start transaction
conn.setAutoCommit(false);
int nrow = 0;
int ncol = variables.size();
VariableTableName variableTableName = new VariableTableName(newTableName.toString());
dao.createTables(conn, newTableName, variableTableName, variables);
String updateString = "INSERT INTO " + newTableName.getNameForDatabase() + " VALUES(";
for(int i=0;i<ncol;i++){
updateString+= "?";
if(i<ncol-1){
updateString+=",";
}else{
updateString+=")";
}
}
pstmt = conn.prepareStatement(updateString);
double residual = 0.0;
if(usingJmle){
for(int i=0;i<numberOfPeople;i++){
//compute residuals and add to db
for(int j=0;j<numberOfItems;j++){
residual = jmle.getResidualAt(i, j);
if(Double.isNaN(residual)){
pstmt.setNull(variables.get(j).positionInDb(), Types.DOUBLE);
}else{
pstmt.setDouble(variables.get(j).positionInDb(), residual);
}
}
pstmt.executeUpdate();
nrow++;
}
}else{
for(int i=0;i<numberOfPeople;i++){
//compute residuals and add to db
for(int j=0;j<numberOfItems;j++){
residual = itemResponseVector[i].getResponseAt(j) - irm[j].expectedValue(theta[i]);
if(Double.isNaN(residual)){
pstmt.setNull(variables.get(j).positionInDb(), Types.DOUBLE);
}else{
pstmt.setDouble(variables.get(j).positionInDb(), residual);
}
}
pstmt.executeUpdate();
nrow++;
}
}
//add row count to row count table
dao.setTableInformation(conn, newTableName, nrow, "IRT table of residuals for analysis of " +
tableName.toString() + ".");
conn.commit();
}catch(SQLException ex){
conn.rollback();
logger.fatal(ex.getMessage(), ex);
throw new SQLException(ex.getMessage());
}finally{
conn.setAutoCommit(true);
if(pstmt!=null) pstmt.close();
}
}
}