package beast.evolution.tree.coalescent;
/*
* IntervalList.java
*
* Copyright (C) 2002-2006 Alexei Drummond and Andrew Rambaut
*
* 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
*/
/**
* An interface for a set of coalescent intervals.
*
* @author Andrew Rambaut
* @author Alexei Drummond
* @version $Id: IntervalList.java,v 1.7 2005/05/24 20:25:56 rambaut Exp $
*/
public interface IntervalList {
/**
* @return the number of intervals
*/
int getIntervalCount();
/**
* @return the total number of sampling events.
*/
int getSampleCount();
/**
* @param i the index of the interval
* @return the size of the i'th interval.
*/
double getInterval(int i);
/**
* Required for s-coalescents, where new lineages are added as
* earlier samples are come across.
*
* @param i the index of the interval
* @return the number of uncoalesced lineages within this interval.
*/
int getLineageCount(int i);
/**
* @param i the index of the interval
* @return the number coalescent events in an interval
*/
int getCoalescentEvents(int i);
/**
* @param i the index of the interval
* @return the type of interval observed.
*/
IntervalType getIntervalType(int i);
/**
* @return the total duration of these intervals.
*/
double getTotalDuration();
/**
* @return true if this set of coalescent intervals is fully resolved
* (i.e. whether is has exactly one coalescent event in each
* subsequent interval), false otherwise.
*/
boolean isBinaryCoalescent();
/**
* @return true if this set of coalescent intervals coalescent only
* (i.e. whether is has exactly one or more coalescent event in each
* subsequent interval), false otherwise
*/
boolean isCoalescentOnly();
public class Utils {
/**
* @param intervals the intervals
* @param t the time that you are counting the number of lineages
* @return the number of lineages at time t.
*/
public static int getLineageCount(IntervalList intervals, double t) {
int i = 0;
while (i < intervals.getIntervalCount() && t > intervals.getInterval(i)) {
t -= intervals.getInterval(i);
i += 1;
}
if (i == intervals.getIntervalCount()) return 1;
return intervals.getLineageCount(i);
}
/**
* @param intervals the intervals for which the delta parameter is calculated.
* @return the delta parameter of Pybus et al (Node spread statistic)
*/
public static double getDelta(IntervalList intervals) {
// Assumes ultrametric beast.tree!
if (!intervals.isCoalescentOnly()) {
throw new IllegalArgumentException("Assumes ultrametric beast.tree!");
}
int n = intervals.getIntervalCount();
int numTips = n + 1;
double transTreeDepth = 0.0;
double cumInts = 0.0;
double sum = 0.0;
// transform intervals
for (int j = 0; j < n; j++) { // move from tips to root
double transInt = intervals.getInterval(j) *
beast.math.Binomial.choose2(intervals.getLineageCount(j)); // coalescent version
//intLenCopy[j] = getInterval(j)*getLineageCount(j); // birth-death version
// don't include the last interval so put this before...
sum += cumInts;
// ...incrementing the cumInts
cumInts += transInt;
transTreeDepth += transInt;
}
double halfTreeDepth = transTreeDepth / 2.0;
sum *= (1.0 / (numTips - 2.0));
double top = halfTreeDepth - sum;
double bottom = transTreeDepth * Math.sqrt((1.0 / (12.0 * (numTips - 2.0))));
return (top / bottom);
}
}
}