forked from trvrb/antigen
-
Notifications
You must be signed in to change notification settings - Fork 0
/
GeometricPhenotype.java
146 lines (122 loc) · 3.97 KB
/
GeometricPhenotype.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/* Antigenic phenotype present in individual Viruses and within Hosts as immune history */
/* Should be able to calculate distance and cross-immunity between two phenotypes */
/* Moving up to multiple dimensions is non-trivial and requires thought on the implementation */
/* Multiple Viruses can reference a single Phenotype object */
import static java.lang.Math.*;
import java.util.*;
public class GeometricPhenotype implements Phenotype {
// fields
private double traitA;
private double traitB;
// constructor
public GeometricPhenotype() {
}
public GeometricPhenotype(double tA, double tB) {
traitA = tA;
traitB = tB;
}
public double getTraitA() {
return traitA;
}
public double getTraitB() {
return traitB;
}
public void setTraitA(double tA) {
traitA = tA;
}
public void setTraitB(double tB) {
traitB = tB;
}
// raw antigenic distance between two phenotypes
public double distance(Phenotype p) {
GeometricPhenotype p2d = (GeometricPhenotype) p;
double distA = (getTraitA() - p2d.getTraitA());
double distB = (getTraitB() - p2d.getTraitB());
double dist = (distA * distA) + (distB * distB);
dist = Math.sqrt(dist);
return dist;
}
// cross immunity between a virus phenotype and a host's immune history
// here encoded more directly as risk of infection, which ranges from 0 to 1
public double riskOfInfection( Phenotype[] history) {
// find closest phenotype in history
double closestDistance = 100.0;
if (history.length > 0) {
for (int i = 0; i < history.length; i++) {
double thisDistance = distance(history[i]);
if (thisDistance < closestDistance) {
closestDistance = thisDistance;
}
if (thisDistance < 0.01) {
break;
}
}
}
double risk = closestDistance * Parameters.smithConversion;
risk = Math.max(0.01, risk);
risk = Math.min(1.0, risk);
return risk;
}
// mutate with exponential
// returns a mutated copy, original Phenotype is unharmed
// public Phenotype mutate() {
//
// // direction of mutation
// double theta = 0;
// if (Parameters.mut2D) {
// theta = Random.nextDouble(0,2*Math.PI);
// } else {
// if (Random.nextBoolean(0.5)) { theta = 0; }
// else { theta = Math.PI; }
// }
//
// // size of mutation
// double r = Random.nextExponential(Parameters.meanStep);
//
// double mutA = getTraitA() + r * Math.cos(theta);
// double mutB = getTraitB() + r * Math.sin(theta);
// Phenotype mutP = new GeometricPhenotype(mutA,mutB);
// return mutP;
//
// }
// mutate with bivariate normal
// returns a mutated copy, original Phenotype is unharmed
// public Phenotype mutate() {
//
// double mutA = getTraitA() + Random.nextNormal(0,Parameters.meanStep);
// double mutB = getTraitB();
// if (Parameters.mut2D) { mutB += Random.nextNormal(0,Parameters.meanStep); }
// Phenotype mutP = new GeometricPhenotype(mutA,mutB);
// return mutP;
//
// }
// returns a mutated copy, original Phenotype is unharmed
// mutate with gamma
public Phenotype mutate() {
// direction of mutation
double theta = 0;
if (Parameters.mut2D) {
theta = Random.nextDouble(0,2*Math.PI);
} else {
if (Random.nextBoolean(0.5)) { theta = 0; }
else { theta = Math.PI; }
}
// size of mutation
double alpha = (Parameters.meanStep * Parameters.meanStep) / (Parameters.sdStep * Parameters.sdStep);
double beta = (Parameters.sdStep * Parameters.sdStep) / Parameters.meanStep;
double r = Random.nextGamma(alpha, beta);
double mutA = getTraitA() + r * Math.cos(theta);
double mutB = getTraitB() + r * Math.sin(theta);
Phenotype mutP = new GeometricPhenotype(mutA,mutB);
return mutP;
}
public String toString() {
String fullString = String.format("%.4f,%.4f", traitA, traitB);
return fullString;
}
// used for memory profiling to show that references are properly used
// public String toString() {
// String fullString = String.format("%s,%.4f,%.4f", Integer.toHexString(this.hashCode()), traitA, traitB);
// return fullString;
// }
}