/*
* F84DistanceMatrix.java
*
* Copyright (c) 2002-2015 Alexei Drummond, Andrew Rambaut and Marc Suchard
*
* This file is part of BEAST.
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership and licensing.
*
* BEAST is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* BEAST 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with BEAST; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301 USA
*/
package dr.evolution.distance;
import dr.evolution.alignment.PatternList;
/**
* compute HKY corrected distance matrix
*
* @version $Id: F84DistanceMatrix.java,v 1.3 2005/05/24 20:25:56 rambaut Exp $
*
* @author Andrew Rambaut
*/
public class F84DistanceMatrix extends DistanceMatrix
{
//
// Public stuff
//
/** constructor */
public F84DistanceMatrix()
{
super();
}
/** constructor taking a pattern source */
public F84DistanceMatrix(PatternList patterns)
{
super(patterns);
}
/**
* set the pattern source
*/
public void setPatterns(PatternList patterns) {
super.setPatterns(patterns);
double[] freqs = patterns.getStateFrequencies();
stateCount = patterns.getStateCount();
if (stateCount != 4) {
throw new IllegalArgumentException("F84DistanceMatrix must have nucleotide patterns");
}
double freqA = freqs[0];
double freqC = freqs[1];
double freqG = freqs[2];
double freqT = freqs[3];
double freqR = freqA + freqG;
double freqY = freqC + freqT;
constA = ((freqA * freqG) / freqR) + ((freqC * freqT) / freqY);
constB = (freqA * freqG) + (freqC * freqT);
constC = (freqR * freqY);
}
/**
* Calculate a pairwise distance
*/
protected double calculatePairwiseDistance(int taxon1, int taxon2) {
int state1, state2;
int n = patterns.getPatternCount();
double weight, distance;
double sumTs = 0.0;
double sumTv = 0.0;
double sumWeight = 0.0;
int[] pattern;
for (int i = 0; i < n; i++) {
pattern = patterns.getPattern(i);
state1 = pattern[taxon1];
state2 = pattern[taxon2];
weight = patterns.getPatternWeight(i);
if (!dataType.isAmbiguousState(state1) && !dataType.isAmbiguousState(state2) && state1 != state2) {
if ((state1 == 0 && state2 == 2) || (state1 == 2 && state2 == 0)) {
// it's a transition
sumTs += weight;
} else {
// it's a transversion
sumTv += weight;
}
}
sumWeight += weight;
}
double P = sumTs / sumWeight;
double Q = sumTv / sumWeight;
double tmp1 = Math.log(1.0 - (P / (2.0 * constA)) -
(((constA - constB) * Q) / (2.0 * constA * constC)));
double tmp2 = Math.log(1.0 - (Q / (2.0 * constC)));
distance = -(2.0 * constA * tmp1) +
(2.0 * (constA - constB - constC) * tmp2);
if (distance < MAX_DISTANCE) {
return distance;
} else {
return MAX_DISTANCE;
}
}
//
// Private stuff
//
private int stateCount;
//used in correction formula
private double constA, constB, constC;
}