/*
Copyright (C) 2011 Diego Darriba, David Posada
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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package es.uvigo.darwin.jmodeltest.gui;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Point;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JMenuBar;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;
import javax.swing.border.LineBorder;
import javax.swing.plaf.BorderUIResource;
import es.uvigo.darwin.jmodeltest.statistics.Statistics;
import es.uvigo.darwin.jmodeltest.utilities.Utilities;
public class Frame_LRTcalculator extends JModelTestFrame {
private static final long serialVersionUID = 3100651418525568495L;
private JPanel jPanelLRTsettings = new JPanel();
private JButton jButtonRunLRT = new JButton();
private JButton jButtonCancelLRT = new JButton();
private JButton jButtonDefaultLRT = new JButton();
private JTextField jTextFieldLRT0 = new JTextField();
private JTextField jTextFieldLRT1 = new JTextField();
private JLabel jLabelLRTpvalue = new JLabel();
private JLabel jLabelLRT = new JLabel();
private JTextField jTextFieldLRTdf = new JTextField();
private JPanel PanelChi2Type = new JPanel();
private JRadioButton ButtonStandardChi = new JRadioButton();
private JRadioButton ButtonMixedChi = new JRadioButton();
private ButtonGroup ButtonGroupChi = new ButtonGroup();
public Frame_LRTcalculator() {
}
public void initComponents() throws Exception {
// Dimensions(width, height));
jPanelLRTsettings.setSize(new java.awt.Dimension(480, 270));
jPanelLRTsettings.setBorder(new BorderUIResource.TitledBorderUIResource(new LineBorder(new java.awt.Color(153, 153, 153), 1, false), "Likelihood Ratio Test for Nested Models", 4, 2, new java.awt.Font("Application", 1, 10), new java.awt.Color(102, 102, 153)));
jPanelLRTsettings.setLocation(new java.awt.Point(10, 10));
jPanelLRTsettings.setVisible(true);
jPanelLRTsettings.setLayout(null);
jTextFieldLRT0.setToolTipText("Enter here the absolute log likelihood of the simple model");
jTextFieldLRT0.setBorder(new BorderUIResource.TitledBorderUIResource(new LineBorder(new java.awt.Color(153, 153, 153), 1, false), "-lnL null model", 4, 2, new java.awt.Font("Application", 1, 10), new java.awt.Color(102, 102, 153)));
jTextFieldLRT0.setVisible(true);
jTextFieldLRT0.setSize(new java.awt.Dimension(150, 50));
jTextFieldLRT0.setLocation(new java.awt.Point(30, 30));
jTextFieldLRT1.setToolTipText("Enter here the absolute log likelihood of the complex model");
jTextFieldLRT1.setBorder(new BorderUIResource.TitledBorderUIResource(new LineBorder(new java.awt.Color(153, 153, 153), 1, false), "-ln alternative model", 4, 2, new java.awt.Font("Application", 1, 10), new java.awt.Color(102, 102, 153)));
jTextFieldLRT1.setVisible(true);
jTextFieldLRT1.setSize(new java.awt.Dimension(150, 50));
jTextFieldLRT1.setLocation(new java.awt.Point(220, 30));
jTextFieldLRTdf.setToolTipText("Enter here the difference in free parameters between the two models");
jTextFieldLRTdf.setBorder(new BorderUIResource.TitledBorderUIResource(new LineBorder(new java.awt.Color(153, 153, 153), 1, false), "degrees of freedom", 4, 2, new java.awt.Font("Application", 1, 10), new java.awt.Color(102, 102, 153)));
jTextFieldLRTdf.setVisible(true);
jTextFieldLRTdf.setSize(new java.awt.Dimension(150, 50));
jTextFieldLRTdf.setLocation(new java.awt.Point(30, 90));
jLabelLRT.setSize(new java.awt.Dimension(330, 40));
jLabelLRT.setLocation(new java.awt.Point(30, 145));
jLabelLRT.setVisible(true);
jLabelLRT.setText("LRT = ");
jLabelLRTpvalue.setSize(new java.awt.Dimension(330, 40));
jLabelLRTpvalue.setLocation(new java.awt.Point(30, 175));
jLabelLRTpvalue.setVisible(true);
jLabelLRTpvalue.setText("P-value =");
PanelChi2Type.setSize(new java.awt.Dimension(210, 50));
PanelChi2Type.setBorder(new BorderUIResource.TitledBorderUIResource(new LineBorder(new java.awt.Color(153, 153, 153), 1, false), "Chi-square distribution", 4, 2, new java.awt.Font("Application", 1, 10), new java.awt.Color(102, 102, 153)));
PanelChi2Type.setLocation(new java.awt.Point(220, 90));
PanelChi2Type.setVisible(true);
PanelChi2Type.setLayout(null);
ButtonStandardChi.setVisible(true);
ButtonStandardChi.setSize(new java.awt.Dimension(100, 20));
ButtonStandardChi.setText("Standard");
ButtonStandardChi.setLocation(new java.awt.Point(20, 20));
ButtonStandardChi.setToolTipText("Select this if the value of the restricted parameter in the null model is not at the boundary of its range");
ButtonStandardChi.setSelected(true);
ButtonMixedChi.setVisible(true);
ButtonMixedChi.setSize(new java.awt.Dimension(70, 20));
ButtonMixedChi.setText("Mixed");
ButtonMixedChi.setToolTipText("Select this if the value of the restricted parameter in the null model is at the boundary of its range");
ButtonMixedChi.setLocation(new java.awt.Point(125, 20));
ButtonGroupChi.add(ButtonStandardChi);
ButtonGroupChi.add(ButtonMixedChi);
PanelChi2Type.add(ButtonStandardChi);
PanelChi2Type.add(ButtonMixedChi);
jButtonDefaultLRT.setVisible(true);
jButtonDefaultLRT.setSize(new java.awt.Dimension(141, 40));
jButtonDefaultLRT.setText("Default Settings");
jButtonDefaultLRT.setLocation(new java.awt.Point(30, 220));
jButtonCancelLRT.setVisible(true);
jButtonCancelLRT.setSize(new java.awt.Dimension(110, 40));
jButtonCancelLRT.setText("Cancel");
jButtonCancelLRT.setLocation(new java.awt.Point(190, 220));
jButtonRunLRT.setVisible(true);
jButtonRunLRT.setSize(new java.awt.Dimension(110, 40));
jButtonRunLRT.setText("Run");
jButtonRunLRT.setLocation(new java.awt.Point(320, 220));
jButtonRunLRT.setToolTipText("Remember that models have to be nested!");
setLocation(new java.awt.Point(281, 80));
getContentPane().setLayout(null);
setTitle("LRT calculator");
jPanelLRTsettings.add(jTextFieldLRT0);
jPanelLRTsettings.add(jTextFieldLRT1);
jPanelLRTsettings.add(jTextFieldLRTdf);
jPanelLRTsettings.add(jButtonDefaultLRT);
jPanelLRTsettings.add(jButtonCancelLRT);
jPanelLRTsettings.add(jButtonRunLRT);
jPanelLRTsettings.add(jLabelLRT);
jPanelLRTsettings.add(jLabelLRTpvalue);
jPanelLRTsettings.add(PanelChi2Type);
getContentPane().add(jPanelLRTsettings);
setSize(new java.awt.Dimension(500, 310));
setResizable(false);
// event handling
jButtonDefaultLRT.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
jButtonDefaultLRTActionPerformed(e);
}
});
jButtonCancelLRT.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
jButtonCancelLRTActionPerformed(e);
}
});
jButtonRunLRT.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
jButtonRunLRTActionPerformed(e);
}
});
addWindowListener(new java.awt.event.WindowAdapter() {
public void windowClosing(java.awt.event.WindowEvent e) {
thisWindowClosing(e);
}
});
}
private boolean mShown = false;
public void addNotify() {
super.addNotify();
if (mShown)
return;
// resize frame to account for menubar
JMenuBar jMenuBar = getJMenuBar();
if (jMenuBar != null) {
int jMenuBarHeight = jMenuBar.getPreferredSize().height;
Dimension dimension = getSize();
dimension.height += jMenuBarHeight;
setSize(dimension);
// move down components in layered pane
Component[] components = getLayeredPane().getComponentsInLayer(JLayeredPane.DEFAULT_LAYER.intValue());
for (int i = 0; i < components.length; i++) {
Point location = components[i].getLocation();
location.move(location.x, location.y + jMenuBarHeight);
components[i].setLocation(location);
}
}
mShown = true;
}
// Close the window when the close box is clicked
void thisWindowClosing(java.awt.event.WindowEvent e) {
setVisible(false);
dispose();
//System.exit(0);
}
/**************************** LRT **************************************
* *
* Computes a likelihood ratio test given a LRT and df *
* Returns P-value according to a standard chi2 distribution *
* *
***********************************************************************/
public double LRT (double delta, int df)
{
double prob;
if (delta == 0)
prob = 1.0;
else
prob = Statistics.chiSquareProbability (delta, df);
return prob;
}
/**************************** LRTboundary *****************************
* *
* Computes a likelihood ratio test given a LRT and df *
* Returns P-value according to a mixed chi2 distribution *
* *
***********************************************************************/
static private double LRTboundary(double delta, int df)
{
double prob;
if (delta == 0)
prob = 1.0;
else
{
if (df == 1)
prob = Statistics.chiSquareProbability(delta,df)/2;
else
prob= (Statistics.chiSquareProbability(delta,df-1) +
Statistics.chiSquareProbability(delta,df)) / 2;
}
return prob;
}
public void jButtonRunLRTActionPerformed(java.awt.event.ActionEvent e)
{
double L0, L1, delta, pvalue;
int df;
String sL0, sL1, sdf;
try
{
// get the strings from the text fields
sL0 = jTextFieldLRT0.getText();
sL1 = jTextFieldLRT1.getText();
sdf = jTextFieldLRTdf.getText();
// check for empty fields and numbers
if (sL0.length() == 0 || !Utilities.isNumber(sL0))
JOptionPane.showMessageDialog (new JFrame(), "Enter a positive likelihood for the null model (" + sL0 + ")",
"jModeltest error", JOptionPane.ERROR_MESSAGE);
else if (sL1.length() == 0 || !Utilities.isNumber(sL1))
JOptionPane.showMessageDialog (new JFrame(), "Enter a positive likelihood for the alternative model",
"jModeltest error", JOptionPane.ERROR_MESSAGE);
else if (sdf.length() == 0 || !Utilities.isNumber(sdf))
JOptionPane.showMessageDialog (new JFrame(), "Enter a positive number of degrees of freedom",
"jModeltest error", JOptionPane.ERROR_MESSAGE);
else
{
// get values
L0 = Double.parseDouble (sL0);
L1 = Double.parseDouble (sL1);
df = Integer.parseInt (sdf);
delta = 2 * (L0 - L1);
// check for valid values
if (L0 <= 0 || Double.isNaN(L0))
JOptionPane.showMessageDialog (new JFrame(), "Enter a positive likelihood for the null model*",
"jModeltest error", JOptionPane.ERROR_MESSAGE);
else if (L1 <= 0 || Double.isNaN(L1))
JOptionPane.showMessageDialog (new JFrame(), "Enter a positive likelihood for the alternative model*",
"jModeltest error", JOptionPane.ERROR_MESSAGE);
else if (df <= 0 || Double.isNaN(df))
JOptionPane.showMessageDialog (new JFrame(), "Enter a positive number of degrees of freedom",
"jModeltest error", JOptionPane.ERROR_MESSAGE);
else if (delta < 0)
JOptionPane.showMessageDialog (new JFrame(), "The likelihood of the null model cannot be bigger than the likelihood of the alternative model!",
"jModeltest error", JOptionPane.ERROR_MESSAGE);
else
{
if (ButtonMixedChi.isSelected())
pvalue = LRTboundary(delta, df);
else
pvalue = LRT(delta, df);
jLabelLRT.setText("LRT = " + Utilities.roundDoubleTo(delta,6));
jLabelLRTpvalue.setText("P-value = " + Utilities.roundDoubleTo(pvalue,6));
}
}
}
catch (Exception f)
{
f.printStackTrace();
}
}
public void jButtonDefaultLRTActionPerformed(java.awt.event.ActionEvent e)
{
try
{
ButtonStandardChi.setSelected(true);
jTextFieldLRT0.setText("");
jTextFieldLRT1.setText("");
jTextFieldLRTdf.setText("");
jLabelLRT.setText("LRT = ");
jLabelLRTpvalue.setText("P-value =");
}
catch (Exception f)
{
f.printStackTrace();
}
}
public void jButtonCancelLRTActionPerformed(java.awt.event.ActionEvent e)
{
try
{
setVisible(false);
dispose();
}
catch (Exception f)
{
f.printStackTrace();
}
}
}