package statalign.model.subst.plugins; import java.io.IOException; import statalign.model.subst.plugins.NucleotideModel; import statalign.model.subst.plugins.NucleotideModelUtils; import statalign.base.*; /** * This class implements the Tamura 1992 model. * * @author lyngsoe */ public class Tamura92 extends NucleotideModel{ public static final String menuName = "Tamura 1992"; //static final double span = 0.1; // largest parameter change when resampling /** * This constructor uses numerical methods to diagonalise the rate * matrix and to set diagonalising matrices. * * @throws IOException */ public Tamura92() throws IOException{ /* Initialise NucleotideModel part of object */ super(); /* Initialise Tamura 1992 specific part of object */ params = new double[2]; oldparams = new double[2]; /* Set all frequencies to 1/4 */ params[0] = 0.5; /* Set all rate ratios to 1 */ params[1] = 1.0; /* Set diagonalising matrices and equilibrium frequencies */ setDiagonal(); } void setDiagonal(){ /* Set equilibrium frequencies */ e[0] = e[3] = (1 - params[0]) / 2.0; e[2] = e[1] = params[0] / 2.0; /* Set diagonalising matrices */ // Set diagonal matrix d[0] = params[0] * params[1] - params[0] - params[1]; d[1] = params[0] - params[0] * params[1] - 1; d[2] = 0; d[3] = (1 - params[0]) / (params[0] - 1); // Set v for (int i = 0; i < alphabet.length; i++){ for (int j = 0; j < alphabet.length; j++) v[i][j] = 1; v[i][1 - i/2] = 0; } v[0][0] = v[2][1] = -1; v[0][3] = v[1][3] = params[0] / (params[0] - 1); // Set w for (int i = 0; i < alphabet.length; i++){ w[i / 2][i] = (i % 2 == 0 ? -0.5 : 0.5); w[1 - i / 2][i] = 0; w[2 + i / 2][i] = (1 - params[0]) / 2.0; w[3 - i / 2][i] = (params[0] - 1 + i / 2) / 2.0; } } /** * Prints the parameters of the 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; if (Utils.generator.nextInt(2) == 0){ /* Resample frequency parameter */ oldparams[0] = params[0]; boolean resample = true; double r, l; do{ /* Frequencies are not allowed to be zero or one */ l = Math.max(0.0, oldparams[0] - span / 2.0); r = Math.min(1.0, oldparams[0] + span / 2.0); params[0] = l + Utils.generator.nextDouble() * (r - l); if ((params[0] > 0) && (params[0] < 1)) resample = false; } while(resample); x = Math.log((Math.min(1.0, params[0] + span / 2.0) - Math.max(0, params[0] - span / 2.0)) / (r - l)); } else{ /* Resample rate ratio parameter */ double r[] = new double[1]; r[0] = params[params.length - 1]; x = NucleotideModelUtils.sampleRates(r, span / 2.0); oldparams[params.length - 1] = params[params.length - 1]; params[params.length - 1] = r[0]; } setDiagonal(); return x; } }