package statalign.model.subst.plugins;
import java.io.IOException;
import statalign.model.subst.plugins.NucleotideModel;
import statalign.model.subst.plugins.NucleotideModelUtils;
/**
* This class implements the Felsenstein 1981 parameter model.
*
* @author lyngsoe
*/
public class Felsenstein81 extends NucleotideModel{
public static final String menuName = "Felsenstein 1981";
//static final double span = 0.1; // largest parameter change when resampling
/**
* This constructor uses the analytical solution to diagonalising
* the rate matrix to set diagonalising matrices.
*
* @throws IOException
*/
public Felsenstein81() throws IOException{
/* Initialise NucleotideModel part of object */
super();
/* Initialise Felsenstein81 specific part of object */
params = new double[3];
oldparams = new double[3];
/* Set all frequencies to 1/4 */
params[0] = params[1] = params[2] = 0.25;
/* Set diagonalising matrices and equilibrium frequencies */
setDiagonal();
}
void setDiagonal(){
/* Set equilibrium frequencies */
e[alphabet.length - 1] = 1.0;
for (int i = 0; i < alphabet.length - 1; i++){
e[i] = params[i];
e[alphabet.length - 1] -= params[i];
}
/* Set diagonalising matrices */
for (int i = 0; i < alphabet.length; i++)
for (int j = 0; j < alphabet.length; j++){
if (j == 0)
v[i][j] = 1;
else if (i == 0)
v[i][j] = -e[alphabet.length - j] / e[0];
else if (i + j == 4)
v[i][j] = 1;
else
v[i][j] = 0;
if (i == 0)
w[i][j] = e[j];
else if (i + j == 4)
w[i][j] = 1 - e[j];
else
w[i][j] = -e[j];
}
/* Set diagonal matrix */
d[0] = 0;
d[1] = d[2] = d[3] = -1;
}
/**
* Prints the current state of model.
*/
public String print(){
return "A\t"+e[0]+"\tC\t"+e[1]+"\tG\t"+e[2]+"\tT\t"+e[3];
}
/**
* This function implements a proposal for new parameter values.
* Returns with the logarithm of the Metropolis-Hastings ratio.
*/
@Override
public double sampleParameter() {
double x = NucleotideModelUtils.sampleFrequencies(e, span);
/* Save current parameters as old parameters, store new
* frequency parameters, and ensure frequencies sum to one.
*/
e[params.length] = 1.0;
for (int i = 0; i < params.length; i++){
oldparams[i] = params[i];
params[i] = e[i];
e[params.length] -= e[i];
}
setDiagonal();
return x;
}
}