@@ -56,10 +56,16 @@ public class MappedMascot extends Mascot implements Loggable {
5656 protected DecimalFormat df ;
5757 protected boolean someMetaDataNeedsLogging ;
5858 protected boolean substitutions = false ;
59+
60+ private enum EventType {
61+ SAMPLE , COALESCENT , RATESHIFT
62+ }
5963
6064 public Tree mappedTree ;
6165
6266 List <Integer > activeStates ;
67+ List <List <Double >> usedTimes ; // keeps track of the timings used for the intermediate results
68+ List <EventType > usedTypes ; // keeps track of the timings used for the intermediate results
6369 double [] migrationRates ;
6470
6571 long lastLog =-1 ;
@@ -107,19 +113,26 @@ public void calcForLogging(long sample) {
107113
108114 @ Override
109115 public double calculateLogP () {
116+
110117// System.out.println(treeIntervals.treeInput.get());
111118 // newly calculate tree intervals (already done by swap() below)
112119 treeIntervals .calculateIntervals ();
113120 // correctly calculate the daughter nodes at coalescent intervals in the case of
114121 // bifurcation or in case two nodes are at the same height
115122 treeIntervals .swap ();
116123
124+ // initialize a new Mapped tree that inclused single child nodes for migration events
117125 mappedTree = new Tree (tree .getRoot ().copy ());
118126 mappedTree .getRoot ().sort ();
119-
127+
128+ // Maps that keep track of the state probabilities and times that fall onto an edge
120129 intermediateStateProbs = new HashMap <>();
121130 intermediateTimes = new HashMap <>();
131+ // reset the usedTimes
132+ usedTimes = new ArrayList <>();
133+ usedTypes = new ArrayList <>();
122134
135+ // The maximum step size for storing intermediate results
123136 double maxStepSize = treeIntervals .treeInput .get ().getRoot ().getHeight () * maxIntegrationStepMappingInput .get ();
124137
125138 // Set up ArrayLists for the indices of active lineages and the lineage state
@@ -129,7 +142,7 @@ public double calculateLogP() {
129142 nrLineages = 0 ;
130143 // linProbs = new double[0];// initialize the tree and rates interval counter
131144 linProbsLength = 0 ;
132- int treeInterval = 0 , ratesInterval = 0 ;
145+ int treeInterval = 0 , ratesInterval = 0 , anyInterval = 0 ;
133146 double nextEventTime = 0.0 ;
134147
135148 // Time to the next rate shift or event on the tree
@@ -144,7 +157,6 @@ public double calculateLogP() {
144157 }
145158
146159// if (first == 0 || !dynamics.areDynamicsKnown()) {
147- // System.out.println("lalal");
148160 setUpDynamics ();
149161// }
150162
@@ -157,11 +169,16 @@ public double calculateLogP() {
157169 double currTime = 0 ;
158170
159171 double lastRateShift = currTime ;
172+
173+ usedTimes .add (new ArrayList <>());
174+
175+ double maxFloatError = treeIntervals .treeInput .get ().getRoot ().getHeight ()*maxDiffInput .get ();
176+
160177
161178 // Calculate the likelihood
162179 do {
163180 nextEventTime = Math .min (nextTreeEvent , nextRateShift );
164- if (nextEventTime > 0 ) { // if true, calculate the interval contribution
181+ if (nextEventTime > maxFloatError ) { // if true, calculate the interval contribution
165182 if (recalculateLogP ) {
166183 System .err .println ("ode calculation stuck, reducing tolerance, new tolerance= " + maxTolerance );
167184 maxTolerance *= 0.9 ;
@@ -170,9 +187,13 @@ public double calculateLogP() {
170187 return calculateLogP ();
171188 }
172189
190+ // calculate the intermediate state probabilities until the next event, either a coal, sample or rate shift
173191 if (nextEventTime < maxStepSize ) {
174192 logP += doEuler (nextEventTime , ratesInterval );
175193 currTime += nextEventTime ;
194+ // add the current time to the used times
195+ usedTimes .get (anyInterval ).add (currTime );
196+ // store the intermediate results
176197 storeIntermediateResults (currTime );
177198 } else {
178199 int nrIntermediates = (int ) (nextEventTime / maxStepSize );
@@ -183,15 +204,23 @@ public double calculateLogP() {
183204 if (i == nrIntermediates )
184205 currTime = oldCurrTime + nextEventTime ;
185206
207+ // add the current time to the used times
208+ usedTimes .get (anyInterval ).add (currTime );
209+ // store the intermediate results
186210 storeIntermediateResults (currTime );
187211 }
188212 }
189213 }
190214
215+ usedTimes .add (new ArrayList <>());
216+ anyInterval ++;
217+
191218 if (nextTreeEvent <= nextRateShift ) {
192219 if (treeIntervals .getIntervalType (treeInterval ) == IntervalType .COALESCENT ) {
193220 nrLineages --; // coalescent event reduces the number of lineages by one
194221 logP += coalesce (treeInterval , ratesInterval , nextTreeEvent , nextRateShift , currTime ); // calculate
222+ usedTimes .get (anyInterval ).add (currTime );
223+ usedTypes .add (EventType .COALESCENT );
195224 // the
196225 // likelihood of the
197226 // coalescent event
@@ -202,7 +231,9 @@ public double calculateLogP() {
202231 // logP += normalizeLineages(linProbs); // normalize all lineages before event
203232 nrLineages ++; // sampling event increases the number of lineages by one
204233 sample (treeInterval , ratesInterval , nextTreeEvent , nextRateShift , currTime ); // calculate the
205- // likelihood of
234+ usedTimes .get (anyInterval ).add (currTime );
235+ usedTypes .add (EventType .SAMPLE );
236+
206237 // the sampling event if
207238 // sampling rate is given
208239 }
@@ -222,6 +253,8 @@ public double calculateLogP() {
222253 nextTreeEvent -= nextRateShift ;
223254 nextRateShift = dynamics .getInterval (ratesInterval );
224255 lastRateShift = currTime ;
256+ usedTimes .get (anyInterval ).add (currTime );
257+ usedTypes .add (EventType .RATESHIFT );
225258 }
226259 if (logP == Double .NEGATIVE_INFINITY ) {
227260 return logP ;
@@ -232,10 +265,9 @@ public double calculateLogP() {
232265 } while (nextTreeEvent <= Double .POSITIVE_INFINITY );
233266
234267 first ++;
235-
268+
236269 resample (treeInterval , ratesInterval , lastRateShift );
237- // System.out.println(treeIntervals.treeInput.get());
238- // System.out.println("");
270+
239271 return logP ;
240272 }
241273
@@ -255,7 +287,6 @@ protected void setUpDynamics() {
255287 euler .setUpDynamics (coalescentRates , migrationRates , indicators , nextRateShift );
256288 }
257289
258-
259290 protected double coalesce (int currTreeInterval , int currRatesInterval , double nextTreeEvent , double nextRateShift ,
260291 double currTime ) {
261292 double logP = super .coalesce (currTreeInterval , currRatesInterval , nextTreeEvent , nextRateShift );
@@ -287,50 +318,53 @@ private void addNewLineage(int nr, double time) {
287318 intermediateTimes .get (nr ).add (time );
288319 }
289320
321+
290322 private void resample (int treeInterval , int ratesInterval , double lastRateShift ) {
291323 treeInterval --;
292324 // start by resampling the root
293325 int rootNr = treeIntervals .getLineagesAdded (treeInterval );
294-
295- // System.out.println(tree);
296-
326+ // the number of lineages at the root is always 1
297327 nrLineages = 1 ;
328+ // the active lineages are the ones that are present at the root
298329 activeStates = new ArrayList <>();
299-
300- // sample rootState
330+ // sample rootState from the state probabilities at the root
301331 int rootState = Randomizer .randomChoicePDF (intermediateStateProbs .get (rootNr ).get (0 ));
302-
332+ // add the rootState to the active states
303333 activeStates .add (rootState );
334+ // keep track of the active lineages
304335 activeLineages .clear ();
305336 activeLineages .add (rootNr );
306337 linProbsLength = 0 ;
307-
338+ // index to keep track of the used times, start with the last one
308339
309340 mappedTree .getRoot ().setMetaData ("location" , rootState );
310341 coalesceDown (treeInterval );
311342
312- double currTime = treeIntervals .treeInput .get ().getRoot ().getHeight ();
313-
314- double nextTreeEvent = treeIntervals .getInterval (treeInterval );
343+ int anyInterval = usedTimes .size () - 2 ; // start with the series of times saved in the last interval before the coalescent event
344+ double currTime = usedTimes .get (anyInterval +1 ).get (0 ); // get the time of the root as the time of the coalescent interval of the last usedTimes
345+ double maxFloatError = currTime *maxDiffInput .get ();
346+
347+ // get the time until the next tree event and the next rate shift
348+ double nextTreeEvent = treeIntervals .getInterval (treeInterval );
315349 double nextRateShift = currTime - lastRateShift ;
316-
350+
317351 double nextEventTime ;
318352 // Calculate the likelihood
319353 do {
320354 nextEventTime = Math .min (nextTreeEvent , nextRateShift );
321- if (nextEventTime > 0 ) { // if true, calculate the interval contribution
322- // System.out.println("currentTime " + currTime);
323- sampleMigrationEvents (currTime , currTime - nextEventTime );
355+ if (nextEventTime > maxFloatError ) { // if true, calculate the interval contribution
356+ // sample the migration events that occurred between now and the next event time (sample, coal, or rate shift)
357+ sampleMigrationEvents (usedTimes . get ( anyInterval ) );
324358 currTime -= nextEventTime ;
325359 }
326-
327- if (nextTreeEvent <= nextRateShift ) {
328- if (treeIntervals . getIntervalType ( treeInterval - 1 ) == IntervalType .COALESCENT ) {
360+ anyInterval --;
361+ if (usedTypes . get ( anyInterval ) != EventType . RATESHIFT ) {
362+ if (usedTypes . get ( anyInterval ) == EventType .COALESCENT ) {
329363 nrLineages ++; // coalescent event reduces the number of lineages by one
330364 coalesceDown (treeInterval - 1 ); // calculate the
331365 }
332366
333- if (treeIntervals . getIntervalType ( treeInterval - 1 ) == IntervalType .SAMPLE ) {
367+ if (usedTypes . get ( anyInterval ) == EventType .SAMPLE ) {
334368 // if (linProbsLength > 0)
335369 // logP += normalizeLineages(linProbs); // normalize all lineages before event
336370 nrLineages --; // sampling event increases the number of lineages by one
@@ -357,42 +391,25 @@ private void resample(int treeInterval, int ratesInterval, double lastRateShift)
357391 // indicators = dynamics.getIndicators(ratesInterval);
358392 }
359393 } while (treeInterval > 0 );
360-
361- first ++;
362-
363394 }
364395
365396
366- private void sampleMigrationEvents (double startTime , double endTime ) {
397+ private void sampleMigrationEvents (List < Double > timesInInterval ) {
367398 for (int i = 0 ; i < activeLineages .size (); i ++) {
368- sampleMigrationEventsLineage (activeLineages .get (i ), i , startTime , endTime );
399+ sampleMigrationEventsLineage (activeLineages .get (i ), i , timesInInterval );
369400 }
370401 }
371402
372- private void sampleMigrationEventsLineage (Integer nodeNr , int index , double startTime , double endTime ) {
403+ private void sampleMigrationEventsLineage (Integer nodeNr , int index , List < Double > timesInInterval ) {
373404 double K = -Math .log (Randomizer .nextDouble ());
374405 double I = 0.0 ;
406+ double startTime = timesInInterval .get (timesInInterval .size () - 1 );
407+ double endTime = timesInInterval .get (0 );
375408 double currentTime = startTime ;
376-
409+
377410 int currTimeInterval = intermediateTimes .get (nodeNr ).indexOf (startTime );
378411 if (currTimeInterval == -1 ) {
379- boolean cont = false ;
380- for (int i = 0 ; i < intermediateTimes .get (nodeNr ).size (); i ++)
381- if (Math .abs (intermediateTimes .get (nodeNr ).get (i ) - startTime ) < maxDiffInput .get ()) {
382- currTimeInterval = i ;
383- cont = true ;
384- break ;
385- }
386-
387- if (!cont ) {
388- for (int i = 0 ; i < intermediateTimes .get (nodeNr ).size (); i ++)
389- System .err .println (intermediateTimes .get (nodeNr ).get (i ) - startTime );
390-
391- // System.out.println(mappedTree);
392-
393-
394- throw new IllegalArgumentException ("timing not found" );
395- }
412+ throw new IllegalArgumentException ("timing not found" );
396413 }
397414
398415 double [] prob_start = intermediateStateProbs .get (nodeNr ).get (currTimeInterval );
0 commit comments