Skip to content

Commit b755138

Browse files
author
Sasha
committed
SA probability
1 parent 1ab6ce2 commit b755138

File tree

1 file changed

+179
-0
lines changed

1 file changed

+179
-0
lines changed
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
package beast.evolution.speciation;
2+
3+
import beast.core.Distribution;
4+
import beast.core.Input;
5+
import beast.core.State;
6+
import beast.core.parameter.IntegerParameter;
7+
import beast.core.parameter.RealParameter;
8+
9+
import java.util.List;
10+
import java.util.Random;
11+
12+
/**
13+
* @author Alexandra Gavryushkina
14+
*/
15+
public class ProbabilitySA extends Distribution {
16+
17+
public final Input<IntegerParameter> SAInput = new Input<IntegerParameter>("SA", "A binary parameter that describe " +
18+
"the fact that a lineage has no sampled descendants (zero) or it has sampled descendants (one)", Input.Validate.REQUIRED);
19+
20+
public Input<RealParameter> timeInput =
21+
new Input<RealParameter>("time", "The time of the lineage",Input.Validate.REQUIRED);
22+
23+
public Input<RealParameter> originInput =
24+
new Input<RealParameter>("origin", "The time when the process started",(RealParameter)null);
25+
26+
//'direct' parameters
27+
public Input<RealParameter> birthRateInput =
28+
new Input<RealParameter>("birthRate", "Birth rate");
29+
public Input<RealParameter> deathRateInput =
30+
new Input<RealParameter>("deathRate", "Death rate");
31+
public Input<RealParameter> samplingRateInput =
32+
new Input<RealParameter>("samplingRate", "Sampling rate per individual");
33+
34+
//transformed parameters:
35+
public Input<RealParameter> diversificationRateInput =
36+
new Input<RealParameter>("diversificationRate", "Net diversification rate. Birth rate - death rate", Input.Validate.XOR, birthRateInput);
37+
public Input<RealParameter> turnoverInput =
38+
new Input<RealParameter>("turnover", "Turnover. Death rate/birth rate", Input.Validate.XOR, deathRateInput);
39+
public Input<RealParameter> samplingProportionInput =
40+
new Input<RealParameter>("samplingProportion", "The probability of sampling prior to death. Sampling rate/(sampling rate + death rate)", Input.Validate.XOR, samplingRateInput);
41+
42+
43+
// r parameter
44+
public Input<RealParameter> removalProbability =
45+
new Input<RealParameter>("removalProbability", "The probability that an individual is removed from the process after the sampling", Input.Validate.REQUIRED);
46+
47+
public Input<RealParameter> rhoProbability =
48+
new Input<RealParameter>("rho", "Probability of an individual to be sampled at present", (RealParameter)null);
49+
50+
// if the tree likelihood is condition on sampling at least one individual then set to true one of the inputs:
51+
public Input<Boolean> conditionOnSamplingInput = new Input<Boolean>("conditionOnSampling", "the tree " +
52+
"likelihood is conditioned on sampling at least one individual", false);
53+
public Input<Boolean> conditionOnRhoSamplingInput = new Input<Boolean>("conditionOnRhoSampling", "the tree " +
54+
"likelihood is conditioned on sampling at least one individual in present", false);
55+
56+
public Input<Boolean> conditionOnRootInput = new Input<Boolean>("conditionOnRoot", "the tree " +
57+
"likelihood is conditioned on the root height otherwise on the time of origin", false);
58+
59+
60+
protected double r;
61+
protected double lambda;
62+
protected double mu;
63+
protected double psi;
64+
protected double c1;
65+
protected double c2;
66+
protected double origin;
67+
protected double rho;
68+
protected boolean transform; //is true if the model is parametrised through transformed parameters
69+
private boolean lambdaExceedsMu = false;
70+
71+
@Override
72+
public List<String> getArguments() {
73+
return null;
74+
}
75+
76+
@Override
77+
public List<String> getConditions() {
78+
return null;
79+
}
80+
81+
@Override
82+
public void sample(State state, Random random) {
83+
84+
}
85+
86+
public void initAndValidate() throws Exception {
87+
88+
if (originInput.get() == null && !conditionOnRootInput.get()) {
89+
throw new RuntimeException("Either specify origin input or set conditionOnRoot input to \"true\"");
90+
}
91+
92+
if (originInput.get() != null && conditionOnRootInput.get()){
93+
throw new RuntimeException("Either don't specify origin input or set conditionOnRoot input to \"false\"");
94+
}
95+
96+
97+
if (conditionOnSamplingInput.get() && conditionOnRhoSamplingInput.get()){
98+
throw new RuntimeException("Either set to \"true\" only one of conditionOnSampling and conditionOnRhoSampling inputs or don't specify both!");
99+
}
100+
101+
if (birthRateInput.get() != null && deathRateInput.get() != null && samplingRateInput.get() != null) {
102+
103+
transform = false;
104+
//mu = deathRateInput.get().getValue();
105+
//psi = samplingRateInput.get().getValue();
106+
//lambda = birthRateInput.get().getValue();
107+
108+
} else if (diversificationRateInput.get() != null && turnoverInput.get() != null && samplingProportionInput.get() != null) {
109+
110+
transform = true;
111+
112+
} else {
113+
throw new RuntimeException("Either specify birthRate, deathRate and samplingRate OR specify diversificationRate, turnover and samplingProportion!");
114+
}
115+
}
116+
117+
118+
private double oneMinusP0(double t, double c1, double c2) {
119+
return 1 - (lambda + mu + psi - c1 * ((1 + c2) - Math.exp(-c1 * t) * (1 - c2)) / ((1 + c2) + Math.exp(-c1 * t) * (1 - c2))) / (2 * lambda);
120+
}
121+
122+
123+
private void transformParameters() {
124+
double d = diversificationRateInput.get().getValue();
125+
double r_turnover = turnoverInput.get().getValue();
126+
double s = samplingProportionInput.get().getValue();
127+
lambda = d/(1-r_turnover);
128+
mu = r_turnover*lambda;
129+
psi = mu*s/(1-s);
130+
}
131+
132+
private void updateParameters() {
133+
134+
if (transform) {
135+
transformParameters();
136+
} else {
137+
lambda = birthRateInput.get().getValue();
138+
mu = deathRateInput.get().getValue();
139+
psi = samplingRateInput.get().getValue();
140+
}
141+
142+
r = removalProbability.get().getValue();
143+
if (rhoProbability.get() != null ) {
144+
rho = rhoProbability.get().getValue();
145+
} else {
146+
rho = 0.;
147+
}
148+
c1 = Math.sqrt((lambda - mu - psi) * (lambda - mu - psi) + 4 * lambda * psi);
149+
c2 = -(lambda - mu - 2*lambda*rho - psi) / c1;
150+
if (originInput.get() != null){
151+
origin = originInput.get().getValue();
152+
} else {
153+
origin = Double.POSITIVE_INFINITY;
154+
}
155+
}
156+
157+
@Override
158+
public double calculateLogP()
159+
{
160+
updateParameters();
161+
162+
if (lambdaExceedsMu && lambda <= mu) {
163+
return Double.NEGATIVE_INFINITY;
164+
}
165+
double t=timeInput.get().getValue();
166+
if (SAInput.get().getValue() == 0) {
167+
logP = Math.log(1 - oneMinusP0(t, c1, c2));
168+
} else {
169+
logP = Math.log(oneMinusP0(t, c1, c2));
170+
}
171+
172+
return logP;
173+
}
174+
175+
@Override
176+
protected boolean requiresRecalculation() {
177+
return true;
178+
}
179+
}

0 commit comments

Comments
 (0)