1 /*
2  *  MrBayes 3
3  *
4  *  (c) 2002-2013
5  *
6  *  John P. Huelsenbeck
7  *  Dept. Integrative Biology
8  *  University of California, Berkeley
9  *  Berkeley, CA 94720-3140
10  *  johnh@berkeley.edu
11  *
12  *  Fredrik Ronquist
13  *  Swedish Museum of Natural History
14  *  Box 50007
15  *  SE-10405 Stockholm, SWEDEN
16  *  fredrik.ronquist@nrm.se
17  *
18  *  With important contributions by
19  *
20  *  Paul van der Mark (paulvdm@sc.fsu.edu)
21  *  Maxim Teslenko (maxkth@gmail.com)
22  *  Chi Zhang (zhangchicool@gmail.com)
23  *
24  *  and by many users (run 'acknowledgments' to see more info)
25  *
26  * This program is free software; you can redistribute it and/or
27  * modify it under the terms of the GNU General Public License
28  * as published by the Free Software Foundation; either version 2
29  * of the License, or (at your option) any later version.
30  *
31  * This program is distributed in the hope that it will be useful,
32  * but WITHOUT ANY WARRANTY; without even the implied warranty of
33  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
34  * GNU General Public License for more details (www.gnu.org).
35  *
36  */
37 
38 #include "bayes.h"
39 #include "command.h"
40 #include "mcmc.h"
41 #include "sumpt.h"
42 #include "utils.h"
43 #if defined(__MWERKS__)
44 #include "SIOUX.h"
45 #endif
46 
47 typedef struct partctr
48     {
49     struct partctr  *left, *right;
50     BitsLong        *partition;
51     int             totCount;
52     int             *count;
53     MrBFlt          **length;
54     MrBFlt          **height;
55     MrBFlt          **age;
56     int             ***nEvents; /* nEvents[0,nESets][0,numRuns][0,count[RunID]] */
57     MrBFlt          ***bRate;   /* bRate  [0,nBSets][0,numRuns][0,count[RunID]] */
58     MrBFlt          ***bLen;    /* bLen   [0,nBSets][0,numRuns][0,count[RunID]] */
59     MrBFlt          **popSize;  /* popSize[0,numRuns][0,count[RunID]]           */
60     }
61     PartCtr;
62 
63 typedef struct treectr
64     {
65     struct treectr  *left, *right;
66     int             count;
67     int             *order;
68     }
69     TreeCtr;
70 
71 typedef struct
72     {
73     int     longestLineLength;
74     int     numTreeBlocks;
75     int     lastTreeBlockBegin;
76     int     lastTreeBlockEnd;
77     int     numTreesInLastBlock;
78     }
79     SumtFileInfo;
80 
81 #define ALLOC_LEN               100     /* number of values to allocate each time in partition counter nodes */
82 
83 #if defined (PRINT_RATEMUL_CPP)
84 FILE     *rateMultfp=NULL;
85 #endif
86 
87 #undef  DEBUG_CONTREE
88 
89 extern int inSumtCommand;
90 extern int inComparetreeCommand;
91 extern int DoUserTree (void);
92 extern int DoUserTreeParm (char *parmName, char *tkn);
93 extern int SafeFclose(FILE **);
94 
95 extern int  SetUpPartitionCounters (void);
96 extern int  AddTreeToPartitionCounters (Tree *tree, int treeId, int runId);
97 extern void CalcTopoConvDiagn2 (int *nTrees);
98 extern void FreeChainMemory (void);
99 
100 /* local prototypes */
101 int      CompareModelProbs (const void *x, const void *y);
102 int      PrintModelStats (char *fileName, char **headerNames, int nHeaders, ParameterSample *parameterSamples, int nRuns, int nSamples);
103 int      PrintOverlayPlot (MrBFlt **xVals, MrBFlt **yVals, int nRows, int startingFrom, int nSamples);
104 int      PrintParamStats (char *fileName, char **headerNames, int nHeaders, ParameterSample *parameterSamples, int nRuns, int nSamples);
105 void     PrintPlotHeader (void);
106 
107 PartCtr *AddSumtPartition (PartCtr *r, PolyTree *t, PolyNode *p, int runId);
108 TreeCtr *AddSumtTree (TreeCtr *r, int *order);
109 PartCtr *AllocPartCtr (void);
110 TreeCtr *AllocTreeCtr (void);
111 void     CalculateTreeToTreeDistance (Tree *tree1, Tree *tree2, MrBFlt *d1, MrBFlt *d2, MrBFlt *d3);
112 int      ConTree (PartCtr **treeParts, int numTreeParts);
113 MrBFlt   CppEvolRate (PolyTree *t, PolyNode *p, int eSet);
114 int      ExamineSumtFile (char *fileName, SumtFileInfo *sumtFileInfo, char *treeName, int *brlensDef);
115 void     FreePartCtr (PartCtr *r);
116 void     FreeSumtParams (void);
117 void     FreeTreeCtr (TreeCtr *r);
118 int      Label (PolyNode *p, int addIndex, char *label, int maxLength);
119 int      OpenBrlensFile (int treeNo);
120 int      OpenComptFiles (void);
121 int      OpenSumtFiles (int treeNo);
122 void     PartCtrUppass (PartCtr *r, PartCtr **uppass, int *index);
123 int      PrintBrParamsToFile (PartCtr **treeParts, int numTreeParts, int treeNo, char *divString);
124 void     PrintConTree (FILE *fp, PolyTree *t);
125 void     PrintFigTreeConTree (FILE *fp, PolyTree *t, PartCtr **treeParts);
126 void     PrintFigTreeNodeInfo (FILE *fp, PartCtr *x, MrBFlt length);
127 void     PrintSumtTableLine (int numRuns, int *rowCount, Stat *theStats, MrBFlt *numPSRFSamples, MrBFlt *maxPSRF, MrBFlt *sumPSRF);
128 void     PrintSumtTaxaInfo (void);
129 void     Range (MrBFlt *vals, int nVals, MrBFlt *min, MrBFlt *max);
130 void     ResetTaxonSet (void);
131 int      ShowConPhylogram (FILE *fp, PolyTree *t, int screenWidth);
132 void     ShowSomeParts (FILE *fp, BitsLong *p, int offset, int nTaxaToShow);
133 void     SortPartCtr (PartCtr **item, int left, int right);
134 void     SortTerminalPartCtr (PartCtr **item, int len);
135 void     SortTreeCtr (TreeCtr **item, int left, int right);
136 int      StoreSumtTree (PackedTree *treeList, int index, PolyTree *t);
137 void     TreeCtrUppass (TreeCtr *r, TreeCtr **uppass, int *index);
138 int      TreeProb (void);
139 void     WriteConTree (PolyNode *p, FILE *fp, int showSupport);
140 void     WriteFigTreeConTree (PolyNode *p, FILE *fp, PartCtr **treeParts);
141 
142 /* local (to this file) */
143 static int          numUniqueSplitsFound, numUniqueTreesFound, numPackedTrees[2], numAsterices;  /* length of local to this file variables */
144 static FILE        *fpParts=NULL, *fpTstat=NULL, *fpVstat, *fpCon=NULL, *fpTrees=NULL, *fpDists=NULL;  /* file pointers */
145 static PartCtr     *partCtrRoot = NULL;        /* binary tree for holding splits info      */
146 static TreeCtr     *treeCtrRoot = NULL;        /* binary tree for holding unique tree info */
147 static PackedTree  *packedTreeList[2];         /* list of trees in packed format           */
148 
149 
150 /* AllocateParameterSamples: Allocate space for parameter samples */
AllocateParameterSamples(ParameterSample ** parameterSamples,int numRuns,int numRows,int numColumns)151 int AllocateParameterSamples (ParameterSample **parameterSamples, int numRuns, int numRows, int numColumns)
152 {
153     int     i, j;
154 
155     (*parameterSamples) = (ParameterSample *) SafeCalloc (numColumns, sizeof(ParameterSample));
156     if (!(*parameterSamples))
157         return ERROR;
158     (*parameterSamples)[0].values = (MrBFlt **) SafeCalloc (numColumns * numRuns, sizeof (MrBFlt *));
159     if (!((*parameterSamples)[0].values))
160         {
161         FreeParameterSamples(*parameterSamples);
162         return ERROR;
163         }
164     (*parameterSamples)[0].values[0] = (MrBFlt *) SafeCalloc (numColumns * numRuns * numRows, sizeof (MrBFlt));
165     for (i=1; i<numColumns; i++)
166         (*parameterSamples)[i].values = (*parameterSamples)[0].values + i*numRuns;
167     for (i=1; i<numRuns; i++)
168         (*parameterSamples)[0].values[i] = (*parameterSamples)[0].values[0] + i*numRows;
169     for (i=1; i<numColumns; i++)
170         {
171         for (j=0; j<numRuns; j++)
172             {
173             (*parameterSamples)[i].values[j] = (*parameterSamples)[0].values[0] + i*numRuns*numRows + j*numRows;
174             }
175         }
176 
177     return NO_ERROR;
178 }
179 
180 
181 /** Compare function (ModelProb) for qsort. Note reverse sort order (from larger to smaller probs) */
CompareModelProbs(const void * x,const void * y)182 int CompareModelProbs (const void *x, const void *y) {
183 
184     if ((*((ModelProb *)(x))).prob > (*((ModelProb *)(y))).prob)
185         return -1;
186     else if ((*((ModelProb *)(x))).prob < (*((ModelProb *)(y))).prob)
187         return 1;
188     else
189         return 0;
190 }
191 
192 
DoSump(void)193 int DoSump (void)
194 {
195     int             i, n, nHeaders=0, numRows, numColumns, numRuns, whichIsX, whichIsY,
196                     unreliable, oneUnreliable, burnin, longestHeader, len;
197     MrBFlt          mean, harm_mean;
198     char            **headerNames=NULL, temp[120];
199     SumpFileInfo    fileInfo, firstFileInfo;
200     ParameterSample *parameterSamples=NULL;
201     FILE            *fpLstat=NULL;
202 
203 #   if defined (MPI_ENABLED)
204     if (proc_id != 0)
205         return NO_ERROR;
206 #   endif
207 
208     /* tell user we are ready to go */
209     if (sumpParams.numRuns == 1)
210         MrBayesPrint ("%s   Summarizing parameters in file %s.p\n", spacer, sumpParams.sumpFileName);
211     else if (sumpParams.numRuns == 2)
212         MrBayesPrint ("%s   Summarizing parameters in files %s.run1.p and %s.run2.p\n", spacer, sumpParams.sumpFileName, sumpParams.sumpFileName);
213     else /* if (sumpParams.numRuns > 2) */
214         {
215         MrBayesPrint ("%s   Summarizing parameters in %d files (%s.run1.p,\n", spacer, sumpParams.numRuns, sumpParams.sumpFileName);
216         MrBayesPrint ("%s      %s.run2.p, etc)\n", spacer, sumpParams.sumpFileName);
217         }
218     MrBayesPrint ("%s   Writing summary statistics to file %s.pstat\n", spacer, sumpParams.sumpFileName);
219 
220     if (chainParams.relativeBurnin == YES)
221         MrBayesPrint ("%s   Using relative burnin ('relburnin=yes'), discarding the first %.0f %% of samples\n",
222             spacer, chainParams.burninFraction*100.0, chainParams.burninFraction);
223     else
224         MrBayesPrint ("%s   Using absolute burnin ('relburnin=no'), discarding the first %d samples\n",
225             spacer, chainParams.chainBurnIn, chainParams.chainBurnIn);
226 
227     /* Initialize to silence warning. */
228     firstFileInfo.numRows = 0;
229     firstFileInfo.numColumns = 0;
230 
231     /* examine input file(s) */
232     for (i=0; i<sumpParams.numRuns; i++)
233         {
234         if (sumpParams.numRuns == 1)
235             sprintf (temp, "%s.p", sumpParams.sumpFileName);
236         else
237             sprintf (temp, "%s.run%d.p", sumpParams.sumpFileName, i+1);
238 
239         if (ExamineSumpFile (temp, &fileInfo, &headerNames, &nHeaders) == ERROR)
240             goto errorExit;
241 
242         if (i==0)
243             {
244             if (fileInfo.numRows == 0 || fileInfo.numColumns == 0)
245                 {
246                 MrBayesPrint ("%s   The number of rows or columns in file %d is equal to zero\n", spacer, temp);
247                 goto errorExit;
248                 }
249             firstFileInfo = fileInfo;
250             }
251         else
252             {
253             if (firstFileInfo.numRows != fileInfo.numRows || firstFileInfo.numColumns != fileInfo.numColumns)
254                 {
255                 MrBayesPrint ("%s   First file had %d rows and %d columns while file %s had %d rows and %d columns\n",
256                     spacer, firstFileInfo.numRows, firstFileInfo.numColumns, temp, fileInfo.numRows, fileInfo.numColumns);
257                 MrBayesPrint ("%s   MrBayes expects the same number of rows and columns in all files\n", spacer);
258                 goto errorExit;
259                 }
260             }
261         }
262 
263     numRows = fileInfo.numRows;
264     numColumns = fileInfo.numColumns;
265     numRuns = sumpParams.numRuns;
266 
267     /* allocate space to hold parameter information */
268     if (AllocateParameterSamples (&parameterSamples, numRuns, numRows, numColumns) == ERROR)
269         return ERROR;
270 
271     /* read samples */
272     for (i=0; i<sumpParams.numRuns; i++)
273         {
274         /* derive file name */
275         if (sumpParams.numRuns == 1)
276             sprintf (temp, "%s.p", sumpParams.sumpFileName);
277         else
278             sprintf (temp, "%s.run%d.p", sumpParams.sumpFileName, i+1);
279 
280         /* read samples */
281         if (ReadParamSamples (temp, &fileInfo, parameterSamples, i) == ERROR)
282             goto errorExit;
283         }
284 
285     /* get length of longest header */
286     longestHeader = 9; /* 9 is the length of the word "parameter" (for printing table) */
287     for (i=0; i<nHeaders; i++)
288         {
289         len = (int) strlen(headerNames[i]);
290         if (len > longestHeader)
291             longestHeader = len;
292         }
293 
294     /* Print header */
295     PrintPlotHeader ();
296 
297     /* Print trace plots */
298     if (FindHeader("Gen", headerNames, nHeaders, &whichIsX) == ERROR)
299         {
300         MrBayesPrint ("%s   Could not find the 'Gen' column\n", spacer);
301         return ERROR;
302         }
303     if (FindHeader("LnL", headerNames, nHeaders, &whichIsY) == ERROR)
304         {
305         MrBayesPrint ("%s   Could not find the 'LnL' column\n", spacer);
306         return ERROR;
307         }
308 
309     if (sumpParams.numRuns > 1)
310         {
311         if (sumpParams.allRuns == YES)
312             {
313             for (i=0; i<sumpParams.numRuns; i++)
314                 {
315                 MrBayesPrint ("\n%s   Samples from run %d:\n", spacer, i+1);
316                 if (PrintPlot (parameterSamples[whichIsX].values[i], parameterSamples[whichIsY].values[i], numRows) == ERROR)
317                     goto errorExit;
318                 }
319             }
320         else
321             {
322             if (PrintOverlayPlot (parameterSamples[whichIsX].values, parameterSamples[whichIsY].values, numRuns, 0, numRows) == ERROR)
323                 goto errorExit;
324             }
325         }
326     else
327         {
328         if (PrintPlot (parameterSamples[whichIsX].values[0], parameterSamples[whichIsY].values[0], numRows) == ERROR)
329             goto errorExit;
330         }
331 
332     /* calculate arithmetic and harmonic means of likelihoods */
333 
334     /* open output file */
335     strncpy (temp, sumpParams.sumpOutfile, 90);
336     strcat (temp, ".lstat");
337     fpLstat = OpenNewMBPrintFile (temp);
338     if (!fpLstat)
339         goto errorExit;
340 
341     /* print unique identifier to the output file */
342     if (strlen(stamp) > 1)
343         MrBayesPrintf (fpLstat, "[ID: %s]\n", stamp);
344 
345     /* print header */
346     if (sumpParams.numRuns == 1)
347         MrBayesPrintf (fpLstat, "arithmetic_mean\tharmonic_mean\tvalues_discarded\n");
348     else
349         MrBayesPrintf (fpLstat, "run\tarithmetic_mean\tharmonic_mean\tvalues_discarded\n");
350 
351     oneUnreliable = NO;
352     for (n=0; n<sumpParams.numRuns; n++)
353         {
354         unreliable = NO;
355         if (HarmonicArithmeticMeanOnLogs (parameterSamples[whichIsY].values[n], numRows, &mean, &harm_mean) == ERROR)
356             {
357             unreliable = YES;
358             oneUnreliable = YES;
359             }
360         if (sumpParams.numRuns == 1)
361             {
362             MrBayesPrint ("\n");
363             MrBayesPrint ("%s   Estimated marginal likelihoods for run sampled in file \"%s.p\":\n", spacer, sumpParams.sumpFileName);
364             MrBayesPrint ("%s      (Use the harmonic mean for Bayes factor comparisons of models)\n", spacer, sumpParams.sumpFileName);
365             MrBayesPrint ("%s      (Values are saved to the file %s.lstat)\n\n", spacer, sumpParams.sumpOutfile);
366             MrBayesPrint ("%s   Arithmetic mean   Harmonic mean\n", spacer);
367             MrBayesPrint ("%s   --------------------------------\n", spacer);
368             if (unreliable == NO)
369                 MrBayesPrint ("%s     %9.2lf        %9.2lf\n", spacer, mean, harm_mean);
370             else
371                 MrBayesPrint ("%s     %9.2lf *      %9.2lf *\n", spacer, mean, harm_mean);
372 
373             /* print to file */
374             MrBayesPrintf (fpLstat, "%s\t", MbPrintNum(mean));
375             MrBayesPrintf (fpLstat, "%s\t", MbPrintNum(harm_mean));
376             if (unreliable == YES)
377                 MrBayesPrintf (fpLstat, "yes\n");
378             else
379                 MrBayesPrintf (fpLstat, "no\n");
380             }
381         else
382             {
383             if (n == 0)
384                 {
385                 MrBayesPrint ("\n");
386                 MrBayesPrint ("%s   Estimated marginal likelihoods for runs sampled in files\n", spacer);
387                 if (sumpParams.numRuns > 2)
388                     MrBayesPrint ("%s      \"%s.run1.p\", \"%s.run2.p\", etc:\n", spacer, sumpParams.sumpFileName, sumpParams.sumpFileName);
389                 else /* if (sumpParams.numRuns == 2) */
390                     MrBayesPrint ("%s      \"%s.run1.p\" and \"%s.run2.p\":\n", spacer, sumpParams.sumpFileName, sumpParams.sumpFileName);
391                 MrBayesPrint ("%s      (Use the harmonic mean for Bayes factor comparisons of models)\n\n", spacer, sumpParams.sumpFileName);
392                 MrBayesPrint ("%s      (Values are saved to the file %s.lstat)\n\n", spacer, sumpParams.sumpOutfile);
393                 MrBayesPrint ("%s   Run   Arithmetic mean   Harmonic mean\n", spacer);
394                 MrBayesPrint ("%s   --------------------------------------\n", spacer);
395                 }
396             if (unreliable == NO)
397                 MrBayesPrint ("%s   %3d     %9.2lf        %9.2lf\n", spacer, n+1, mean, harm_mean);
398             else
399                 MrBayesPrint ("%s   %3d     %9.2lf *      %9.2lf *\n", spacer, n+1, mean, harm_mean);
400 
401             /* print to file */
402             MrBayesPrintf (fpLstat, "%d\t", n+1);
403             MrBayesPrintf (fpLstat, "%s\t", MbPrintNum(mean));
404             MrBayesPrintf (fpLstat, "%s\t", MbPrintNum(harm_mean));
405             if (unreliable == YES)
406                 MrBayesPrintf (fpLstat, "yes\n");
407             else
408                 MrBayesPrintf (fpLstat, "no\n");
409             }
410         }   /* next run */
411     if (sumpParams.numRuns == 1)
412         {
413         MrBayesPrint ("%s   --------------------------------\n", spacer);
414         }
415     else
416         {
417         if (HarmonicArithmeticMeanOnLogs (parameterSamples[whichIsY].values[0], sumpParams.numRuns*numRows, &mean, &harm_mean) == ERROR)
418             {
419             unreliable = YES;
420             oneUnreliable = YES;
421             }
422         else
423             unreliable = NO;
424         MrBayesPrint ("%s   --------------------------------------\n", spacer);
425         if (unreliable == YES)
426             MrBayesPrint ("%s   TOTAL   %9.2lf *      %9.2lf *\n", spacer, mean, harm_mean);
427         else
428             MrBayesPrint ("%s   TOTAL   %9.2lf        %9.2lf\n", spacer, mean, harm_mean);
429         MrBayesPrint ("%s   --------------------------------------\n", spacer);
430 
431         /* print total to file */
432         MrBayesPrintf (fpLstat, "all\t");
433         MrBayesPrintf (fpLstat, "%s\t", MbPrintNum(mean));
434         MrBayesPrintf (fpLstat, "%s\t", MbPrintNum(harm_mean));
435         if (unreliable == YES)
436             MrBayesPrintf (fpLstat, "yes\n");
437         else
438             MrBayesPrintf (fpLstat, "no\n");
439         }
440     if (oneUnreliable == YES)
441         {
442         MrBayesPrint ("%s   * These estimates may be unreliable because \n", spacer);
443         MrBayesPrint ("%s     some extreme values were excluded\n\n", spacer);
444         }
445     else
446         {
447         MrBayesPrint ("\n");
448         }
449     SafeFclose(&fpLstat);
450 
451     /* Calculate burnin */
452     burnin = fileInfo.firstParamLine - fileInfo.headerLine;
453 
454     /* Print parameter information to screen and to file. */
455     if (sumpParams.numRuns > 1 && sumpParams.allRuns == YES)
456         {
457         for (i=0; i<sumpParams.numRuns; i++)
458             {
459             /* print table header */
460             MrBayesPrint ("\n");
461             MrBayesPrint ("%s   Model parameter summaries for run sampled in file \"%s.run%d.p\":\n", spacer, sumpParams.sumpFileName, i+1);
462             MrBayesPrint ("%s      (Based on %d samples out of a total of %d samples from this analysis)\n\n", spacer, numRows, numRows + burnin);
463             if (PrintParamStats (sumpParams.sumpOutfile, headerNames, nHeaders, parameterSamples, numRuns, numRows) == ERROR)
464                 goto errorExit;
465             if (PrintModelStats (sumpParams.sumpOutfile, headerNames, nHeaders, parameterSamples, numRuns, numRows) == ERROR)
466                 goto errorExit;
467             }
468         }
469 
470     MrBayesPrint ("\n");
471     if (sumpParams.numRuns == 1)
472         MrBayesPrint ("%s   Model parameter summaries for run sampled in file \"%s\":\n", spacer, sumpParams.sumpFileName);
473     else if (sumpParams.numRuns == 2)
474         {
475         MrBayesPrint ("%s   Model parameter summaries over the runs sampled in files\n", spacer);
476         MrBayesPrint ("%s      \"%s.run1.p\" and \"%s.run2.p\":\n", spacer, sumpParams.sumpFileName, sumpParams.sumpFileName);
477         }
478     else
479         {
480         MrBayesPrint ("%s   Model parameter summaries over all %d runs sampled in files\n", spacer, sumpParams.numRuns);
481         MrBayesPrint ("%s      \"%s.run1.p\", \"%s.run2.p\" etc:\n", spacer, sumpParams.sumpFileName, sumpParams.sumpFileName);
482         }
483 
484     if (sumpParams.numRuns == 1)
485         {
486         MrBayesPrint ("%s      Based on a total of %d samples out of a total of %d samples\n", spacer, numRows, numRows + burnin);
487         MrBayesPrint ("%s         from this analysis.\n", spacer);
488         }
489     else
490         {
491         MrBayesPrint ("%s      Summaries are based on a total of %d samples from %d runs.\n", spacer, sumpParams.numRuns*numRows, sumpParams.numRuns);
492         MrBayesPrint ("%s      Each run produced %d samples of which %d samples were included.\n", spacer, numRows + burnin, numRows);
493         }
494     MrBayesPrint ("%s      Parameter summaries saved to file \"%s.pstat\".\n", spacer, sumpParams.sumpOutfile);
495 
496     if (PrintParamStats (sumpParams.sumpOutfile, headerNames, nHeaders, parameterSamples, numRuns, numRows) == ERROR)
497         goto errorExit;
498     if (PrintModelStats (sumpParams.sumpOutfile, headerNames, nHeaders, parameterSamples, numRuns, numRows) == ERROR)
499         goto errorExit;
500 
501     /* free memory */
502     FreeParameterSamples(parameterSamples);
503     for (i=0; i<nHeaders; i++)
504         free (headerNames[i]);
505     free (headerNames);
506 
507     expecting = Expecting(COMMAND);
508     strcpy (spacer, "");
509 
510     return (NO_ERROR);
511 
512 errorExit:
513 
514     /* free memory */
515     FreeParameterSamples (parameterSamples);
516     for (i=0; i<nHeaders; i++)
517         free (headerNames[i]);
518     free (headerNames);
519 
520     if (fpLstat)
521         SafeFclose (&fpLstat);
522 
523     expecting = Expecting(COMMAND);
524     strcpy (spacer, "");
525 
526     return (ERROR);
527 }
528 
529 
DoSumSs(void)530 int DoSumSs (void)
531 {
532     int             i, nHeaders=0, numRows, numColumns, numRuns, whichIsX, whichIsY,
533                     longestHeader, len;
534     char            **headerNames=NULL, temp[120];
535     SumpFileInfo    fileInfo, firstFileInfo;
536     ParameterSample *parameterSamples=NULL;
537     int             stepIndexSS,numSamplesInStepSS, stepBeginSS, stepBurnin;
538     MrBFlt          *lnlp, *nextSteplnlp, *firstlnlp;
539     MrBFlt          *marginalLnLSS=NULL,stepScalerSS,stepAcumulatorSS, stepLengthSS, tmpMfl;
540     int             beginPrint, countPrint;
541     float           tmpf;
542     MrBFlt          **plotArrayY=NULL,**plotArrayX=NULL;
543     int             j, k, count;
544     MrBFlt          sum;
545     int             firstPass = YES;
546 
547 #   if defined (MPI_ENABLED)
548     if (proc_id != 0)
549         return NO_ERROR;
550 #   endif
551 
552     chainParams.isSS=YES;
553 
554     /* tell user we are ready to go */
555     if (sumssParams.numRuns == 1)
556         MrBayesPrint ("%s   Summarizing parameters in file %s.p\n", spacer, sumpParams.sumpFileName);
557     else if (sumssParams.numRuns == 2)
558         MrBayesPrint ("%s   Summarizing parameters in files %s.run1.p and %s.run2.p\n", spacer, sumpParams.sumpFileName, sumpParams.sumpFileName);
559     else /* if (sumssParams.numRuns > 2) */
560         {
561         MrBayesPrint ("%s   Summarizing parameters in %d files (%s.run1.p,\n", spacer, sumssParams.numRuns, sumpParams.sumpFileName);
562         MrBayesPrint ("%s      %s.run2.p, etc)\n", spacer, sumpParams.sumpFileName);
563         }
564     //MrBayesPrint ("%s   Writing summary statistics to file %s.pstat\n", spacer, sumpParams.sumpFileName);
565 
566     if (chainParams.relativeBurnin == YES)
567         MrBayesPrint ("%s   Using relative burnin ('relburnin=yes'), discarding the first %.0f %% of samples within each step.\n",
568             spacer, chainParams.burninFraction*100.0, chainParams.burninFraction);
569     else
570         MrBayesPrint ("%s   Using absolute burnin ('relburnin=no'), discarding the first %d samples within each step.\n",
571             spacer, chainParams.chainBurnIn, chainParams.chainBurnIn);
572 
573     /* Initialize to silence warning. */
574     firstFileInfo.numRows = 0;
575     firstFileInfo.numColumns = 0;
576 
577     /* examine input file(s) */
578     for (i=0; i<sumssParams.numRuns; i++)
579         {
580         if (sumssParams.numRuns == 1)
581             sprintf (temp, "%s.p", sumpParams.sumpFileName);
582         else
583             sprintf (temp, "%s.run%d.p", sumpParams.sumpFileName, i+1);
584 
585         if (ExamineSumpFile (temp, &fileInfo, &headerNames, &nHeaders) == ERROR)
586             goto errorExit;
587 
588         if (i==0)
589             {
590             if (fileInfo.numRows == 0 || fileInfo.numColumns == 0)
591                 {
592                 MrBayesPrint ("%s   The number of rows or columns in file %d is equal to zero\n", spacer, temp);
593                 goto errorExit;
594                 }
595             firstFileInfo = fileInfo;
596             }
597         else
598             {
599             if (firstFileInfo.numRows != fileInfo.numRows || firstFileInfo.numColumns != fileInfo.numColumns)
600                 {
601                 MrBayesPrint ("%s   First file had %d rows and %d columns while file %s had %d rows and %d columns\n",
602                     spacer, firstFileInfo.numRows, firstFileInfo.numColumns, temp, fileInfo.numRows, fileInfo.numColumns);
603                 MrBayesPrint ("%s   MrBayes expects the same number of rows and columns in all files\n", spacer);
604                 goto errorExit;
605                 }
606             }
607         }
608 
609     numRows = fileInfo.numRows;
610     numColumns = fileInfo.numColumns;
611     numRuns = sumssParams.numRuns;
612 
613     /* allocate space to hold parameter information */
614     if (AllocateParameterSamples (&parameterSamples, numRuns, numRows, numColumns) == ERROR)
615         goto errorExit;
616 
617     /* read samples */
618     for (i=0; i<sumssParams.numRuns; i++)
619         {
620         /* derive file name */
621         if (sumssParams.numRuns == 1)
622             sprintf (temp, "%s.p", sumpParams.sumpFileName);
623         else
624             sprintf (temp, "%s.run%d.p", sumpParams.sumpFileName, i+1);
625 
626         /* read samples */
627         if (ReadParamSamples (temp, &fileInfo, parameterSamples, i) == ERROR)
628             goto errorExit;
629         }
630 
631     /* get length of longest header */
632     longestHeader = 9; /* 9 is the length of the word "parameter" (for printing table) */
633     for (i=0; i<nHeaders; i++)
634         {
635         len = (int) strlen(headerNames[i]);
636         if (len > longestHeader)
637             longestHeader = len;
638         }
639 
640     /* Print trace plots */
641     if (FindHeader("Gen", headerNames, nHeaders, &whichIsX) == ERROR)
642         {
643         MrBayesPrint ("%s   Could not find the 'Gen' column\n", spacer);
644         goto errorExit;
645         }
646     if (FindHeader("LnL", headerNames, nHeaders, &whichIsY) == ERROR)
647         {
648         MrBayesPrint ("%s   Could not find the 'LnL' column\n", spacer);
649         goto errorExit;
650         }
651 
652     if (chainParams.burninSS > 0)
653         {
654         stepBeginSS = chainParams.burninSS + 1;
655         }
656     else
657         {
658         numSamplesInStepSS = (numRows-1)/(chainParams.numStepsSS-chainParams.burninSS);
659         stepBeginSS = numSamplesInStepSS + 1;
660         }
661 
662     numSamplesInStepSS = (numRows - stepBeginSS)/chainParams.numStepsSS;
663     if ((numRows - stepBeginSS)%chainParams.numStepsSS!=0)
664         {
665         MrBayesPrint ("%s   Error:  Number of samples could not be evenly divided among steps (%d samples among %d steps). \n", spacer,(numRows - stepBeginSS),chainParams.numStepsSS);
666         goto errorExit;
667         }
668 
669     if (chainParams.relativeBurnin == YES)
670         {
671         stepBurnin = (int)(numSamplesInStepSS*chainParams.burninFraction);
672         }
673     else
674         {
675         stepBurnin = chainParams.chainBurnIn;
676         if (stepBurnin >= numSamplesInStepSS)
677             {
678             MrBayesPrint ("%s   Error:  Burnin in each step(%d) is longer then the step itself(%d). \n", spacer,stepBurnin, numSamplesInStepSS);
679             goto errorExit;
680             }
681         }
682 
683     marginalLnLSS = (MrBFlt *) SafeCalloc (sumssParams.numRuns, sizeof(MrBFlt));
684         /*Preparing and printing joined plot.*/
685     plotArrayY = (MrBFlt **) SafeCalloc (sumssParams.numRuns+1, sizeof(MrBFlt*));
686     for (i=0; i<sumssParams.numRuns+1; i++)
687         plotArrayY[i] = (MrBFlt *) SafeCalloc (numSamplesInStepSS, sizeof(MrBFlt));
688 
689     plotArrayX = (MrBFlt **) SafeCalloc (sumssParams.numRuns, sizeof(MrBFlt*));
690     for (i=0; i<sumssParams.numRuns; i++)
691         {
692         plotArrayX[i] = (MrBFlt *) SafeCalloc (numSamplesInStepSS, sizeof(MrBFlt));
693         for (j=0; j<numSamplesInStepSS; j++)
694             plotArrayX[i][j]=j+1;
695         }
696 
697     MrBayesPrint ("%s   In total %d sampls are red from .p files.\n", spacer, numRows);
698     MrBayesPrint ("\n");
699     MrBayesPrint ("%s   Marginal likelihood (in natural log units) is estimated using stepping-stone sampling\n", spacer);
700     MrBayesPrint ("%s   based on %d steps with %d samples within each step. \n", spacer, chainParams.numStepsSS, numSamplesInStepSS);
701     MrBayesPrint ("%s   First %d samples (including generation 0) are discarded as initial burn-in.\n", spacer, stepBeginSS);
702         if (chainParams.startFromPriorSS==YES)
703             MrBayesPrint ("%s   Sampling is assumed have being done from prior to posterior.\n", spacer);
704         else
705             {
706             MrBayesPrint ("%s   Sampling is assumed have being done from posterior to prior.\n", spacer);
707             }
708 
709 sumssTable:
710 
711     MrBayesPrint ("\n\n%s   Step contribution table.\n\n",spacer);
712     MrBayesPrint ("   Columns in the table: \n");
713     MrBayesPrint ("   Step -- Index of the step \n");
714     MrBayesPrint ("   runX -- Contribution to the marginal log likelihood of run X, i.e. marginal \n");
715     MrBayesPrint ("           log likelihood for run X is the sum across all steps in column runX.\n\n");
716 
717     if (firstPass == YES && chainParams.relativeBurnin == YES)
718         MrBayesPrint ("%s   The table entrances are based on samples excluding burn-in %d samples  (%d%%)    \n", spacer, stepBurnin,(int)(100*chainParams.burninFraction));
719     else
720         MrBayesPrint ("%s   The table entrances are based on samples excluding burn-in %d samples      \n", spacer, stepBurnin);
721     MrBayesPrint ("%s   discarded at the beginning of each step.  \n\n", spacer);
722 
723     //MrBayesPrint ("%s       Run   Marginal likelihood (ln)\n",spacer);
724     //MrBayesPrint ("%s       ------------------------------\n",spacer);
725     MrBayesPrint ("   Step");
726     for (j=0; j<sumssParams.numRuns ; j++)
727         {
728         if (j<9)
729             MrBayesPrint (" ");
730         MrBayesPrint ("      run%d", j+1);
731         }
732     MrBayesPrint ("\n");
733     for (i=0; i<sumssParams.numRuns; i++)
734         {
735         marginalLnLSS[i] = 0.0;
736         }
737     for (stepIndexSS = chainParams.numStepsSS-1; stepIndexSS>=0; stepIndexSS--)
738         {
739         if (chainParams.startFromPriorSS==YES)
740             {
741             stepLengthSS = BetaQuantile(chainParams.alphaSS, 1.0, (MrBFlt)(chainParams.numStepsSS-stepIndexSS)/(MrBFlt)chainParams.numStepsSS) - BetaQuantile(chainParams.alphaSS, 1.0, (MrBFlt)(chainParams.numStepsSS-1-stepIndexSS)/(MrBFlt)chainParams.numStepsSS);
742             }
743         else
744             {
745             stepLengthSS = BetaQuantile(chainParams.alphaSS, 1.0, (MrBFlt)(stepIndexSS+1)/(MrBFlt)chainParams.numStepsSS) - BetaQuantile(chainParams.alphaSS, 1.0, (MrBFlt)stepIndexSS/(MrBFlt)chainParams.numStepsSS);
746             }
747         MrBayesPrint ("   %3d   ", chainParams.numStepsSS-stepIndexSS);
748         for (i=0; i<sumssParams.numRuns; i++)
749             {
750             lnlp = parameterSamples[whichIsY].values[i] + stepBeginSS + (chainParams.numStepsSS-stepIndexSS-1)*numSamplesInStepSS;
751             nextSteplnlp = lnlp+numSamplesInStepSS;
752             lnlp+= stepBurnin;
753             stepAcumulatorSS = 0.0;
754             stepScalerSS = *lnlp*stepLengthSS;
755             while (lnlp < nextSteplnlp)
756                 {
757                if (*lnlp*stepLengthSS > stepScalerSS + 200.0)
758                     {
759                     // adjust scaler;
760                     stepAcumulatorSS /= exp(*lnlp*stepLengthSS - 100.0 - stepScalerSS);
761                     stepScalerSS= *lnlp*stepLengthSS - 100.0;
762                     }
763                 stepAcumulatorSS += exp(*lnlp*stepLengthSS - stepScalerSS);
764                 lnlp++;
765                 }
766             tmpMfl = (log(stepAcumulatorSS/(numSamplesInStepSS-stepBurnin)) + stepScalerSS);
767             MrBayesPrint (" %10.3lf", tmpMfl);
768             marginalLnLSS[i] += tmpMfl;
769             }
770         MrBayesPrint ("\n");
771         //MrBayesPrint ("%s       %3d    %9.2f   \n", spacer, i+1, marginalLnLSS);
772         }
773     MrBayesPrint ("         ");
774     for (j=0; j<sumssParams.numRuns ; j++)
775         {
776         if (j<9)
777             MrBayesPrint ("-");
778         MrBayesPrint ("----------");
779         }
780     MrBayesPrint ("\n");
781     MrBayesPrint ("   Sum:  ");
782     for (j=0; j<sumssParams.numRuns ; j++)
783         MrBayesPrint (" %10.3lf", marginalLnLSS[j]);
784 
785     MrBayesPrint ("\n");
786 
787     /*
788         if (sumssParams.numRuns > 1)
789             {
790             MrBayesPrint ("%s   Below are rough plots of the generations (x-axis) during burn in  \n", spacer);
791             MrBayesPrint ("%s   phase versus the log probability of observing the data (y-axis).  \n", spacer);
792             MrBayesPrint ("%s   You can use these graphs to determine if the burn in for your SS  \n", spacer);
793             MrBayesPrint ("%s   analysis was sufficiant. The log probability suppose to plateau   \n", spacer);
794             MrBayesPrint ("%s   indicating that you may be at stationarity by the time you finish \n", spacer);
795             MrBayesPrint ("%s   burn in phase. This burn in, unlike burn in within each step, is  \n", spacer);
796             MrBayesPrint ("%s   fixed and can not be changed.                                     \n", spacer);
797             }
798         else
799             {
800             MrBayesPrint ("%s   Below is a rough plot of the generations (x-axis) during burn in  \n", spacer);
801             MrBayesPrint ("%s   phase versus the log probability of observing the data (y-axis).  \n", spacer);
802             MrBayesPrint ("%s   You can use these graph to determine if the burn in for your SS   \n", spacer);
803             MrBayesPrint ("%s   analysis was sufficiant. The log probability suppose to plateau   \n", spacer);
804             MrBayesPrint ("%s   indicating that you may be at stationarity by the time you finish \n", spacer);
805             MrBayesPrint ("%s   burn in phase. This burn in, unlike burn in within each step, is  \n", spacer);
806             MrBayesPrint ("%s   fixed and can not be changed.                                     \n", spacer);
807             }
808     */
809 
810     if (firstPass == NO)
811         goto sumssExitOptions;
812 
813     sumssStepPlot:
814 
815     MrBayesPrint ("\n\n%s   Step plot(s).\n",spacer);
816     while (1)
817         {
818          MrBayesPrint ("\n");
819         if (sumssParams.stepToPlot == 0)
820             {
821             beginPrint=(int)(sumssParams.discardFraction*stepBeginSS);
822             countPrint=stepBeginSS-beginPrint;
823             MrBayesPrint ("%s   Plotting step 0, i.e initial burn-in phase consisting of %d samples.\n", spacer,stepBeginSS);
824             MrBayesPrint ("%s   According to 'Discardfrac=%.2f', first %d samples are not ploted.\n", spacer,sumssParams.discardFraction,beginPrint);
825             }
826         else
827             {
828             if (sumssParams.stepToPlot > chainParams.numStepsSS)
829                 {
830                 MrBayesPrint ("%s   Chosen index of step to print %d is out of range of step indices[0,...,%d].\n", spacer,sumssParams.stepToPlot,chainParams.numStepsSS);
831                 goto errorExit;
832                 }
833             beginPrint=stepBeginSS+(sumssParams.stepToPlot-1)*numSamplesInStepSS + (int)(sumssParams.discardFraction*numSamplesInStepSS);
834             countPrint=numSamplesInStepSS-(int)(sumssParams.discardFraction*numSamplesInStepSS);
835             MrBayesPrint ("%s   Plotting step %d consisting of %d samples.\n", spacer,sumssParams.stepToPlot,numSamplesInStepSS);
836             MrBayesPrint ("%s   According to 'Discardfrac=%.2f', first %d samples are not ploted.\n", spacer,sumssParams.discardFraction,(int)(sumssParams.discardFraction*numSamplesInStepSS));
837             }
838 
839         if (sumssParams.numRuns > 1)
840             {
841             if (sumpParams.allRuns == YES)
842                 {
843                 for (i=0; i<sumssParams.numRuns; i++)
844                     {
845                     MrBayesPrint ("\n%s   Samples from run %d:\n", spacer, i+1);
846                     if (PrintPlot (parameterSamples[whichIsX].values[i]+beginPrint, parameterSamples[whichIsY].values[i]+beginPrint, countPrint) == ERROR)
847                         goto errorExit;
848                     }
849                 }
850             else
851                 {
852                 if (PrintOverlayPlot (parameterSamples[whichIsX].values, parameterSamples[whichIsY].values, numRuns, beginPrint, countPrint) == ERROR)
853                     goto errorExit;
854                 }
855             }
856         else
857             {
858             if (PrintPlot (parameterSamples[whichIsX].values[0]+beginPrint, parameterSamples[whichIsY].values[0]+beginPrint, countPrint) == ERROR)
859                 goto errorExit;
860             }
861 
862         if (sumssParams.askForMorePlots == NO || firstPass == YES)
863             break;
864 
865         MrBayesPrint (" You can choose to print new step plots for different steps or discard fractions.\n");
866         MrBayesPrint (" Allowed range of 'Steptoplot' are from 0 to %d.\n", chainParams.numStepsSS);
867         MrBayesPrint (" If the next entered value is negative, 'sumss' will stop printing step plots.\n");
868         MrBayesPrint (" If the next entered value is positive, but out of range, you will be offered\n");
869         MrBayesPrint (" to change parameter 'Discardfrac' of 'sumss'.\n");
870         MrBayesPrint (" Enter new step number 'Steptoplot':");
871         k = scanf("%d",&j);
872         if (j < 0)
873             break;
874         if (j > chainParams.numStepsSS)
875             {
876             do
877                 {
878                 MrBayesPrint (" Enter new value for 'Discardfrac', should be in range 0.0 to 1.0:");
879                 k = scanf("%f",&tmpf);
880                 sumssParams.discardFraction =  (MrBFlt)tmpf;
881                 }
882             while (sumssParams.discardFraction < 0.0 || sumssParams.discardFraction > 1.0);
883             }
884         else
885             sumssParams.stepToPlot=j;
886     }
887 
888     if (firstPass == NO)
889         goto sumssExitOptions;
890 
891     sumssJoinedPlot:
892 
893     MrBayesPrint ("\n\n%s   Joined plot(s).\n",spacer);
894     while (1)
895         {
896         MrBayesPrint ("\n");
897         MrBayesPrint ("%s   Joined plot of %d samples of all steps together. 'smoothing' is set to:%d\n", spacer,numSamplesInStepSS,sumssParams.smoothing);
898         MrBayesPrint ("%s   According to step burn-in, first %d samples are not ploted.\n", spacer,stepBurnin);
899 
900         for (i=0; i<sumssParams.numRuns; i++)
901             {
902             for (j=stepBurnin;j<numSamplesInStepSS;j++)
903                 plotArrayY[sumssParams.numRuns][j]=0.0;
904             lnlp= parameterSamples[whichIsY].values[i] + stepBeginSS;
905             nextSteplnlp=lnlp;
906             for (stepIndexSS = chainParams.numStepsSS-1; stepIndexSS>0; stepIndexSS--)
907                 {
908                 firstlnlp=plotArrayY[sumssParams.numRuns] + stepBurnin;
909                 lnlp+=stepBurnin;
910                 nextSteplnlp += numSamplesInStepSS;
911                 while (lnlp < nextSteplnlp)
912                     {
913                     *firstlnlp+=*lnlp;
914                     firstlnlp++;
915                     lnlp++;
916                     }
917                 }
918             for (j=stepBurnin;j<numSamplesInStepSS;j++)
919                 {
920                 sum=0.0;
921                 count=0;
922                 for (k=j-sumssParams.smoothing;k<=j+sumssParams.smoothing;k++)
923                     {
924                     if (k>=stepBurnin && k<numSamplesInStepSS)
925                         {
926                         sum += plotArrayY[sumssParams.numRuns][k];
927                         count++;
928                         }
929                     }
930                 plotArrayY[i][j] = sum/count;
931                 /*
932                 if (max < plotArrayY[i][j])
933                     max=plotArrayY[i][j];
934                     */
935                 }
936         /*  for (j=stepBurnin;j<numSamplesInStepSS;j++)
937                 {
938                 plotArrayY[i][j] /= max;
939                 }*/
940             }
941 
942         beginPrint=stepBurnin;
943         countPrint=numSamplesInStepSS-stepBurnin;
944 
945         if (sumssParams.numRuns > 1)
946             {
947             if (sumpParams.allRuns == YES)
948                 {
949                 for (i=0; i<sumssParams.numRuns; i++)
950                     {
951                     MrBayesPrint ("\n%s   Samples from run %d:\n", spacer, i+1);
952                     if (PrintPlot (plotArrayX[i]+beginPrint, plotArrayY[i]+beginPrint, countPrint) == ERROR)
953                         goto errorExit;
954                     }
955                 }
956             else
957                 {
958                 if (PrintOverlayPlot (plotArrayX, plotArrayY, numRuns, beginPrint, countPrint) == ERROR)
959                     goto errorExit;
960                 }
961             }
962         else
963             {
964             if (PrintPlot (plotArrayX[0]+beginPrint, plotArrayY[0]+beginPrint, countPrint) == ERROR)
965                 goto errorExit;
966             }
967 
968         if (sumssParams.askForMorePlots == NO || firstPass == YES)
969             break;
970 
971         MrBayesPrint (" You can choose to print new joined plots with different step burn-in or smoothing.\n");
972         MrBayesPrint (" Allowed range of step burn-in values are from 0 to %d.\n", numSamplesInStepSS-1);
973         MrBayesPrint (" If the next entered value is negative, 'sumss' will stop printing joined plots.\n");
974         MrBayesPrint (" If the next entered value is positive, but out of range, you will be offered\n");
975         MrBayesPrint (" to change 'Smoothing'.\n");
976         MrBayesPrint (" Enter new step burn-in:");
977         k = scanf("%d",&j);
978         if (j < 0)
979             break;
980         if (j >= numSamplesInStepSS)
981             {
982             MrBayesPrint (" Enter new value for 'Smoothing':");
983             k = scanf("%d",&j);
984             sumssParams.smoothing = abs(j);
985             }
986         else
987             stepBurnin=j;
988     }
989 
990     firstPass = NO;
991 
992 sumssExitOptions:
993 
994     if (sumssParams.askForMorePlots == YES)
995         {
996         MrBayesPrint ("\n");
997         MrBayesPrint (" Sumss is interactive, because of parameter 'Askmore=YES' setting. \n");
998         MrBayesPrint (" What would you like to do next?\n");
999         MrBayesPrint ("   1) Print updated table according to new step burn-in.\n");
1000         MrBayesPrint ("   2) Print Step plot(s).\n");
1001         MrBayesPrint ("   3) Print Joined plot(s).\n");
1002         MrBayesPrint ("   4) Exit 'sumss'.\n");
1003         MrBayesPrint (" Enter a number that corresponds to one of the options:");
1004         do
1005             {
1006             k = scanf("%d",&j);
1007             }while (j<1 || j>4);
1008 
1009         if (j == 1)
1010             {
1011             MrBayesPrint (" Allowed range of step burn-in values are from 0 to %d\n", numSamplesInStepSS-1);
1012             MrBayesPrint (" Current step burn-in value is:%d\n", stepBurnin);
1013             MrBayesPrint (" Enter new step burn-in:");
1014             do
1015                 {
1016                 k = scanf("%d",&stepBurnin);
1017                 }
1018             while (stepBurnin < 0 || stepBurnin > numSamplesInStepSS-1);
1019             MrBayesPrint ("\n");
1020             goto sumssTable;
1021             }
1022         else if (j == 2)
1023             {
1024             goto sumssStepPlot;
1025             }
1026         else if (j == 3)
1027             goto sumssJoinedPlot;
1028         }
1029 
1030     /* free memory */
1031     FreeParameterSamples(parameterSamples);
1032     for (i=0; i<nHeaders; i++)
1033         free (headerNames[i]);
1034     free (headerNames);
1035 
1036     expecting = Expecting(COMMAND);
1037     strcpy (spacer, "");
1038     chainParams.isSS=NO;
1039     for (i=0; i<sumssParams.numRuns+1; i++)
1040         free(plotArrayY[i]);
1041     free(plotArrayY);
1042     for (i=0; i<sumssParams.numRuns; i++)
1043         free(plotArrayX[i]);
1044     free(plotArrayX);
1045     free(marginalLnLSS);
1046 
1047     return (NO_ERROR);
1048 
1049 errorExit:
1050 
1051     /* free memory */
1052     FreeParameterSamples (parameterSamples);
1053     if (headerNames!=NULL)
1054         for (i=0; i<nHeaders; i++)
1055             free (headerNames[i]);
1056     free (headerNames);
1057 
1058     expecting = Expecting(COMMAND);
1059     strcpy (spacer, "");
1060     chainParams.isSS=NO;
1061     if (plotArrayY!=NULL)
1062         for (i=0; i<sumssParams.numRuns+1; i++)
1063             free(plotArrayY[i]);
1064     free(plotArrayY);
1065     if (plotArrayX!=NULL)
1066         for (i=0; i<sumssParams.numRuns; i++)
1067             free(plotArrayX[i]);
1068     free(plotArrayX);
1069     free(marginalLnLSS);
1070 
1071     return (ERROR);
1072 }
1073 
1074 
DoSumpParm(char * parmName,char * tkn)1075 int DoSumpParm (char *parmName, char *tkn)
1076 {
1077     int         tempI;
1078     MrBFlt      tempD;
1079     char        tempStr[100];
1080 
1081     if (expecting == Expecting(PARAMETER))
1082         {
1083         expecting = Expecting(EQUALSIGN);
1084         }
1085     else
1086         {
1087         if (!strcmp(parmName, "Xxxxxxxxxx"))
1088             {
1089             expecting  = Expecting(PARAMETER);
1090             expecting |= Expecting(SEMICOLON);
1091             }
1092         /* set Filename (sumpParams.sumpFileName) ***************************************************/
1093         else if (!strcmp(parmName, "Filename"))
1094             {
1095             if (expecting == Expecting(EQUALSIGN))
1096                 {
1097                 expecting = Expecting(ALPHA);
1098                 readWord = YES;
1099                 }
1100             else if (expecting == Expecting(ALPHA))
1101                 {
1102                 if (strlen(tkn)>99 && (strchr(tkn,' ')-tkn) > 99)
1103                     {
1104                     MrBayesPrint ("%s   Maximum allowed length of file name is 99 characters. The given name:\n", spacer);
1105                     MrBayesPrint ("%s      '%s'\n", spacer,tkn);
1106                     return (ERROR);
1107                     }
1108                 sscanf (tkn, "%s", tempStr);
1109                 strcpy (sumpParams.sumpFileName, tempStr);
1110                 strcpy (sumpParams.sumpOutfile, tempStr);
1111                 MrBayesPrint ("%s   Setting sump filename and output file name to %s\n", spacer, sumpParams.sumpFileName);
1112                 expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
1113                 }
1114             else
1115                 return (ERROR);
1116             }
1117         /* set Outputname (sumpParams.sumpOutfile) *******************************************************/
1118         else if (!strcmp(parmName, "Outputname"))
1119             {
1120             if (expecting == Expecting(EQUALSIGN))
1121                 {
1122                 expecting = Expecting(ALPHA);
1123                 readWord = YES;
1124                 }
1125             else if (expecting == Expecting(ALPHA))
1126                 {
1127                 if (strlen(tkn)>99 && (strchr(tkn,' ')-tkn) > 99)
1128                     {
1129                     MrBayesPrint ("%s   Maximum allowed length of file name is 99 characters. The given name:\n", spacer);
1130                     MrBayesPrint ("%s      '%s'\n", spacer,tkn);
1131                     return (ERROR);
1132                     }
1133                 sscanf (tkn, "%s", tempStr);
1134                 strcpy (sumpParams.sumpOutfile, tempStr);
1135                 MrBayesPrint ("%s   Setting sump output file name to \"%s\"\n", spacer, sumpParams.sumpOutfile);
1136                 expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
1137                 }
1138             else
1139                 return (ERROR);
1140             }
1141         /* set Relburnin (chainParams.relativeBurnin) ********************************************************/
1142         else if (!strcmp(parmName, "Relburnin"))
1143             {
1144             if (expecting == Expecting(EQUALSIGN))
1145                 expecting = Expecting(ALPHA);
1146             else if (expecting == Expecting(ALPHA))
1147                 {
1148                 if (IsArgValid(tkn, tempStr) == NO_ERROR)
1149                     {
1150                     if (!strcmp(tempStr, "Yes"))
1151                         chainParams.relativeBurnin = YES;
1152                     else
1153                         chainParams.relativeBurnin = NO;
1154                     }
1155                 else
1156                     {
1157                     MrBayesPrint ("%s   Invalid argument for Relburnin\n", spacer);
1158                     return (ERROR);
1159                     }
1160                 if (chainParams.relativeBurnin == YES)
1161                     MrBayesPrint ("%s   Using relative burnin (a fraction of samples discarded).\n", spacer);
1162                 else
1163                     MrBayesPrint ("%s   Using absolute burnin (a fixed number of samples discarded).\n", spacer);
1164                 expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
1165                 }
1166             else
1167                 {
1168                 return (ERROR);
1169                 }
1170             }
1171         /* set Burnin (chainParams.chainBurnIn) ***********************************************************/
1172         else if (!strcmp(parmName, "Burnin"))
1173             {
1174             if (expecting == Expecting(EQUALSIGN))
1175                 expecting = Expecting(NUMBER);
1176             else if (expecting == Expecting(NUMBER))
1177                 {
1178                 sscanf (tkn, "%d", &tempI);
1179                 chainParams.chainBurnIn = tempI;
1180                 MrBayesPrint ("%s   Setting burn-in to %d\n", spacer, chainParams.chainBurnIn);
1181                 expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
1182                 }
1183             else
1184                 {
1185                 return (ERROR);
1186                 }
1187             }
1188         /* set Burninfrac (chainParams.burninFraction) ************************************************************/
1189         else if (!strcmp(parmName, "Burninfrac"))
1190             {
1191             if (expecting == Expecting(EQUALSIGN))
1192                 expecting = Expecting(NUMBER);
1193             else if (expecting == Expecting(NUMBER))
1194                 {
1195                 sscanf (tkn, "%lf", &tempD);
1196                 if (tempD < 0.01)
1197                     {
1198                     MrBayesPrint ("%s   Burnin fraction too low (< 0.01)\n", spacer);
1199                     return (ERROR);
1200                     }
1201                 if (tempD > 0.50)
1202                     {
1203                     MrBayesPrint ("%s   Burnin fraction too high (> 0.50)\n", spacer);
1204                     return (ERROR);
1205                     }
1206                 chainParams.burninFraction = tempD;
1207                 MrBayesPrint ("%s   Setting burnin fraction to %.2f\n", spacer, chainParams.burninFraction);
1208                 expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
1209                 }
1210             else
1211                 {
1212                 return (ERROR);
1213                 }
1214             }
1215         /* set Minprob (sumpParams.minProb) ************************************************************/
1216         else if (!strcmp(parmName, "Minprob"))
1217             {
1218             if (expecting == Expecting(EQUALSIGN))
1219                 expecting = Expecting(NUMBER);
1220             else if (expecting == Expecting(NUMBER))
1221                 {
1222                 sscanf (tkn, "%lf", &tempD);
1223                 if (tempD > 0.50)
1224                     {
1225                     MrBayesPrint ("%s   Minprob too high (it should be smaller than 0.50)\n", spacer);
1226                     return (ERROR);
1227                     }
1228                 sumpParams.minProb = tempD;
1229                 MrBayesPrint ("%s   Setting minprob to %1.3f\n", spacer, sumpParams.minProb);
1230                 expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
1231                 }
1232             else
1233                 {
1234                 return (ERROR);
1235                 }
1236             }
1237         /* set Nruns (sumpParams.numRuns) *******************************************************/
1238         else if (!strcmp(parmName, "Nruns"))
1239             {
1240             if (expecting == Expecting(EQUALSIGN))
1241                 expecting = Expecting(NUMBER);
1242             else if (expecting == Expecting(NUMBER))
1243                 {
1244                 sscanf (tkn, "%d", &tempI);
1245                 if (tempI < 1)
1246                     {
1247                     MrBayesPrint ("%s   Nruns must be at least 1\n", spacer);
1248                     return (ERROR);
1249                     }
1250                 else
1251                     {
1252                     sumpParams.numRuns = tempI;
1253                     MrBayesPrint ("%s   Setting sump nruns to %d\n", spacer, sumpParams.numRuns);
1254                     expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
1255                     }
1256                 }
1257             else
1258                 return (ERROR);
1259             }
1260         /* set Hpd (sumpParams.HPD) ********************************************************/
1261         else if (!strcmp(parmName, "Hpd"))
1262             {
1263             if (expecting == Expecting(EQUALSIGN))
1264                 expecting = Expecting(ALPHA);
1265             else if (expecting == Expecting(ALPHA))
1266                 {
1267                 if (IsArgValid(tkn, tempStr) == NO_ERROR)
1268                     {
1269                     if (!strcmp(tempStr, "Yes"))
1270                         sumpParams.HPD = YES;
1271                     else
1272                         sumpParams.HPD = NO;
1273                     }
1274                 else
1275                     {
1276                     MrBayesPrint ("%s   Invalid argument for Hpd\n", spacer);
1277                     return (ERROR);
1278                     }
1279                 if (sumpParams.HPD == YES)
1280                     MrBayesPrint ("%s   Reporting 95 %% region of Highest Posterior Density (HPD).\n", spacer);
1281                 else
1282                     MrBayesPrint ("%s   Reporting median interval containing 95 %% of values.\n", spacer);
1283                 expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
1284                 }
1285             else
1286                 {
1287                 return (ERROR);
1288                 }
1289             }
1290         /* set Allruns (sumpParams.allRuns) ********************************************************/
1291         else if (!strcmp(parmName, "Allruns"))
1292             {
1293             if (expecting == Expecting(EQUALSIGN))
1294                 expecting = Expecting(ALPHA);
1295             else if (expecting == Expecting(ALPHA))
1296                 {
1297                 if (IsArgValid(tkn, tempStr) == NO_ERROR)
1298                     {
1299                     if (!strcmp(tempStr, "Yes"))
1300                         sumpParams.allRuns = YES;
1301                     else
1302                         sumpParams.allRuns = NO;
1303                     }
1304                 else
1305                     {
1306                     MrBayesPrint ("%s   Invalid argument for allruns (valid arguments are 'yes' and 'no')\n", spacer);
1307                     return (ERROR);
1308                     }
1309                 if (sumpParams.allRuns == YES)
1310                     MrBayesPrint ("%s   Setting sump to print information for each run\n", spacer);
1311                 else
1312                     MrBayesPrint ("%s   Setting sump to print only summary information for all runs\n", spacer);
1313                 expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
1314                 }
1315             else
1316                 return (ERROR);
1317             }
1318         else
1319             return (ERROR);
1320         }
1321 
1322     return (NO_ERROR);
1323 }
1324 
1325 
DoSumSsParm(char * parmName,char * tkn)1326 int DoSumSsParm (char *parmName, char *tkn)
1327 {
1328     int         tempI;
1329     MrBFlt      tempD;
1330     char        tempStr[100];
1331 
1332     if (expecting == Expecting(PARAMETER))
1333         {
1334         expecting = Expecting(EQUALSIGN);
1335         }
1336     else
1337         {
1338         if (!strcmp(parmName, "Xxxxxxxxxx"))
1339             {
1340             expecting  = Expecting(PARAMETER);
1341             expecting |= Expecting(SEMICOLON);
1342             }
1343         /* set Filename (sumpParams.sumpFileName) ***************************************************/
1344         else if (!strcmp(parmName, "Filename"))
1345             {
1346             if (expecting == Expecting(EQUALSIGN))
1347                 {
1348                 expecting = Expecting(ALPHA);
1349                 readWord = YES;
1350                 }
1351             else if (expecting == Expecting(ALPHA))
1352                 {
1353                 if (strlen(tkn)>99 && (strchr(tkn,' ')-tkn) > 99)
1354                     {
1355                     MrBayesPrint ("%s   Maximum allowed length of file name is 99 characters. The given name:\n", spacer);
1356                     MrBayesPrint ("%s      '%s'\n", spacer,tkn);
1357                     return (ERROR);
1358                     }
1359                 sscanf (tkn, "%s", tempStr);
1360                 strcpy (sumpParams.sumpFileName, tempStr);
1361                 strcpy (sumpParams.sumpOutfile, tempStr);
1362                 MrBayesPrint ("%s   Setting sump filename and output file name to %s\n", spacer, sumpParams.sumpFileName);
1363                 expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
1364                 }
1365             else
1366                 return (ERROR);
1367             }
1368         /* set Outputname (sumpParams.sumpOutfile) *******************************************************/
1369         /*else if (!strcmp(parmName, "Outputname"))
1370             {
1371             if (expecting == Expecting(EQUALSIGN))
1372                 {
1373                 expecting = Expecting(ALPHA);
1374                 readWord = YES;
1375                 }
1376             else if (expecting == Expecting(ALPHA))
1377                 {
1378                 if (strlen(tkn)>99 && (strchr(tkn,' ')-tkn) > 99)
1379                     {
1380                     MrBayesPrint ("%s   Maximum allowed length of file name is 99 characters. The given name:\n", spacer);
1381                     MrBayesPrint ("%s      '%s'\n", spacer,tkn);
1382                     return (ERROR);
1383                     }
1384                 sscanf (tkn, "%s", tempStr);
1385                 strcpy (sumpParams.sumpOutfile, tempStr);
1386                 MrBayesPrint ("%s   Setting sump output file name to \"%s\"\n", spacer, sumpParams.sumpOutfile);
1387                 expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
1388                 }
1389             else
1390                 return (ERROR);
1391             }*/
1392         /* set Relburnin (chainParams.relativeBurnin) ********************************************************/
1393         else if (!strcmp(parmName, "Relburnin"))
1394             {
1395             if (expecting == Expecting(EQUALSIGN))
1396                 expecting = Expecting(ALPHA);
1397             else if (expecting == Expecting(ALPHA))
1398                 {
1399                 if (IsArgValid(tkn, tempStr) == NO_ERROR)
1400                     {
1401                     if (!strcmp(tempStr, "Yes"))
1402                         chainParams.relativeBurnin = YES;
1403                     else
1404                         chainParams.relativeBurnin = NO;
1405                     }
1406                 else
1407                     {
1408                     MrBayesPrint ("%s   Invalid argument for Relburnin\n", spacer);
1409                     return (ERROR);
1410                     }
1411                 if (chainParams.relativeBurnin == YES)
1412                     MrBayesPrint ("%s   Using relative burnin (a fraction of samples discarded).\n", spacer);
1413                 else
1414                     MrBayesPrint ("%s   Using absolute burnin (a fixed number of samples discarded).\n", spacer);
1415                 expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
1416                 }
1417             else
1418                 {
1419                 return (ERROR);
1420                 }
1421             }
1422         /* set Burnin (chainParams.chainBurnIn) ***********************************************************/
1423         else if (!strcmp(parmName, "Burnin"))
1424             {
1425             if (expecting == Expecting(EQUALSIGN))
1426                 expecting = Expecting(NUMBER);
1427             else if (expecting == Expecting(NUMBER))
1428                 {
1429                 sscanf (tkn, "%d", &tempI);
1430                 chainParams.chainBurnIn = tempI;
1431                 MrBayesPrint ("%s   Setting burn-in to %d\n", spacer, chainParams.chainBurnIn);
1432                 expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
1433                 }
1434             else
1435                 {
1436                 return (ERROR);
1437                 }
1438             }
1439         /* set Burninfrac (chainParams.burninFraction) ************************************************************/
1440         else if (!strcmp(parmName, "Burninfrac"))
1441             {
1442             if (expecting == Expecting(EQUALSIGN))
1443                 expecting = Expecting(NUMBER);
1444             else if (expecting == Expecting(NUMBER))
1445                 {
1446                 sscanf (tkn, "%lf", &tempD);
1447                 if (tempD < 0.01)
1448                     {
1449                     MrBayesPrint ("%s   Burnin fraction too low (< 0.01)\n", spacer);
1450                     return (ERROR);
1451                     }
1452                 if (tempD > 0.50)
1453                     {
1454                     MrBayesPrint ("%s   Burnin fraction too high (> 0.50)\n", spacer);
1455                     return (ERROR);
1456                     }
1457                 chainParams.burninFraction = tempD;
1458                 MrBayesPrint ("%s   Setting burnin fraction to %.2f\n", spacer, chainParams.burninFraction);
1459                 expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
1460                 }
1461             else
1462                 {
1463                 return (ERROR);
1464                 }
1465             }
1466         /* set Nruns (sumssParams.numRuns) *******************************************************/
1467         else if (!strcmp(parmName, "Nruns"))
1468             {
1469             if (expecting == Expecting(EQUALSIGN))
1470                 expecting = Expecting(NUMBER);
1471             else if (expecting == Expecting(NUMBER))
1472                 {
1473                 sscanf (tkn, "%d", &tempI);
1474                 if (tempI < 1)
1475                     {
1476                     MrBayesPrint ("%s   Nruns must be at least 1\n", spacer);
1477                     return (ERROR);
1478                     }
1479                 else
1480                     {
1481                     sumssParams.numRuns = tempI;
1482                     MrBayesPrint ("%s   Setting sumss nruns to %d\n", spacer, sumssParams.numRuns);
1483                     expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
1484                     }
1485                 }
1486             else
1487                 return (ERROR);
1488             }
1489         /* set Allruns (sumssParams.allRuns) ********************************************************/
1490         else if (!strcmp(parmName, "Allruns"))
1491             {
1492             if (expecting == Expecting(EQUALSIGN))
1493                 expecting = Expecting(ALPHA);
1494             else if (expecting == Expecting(ALPHA))
1495                 {
1496                 if (IsArgValid(tkn, tempStr) == NO_ERROR)
1497                     {
1498                     if (!strcmp(tempStr, "Yes"))
1499                         sumssParams.allRuns = YES;
1500                     else
1501                         sumssParams.allRuns = NO;
1502                     }
1503                 else
1504                     {
1505                     MrBayesPrint ("%s   Invalid argument for allruns (valid arguments are 'yes' and 'no')\n", spacer);
1506                     return (ERROR);
1507                     }
1508                 if (sumssParams.allRuns == YES)
1509                     MrBayesPrint ("%s   Setting sump to print information for each run\n", spacer);
1510                 else
1511                     MrBayesPrint ("%s   Setting sump to print only summary information for all runs\n", spacer);
1512                 expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
1513                 }
1514             else
1515                 return (ERROR);
1516             }
1517         /* set Steptoplot (sumssParams.stepToPlot) *******************************************************/
1518         else if (!strcmp(parmName, "Steptoplot"))
1519             {
1520             if (expecting == Expecting(EQUALSIGN))
1521                 expecting = Expecting(NUMBER);
1522             else if (expecting == Expecting(NUMBER))
1523                 {
1524                 sscanf (tkn, "%d", &tempI);
1525                 if (tempI < 0)
1526                     {
1527                     MrBayesPrint ("%s   Steptoplot must be at least 0\n", spacer);
1528                     return (ERROR);
1529                     }
1530                 else
1531                     {
1532                     sumssParams.stepToPlot = tempI;
1533                     MrBayesPrint ("%s   Setting sumss steptoplot to %d\n", spacer, sumssParams.stepToPlot);
1534                     expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
1535                     }
1536                 }
1537             else
1538                 return (ERROR);
1539             }
1540         /* set Smoothing (sumssParams.smoothing) *******************************************************/
1541         else if (!strcmp(parmName, "Smoothing"))
1542             {
1543             if (expecting == Expecting(EQUALSIGN))
1544                 expecting = Expecting(NUMBER);
1545             else if (expecting == Expecting(NUMBER))
1546                 {
1547                 sscanf (tkn, "%d", &tempI);
1548                 if (tempI < 0)
1549                     {
1550                     MrBayesPrint ("%s   Smoothing must be at least 0\n", spacer);
1551                     return (ERROR);
1552                     }
1553                 else
1554                     {
1555                     sumssParams.smoothing  = tempI;
1556                     MrBayesPrint ("%s   Setting sumss smoothing to %d\n", spacer, sumssParams.smoothing);
1557                     expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
1558                     }
1559                 }
1560             else
1561                 return (ERROR);
1562             }
1563         /* set Allruns (sumssParams.askForMorePlots) ********************************************************/
1564         else if (!strcmp(parmName, "Askmore"))
1565             {
1566             if (expecting == Expecting(EQUALSIGN))
1567                 expecting = Expecting(ALPHA);
1568             else if (expecting == Expecting(ALPHA))
1569                 {
1570                 if (IsArgValid(tkn, tempStr) == NO_ERROR)
1571                     {
1572                     if (!strcmp(tempStr, "Yes"))
1573                         sumssParams.askForMorePlots = YES;
1574                     else
1575                         sumssParams.askForMorePlots = NO;
1576                     }
1577                 else
1578                     {
1579                     MrBayesPrint ("%s   Invalid argument for askmore (valid arguments are 'yes' and 'no')\n", spacer);
1580                     return (ERROR);
1581                     }
1582                 if (sumssParams.askForMorePlots == YES)
1583                     MrBayesPrint ("%s   Setting sumss to be interactiva by asking for more plots of burn-in or individual steps.\n", spacer);
1584                 else
1585                     MrBayesPrint ("%s   Setting sumss not to be interactive. It will not ask to print more plots.\n", spacer);
1586                 expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
1587                 }
1588             else
1589                 return (ERROR);
1590             }
1591         /* set Discardfrac (sumssParams.discardFraction) ************************************************************/
1592         else if (!strcmp(parmName, "Discardfrac"))
1593             {
1594             if (expecting == Expecting(EQUALSIGN))
1595                 expecting = Expecting(NUMBER);
1596             else if (expecting == Expecting(NUMBER))
1597                 {
1598                 sscanf (tkn, "%lf", &tempD);
1599                 if (tempD < 0.00)
1600                     {
1601                     MrBayesPrint ("%s   Discard fraction too low (< 0.00)\n", spacer);
1602                     return (ERROR);
1603                     }
1604                 if (tempD > 1.00)
1605                     {
1606                     MrBayesPrint ("%s   Discard fraction too high (> 1.00)\n", spacer);
1607                     return (ERROR);
1608                     }
1609                 sumssParams.discardFraction = tempD;
1610                 MrBayesPrint ("%s   Setting discard fraction to %.2f\n", spacer, sumssParams.discardFraction);
1611                 expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
1612                 }
1613             else
1614                 {
1615                 return (ERROR);
1616                 }
1617             }
1618         else
1619             return (ERROR);
1620         }
1621 
1622     return (NO_ERROR);
1623 }
1624 
1625 
1626 /* ExamineSumpFile: Collect info on the parameter samples in the file */
ExamineSumpFile(char * fileName,SumpFileInfo * fileInfo,char *** headerNames,int * nHeaders)1627 int ExamineSumpFile (char *fileName, SumpFileInfo *fileInfo, char ***headerNames, int *nHeaders)
1628 {
1629     char    *sumpTokenP, sumpToken[CMD_STRING_LENGTH], *s=NULL, *headerLine, *t;
1630     int     i, lineTerm, inSumpComment, lineNum, lastNonDigitLine, numParamLines, allDigitLine,
1631             lastTokenWasDash, nNumbersOnThisLine, tokenType, burnin, nLines, firstNumCols;
1632     MrBFlt  tempD;
1633     FILE    *fp = NULL;
1634 
1635     /* open binary file */
1636     if ((fp = OpenBinaryFileR(fileName)) == NULL)
1637         {
1638         /* test for some simple errors */
1639         if (strlen(sumpParams.sumpFileName) > 2)
1640             {
1641             s = sumpParams.sumpFileName + (int) strlen(sumpParams.sumpFileName) - 2;
1642             if (strcmp(s, ".p") == 0)
1643                 {
1644                 MrBayesPrint ("%s   It appears that you need to remove '.p' from the 'Filename' parameter\n", spacer);
1645                 MrBayesPrint ("%s   Also make sure that 'Nruns' is set correctly\n", spacer);
1646                 return ERROR;
1647                 }
1648             }
1649         MrBayesPrint ("%s   Make sure that 'Nruns' is set correctly\n", spacer);
1650         return ERROR;
1651         }
1652 
1653     /* find out what type of line termination is used */
1654     lineTerm = LineTermType (fp);
1655     if (lineTerm != LINETERM_MAC && lineTerm != LINETERM_DOS && lineTerm != LINETERM_UNIX)
1656         {
1657         MrBayesPrint ("%s   Unknown line termination\n", spacer);
1658         goto errorExit;
1659         }
1660 
1661     /* find length of longest line */
1662     fileInfo->longestLineLength = LongestLine (fp);
1663     fileInfo->longestLineLength += 10;      /* better safe than sorry; if you fgets with raw longestLineLength, you run into problems */
1664 
1665     /* allocate string long enough to hold a line */
1666     s = (char *)SafeMalloc(2 * ((size_t)(fileInfo->longestLineLength) +10) * sizeof(char));
1667     if (!s)
1668         {
1669         MrBayesPrint ("%s   Problem allocating string for reading sump file\n", spacer);
1670         goto errorExit;
1671         }
1672     headerLine = s + fileInfo->longestLineLength + 10;
1673 
1674     /* close binary file */
1675     SafeFclose (&fp);
1676 
1677     /* open text file */
1678     if ((fp = OpenTextFileR(fileName)) == NULL)
1679         goto errorExit;
1680 
1681     /* Check file for appropriate blocks. We want to find the last block
1682        in the file and start from there. */
1683     inSumpComment = NO;
1684     lineNum = lastNonDigitLine = numParamLines = 0;
1685     while (fgets (s, fileInfo->longestLineLength + 2, fp) != NULL)
1686         {
1687         sumpTokenP = &s[0];
1688         allDigitLine = YES;
1689         lastTokenWasDash = NO;
1690         nNumbersOnThisLine = 0;
1691         do {
1692             if (GetToken (sumpToken, &tokenType, &sumpTokenP))
1693                 goto errorExit;
1694             /* printf ("%s (%d)\n", sumpToken, tokenType); */
1695             if (IsSame("[", sumpToken) == SAME)
1696                 inSumpComment = YES;
1697             if (IsSame("]", sumpToken) == SAME)
1698                 inSumpComment = NO;
1699 
1700             if (inSumpComment == NO)
1701                 {
1702                 if (tokenType == NUMBER)
1703                     {
1704                     sscanf (sumpToken, "%lf", &tempD);
1705                     if (lastTokenWasDash == YES)
1706                         tempD *= -1.0;
1707                     nNumbersOnThisLine++;
1708                     lastTokenWasDash = NO;
1709                     }
1710                 else if (tokenType == DASH)
1711                     {
1712                     lastTokenWasDash = YES;
1713                     }
1714                 else if (tokenType != UNKNOWN_TOKEN_TYPE)
1715                     {
1716                     allDigitLine = NO;
1717                     lastTokenWasDash = NO;
1718                     }
1719                 }
1720             } while (*sumpToken);
1721         lineNum++;
1722 
1723         if (allDigitLine == NO)
1724             {
1725             lastNonDigitLine = lineNum;
1726             numParamLines = 0;
1727             }
1728         else
1729             {
1730             if (nNumbersOnThisLine > 0)
1731                 numParamLines++;
1732             }
1733         }
1734 
1735     /* Now, check some aspects of the .p file. */
1736     if (inSumpComment == YES)
1737         {
1738         MrBayesPrint ("%s   Unterminated comment in file \"%s\"\n", spacer, fileName);
1739             goto errorExit;
1740         }
1741     if (numParamLines <= 0)
1742         {
1743         MrBayesPrint ("%s   No parameters were found in file or there characters not representing a number in last string of the file.\"%s\"\n", spacer, fileName);
1744             goto errorExit;
1745         }
1746 
1747     /* calculate burnin */
1748     if (chainParams.isSS == YES)
1749         {
1750         burnin = 0;
1751         }
1752     else
1753         {
1754         if (chainParams.relativeBurnin == YES)
1755             burnin = (int) (chainParams.burninFraction * numParamLines);
1756         else
1757             burnin = chainParams.chainBurnIn;
1758         }
1759 
1760     /* check against burnin */
1761     if (burnin > numParamLines)
1762         {
1763         MrBayesPrint ("%s   No parameters can be sampled from file %s as the burnin (%d) exceeds the number of lines in last block (%d)\n",
1764             spacer, fileName, burnin, numParamLines);
1765         MrBayesPrint ("%s   Try setting burnin to a number less than %d\n", spacer, numParamLines);
1766         goto errorExit;
1767         }
1768 
1769     /* Set some info in fileInfo */
1770     fileInfo->firstParamLine = lastNonDigitLine + burnin;
1771     fileInfo->headerLine = lastNonDigitLine;
1772 
1773     /* Calculate and check the number of columns and rows for the file; get header line at the same time */
1774     (void)fseek(fp, 0L, 0);
1775     for (lineNum=0; lineNum<lastNonDigitLine; lineNum++)
1776         if (fgets (s, fileInfo->longestLineLength + 2, fp)==NULL)
1777             goto errorExit;
1778     strcpy(headerLine, s);
1779     for (; lineNum < lastNonDigitLine+burnin; lineNum++)
1780         if (fgets (s, fileInfo->longestLineLength + 2, fp)==NULL)
1781             goto errorExit;
1782 
1783     inSumpComment = NO;
1784     nLines = 0;
1785     firstNumCols = 0;
1786     while (fgets (s, fileInfo->longestLineLength + 2, fp) != NULL)
1787         {
1788         sumpTokenP = &s[0];
1789         allDigitLine = YES;
1790         lastTokenWasDash = NO;
1791         nNumbersOnThisLine = 0;
1792         do {
1793             if (GetToken (sumpToken, &tokenType, &sumpTokenP))
1794                 goto errorExit;
1795             if (IsSame("[", sumpToken) == SAME)
1796                 inSumpComment = YES;
1797             if (IsSame("]", sumpToken) == SAME)
1798                 inSumpComment = NO;
1799             if (inSumpComment == NO)
1800                 {
1801                 if (tokenType == NUMBER)
1802                     {
1803                     nNumbersOnThisLine++;
1804                     lastTokenWasDash = NO;
1805                     }
1806                 else if (tokenType == DASH)
1807                     {
1808                     lastTokenWasDash = YES;
1809                     }
1810                 else if (tokenType != UNKNOWN_TOKEN_TYPE)
1811                     {
1812                     allDigitLine = NO;
1813                     lastTokenWasDash = NO;
1814                     }
1815                 }
1816             } while (*sumpToken);
1817         lineNum++;
1818         if (allDigitLine == NO)
1819             {
1820             MrBayesPrint ("%s   Found a line with non-digit characters (line %d) in file %s\n", spacer, lineNum, fileName);
1821             goto errorExit;
1822             }
1823         else
1824             {
1825             if (nNumbersOnThisLine > 0)
1826                 {
1827                 nLines++;
1828                 if (nLines == 1)
1829                     firstNumCols = nNumbersOnThisLine;
1830                 else
1831                     {
1832                     if (nNumbersOnThisLine != firstNumCols)
1833                         {
1834                         MrBayesPrint ("%s   Number of columns is not even (%d in first line and %d in line %d of file %s)\n", spacer, firstNumCols, nNumbersOnThisLine, lineNum, fileName);
1835                         goto errorExit;
1836                         }
1837                     }
1838                 }
1839             }
1840         }
1841     fileInfo->numRows = nLines;
1842     fileInfo->numColumns = firstNumCols;
1843 
1844     /* set or check headers */
1845     if ((*headerNames) == NULL)
1846         {
1847         GetHeaders (headerNames, headerLine, nHeaders);
1848         if (*nHeaders != fileInfo->numColumns)
1849             {
1850             MrBayesPrint ("%s   Expected %d headers but found %d headers\n", spacer, fileInfo->numColumns, *nHeaders);
1851             for (i=0; i<*nHeaders; i++)
1852                 SAFEFREE ((*headerNames)[i]);
1853             SAFEFREE (*headerNames);
1854             *nHeaders=0;
1855             goto errorExit;
1856             }
1857         }
1858     else
1859         {
1860         if (*nHeaders != fileInfo->numColumns)
1861             {
1862             MrBayesPrint ("%s   Expected %d columns but found %d columns\n", spacer, *nHeaders, fileInfo->numColumns);
1863             goto errorExit;
1864             }
1865         for (i=0, t=strtok(headerLine,"\t\n\r"); t!=NULL; t=strtok(NULL,"\t\n\r"), i++)
1866             {
1867             if (i == *nHeaders)
1868                 {
1869                 MrBayesPrint ("%s   Expected %d headers but found more headers.\n",
1870                 spacer, fileInfo->numColumns);
1871                 goto errorExit;
1872                 }
1873             if (strcmp(t,(*headerNames)[i])!=0)
1874                 {
1875                 MrBayesPrint ("%s   Expected header '%s' for column %d but the header for this column was '%s' in file '%s'\n", spacer, (*headerNames)[i], i+1, t, fileName);
1876                 MrBayesPrint ("%s   It could be that some parameter values are not numbers and the whole string containing \n",spacer);
1877                 MrBayesPrint ("%s   this wrongly formatted parameter is treated as a header.\n",spacer);
1878                 goto errorExit;
1879                 }
1880             }
1881         if (t != NULL)
1882             {
1883             MrBayesPrint ("%s   Expected %d headers but found more headers.\n",spacer, fileInfo->numColumns);
1884             goto errorExit;
1885             }
1886         if (i < *nHeaders)
1887             {
1888             MrBayesPrint ("%s   Expected header '%s' for column %d but the header for this column was '%s' in file '%s'\n",
1889                 spacer, (*headerNames)[i], i+1, t, fileName);
1890             goto errorExit;
1891             }
1892         }
1893 
1894     free (s);
1895     fclose(fp);
1896     return (NO_ERROR);
1897 
1898 errorExit:
1899 
1900     free(s);
1901     fclose(fp);
1902     return (ERROR);
1903 }
1904 
1905 
1906 /***************************************************
1907 |
1908 |   FindHeader: Find token in list
1909 |
1910 ----------------------------------------------------*/
FindHeader(char * token,char ** headerNames,int nHeaders,int * index)1911 int FindHeader (char *token, char **headerNames, int nHeaders, int *index)
1912 {
1913     int         i, match=0, nMatches;
1914 
1915     *index = -1;
1916     nMatches = 0;
1917     for (i=0; i<nHeaders; i++)
1918         {
1919         if (!strcmp(token,headerNames[i]))
1920             {
1921             nMatches++;
1922             match = i;
1923             }
1924         }
1925 
1926     if (nMatches != 1)
1927         return (ERROR);
1928 
1929     *index = match;
1930     return (NO_ERROR);
1931 }
1932 
1933 
1934 /* FreeParameterSamples: Free parameter samples space */
FreeParameterSamples(ParameterSample * parameterSamples)1935 void FreeParameterSamples (ParameterSample *parameterSamples)
1936 {
1937     if (parameterSamples != NULL)
1938         {
1939         free (parameterSamples[0].values[0]);
1940         free (parameterSamples[0].values);
1941         free (parameterSamples);
1942         }
1943 }
1944 
1945 
1946 /***************************************************
1947 |
1948 |   GetHeaders: Get headers from headerLine and put
1949 |      them in list while updating nHeaders to reflect
1950 |      the number of headers
1951 |
1952 ----------------------------------------------------*/
GetHeaders(char *** headerNames,char * headerLine,int * nHeaders)1953 int GetHeaders (char ***headerNames, char *headerLine, int *nHeaders)
1954 {
1955     char        *s;
1956 
1957     (*nHeaders) = 0;
1958     for (s=strtok(headerLine," \t\n\r"); s!=NULL; s=strtok(NULL," \t\n\r"))
1959         {
1960         if (AddString (headerNames, *nHeaders, s) == ERROR)
1961             {
1962             MrBayesPrint ("%s   Error adding header to list of headers \n", spacer, s);
1963             return ERROR;
1964             }
1965         (*nHeaders)++;
1966         }
1967 
1968     return (NO_ERROR);
1969 }
1970 
1971 
1972 /* PrintMargLikes: Print marginal likelihoods to screen and to .lstat file */
PrintMargLikes(char * fileName,char ** headerNames,int nHeaders,ParameterSample * parameterSamples,int nRuns,int nSamples)1973 int PrintMargLikes (char *fileName, char **headerNames, int nHeaders, ParameterSample *parameterSamples, int nRuns, int nSamples)
1974 {
1975     int     i, j, len, longestHeader, *sampleCounts=NULL;
1976     char    temp[100];
1977     Stat    theStats;
1978     FILE    *fp;
1979 
1980     /* calculate longest header */
1981     longestHeader = 9;  /* length of 'parameter' */
1982     for (i=0; i<nHeaders; i++)
1983         {
1984         strcpy (temp, headerNames[i]);
1985         len = (int) strlen(temp);
1986         for (j=0; modelIndicatorParams[j][0]!='\0'; j++)
1987             if (IsSame (temp,modelIndicatorParams[j]) != DIFFERENT)
1988                 break;
1989         if (modelIndicatorParams[j][0]!='\0')
1990             continue;
1991         if (!strcmp (temp, "Gen") || !strcmp (temp, "LnL") || !strcmp (temp, "LnPr"))
1992             continue;
1993         if (len > longestHeader)
1994             longestHeader = len;
1995         }
1996 
1997     /* open output file */
1998     strncpy (temp, fileName, 90);
1999     strcat (temp, ".pstat");
2000     fp = OpenNewMBPrintFile (temp);
2001     if (!fp)
2002         return ERROR;
2003 
2004     /* print unique identifier to the output file */
2005     if (strlen(stamp) > 1)
2006         MrBayesPrintf (fp, "[ID: %s]\n", stamp);
2007 
2008     /* allocate and set nSamples */
2009     sampleCounts = (int *) SafeCalloc (nRuns, sizeof(int));
2010     if (!sampleCounts)
2011         {
2012         fclose(fp);
2013         return ERROR;
2014         }
2015     for (i=0; i<nRuns; i++)
2016         sampleCounts[i] = nSamples;
2017 
2018     /* print the header rows */
2019     MrBayesPrint ("\n");
2020     if (sumpParams.HPD == YES)
2021         MrBayesPrint ("%s   %*c                             95%% HPD Interval\n", spacer, longestHeader, ' ');
2022     else
2023         MrBayesPrint ("%s   %*c                            95%% Cred. Interval\n", spacer, longestHeader, ' ');
2024     MrBayesPrint ("%s   %*c                           --------------------\n", spacer, longestHeader, ' ');
2025 
2026     MrBayesPrint ("%s   Parameter%*c      Mean     Variance     Lower       Upper       Median", spacer, longestHeader-9, ' ');
2027     if (nRuns > 1)
2028         MrBayesPrint ("     PSRF+ ");
2029     MrBayesPrint ("\n");
2030 
2031     MrBayesPrint ("%s   ", spacer);
2032     for (j=0; j<longestHeader+1; j++)
2033         MrBayesPrint ("-");
2034     MrBayesPrint ("-----------------------------------------------------------");
2035     if (nRuns > 1)
2036         MrBayesPrint ("----------");
2037     MrBayesPrint ("\n");
2038     if (nRuns > 1)
2039         MrBayesPrintf (fp, "Parameter\tMean\tVariance\tLower\tUpper\tMedian\tPSRF\n");
2040     else
2041         MrBayesPrintf (fp, "Parameter\tMean\tVariance\tLower\tUpper\tMedian\n");
2042 
2043     /* print table values */
2044     for (i=0; i<nHeaders; i++)
2045         {
2046         strcpy (temp, headerNames[i]);
2047         for (j=0; modelIndicatorParams[j][0]!='\0'; j++)
2048             if (IsSame (temp,modelIndicatorParams[j]) != DIFFERENT)
2049                 break;
2050         if (!strcmp (temp, "Gen") || !strcmp (temp, "LnL") || !strcmp (temp, "LnPr"))
2051             continue;
2052 
2053         GetSummary (parameterSamples[i].values, nRuns, sampleCounts, &theStats, sumpParams.HPD);
2054 
2055         MrBayesPrint ("%s   %-*s ", spacer, longestHeader, temp);
2056         MrBayesPrint ("%10.6lf  %10.6lf  %10.6lf  %10.6lf  %10.6lf", theStats.mean, theStats.var, theStats.lower, theStats.upper, theStats.median);
2057         MrBayesPrintf (fp, "%s", temp);
2058         MrBayesPrintf (fp, "\t%s", MbPrintNum(theStats.mean));
2059         MrBayesPrintf (fp, "\t%s", MbPrintNum(theStats.var));
2060         MrBayesPrintf (fp, "\t%s", MbPrintNum(theStats.lower));
2061         MrBayesPrintf (fp, "\t%s", MbPrintNum(theStats.upper));
2062         MrBayesPrintf (fp, "\t%s", MbPrintNum(theStats.median));
2063         if (nRuns > 1)
2064             {
2065             if (theStats.PSRF < 0.0)
2066                 {
2067                 MrBayesPrint ("     NA   ");
2068                 MrBayesPrintf (fp, "NA");
2069                 }
2070             else
2071                 {
2072                 MrBayesPrint ("  %7.3lf", theStats.PSRF);
2073                 MrBayesPrintf (fp, "\t%s", MbPrintNum(theStats.PSRF));
2074                 }
2075             }
2076         MrBayesPrint ("\n");
2077         MrBayesPrintf (fp, "\n");
2078         }
2079     MrBayesPrint ("%s   ", spacer);
2080     for (j=0; j<longestHeader+1; j++)
2081         MrBayesPrint ("-");
2082     MrBayesPrint ("-----------------------------------------------------------");
2083     if (nRuns > 1)
2084         MrBayesPrint ("----------");
2085     MrBayesPrint ("\n");
2086     if (nRuns > 1)
2087         {
2088         MrBayesPrint ("%s   + Convergence diagnostic (PSRF = Potential Scale Reduction Factor; Gelman\n", spacer);
2089         MrBayesPrint ("%s     and Rubin, 1992) should approach 1.0 as runs converge.\n", spacer);
2090         }
2091 
2092     fclose (fp);
2093     free (sampleCounts);
2094 
2095     return (NO_ERROR);
2096 }
2097 
2098 
2099 /* PrintModelStats: Print model stats to screen and to .mstat file */
PrintModelStats(char * fileName,char ** headerNames,int nHeaders,ParameterSample * parameterSamples,int nRuns,int nSamples)2100 int PrintModelStats (char *fileName, char **headerNames, int nHeaders, ParameterSample *parameterSamples, int nRuns, int nSamples)
2101 {
2102     int         i, j, j1, j2, k, longestName, nElements, *modelCounts=NULL;
2103     MrBFlt      f, *prob=NULL, *sum=NULL, *ssq=NULL, *min=NULL, *max=NULL, *stddev=NULL;
2104     char        temp[100];
2105     FILE        *fp;
2106     ModelProb   *elem = NULL;
2107 
2108     /* nHeaders - is a convenient synonym for number of column headers */
2109 
2110     /* check if we have any model indicator variables and also check for longest header */
2111     k = 0;
2112     longestName = 0;
2113     for (i=0; i<nHeaders; i++)
2114         {
2115         for (j=0; strcmp(modelIndicatorParams[j],"")!=0; j++)
2116             {
2117             if (IsSame (headerNames[i], modelIndicatorParams[j]) != DIFFERENT)
2118                 {
2119                 k++;
2120                 for (j1=0; strcmp(modelElementNames[j][j1],"")!=0; j1++)
2121                     {
2122                     j2 = (int)(strlen(headerNames[i]) + 2 + strlen(modelElementNames[j][j1]));
2123                     if (j2 > longestName)
2124                         longestName = j2;
2125                     }
2126                 break;
2127                 }
2128             }
2129         }
2130 
2131     /* return if nothing to do */
2132     if (k==0)
2133         return NO_ERROR;
2134 
2135     /* open output file */
2136     MrBayesPrint ("%s   Model probabilities above %1.3lf\n", spacer, sumpParams.minProb);
2137     MrBayesPrint ("%s   Estimates saved to file \"%s.mstat\".\n", spacer, sumpParams.sumpOutfile);
2138     strncpy (temp,fileName,90);
2139     strcat (temp, ".mstat");
2140     fp = OpenNewMBPrintFile(temp);
2141     if (!fp)
2142         return ERROR;
2143     MrBayesPrint ("\n");
2144 
2145     /* print unique identifier to the output file */
2146     if (strlen(stamp) > 1)
2147         MrBayesPrintf (fp, "[ID: %s]\n", stamp);
2148 
2149     /* print header */
2150     MrBayesPrintf (fp, "\n\n");
2151     if (nRuns == 1)
2152         {
2153         MrBayesPrint ("%s        %*c        Posterior\n", spacer, longestName-5, ' ');
2154         MrBayesPrint ("%s   Model%*c       Probability\n", spacer, longestName-5, ' ');
2155         MrBayesPrint ("%s   -----", spacer);
2156         for (i=0; i<longestName-5; i++)
2157             MrBayesPrint ("-");
2158         MrBayesPrint ("------------------\n");
2159         MrBayesPrintf (fp, "Model\tProbability\n");
2160         }
2161     else
2162         {
2163         MrBayesPrint ("%s        %*c        Posterior      Standard         Min.           Max.   \n", spacer, longestName-5, ' ');
2164         MrBayesPrint ("%s   Model%*c       Probability     Deviation     Probability    Probability\n", spacer, longestName-5, ' ');
2165         MrBayesPrint ("%s   -----", spacer);
2166         for (i=0; i<longestName-5; i++)
2167             MrBayesPrint ("-");
2168         MrBayesPrint ("---------------------------------------------------------------\n");
2169         MrBayesPrintf (fp, "Model\tProbability\tStd_dev\tMin_prob\tMax_prob\n");
2170         }
2171 
2172     /* calculate and print values */
2173     for (i=0; i<nHeaders; i++)
2174         {
2175         for (j=0; modelIndicatorParams[j][0]!='\0'; j++)
2176             if (IsSame (headerNames[i], modelIndicatorParams[j]) != DIFFERENT)
2177                 break;
2178         if (modelIndicatorParams[j][0] == '\0')
2179             continue;
2180 
2181         for (nElements=0; modelElementNames[j][nElements][0]!='\0'; nElements++)
2182             ;
2183 
2184         modelCounts = (int *) SafeCalloc (nElements, sizeof(int));
2185         if (!modelCounts)
2186             {
2187             fclose(fp);
2188             return ERROR;
2189             }
2190         prob = (MrBFlt *) SafeCalloc (6*nElements, sizeof(MrBFlt));
2191         if (!prob)
2192             {
2193             free (modelCounts);
2194             fclose (fp);
2195             return ERROR;
2196             }
2197         sum    = prob + nElements;
2198         ssq    = prob + 2*nElements;
2199         stddev = prob + 3*nElements;
2200         min    = prob + 4*nElements;
2201         max    = prob + 5*nElements;
2202 
2203         for (j1=0; j1<nElements; j1++)
2204             min[j1] = 1.0;
2205 
2206         for (j1=0; j1<nRuns; j1++)
2207             {
2208             for (j2=0; j2<nElements; j2++)
2209                 modelCounts[j2] = 0;
2210             for (j2=0; j2<nSamples; j2++)
2211                 modelCounts[(int)(parameterSamples[i].values[j1][j2] + 0.1)]++;
2212             for (j2=0; j2<nElements; j2++)
2213                 {
2214                 f = (MrBFlt) modelCounts[j2] / (MrBFlt) nSamples;
2215                 sum[j2] += f;
2216                 ssq[j2] += f*f;
2217                 if (f<min[j2])
2218                     min[j2] = f;
2219                 if (f > max[j2])
2220                     max[j2] = f;
2221                 }
2222             }
2223 
2224         for (j1=0; j1<nElements; j1++)
2225             {
2226             prob[j1] = sum[j1] / (MrBFlt) nRuns;
2227             f = ssq[j1] - (sum[j1] * sum[j1] / (MrBFlt) nRuns);
2228             f /= (nRuns - 1);
2229             if (f <= 0.0)
2230                 stddev[j1] = 0.0;
2231             else
2232                 stddev[j1] = sqrt (f);
2233             }
2234 
2235         elem = (ModelProb *) SafeCalloc (nElements, sizeof(ModelProb));
2236         for (j1=0; j1<nElements; j1++)
2237             {
2238             elem[j1].index = j1;
2239             elem[j1].prob = prob[j1];
2240             }
2241 
2242         /* sort in terms of decreasing probabilities */
2243         qsort((void *)elem, (size_t)nElements, sizeof(ModelProb), CompareModelProbs);
2244 
2245         for (j1=0; j1<nElements; j1++)
2246             {
2247             if (elem[j1].prob <= sumpParams.minProb)
2248                 break;
2249 
2250             if (nRuns == 1)
2251                 {
2252                 sprintf (temp, "%s[%s]", headerNames[i], modelElementNames[j][elem[j1].index]);
2253                 MrBayesPrint ("%s   %-*s          %1.3lf\n", spacer, longestName, temp, prob[elem[j1].index]);
2254                 MrBayesPrintf (fp, "%s\t%s\n", temp, MbPrintNum(prob[elem[j1].index]));
2255                 }
2256             else /* if (nRuns > 1) */
2257                 {
2258                 sprintf (temp, "%s[%s]", headerNames[i], modelElementNames[j][elem[j1].index]);
2259                 MrBayesPrint ("%s   %-*s          %1.3lf          %1.3lf          %1.3lf          %1.3lf\n",
2260                     spacer, longestName, temp, prob[elem[j1].index], stddev[elem[j1].index], min[elem[j1].index], max[elem[j1].index]);
2261                 MrBayesPrintf (fp, "%s", temp);
2262                 MrBayesPrintf (fp, "\t%s", MbPrintNum(prob[elem[j1].index]));
2263                 MrBayesPrintf (fp, "\t%s", MbPrintNum(stddev[elem[j1].index]));
2264                 MrBayesPrintf (fp, "\t%s", MbPrintNum(min[elem[j1].index]));
2265                 MrBayesPrintf (fp, "\t%s", MbPrintNum(max[elem[j1].index]));
2266                 MrBayesPrintf (fp, "\n");
2267                 }
2268             }
2269         free(elem);
2270         elem = NULL;
2271         free(modelCounts);
2272         modelCounts = NULL;
2273         free (prob);
2274         prob = NULL;
2275         }
2276 
2277     /* print footer */
2278     if (nRuns == 1)
2279         {
2280         MrBayesPrint ("%s   -----", spacer);
2281         for (i=0; i<longestName-5; i++)
2282             MrBayesPrint ("-");
2283         MrBayesPrint ("------------------\n\n");
2284         }
2285     else
2286         {
2287         MrBayesPrint ("%s   -----", spacer);
2288         for (i=0; i<longestName-5; i++)
2289             MrBayesPrint ("-");
2290         MrBayesPrint ("---------------------------------------------------------------\n\n");
2291         }
2292 
2293     /* close output file */
2294     fclose (fp);
2295 
2296     return (NO_ERROR);
2297 }
2298 
2299 
2300 /* PrintOverlayPlot: Print overlay x-y plot of log likelihood vs. generation for several runs */
PrintOverlayPlot(MrBFlt ** xVals,MrBFlt ** yVals,int nRuns,int startingFrom,int nSamples)2301 int PrintOverlayPlot (MrBFlt **xVals, MrBFlt **yVals, int nRuns,  int startingFrom, int nSamples)
2302 {
2303     int     i, j, k, k2, n, screenHeight, screenWidth, numY[60], width;
2304     char    plotSymbol[15][60];
2305     MrBFlt  x, y, minX, maxX, minY, maxY, meanY[60];
2306 
2307     if (nRuns == 2)
2308         MrBayesPrint ("\n%s   Overlay plot for both runs:\n", spacer);
2309     else
2310         MrBayesPrint ("\n%s   Overlay plot for all %d runs:\n", spacer, sumpParams.numRuns);
2311     if (nRuns > 9)
2312         MrBayesPrint ("%s   (1 = Run number 1; 2 = Run number 2 etc.; x = Run number 10 or above; * = Several runs)\n", spacer);
2313     else if (nRuns > 2)
2314         MrBayesPrint ("%s   (1 = Run number 1; 2 = Run number 2 etc.; * = Several runs)\n", spacer);
2315     else
2316         MrBayesPrint ("%s   (1 = Run number 1; 2 = Run number 2; * = Both runs)\n", spacer);
2317 
2318     /* print overlay x-y plot of log likelihood vs. generation for all runs */
2319     screenWidth = 60; /* don't change this without changing numY, meanY, and plotSymbol declared above */
2320     screenHeight = 15;
2321 
2322     /* find minX, minY, maxX, and maxY over all runs */
2323     minX = minY = 1000000000.0;
2324     maxX = maxY = -1000000000.0;
2325     for (n=0; n<nRuns; n++)
2326         {
2327         for (i=startingFrom; i<startingFrom+nSamples; i++)
2328             {
2329             x = xVals[n][i];
2330             if (x < minX)
2331                 minX = x;
2332             if (x > maxX)
2333                 maxX = x;
2334             }
2335         }
2336     for (n=0; n<nRuns; n++)
2337         {
2338         y = 0.0;
2339         j = 0;
2340         k2 = 0;
2341         for (i=startingFrom; i<startingFrom+nSamples; i++)
2342             {
2343             x = xVals[n][i];
2344             k = (int) (((x - minX) / (maxX - minX)) * screenWidth);
2345             if (k <= 0)
2346                 k = 0;
2347             if (k >= screenWidth)
2348                 k = screenWidth - 1;
2349             if (k == j)
2350                 {
2351                 y += yVals[n][i];
2352                 k2 ++;
2353                 }
2354             else
2355                 {
2356                 y /= k2;
2357                 if (y < minY)
2358                     minY = y;
2359                 if (y > maxY)
2360                     maxY = y;
2361                 k2 = 1;
2362                 y = yVals[n][i];
2363                 j++;
2364                 }
2365             }
2366         if (k2 > 0)
2367             {
2368             y /= k2;
2369             if (y < minY)
2370                 minY = y;
2371             if (y > maxY)
2372                 maxY = y;
2373             }
2374         }
2375 
2376     /* initialize the plot symbols */
2377     for (i=0; i<screenHeight; i++)
2378         for (j=0; j<screenWidth; j++)
2379             plotSymbol[i][j] = ' ';
2380 
2381     /* assemble the plot symbols */
2382     for (n=0; n<nRuns; n++)
2383         {
2384         /* find the plot points for this run */
2385         for (i=0; i<screenWidth; i++)
2386             {
2387             numY[i] = 0;
2388             meanY[i] = 0.0;
2389             }
2390         for (i=startingFrom; i<startingFrom+nSamples; i++)
2391             {
2392             x = xVals[n][i];
2393             y = yVals[n][i];
2394             k = (int)(((x - minX) / (maxX - minX)) * screenWidth);
2395             if (k >= screenWidth)
2396                 k = screenWidth - 1;
2397             if (k <= 0)
2398                 k = 0;
2399             meanY[k] += y;
2400             numY[k]++;
2401             }
2402 
2403         /* transfer these points to the overlay */
2404         for (i=0; i<screenWidth; i++)
2405             {
2406             if (numY[i] > 0)
2407                 {
2408                 k = (int) ((((meanY[i] / numY[i]) - minY)/ (maxY - minY)) * screenHeight);
2409                 if (k < 0)
2410                     k = 0;
2411                 else if (k >= screenHeight)
2412                     k = screenHeight - 1;
2413                 if (plotSymbol[k][i] == ' ')
2414                     {
2415                     if (n <= 8)
2416                         plotSymbol[k][i] = '1' + n;
2417                     else
2418                         plotSymbol[k][i] = 'x';
2419                     }
2420                 else
2421                     plotSymbol[k][i] = '*';
2422                 }
2423             }
2424         } /* next run */
2425 
2426     /* now print the overlay plot */
2427     MrBayesPrint ("\n%s   +", spacer);
2428     for (i=0; i<screenWidth; i++)
2429         MrBayesPrint ("-");
2430     MrBayesPrint ("+ %1.2lf\n", maxY);
2431     for (i=screenHeight-1; i>=0; i--)
2432         {
2433         MrBayesPrint ("%s   |", spacer);
2434         for (j=0; j<screenWidth; j++)
2435             {
2436             MrBayesPrint ("%c", plotSymbol[i][j]);
2437             }
2438         MrBayesPrint ("|\n");
2439         }
2440     MrBayesPrint ("%s   +", spacer);
2441     for (i=0; i<screenWidth; i++)
2442         {
2443         if (i % (screenWidth/10) == 0 && i != 0)
2444             MrBayesPrint ("+");
2445         else
2446             MrBayesPrint ("-");
2447         }
2448     MrBayesPrint ("+ %1.2lf\n", minY);
2449     MrBayesPrint ("%s   ^", spacer);
2450     for (i=0; i<screenWidth; i++)
2451         MrBayesPrint (" ");
2452     MrBayesPrint ("^\n");
2453     MrBayesPrint ("%s   %1.0lf", spacer, minX);
2454     if ((int)minX>0)
2455         width=(int)(log10(minX));
2456     else if ((int)minX==0)
2457         width=1;
2458     else
2459         width=(int)(log10(-minX))+1;
2460     for (i=0; i<screenWidth-width; i++)
2461         MrBayesPrint (" ");
2462     MrBayesPrint ("%1.0lf\n\n", maxX);
2463 
2464     return (NO_ERROR);
2465 }
2466 
2467 
2468 /* PrintParamStats: Print parameter table (not model indicator params) to screen and .pstat file */
PrintParamStats(char * fileName,char ** headerNames,int nHeaders,ParameterSample * parameterSamples,int nRuns,int nSamples)2469 int PrintParamStats (char *fileName, char **headerNames, int nHeaders, ParameterSample *parameterSamples, int nRuns, int nSamples)
2470 {
2471     int     i, j, len, longestHeader, *sampleCounts=NULL;
2472     static char *temp=NULL;
2473     char    tempf[100];
2474     Stat    theStats;
2475     FILE    *fp;
2476 
2477     /* calculate longest header */
2478     longestHeader = 9;  /* length of 'parameter' */
2479     for (i=0; i<nHeaders; i++)
2480         {
2481         SafeStrcpy (&temp, headerNames[i]);
2482         len = (int) strlen(temp);
2483         for (j=0; modelIndicatorParams[j][0]!='\0'; j++)
2484             if (IsSame (temp,modelIndicatorParams[j]) != DIFFERENT)
2485                 break;
2486         if (modelIndicatorParams[j][0]!='\0')
2487             continue;
2488         if (!strcmp (temp, "Gen") || !strcmp (temp, "LnL") || !strcmp (temp, "LnPr"))
2489             continue;
2490         if (len > longestHeader)
2491             longestHeader = len;
2492         }
2493 
2494     /* open output file */
2495     strncpy (tempf, fileName, 90);
2496     strcat (tempf, ".pstat");
2497     fp = OpenNewMBPrintFile (tempf);
2498     if (!fp)
2499         return ERROR;
2500 
2501     /* print unique identifier to the output file */
2502     if (strlen(stamp) > 1)
2503         MrBayesPrintf (fp, "[ID: %s]\n", stamp);
2504 
2505     /* allocate and set nSamples */
2506     sampleCounts = (int *) SafeCalloc (nRuns, sizeof(int));
2507     if (!sampleCounts)
2508         {
2509         fclose(fp);
2510         return ERROR;
2511         }
2512     for (i=0; i<nRuns; i++)
2513         sampleCounts[i] = nSamples;
2514 
2515     /* print the header rows */
2516     MrBayesPrint ("\n");
2517     if (sumpParams.HPD == YES)
2518         MrBayesPrint ("%s   %*c                             95%% HPD Interval\n", spacer, longestHeader, ' ');
2519     else
2520         MrBayesPrint ("%s   %*c                            95%% Cred. Interval\n", spacer, longestHeader, ' ');
2521     MrBayesPrint ("%s   %*c                           --------------------\n", spacer, longestHeader, ' ');
2522 
2523     if (nRuns > 1)
2524         MrBayesPrint ("%s   Parameter%*c     Mean      Variance     Lower       Upper       Median    min ESS*  avg ESS    PSRF+ ", spacer, longestHeader-9, ' ');
2525     else
2526         MrBayesPrint ("%s   Parameter%*c     Mean      Variance     Lower       Upper       Median     ESS*", spacer, longestHeader-9, ' ');
2527     MrBayesPrint ("\n");
2528 
2529     MrBayesPrint ("%s   ", spacer);
2530     for (j=0; j<longestHeader+1; j++)
2531         MrBayesPrint ("-");
2532     MrBayesPrint ("---------------------------------------------------------------------");
2533     if (nRuns > 1)
2534         MrBayesPrint ("-------------------");
2535     MrBayesPrint ("\n");
2536     if (nRuns > 1)
2537         MrBayesPrintf (fp, "Parameter\tMean\tVariance\tLower\tUpper\tMedian\tminESS\tavgESS\tPSRF\n");
2538     else
2539         MrBayesPrintf (fp, "Parameter\tMean\tVariance\tLower\tUpper\tMedian\tESS\n");
2540 
2541     /* print table values */
2542     for (i=0; i<nHeaders; i++)
2543         {
2544         SafeStrcpy(&temp, headerNames[i]);
2545         for (j=0; modelIndicatorParams[j][0]!='\0'; j++)
2546             if (IsSame (temp,modelIndicatorParams[j]) != DIFFERENT)
2547                 break;
2548         if (modelIndicatorParams[j][0]!='\0')
2549             continue;
2550         if (!strcmp (temp, "Gen") || !strcmp (temp, "LnL") || !strcmp (temp, "LnPr"))
2551             continue;
2552 
2553         GetSummary (parameterSamples[i].values, nRuns, sampleCounts, &theStats, sumpParams.HPD);
2554 
2555         MrBayesPrint ("%s   %-*s ", spacer, longestHeader, temp);
2556         MrBayesPrint ("%10.6lf  %10.6lf  %10.6lf  %10.6lf  %10.6lf", theStats.mean, theStats.var, theStats.lower, theStats.upper, theStats.median);
2557         MrBayesPrintf (fp, "%s", temp);
2558         MrBayesPrintf (fp, "\t%s", MbPrintNum(theStats.mean));
2559         MrBayesPrintf (fp, "\t%s", MbPrintNum(theStats.var));
2560         MrBayesPrintf (fp, "\t%s", MbPrintNum(theStats.lower));
2561         MrBayesPrintf (fp, "\t%s", MbPrintNum(theStats.upper));
2562         MrBayesPrintf (fp, "\t%s", MbPrintNum(theStats.median));
2563 
2564         if (theStats.minESS == theStats.minESS)
2565             {
2566             MrBayesPrintf (fp, "\t%s", MbPrintNum(theStats.minESS));
2567             MrBayesPrint ("  %8.2lf", theStats.minESS);
2568             }
2569         else
2570             {
2571             MrBayesPrint ("       NA ");
2572             MrBayesPrintf (fp, "NA");
2573             }
2574         if (nRuns > 1)
2575             {
2576             if (theStats.minESS == theStats.minESS)
2577                 {
2578                 MrBayesPrint ("  %8.2lf", theStats.avrESS);
2579                 MrBayesPrintf (fp, "\t%s", MbPrintNum(theStats.avrESS));
2580                 }
2581             else
2582                 {
2583                 MrBayesPrint ("       NA ");
2584                 MrBayesPrintf (fp, "NA");
2585                 }
2586             if (theStats.PSRF < 0.0)
2587                 {
2588                 MrBayesPrint ("     NA   ");
2589                 MrBayesPrintf (fp, "NA");
2590                 }
2591             else
2592                 {
2593                 MrBayesPrint ("  %7.3lf", theStats.PSRF);
2594                 MrBayesPrintf (fp, "\t%s", MbPrintNum(theStats.PSRF));
2595                 }
2596             }
2597         MrBayesPrint ("\n");
2598         MrBayesPrintf (fp, "\n");
2599         }
2600     MrBayesPrint ("%s   ", spacer);
2601     for (j=0; j<longestHeader+1; j++)
2602         MrBayesPrint ("-");
2603     MrBayesPrint ("---------------------------------------------------------------------");
2604     if (nRuns > 1)
2605         MrBayesPrint ("-------------------");
2606     MrBayesPrint ("\n");
2607     if (nRuns > 1)
2608         {
2609         MrBayesPrint ("%s   * Convergence diagnostic (ESS = Estimated Sample Size); min and avg values\n", spacer);
2610         MrBayesPrint ("%s     correspond to minimal and average ESS among runs. \n", spacer);
2611         MrBayesPrint ("%s     ESS value below 100 may indicate that the parameter is undersampled. \n", spacer);
2612         MrBayesPrint ("%s   + Convergence diagnostic (PSRF = Potential Scale Reduction Factor; Gelman\n", spacer);
2613         MrBayesPrint ("%s     and Rubin, 1992) should approach 1.0 as runs converge.\n", spacer);
2614         }
2615     else
2616         {
2617         MrBayesPrint ("%s   * Convergence diagnostic (ESS = Estimated Sample Size); ESS value \n", spacer);
2618         MrBayesPrint ("%s     below 100 may indicate that the parameter is undersampled. \n", spacer);
2619         }
2620     MrBayesPrint ("\n\n");
2621 
2622     fclose (fp);
2623     free (sampleCounts);
2624     SAFEFREE (temp);
2625 
2626     return (NO_ERROR);
2627 }
2628 
2629 
2630 /* PrintPlot: Print x-y plot of log likelihood vs. generation */
PrintPlot(MrBFlt * xVals,MrBFlt * yVals,int numVals)2631 int PrintPlot (MrBFlt *xVals, MrBFlt *yVals, int numVals)
2632 {
2633     int     i, j, k, numY[60], screenWidth, screenHeight;
2634     MrBFlt  x, y, minX, maxX, minY, maxY, meanY[60], diff;
2635 
2636     /* print x-y plot of log likelihood vs. generation */
2637     screenWidth = 60; /* don't change this without changing numY and meanY, declared above */
2638     screenHeight = 15;
2639 
2640     /* find minX and maxX */
2641     minX = xVals[0];
2642     maxX = xVals[0];
2643     for (i=0; i<numVals; i++)
2644         {
2645         x = xVals[i];
2646         if (x < minX)
2647             minX = x;
2648         if (x > maxX)
2649             maxX = x;
2650         }
2651 
2652     /* collect Y data */
2653     for (i=0; i<screenWidth; i++)
2654         {
2655         numY[i] = 0;
2656         meanY[i] = 0.0;
2657         }
2658     for (i=0; i<numVals; i++)
2659         {
2660         x = xVals[i];
2661         y = yVals[i];
2662         k = (int)(((x - minX) / (maxX - minX)) * screenWidth);
2663         if (k >= screenWidth)
2664             k = screenWidth - 1;
2665         if (k < 0)
2666             k = 0;
2667         meanY[k] += y;
2668         numY[k]++;
2669         }
2670 
2671     /* find minY and maxY */
2672     minY = maxY = meanY[0] / numY[0];
2673     for (i=0; i<screenWidth; i++)
2674         {
2675         if (meanY[i] == 0) /* with some compilers if (NaN < 1) is equal true !!! so we realy need this check*/
2676             continue;
2677         meanY[i] /= numY[i];
2678         if (meanY[i] < minY)
2679             minY = meanY[i];
2680         if (meanY[i] > maxY)
2681             maxY = meanY[i];
2682         }
2683 
2684     /* find difference */
2685     diff = maxY - minY;
2686 
2687     /* print plot */
2688     MrBayesPrint ("\n   +");
2689     for (i=0; i<screenWidth; i++)
2690         MrBayesPrint ("-");
2691     MrBayesPrint ("+ %1.3lf\n", maxY);
2692     for (j=screenHeight-1; j>=0; j--)
2693         {
2694         MrBayesPrint ("   |");
2695         for (i=0; i<screenWidth; i++)
2696             {
2697             if (numY[i] > 0)
2698                 {
2699                 if ((meanY[i] > ((diff/screenHeight)*j)+minY && meanY[i] <= ((diff/screenHeight)*(j+1))+minY) ||
2700                     (j == 0 && meanY[i] <= minY))
2701                     MrBayesPrint ("*");
2702                 else
2703                     MrBayesPrint (" ");
2704                 }
2705             else
2706                 {
2707                 MrBayesPrint (" ");
2708                 }
2709             }
2710         MrBayesPrint ("|\n");
2711         }
2712     MrBayesPrint ("   +");
2713     for (i=0; i<screenWidth; i++)
2714         {
2715         if (i % (screenWidth/10) == 0 && i != 0)
2716             MrBayesPrint ("+");
2717         else
2718             MrBayesPrint ("-");
2719         }
2720     MrBayesPrint ("+ %1.3lf\n", minY);
2721     MrBayesPrint ("   ^");
2722     for (i=0; i<screenWidth; i++)
2723         MrBayesPrint (" ");
2724     MrBayesPrint ("^\n");
2725     MrBayesPrint ("   %1.0lf", minX);
2726     if (minX == 0)
2727         j = 1;
2728     else
2729         j = (int)(log10(minX)) + 1;
2730     for (i=0; i<screenWidth-j; i++)
2731         MrBayesPrint (" ");
2732     MrBayesPrint ("%1.0lf\n\n", maxX);
2733 
2734     return (NO_ERROR);
2735 }
2736 
2737 
PrintPlotHeader(void)2738 void PrintPlotHeader (void)
2739 {
2740     MrBayesPrint ("\n");
2741     if (sumpParams.numRuns > 1)
2742         {
2743         MrBayesPrint ("%s   Below are rough plots of the generation (x-axis) versus the log   \n", spacer);
2744         MrBayesPrint ("%s   probability of observing the data (y-axis). You can use these     \n", spacer);
2745         MrBayesPrint ("%s   graphs to determine what the burn in for your analysis should be. \n", spacer);
2746         MrBayesPrint ("%s   When the log probability starts to plateau you may be at station- \n", spacer);
2747         MrBayesPrint ("%s   arity. Sample trees and parameters after the log probability      \n", spacer);
2748         MrBayesPrint ("%s   plateaus. Of course, this is not a guarantee that you are at sta- \n", spacer);
2749         MrBayesPrint ("%s   tionarity. Also examine the convergence diagnostics provided by   \n", spacer);
2750         MrBayesPrint ("%s   the 'sump' and 'sumt' commands for all the parameters in your     \n", spacer);
2751         MrBayesPrint ("%s   model. Remember that the burn in is the number of samples to dis- \n", spacer);
2752         MrBayesPrint ("%s   card. There are a total of ngen / samplefreq samples taken during \n", spacer);
2753         MrBayesPrint ("%s   a MCMC analysis.                                                  \n", spacer);
2754         }
2755     else
2756         {
2757         MrBayesPrint ("%s   Below is a rough plot of the generation (x-axis) versus the log   \n", spacer);
2758         MrBayesPrint ("%s   probability of observing the data (y-axis). You can use this      \n", spacer);
2759         MrBayesPrint ("%s   graph to determine what the burn in for your analysis should be.  \n", spacer);
2760         MrBayesPrint ("%s   When the log probability starts to plateau you may be at station- \n", spacer);
2761         MrBayesPrint ("%s   arity. Sample trees and parameters after the log probability      \n", spacer);
2762         MrBayesPrint ("%s   plateaus. Of course, this is not a guarantee that you are at sta- \n", spacer);
2763         MrBayesPrint ("%s   analysis should be. When the log probability starts to plateau    \n", spacer);
2764         MrBayesPrint ("%s   tionarity. When possible, run multiple analyses starting from dif-\n", spacer);
2765         MrBayesPrint ("%s   ferent random trees; if the inferences you make for independent   \n", spacer);
2766         MrBayesPrint ("%s   analyses are the same, this is reasonable evidence that the chains\n", spacer);
2767         MrBayesPrint ("%s   have converged. You can use MrBayes to run several independent    \n", spacer);
2768         MrBayesPrint ("%s   analyses simultaneously. During such a run, MrBayes will monitor  \n", spacer);
2769         MrBayesPrint ("%s   the convergence of topologies. After the run has been completed,  \n", spacer);
2770         MrBayesPrint ("%s   the 'sumt' and 'sump' functions will provide additional conver-   \n", spacer);
2771         MrBayesPrint ("%s   gence diagnostics for all the parameters in your model. Remember  \n", spacer);
2772         MrBayesPrint ("%s   that the burn in is the number of samples to discard. There are   \n", spacer);
2773         MrBayesPrint ("%s   a total of ngen / samplefreq samples taken during a MCMC analysis.\n", spacer);
2774         }
2775 }
2776 
2777 
2778 /* ReadParamSamples: Read parameter samples from .p file */
ReadParamSamples(char * fileName,SumpFileInfo * fileInfo,ParameterSample * parameterSamples,int runNo)2779 int ReadParamSamples (char *fileName, SumpFileInfo *fileInfo, ParameterSample *parameterSamples, int runNo)
2780 {
2781     char    sumpToken[CMD_STRING_LENGTH], *s=NULL, *p;
2782     int     inSumpComment, lineNum, numLinesRead, numLinesToRead, column, lastTokenWasDash,
2783             tokenType;
2784     MrBFlt  tempD;
2785     FILE    *fp;
2786 
2787     /* open file */
2788     if ((fp = OpenTextFileR (fileName)) == NULL)
2789         return ERROR;
2790 
2791     /* allocate space for reading lines */
2792     s = (char *) SafeCalloc (fileInfo->longestLineLength + 10, sizeof(char));
2793 
2794     /* fast forward to beginning of last unburned parameter line. */
2795     for (lineNum=0; lineNum<fileInfo->firstParamLine; lineNum++)
2796       if (fgets (s, fileInfo->longestLineLength + 5, fp) == 0)
2797           goto errorExit;
2798 
2799     /* parse file, line-by-line. We are only parsing lines that have digits that should be read. */
2800     inSumpComment = NO;
2801     numLinesToRead = fileInfo->numRows;
2802     numLinesRead = 0;
2803     while (fgets (s, fileInfo->longestLineLength + 1, fp) != NULL)
2804         {
2805         lastTokenWasDash = NO;
2806         column = 0;
2807         p = s;
2808         do {
2809             if (GetToken (sumpToken, &tokenType, &p))
2810                 goto errorExit;
2811             if (IsSame("[", sumpToken) == SAME)
2812                 inSumpComment = YES;
2813             if (IsSame("]", sumpToken) == SAME)
2814                 inSumpComment = NO;
2815             if (inSumpComment == NO)
2816                 {
2817                 if (tokenType == NUMBER)
2818                     {
2819                     /* read the number */
2820                     if (column >= fileInfo->numColumns)
2821                         {
2822                         MrBayesPrint ("%s   Too many values read on line %d of file %s\n", spacer, lineNum, fileName);
2823                         goto errorExit;
2824                         }
2825                     sscanf (sumpToken, "%lf", &tempD);
2826                     if (lastTokenWasDash == YES)
2827                         tempD *= -1.0;
2828                     parameterSamples[column].values[runNo][numLinesRead] = tempD;
2829                     column++;
2830                     lastTokenWasDash = NO;
2831                     }
2832                 else if (tokenType == DASH)
2833                     {
2834                     lastTokenWasDash = YES;
2835                     }
2836                 else if (tokenType != UNKNOWN_TOKEN_TYPE)
2837                     {
2838                     /* we have a problem */
2839                     MrBayesPrint ("%s   Line %d of file %s has non-digit characters\n", spacer, lineNum, fileName);
2840                     goto errorExit;
2841                     }
2842                 }
2843             } while (*sumpToken);
2844 
2845         lineNum++;
2846         if (column == fileInfo->numColumns)
2847             numLinesRead++;
2848         else if (column != 0)
2849             {
2850             MrBayesPrint ("%s   Too few values on line %d of file %s\n", spacer, lineNum, fileName);
2851             goto errorExit;
2852             }
2853         }
2854 
2855 
2856     /* Check how many parameter line was read in. */
2857     if (numLinesRead != numLinesToRead)
2858         {
2859         MrBayesPrint ("%s   Unable to read all lines that should contain parameter samples\n", spacer);
2860         goto errorExit;
2861         }
2862 
2863     fclose (fp);
2864     free (s);
2865 
2866     return (NO_ERROR);
2867 
2868 errorExit:
2869 
2870     fclose (fp);
2871     free (s);
2872 
2873     return ERROR;
2874 }
2875 
2876 
2877 /* the following are moved from sumt.c to combine with sump.c */
AddSumtPartition(PartCtr * r,PolyTree * t,PolyNode * p,int runId)2878 PartCtr *AddSumtPartition (PartCtr *r, PolyTree *t, PolyNode *p, int runId)
2879 {
2880     int     i, n, comp, nLongsNeeded = sumtParams.BitsLongsNeeded;
2881 
2882     if (r == NULL)
2883         {
2884         /* new partition */
2885         /* create a new node */
2886         r = AllocPartCtr ();
2887         if (r == NULL)
2888             return NULL;
2889         numUniqueSplitsFound++;
2890         for (i=0; i<nLongsNeeded; i++)
2891             r->partition[i] = p->partition[i];
2892         for (i=0; i<sumtParams.numRuns; i++)
2893             r->count[i] = 0;
2894         r->left = r->right = NULL;
2895         /* record values */
2896         if (sumtParams.brlensDef == YES)
2897             r->length[runId][0]= p->length;
2898         if (sumtParams.isClock == YES)
2899             r->height[runId][0]= p->depth;
2900         if (sumtParams.isCalibrated == YES)
2901             r->age[runId][0]= p->age;
2902         for (i=0; i<sumtParams.nESets; i++)
2903             r->nEvents[i][runId][0] = t->nEvents[i][p->index];
2904         for (i=0; i<sumtParams.nBSets; i++)
2905             {
2906             r->bLen [i][runId][0] = t->effectiveBrLen[i][p->index];
2907             r->bRate[i][runId][0] = t->effectiveBrLen[i][p->index] / p->length;
2908             if (p->length == 0.0)   r->bRate[i][runId][0] = 1.0;  // deal with zero brl
2909             }
2910         if (t->popSizeSet == YES)
2911             r->popSize[runId][0] = t->popSize[p->index];
2912         r->count[runId] ++;
2913         r->totCount++;
2914         }
2915     else
2916         {
2917         for (i=0; i<nLongsNeeded; i++)
2918             {
2919             if (r->partition[i] != p->partition[i])
2920                 break;
2921             }
2922 
2923         if (i == nLongsNeeded)
2924             comp = 0;
2925         else if (r->partition[i] < p->partition[i])
2926             comp = -1;
2927         else
2928             comp = 1;
2929 
2930         if (comp == 0)          /* repeated partition */
2931             {
2932             n = r->count[runId];
2933             /* check if we need to allocate more space */
2934             if (n % ALLOC_LEN == 0)
2935                 {
2936                 /* allocate more space */
2937                 if (sumtParams.brlensDef == YES)
2938                     r->length[runId] = (MrBFlt *) SafeRealloc ((void *)r->length[runId], ((size_t)n+ALLOC_LEN)*sizeof(MrBFlt));
2939                 if (sumtParams.isClock == YES)
2940                     r->height[runId] = (MrBFlt *) SafeRealloc ((void *)r->height[runId], ((size_t)n+ALLOC_LEN)*sizeof(MrBFlt));
2941                 if (sumtParams.isCalibrated == YES)
2942                     r->age[runId] = (MrBFlt *) SafeRealloc ((void *)r->age[runId], ((size_t)n+ALLOC_LEN)*sizeof(MrBFlt));
2943                 if (sumtParams.nESets > 0)
2944                     {
2945                     for (i=0; i<sumtParams.nESets; i++)
2946                         r->nEvents[i][runId] = (int *) SafeRealloc ((void *)r->nEvents[i][runId], ((size_t)n+ALLOC_LEN)*sizeof(int));
2947                     }
2948                 if (sumtParams.nBSets > 0)
2949                     {
2950                     for (i=0; i<sumtParams.nBSets; i++)
2951                         {
2952                         r->bRate[i][runId] = (MrBFlt *) SafeRealloc ((void *)r->bRate[i][runId], ((size_t)n+ALLOC_LEN)*sizeof(MrBFlt));
2953                         r->bLen [i][runId] = (MrBFlt *) SafeRealloc ((void *)r->bLen [i][runId], ((size_t)n+ALLOC_LEN)*sizeof(MrBFlt));
2954                         }
2955                     }
2956                 if (sumtParams.popSizeSet == YES)
2957                     r->popSize[runId] = (MrBFlt *) SafeRealloc ((void *)r->popSize[runId], ((size_t)n+ALLOC_LEN)*sizeof(MrBFlt));
2958                 }
2959             /* record values */
2960             r->count[runId]++;
2961             r->totCount++;
2962             if (sumtParams.brlensDef == YES)
2963                 r->length[runId][n]= p->length;
2964             if (sumtParams.isClock == YES)
2965                 r->height[runId][n]= p->depth;
2966             if (sumtParams.isCalibrated == YES)
2967                 r->age[runId][n]= p->age;
2968             if (sumtParams.nESets > 0)
2969                 {
2970                 for (i=0; i<sumtParams.nESets; i++)
2971                     r->nEvents[i][runId][n] = t->nEvents[i][p->index];
2972                 }
2973             if (sumtParams.nBSets > 0)
2974                 {
2975                 for (i=0; i<sumtParams.nBSets; i++)
2976                     {
2977                     r->bLen [i][runId][n] = t->effectiveBrLen[i][p->index];
2978                     r->bRate[i][runId][n] = t->effectiveBrLen[i][p->index] / p->length;
2979                     if (p->length == 0.0)   r->bRate[i][runId][n] = 1.0;  // deal with zero brl
2980                     }
2981                 }
2982             if (sumtParams.popSizeSet == YES)
2983                 r->popSize[runId][n] = t->popSize[p->index];
2984             }
2985         else if (comp < 0)      /* greater than -> into left subtree */
2986             {
2987             if ((r->left = AddSumtPartition (r->left, t, p, runId)) == NULL)
2988                 {
2989                 FreePartCtr (r);
2990                 return NULL;
2991                 }
2992             }
2993         else
2994             {
2995             /* smaller than -> into right subtree */
2996             if ((r->right = AddSumtPartition (r->right, t, p, runId)) == NULL)
2997                 {
2998                 FreePartCtr (r);
2999                 return NULL;
3000                 }
3001             }
3002         }
3003 
3004     return r;
3005 }
3006 
3007 
AddSumtTree(TreeCtr * r,int * order)3008 TreeCtr *AddSumtTree (TreeCtr *r, int *order)
3009 {
3010     int     i, comp;
3011 
3012     if (r == NULL)
3013         {
3014         /* new tree */
3015         /* create a new node */
3016         r = AllocTreeCtr();
3017         if (!r)
3018             return NULL;
3019         numUniqueTreesFound++;
3020         for (i=0; i<sumtParams.orderLen; i++)
3021             r->order[i] = order[i];
3022         r->count = 1;
3023         }
3024     else
3025         {
3026         for (i=0; i<sumtParams.orderLen; i++)
3027             if (r->order[i] != order[i])
3028                 break;
3029 
3030         if (i==sumtParams.orderLen)
3031             comp = 0;
3032         else if (order[i] < r->order[i])
3033             comp = 1;
3034         else
3035             comp = -1;
3036 
3037         if (comp == 0)          /* repeated partition */
3038             r->count++;
3039         else if (comp < 0)      /* greater than -> into left subtree */
3040             {
3041             if ((r->left = AddSumtTree (r->left, order)) == NULL)
3042                 {
3043                 FreeTreeCtr (r);
3044                 return NULL;
3045                 }
3046             }
3047         else
3048             {
3049             /* smaller than -> into right subtree */
3050             if ((r->right = AddSumtTree (r->right, order)) == NULL)
3051                 {
3052                 FreeTreeCtr (r);
3053                 return NULL;
3054                 }
3055             }
3056         }
3057 
3058     return r;
3059 }
3060 
3061 
3062 /* AllocPartCtr: Allocate space for one partition counter node using info in sumtParams */
AllocPartCtr()3063 PartCtr *AllocPartCtr ()
3064 {
3065     int             i, j;
3066     PartCtr         *r;
3067 
3068     /* allocate basic stuff */
3069     r = (PartCtr *) SafeCalloc (1, sizeof(PartCtr));
3070     r->left = r->right = NULL;
3071     r->partition = (BitsLong *) SafeCalloc ((size_t)(sumtParams.BitsLongsNeeded), sizeof(BitsLong));
3072     r->count = (int *) SafeCalloc ((size_t)(sumtParams.numRuns), sizeof (int));
3073     if (sumtParams.brlensDef)
3074         {
3075         r->length = (MrBFlt **) SafeCalloc ((size_t)(sumtParams.numRuns), sizeof (MrBFlt *));
3076         for (i=0; i<sumtParams.numRuns; i++)
3077             r->length[i] = (MrBFlt *) SafeCalloc ((size_t)ALLOC_LEN, sizeof(MrBFlt));
3078         }
3079     if (sumtParams.isClock)
3080         {
3081         r->height = (MrBFlt **) SafeCalloc ((size_t)(sumtParams.numRuns), sizeof (MrBFlt *));
3082         for (i=0; i<sumtParams.numRuns; i++)
3083             r->height[i] = (MrBFlt *) SafeCalloc ((size_t)ALLOC_LEN, sizeof(MrBFlt));
3084         r->age = (MrBFlt **) SafeCalloc ((size_t)(sumtParams.numRuns), sizeof (MrBFlt *));
3085         for (i=0; i<sumtParams.numRuns; i++)
3086             r->age[i] = (MrBFlt *) SafeCalloc ((size_t)ALLOC_LEN, sizeof(MrBFlt));
3087         }
3088 
3089     /* allocate relaxed clock parameters: eRate, nEvents, bRate */
3090     if (sumtParams.nESets > 0)
3091         r->nEvents = (int    ***) SafeCalloc ((size_t)(sumtParams.nESets), sizeof(int **));
3092     for (i=0; i<sumtParams.nESets; i++)
3093         {
3094         r->nEvents[i] = (int    **) SafeCalloc ((size_t)(sumtParams.numRuns), sizeof(int *));
3095         for (j=0; j<sumtParams.numRuns; j++)
3096             r->nEvents[i][j] = (int    *) SafeCalloc ((size_t) ALLOC_LEN, sizeof(int));
3097         }
3098     if (sumtParams.nBSets > 0)
3099         {
3100         r->bLen  = (MrBFlt ***) SafeCalloc ((size_t)(sumtParams.nBSets), sizeof(MrBFlt **));
3101         r->bRate = (MrBFlt ***) SafeCalloc ((size_t)(sumtParams.nBSets), sizeof(MrBFlt **));
3102         }
3103     for (i=0; i<sumtParams.nBSets; i++)
3104         {
3105         r->bLen[i]    = (MrBFlt **) SafeCalloc ((size_t)(sumtParams.numRuns), sizeof(MrBFlt *));
3106         r->bRate[i]   = (MrBFlt **) SafeCalloc ((size_t)(sumtParams.numRuns), sizeof(MrBFlt *));
3107         for (j=0; j<sumtParams.numRuns; j++)
3108             {
3109             r->bLen[i][j]    = (MrBFlt *) SafeCalloc ((size_t)ALLOC_LEN, sizeof(MrBFlt));
3110             r->bRate[i][j]   = (MrBFlt *) SafeCalloc ((size_t)ALLOC_LEN, sizeof(MrBFlt));
3111             }
3112         }
3113     if (sumtParams.popSizeSet == YES)
3114         {
3115         r->popSize = (MrBFlt **) SafeCalloc ((size_t)(sumtParams.numRuns), sizeof (MrBFlt *));
3116         for (i=0; i<sumtParams.numRuns; i++)
3117             r->popSize[i] = (MrBFlt *) SafeCalloc ((size_t)ALLOC_LEN, sizeof(MrBFlt));
3118         }
3119 
3120     return r;
3121 }
3122 
3123 
3124 /* AllocTreeCtr: Allocate space for a tree counter node using info in sumtParams struct*/
AllocTreeCtr()3125 TreeCtr *AllocTreeCtr ()
3126 {
3127     TreeCtr     *r;
3128 
3129     r = (TreeCtr *) SafeCalloc (1, sizeof(TreeCtr));
3130 
3131     r->left = r->right = NULL;
3132 
3133     r->order = (int *) SafeCalloc ((size_t)(sumtParams.orderLen), sizeof(int));
3134 
3135     return r;
3136 }
3137 
3138 
CalculateTreeToTreeDistance(Tree * tree1,Tree * tree2,MrBFlt * d1,MrBFlt * d2,MrBFlt * d3)3139 void CalculateTreeToTreeDistance (Tree *tree1, Tree *tree2, MrBFlt *d1, MrBFlt *d2, MrBFlt *d3)
3140 {
3141     int         i, j, k;
3142     MrBFlt      treeLen1=0.0, treeLen2=0.0;
3143     TreeNode    *p, *q=NULL;
3144 
3145     (*d1) = (*d2) = (*d3) = 0.0;
3146 
3147     /* set distance-based measures to max value */
3148     if (sumtParams.brlensDef == YES)
3149         {
3150         treeLen1 = TreeLen(tree1);
3151         treeLen2 = TreeLen(tree2);
3152         (*d2) = treeLen1 + treeLen2;
3153         (*d3) = 2.0;
3154         }
3155 
3156     /* now we can get distances in a single pass */
3157     for (i=0; i<tree1->nNodes; i++)
3158         {
3159         p = tree1->allDownPass[i];
3160         for (j=0; j<tree2->nNodes; j++)
3161             {
3162             q = tree2->allDownPass[j];
3163             for (k=0; k<sumtParams.BitsLongsNeeded; k++)
3164                 if (p->partition[k] != q->partition[k])
3165                     break;
3166             if (k == sumtParams.BitsLongsNeeded)
3167                 break;
3168             }
3169         if (j < tree2->nNodes)
3170             {
3171             /* match */
3172             if (sumtParams.brlensDef == YES)
3173                 {
3174                 (*d2) -= (p->length + q->length - fabs(p->length - q->length));
3175                 (*d3) -= (p->length/treeLen1 + q->length/treeLen2 - fabs(p->length/treeLen1 - q->length/treeLen2));
3176                 }
3177             }
3178         else /* if (k < sumtParams.BitsLongsNeeded) */
3179             {
3180             /* no match */
3181             (*d1) += 2.0;
3182             }
3183         }
3184 
3185 #   if 0
3186     printf ("DISTANCES: %lf %lf %lf (%lf %lf)\n", *d1, *d2, *d3, tl1, tl2);
3187     for (i=0; i<nnds; i++)
3188         {
3189         printf ("%4d -- %4d (%lf) %4d (%lf)\n", i, list1[i], lengths1[i], list2[i], lengths2[i]);
3190         }
3191 #   endif
3192 }
3193 
3194 
3195 /* ConTree: Construct consensus tree FIXME: numTreeParts is not used*/
ConTree(PartCtr ** treeParts,int numTreeParts)3196 int ConTree (PartCtr **treeParts, int numTreeParts)
3197 {
3198     int         i, j, targetNode, nBits, isCompat, numTerminalsEncountered;
3199     BitsLong    x, *partition = NULL, bitsLongOne;
3200     MrBFlt      freq, freqInterapted=0;
3201     PolyTree    *t, *t2=NULL;
3202     PolyNode    *p, *q, *r, *ql, *pl;
3203     PartCtr     *part;
3204     Stat        theStats;
3205     int         isFirstLoop=1, isInterapted=0;
3206 
3207     /* we use a BitsLong variable set to one to escape dependence on interpretation of constant (signed?) int/long '1L' */
3208     bitsLongOne = 1;
3209 
3210     /* check that we have at least three species */
3211     if (sumtParams.numTaxa < 3)
3212         {
3213         MrBayesPrint ("%s   Too few taxa included to show consensus trees\n", spacer);
3214         return ERROR;
3215         }
3216 
3217 treeConstruction:
3218     /* now, make a consensus tree */
3219     /* first allocate and initialize consensus tree */
3220     t = AllocatePolyTree(sumtParams.numTaxa);
3221     if (!t)
3222         {
3223         MrBayesPrint ("%s   Could not allocate consensus tree\n", spacer);
3224         return(ERROR);
3225         }
3226     t->isRooted = sumtParams.isRooted;
3227     t->isClock = sumtParams.isClock;
3228     t->isRelaxed = sumtParams.isRelaxed;
3229 
3230     /* initialize consensus tree nodes */
3231     for (i=0; i<sumtParams.numTaxa; i++)
3232         {
3233         t->nodes[i].left = NULL;
3234         t->nodes[i].sib = NULL;
3235         t->nodes[i].index = i;
3236         t->nodes[i].partitionIndex = -1;     /* partition ID */
3237         t->nodes[i].age = 0.0;              /* temporally set to minimum value to allow any insertion in front of the terminal before actual
3238                                                values of age and depth are available */
3239         strcpy(t->nodes[i].label, sumtParams.taxaNames[i]);
3240         t->nodes[i].depth = 0.0;
3241         }
3242     for (; i<t->memNodes; i++)
3243         {
3244         t->nodes[i].left = NULL;
3245         t->nodes[i].sib = NULL;
3246         t->nodes[i].index = i;
3247         t->nodes[i].partitionIndex = -1;     /* partition ID */
3248         strcpy (t->nodes[i].label, "");
3249         }
3250 
3251     /* create bush
3252        ->x counts number of subtended terminals
3253        make sure t->root->left is in outgroup */
3254     p = t->root = &t->nodes[sumtParams.numTaxa];
3255     p->anc = p->sib = NULL;
3256     p->x = sumtParams.numTaxa;
3257     p->age = MRBFLT_MAX; /* temporarily set to maximum value to allow any insertion in front of the root before actual values of age and depth are available */
3258     p->depth = MRBFLT_MAX;
3259     j = localOutGroup;
3260     q = &t->nodes[j];
3261     p->left = q;
3262     q->anc = p;
3263     q->x = 1;
3264     for (i=0; i<sumtParams.numTaxa; i++)
3265         {
3266         if (i != j)
3267             {
3268             q->sib = &t->nodes[i];
3269             q = q->sib;
3270             q->anc = p;
3271             q->x = 1;
3272             }
3273         }
3274     q->sib = NULL;
3275 
3276     /* Resolve bush according to partitions.
3277        Partitions may include incompatible ones.
3278        Partitions must be sorted from most frequent to least frequent
3279        for quit test to work when a 50% majority rule tree is requested
3280        and in general for consensus tree to be correct. */
3281     t->nNodes = sumtParams.numTaxa + 1;
3282     t->nIntNodes = 1;
3283     if (sumtParams.isRooted == YES)
3284         targetNode = 2 * sumtParams.numTaxa - 2;
3285     else
3286         targetNode = 2 * sumtParams.numTaxa - 3;
3287 
3288     numTerminalsEncountered = 0;
3289     for (i=0; i<numUniqueSplitsFound; i++)
3290         {
3291         /* get partition */
3292         part = treeParts[i];
3293 
3294         /* calculate frequency and test if time to quit */
3295         if (t->nNodes > targetNode && numTerminalsEncountered == sumtParams.numTaxa)
3296             break;
3297         freq = (MrBFlt)(part->totCount) / (MrBFlt)(sumtParams.numTreesSampled);
3298         if (freq < 0.50 && !strcmp(sumtParams.sumtConType, "Halfcompat"))
3299             break;
3300 
3301         /* get partition */
3302         partition = part->partition;
3303 
3304         /* count bits in this partition */
3305         for (j=nBits=0; j<sumtParams.BitsLongsNeeded; j++)
3306             {
3307             for (x = partition[j]; x != 0; x &= (x - 1))
3308                 nBits++;
3309             }
3310 
3311         /* find out if this is an informative partition */
3312         if (nBits == sumtParams.numTaxa || nBits == 0)
3313             {
3314             /* this is the root (for setting age of root node when tree is dated) */
3315             q = t->root;
3316             q->partitionIndex = i;
3317             if (sumtParams.isClock == YES)
3318                 {
3319                 GetSummary(part->height, sumtParams.numRuns, part->count, &theStats, sumtParams.HPD);
3320                 q->depth = theStats.median;
3321                 for (p = q->left; p!=NULL; p = p->sib)
3322                     {
3323                     if (q->depth <= p->depth)
3324                         break;
3325                     }
3326                 assert (p==NULL); /* Root always has 100% freq and it should be older than any other node that has 100% freq. */
3327                 }
3328             if (sumtParams.isCalibrated == YES)
3329                 {
3330                 GetSummary(part->age, sumtParams.numRuns, part->count, &theStats, sumtParams.HPD);
3331                 q->age = theStats.median;
3332                 for (p = q->left; p!=NULL; p = p->sib)
3333                     {
3334                     if (q->age <= p->age)
3335                         break;
3336                     }
3337                 assert (p==NULL); /* Root always has 100% freq and it should be older than any other node that has 100% freq. */
3338                 }
3339             }
3340         else if (nBits > 1 && !(nBits == sumtParams.numTaxa - 1 && sumtParams.isRooted == NO))
3341             {
3342             /* this is an informative partition */
3343             /* find anc of partition */
3344             j = FirstTaxonInPartition (partition, sumtParams.BitsLongsNeeded);
3345             for (p = &t->nodes[j]; p!=NULL; p = p->anc)
3346                 if (p->x > nBits)
3347                     break;
3348 
3349             /* do not include if incompatible with ancestor or any of descendants
3350                do not check terminals or root because it is
3351                redundant and partitions have not necessarily been set for those */
3352             isCompat = YES;
3353             if (p->anc != NULL && IsPartNested(partition, p->partition, sumtParams.BitsLongsNeeded)==NO)
3354                 isCompat = NO;
3355             else
3356                 {
3357                 for (q=p->left; q!=NULL; q=q->sib)
3358                     {
3359                     if (q->x > 1 && IsPartCompatible(q->partition, partition, sumtParams.BitsLongsNeeded)==NO)
3360                         break;
3361                     }
3362                 if (q!=NULL)
3363                     isCompat = NO;
3364                 }
3365 
3366             if (isCompat == NO)
3367                 continue;
3368 
3369             /* set new node */
3370             q = &t->nodes[t->nNodes];
3371             q->partitionIndex = i;
3372             q->x = nBits;
3373             q->partition = partition;
3374             GetSummary(part->length, sumtParams.numRuns, part->count, &theStats, sumtParams.HPD);
3375             q->support = freq;
3376             q->length = theStats.median;
3377             r=NULL;
3378             if (sumtParams.isClock == YES)
3379                 {
3380                 GetSummary(part->height, sumtParams.numRuns, part->count, &theStats, sumtParams.HPD);
3381                 q->depth = theStats.median;
3382                 if (freq < 1.00)
3383                     {
3384                     for (r = p->left; r!=NULL; r = r->sib)
3385                         {
3386                         if (IsPartNested(r->partition, partition, sumtParams.BitsLongsNeeded) &&  r->depth >= q->depth)
3387                             break; /* child is older then the node we try to add. Not good.*/
3388                         }
3389                     if (p->depth <= q->depth)
3390                         {      /* New node older than the parent. Not good.*/
3391                         r = p; /* Just to make r!=NULL*/
3392                         }
3393                     }
3394                 }
3395             if (sumtParams.isCalibrated == YES)
3396                 {
3397                 GetSummary(part->age, sumtParams.numRuns, part->count, &theStats, sumtParams.HPD);
3398                 q->age = theStats.median;
3399                 if (freq < 1.00)
3400                     {
3401                     for (r = p->left; r!=NULL; r = r->sib)
3402                         {
3403                         if (freq < 1.00 && IsPartNested(r->partition, partition, sumtParams.BitsLongsNeeded) && r->age >= q->age)
3404                             break; /* child is older then the node we try to add. Not good.*/
3405                         }
3406                     if (p->age <= q->age)
3407                         {      /* New node older than the parent. Not good.*/
3408                         r = p; /* Just to make r!=NULL*/
3409                         }
3410                     }
3411                 }
3412 
3413             if (r!=NULL && isFirstLoop)
3414                 {
3415                  /* cancel the addition of the new node*/
3416                 isInterapted =1;
3417                 freqInterapted=freq;
3418                 break; /* Finish creating the polytree */
3419                 }
3420             t->nNodes++;
3421             t->nIntNodes++;
3422 
3423             /* go through descendants of anc */
3424             ql = pl = NULL;
3425             for (r=p->left; r!=NULL; r=r ->sib)
3426                 {
3427                 /* test if r is in the new partition or not */
3428                 if ((r->x > 1 && IsPartNested(r->partition, partition, sumtParams.BitsLongsNeeded)) || (r->x == 1 && (partition[r->index / nBitsInALong] & (bitsLongOne << (r->index % nBitsInALong))) != 0))
3429                     {
3430                     /* r is in the partition */
3431                     if (ql == NULL)
3432                         q->left = r;
3433                     else
3434                         ql->sib = r;
3435                     ql = r;
3436                     r->anc = q;
3437                     }
3438                 else
3439                     {
3440                     /* r is not in the partition */
3441                     if (pl == NULL)
3442                         p->left = r;
3443                     else
3444                         pl->sib = r;
3445                     pl = r;
3446                     }
3447                 }
3448             /* terminate new sib-node chain */
3449             ql->sib = NULL;
3450             /* new node is last in old sib-node chain */
3451             pl->sib = q;
3452             q->sib = NULL;
3453             q->anc = p;
3454             }
3455         else
3456             /* singleton partition */
3457             {
3458             if (nBits == sumtParams.numTaxa - 1)
3459                 j = localOutGroup;
3460             else
3461                 j = FirstTaxonInPartition(partition, sumtParams.BitsLongsNeeded); /* nbits == 1 */
3462             q = &t->nodes[j];
3463             q->partitionIndex = i;
3464             q->partition = partition;
3465             numTerminalsEncountered++;
3466             GetSummary(part->length, sumtParams.numRuns, part->count, &theStats, sumtParams.HPD);
3467             q->length = theStats.median;
3468             if (sumtParams.isClock == YES)
3469                 {
3470                 GetSummary(part->height, sumtParams.numRuns, part->count, &theStats, sumtParams.HPD);
3471                 q->depth = theStats.median;
3472                 if (q->anc->depth < q->depth)
3473                     {
3474                     /* We never should get here because terminals always have 100% freq and they are younger than any other node that has 100% freq. */
3475                     /* We should be careful with the trees with 0-brl generated under the fossilized birth-death prior! (<= is changed to <) */
3476                     assert (0);
3477                     }
3478                 }
3479             if (sumtParams.isCalibrated == YES)
3480                 {
3481                 GetSummary(part->age, sumtParams.numRuns, part->count, &theStats, sumtParams.HPD);
3482                 q->age = theStats.median;
3483                 if (q->anc->age < q->age)
3484                     {
3485                     /* We never should get here because terminals always have 100% freq and they are younger than any other node that has 100% freq. */
3486                     /* We should be careful with the trees with 0-brl generated under the fossilized birth-death prior! (<= is changed to <) */
3487                     assert (0);
3488                     }
3489                 }
3490             }
3491         }
3492 
3493     if (isFirstLoop)
3494         {
3495         t2 = t;
3496         if (isInterapted)
3497             {
3498             isFirstLoop = 0;
3499             goto treeConstruction;
3500             }
3501         }
3502 
3503     /* get downpass arrays */
3504     GetPolyDownPass(t);
3505 
3506     /* order tips */
3507     if (sumtParams.orderTaxa == YES)
3508         OrderTips (t);
3509 
3510     if (t!=t2)
3511         {
3512         /* get downpass arrays */
3513         GetPolyDownPass(t2);
3514 
3515         /* order tips */
3516         if (sumtParams.orderTaxa == YES)
3517             OrderTips (t2);
3518         }
3519 
3520     /* draw tree to stdout and fp */
3521     MrBayesPrint ("\n%s   Clade credibility values:\n\n", spacer);
3522     ShowConTree (stdout, t, 80, YES);
3523     if (logToFile == YES)
3524         ShowConTree (logFileFp, t, 80, YES);
3525     if (sumtParams.brlensDef == YES)
3526         {
3527         MrBayesPrint ("\n");
3528         if (sumtParams.isClock == YES)
3529             MrBayesPrint ("%s   Phylogram (based on median node depths):\n", spacer);
3530         else
3531             MrBayesPrint ("%s   Phylogram (based on average branch lengths):\n", spacer);
3532         if (isInterapted)
3533             {
3534             MrBayesPrint ("%s   Warning. Phylogram containing all nodes with credibility values exceeding\n",spacer);
3535             MrBayesPrint ("%s   the level set by Contype could not be constructed.\n",spacer);
3536             MrBayesPrint ("%s   Only nodes with credibility values exceeding %.2f%% (percentage of trees\n", spacer, freqInterapted*100);
3537             MrBayesPrint ("%s   where the node is present) were included in the phylogram.\n", spacer);
3538             }
3539         MrBayesPrint ("\n");
3540         ShowConPhylogram (stdout, t2, 80);
3541         if (logToFile == YES)
3542             ShowConPhylogram (logFileFp, t2, 80);
3543         }
3544 
3545     /* print taxa block */
3546     MrBayesPrintf (fpCon, "begin taxa;\n");
3547     MrBayesPrintf (fpCon, "\tdimensions ntax=%d;\n", sumtParams.numTaxa);
3548     MrBayesPrintf (fpCon, "\ttaxlabels\n", sumtParams.numTaxa);
3549     for (i=0; i<sumtParams.numTaxa; i++)
3550         {
3551         for (j=0; j<t2->nNodes; j++)
3552             if (t2->nodes[j].index == i)
3553                 break;
3554         MrBayesPrintf (fpCon, "\t\t%s\n", t2->nodes[j].label);
3555         }
3556     MrBayesPrintf (fpCon, "\t\t;\nend;\n");
3557 
3558     MrBayesPrintf (fpCon, "begin trees;\n");
3559     MrBayesPrintf (fpCon, "\ttranslate\n");
3560     for (i=0; i<sumtParams.numTaxa; i++)
3561         {
3562         for (j=0; j<t2->nNodes; j++)
3563             if (t2->nodes[j].index == i)
3564                 break;
3565         if (i == sumtParams.numTaxa-1)
3566             MrBayesPrintf (fpCon, "\t\t%d\t%s\n", t2->nodes[i].index+1, t2->nodes[i].label);
3567         else
3568             MrBayesPrintf (fpCon, "\t\t%d\t%s,\n", t2->nodes[i].index+1, t2->nodes[i].label);
3569         }
3570     MrBayesPrintf (fpCon, "\t\t;\n");
3571     if (sumtParams.consensusFormat == SIMPLE)
3572         PrintConTree(fpCon, t2);
3573     else if (sumtParams.consensusFormat == FIGTREE)
3574         PrintFigTreeConTree(fpCon, t2, treeParts);
3575     MrBayesPrintf (fpCon, "end;\n");
3576 
3577     if (t!=t2)
3578         {
3579         FreePolyTree (t2);
3580         }
3581     /* free memory */
3582     FreePolyTree (t);
3583 
3584     return (NO_ERROR);
3585 }
3586 
3587 
CppEvolRate(PolyTree * t,PolyNode * p,int eSet)3588 MrBFlt CppEvolRate (PolyTree *t, PolyNode *p, int eSet)
3589 {
3590     int         i, nEvents;
3591     MrBFlt      ancRate, branchRate, *rate, *pos;
3592     PolyNode    *q;
3593 
3594     nEvents = t->nEvents[eSet][p->index];
3595     pos = t->position[eSet][p->index];
3596     rate = t->rateMult[eSet][p->index];
3597 
3598     /* note that event positions are from top of branch (more recent, descendant tip) */
3599     ancRate = 1.0;
3600 //  if (t->eType[eSet] == CPPm)
3601 //      {
3602     for (q=p; q->anc != NULL; q=q->anc)
3603         {
3604         for (i=0; i<t->nEvents[eSet][p->index]; i++)
3605             ancRate *= t->rateMult[eSet][p->index][i];
3606         }
3607     if (nEvents > 0)
3608         {
3609         branchRate = rate[0] * pos[0];
3610         for (i=1; i<nEvents; i++)
3611             {
3612             branchRate += (pos[i] - pos[i-1]);
3613             branchRate *= rate[i];
3614             }
3615         branchRate += 1.0 - pos[nEvents-1];
3616         branchRate *= ancRate;
3617         }
3618     else
3619         branchRate = ancRate;
3620 //      }
3621 /*
3622     else if (t->eType[eSet] == CPPi)
3623         {
3624         for (q=p; q->anc != NULL; q=q->anc)
3625             {
3626             if (t->nEvents[eSet][p->index]>0)
3627                 {
3628                 ancRate = t->rateMult[eSet][p->index][0];
3629                 break;
3630                 }
3631             }
3632         if (nEvents > 0)
3633             {
3634             branchRate = ancRate * (1.0 - pos[nEvents-1]);
3635             for (i=nEvents-2; i>=0; i--)
3636                 {
3637                 branchRate += (rate[i+1] * (pos[i+1] - pos[i]));
3638                 }
3639             branchRate += (rate[0] * pos[0]);
3640             }
3641         else
3642             branchRate = ancRate;
3643         }
3644 */
3645 
3646     return branchRate;
3647 }
3648 
3649 
DoCompareTree(void)3650 int DoCompareTree (void)
3651 {
3652     int             i, j, k, n, longestLineLength, brlensDef[2], numTreesInLastBlock[2],
3653                     lastTreeBlockBegin[2], lastTreeBlockEnd[2], xaxis, yaxis, starHolder[80],
3654                     minNumTrees, screenWidth, screenHeigth, numY[60], nSamples;
3655     RandLong        temporarySeed;
3656     BitsLong        *mask;
3657     PartCtr         *x;
3658     MrBFlt          xProb, yProb, xInc, yInc, xUpper, xLower, yUpper, yLower, *dT1=NULL, *dT2=NULL, *dT3=NULL, d1, d2, d3,
3659                     meanY[60], xVal, yVal, minX, minY, maxX, maxY, sums[3];
3660     char            *s=NULL, prCh, treeName[2][100];
3661     FILE            *fp;
3662     time_t          curTime;
3663     PartCtr         **treeParts=NULL;
3664     Tree            *tree1=NULL, *tree2=NULL;
3665     SumtFileInfo    sumtFileInfo;
3666 
3667 #   if defined (MPI_ENABLED)
3668     if (proc_id == 0)
3669         {
3670 #   endif
3671 
3672     /* Make sure we read trees using DoSumtTree() code instead of with the user tree code */
3673     inComparetreeCommand = YES;
3674 
3675     /* set file pointer to NULL */
3676     fp = NULL;
3677 
3678     strcpy(treeName[0],"tree"); //in case if parameter is not specified in a .t file
3679     strcpy(treeName[1],"tree");
3680 
3681     /* Check that a data set has been read in. We check taxon names against
3682        those read in. */
3683     if (isTaxsetDef == NO)
3684         {
3685         MrBayesPrint ("%s   A matrix or set of taxon labels must be specified before comparetree can be used\n", spacer);
3686         goto errorExit;
3687         }
3688 
3689     /* open output files for summary information (two files); check if we want to overwrite previous results */
3690     if (OpenComptFiles () == ERROR)
3691         goto errorExit;
3692 
3693     MrBayesPrint ("%s   Examining files ...\n", spacer);
3694 
3695     /* Examine first file */
3696     if (ExamineSumtFile(comptreeParams.comptFileName1, &sumtFileInfo, treeName[0], &(brlensDef[0])) == ERROR)
3697         return ERROR;
3698 
3699     /* Capture info */
3700     longestLineLength      = sumtFileInfo.longestLineLength;
3701     numTreesInLastBlock[0] = sumtFileInfo.numTreesInLastBlock;
3702     lastTreeBlockBegin[0]  = sumtFileInfo.lastTreeBlockBegin;
3703     lastTreeBlockEnd[0]    = sumtFileInfo.lastTreeBlockEnd;
3704 
3705     /* Examine second file */
3706     if (ExamineSumtFile(comptreeParams.comptFileName2, &sumtFileInfo, treeName[1], &brlensDef[1]) == ERROR)
3707         return ERROR;
3708 
3709     /* Capture info */
3710     if (longestLineLength < sumtFileInfo.longestLineLength)
3711         longestLineLength = sumtFileInfo.longestLineLength;
3712     numTreesInLastBlock[1] = sumtFileInfo.numTreesInLastBlock;
3713     lastTreeBlockBegin[1]  = sumtFileInfo.lastTreeBlockBegin;
3714     lastTreeBlockEnd[1]    = sumtFileInfo.lastTreeBlockEnd;
3715 
3716     /* Check whether we should work with brlens */
3717     if (brlensDef[0] == YES && brlensDef[1] == YES)
3718         sumtParams.brlensDef = YES;
3719     else
3720         sumtParams.brlensDef = NO;
3721 
3722     /* Allocate space for command string */
3723     longestLineLength += 10;
3724     s = (char *)SafeMalloc((size_t)longestLineLength * sizeof(char));
3725     if (!s)
3726         {
3727         MrBayesPrint ("%s   Problem allocating string for reading tree file\n", spacer);
3728         goto errorExit;
3729         }
3730 
3731     /* Allocate space for packed trees */
3732     if (chainParams.relativeBurnin == YES)
3733         {
3734         numPackedTrees[0] = numTreesInLastBlock[0] - (int)(chainParams.burninFraction * numTreesInLastBlock[0]);
3735         numPackedTrees[1] = numTreesInLastBlock[1] - (int)(chainParams.burninFraction * numTreesInLastBlock[1]);
3736         }
3737     else
3738         {
3739         numPackedTrees[0] = numTreesInLastBlock[0] - chainParams.chainBurnIn;
3740         numPackedTrees[1] = numTreesInLastBlock[1] - chainParams.chainBurnIn;
3741         }
3742     if (memAllocs[ALLOC_PACKEDTREES] == YES)
3743         {
3744         MrBayesPrint ("%s   packedTreeList is already allocated\n", spacer);
3745         goto errorExit;
3746         }
3747     packedTreeList[0] = (PackedTree *) SafeCalloc(numPackedTrees[0]+numPackedTrees[1], sizeof(PackedTree));
3748     packedTreeList[1] = packedTreeList[0] + numPackedTrees[0];
3749     if (!packedTreeList[0])
3750         {
3751         MrBayesPrint ("%s   Problem allocating packed tree list\n", spacer);
3752         goto errorExit;
3753         }
3754     memAllocs[ALLOC_PACKEDTREES] = YES;
3755 
3756     /* Tell user we are ready to go */
3757     MrBayesPrint ("%s   Summarizing trees in files \"%s\" and \"%s\"\n", spacer,
3758         comptreeParams.comptFileName1,
3759         comptreeParams.comptFileName2);
3760 
3761     if (chainParams.relativeBurnin == YES)
3762         MrBayesPrint ("%s   Using relative burnin ('relburnin=yes'), discarding the first %.0f %% ('burninfrac=%1.2f') of sampled trees\n",
3763             spacer, chainParams.burninFraction*100.0, chainParams.burninFraction);
3764     else
3765         MrBayesPrint ("%s   Using absolute burnin ('relburnin=no'), discarding the first %d ('burnin=%d') sampled trees\n",
3766             spacer, chainParams.chainBurnIn, chainParams.chainBurnIn);
3767 
3768     MrBayesPrint ("%s   Writing statistics to file %s.<dists|pairs>\n", spacer, comptreeParams.comptOutfile);
3769 
3770     /* Set up cheap status bar. */
3771     MrBayesPrint ("\n%s   Tree reading status:\n\n", spacer);
3772     MrBayesPrint ("%s   0      10      20      30      40      50      60      70      80      90     100\n", spacer);
3773     MrBayesPrint ("%s   v-------v-------v-------v-------v-------v-------v-------v-------v-------v-------v\n", spacer);
3774     MrBayesPrint ("%s   *", spacer);
3775     numAsterices = 0;
3776 
3777     /* Read file 1 for real */
3778     if ((fp = OpenTextFileR(comptreeParams.comptFileName1)) == NULL)
3779         goto errorExit;
3780 
3781     /* ...and fast forward to beginning of last tree block (skipping begin trees). */
3782     for (i=0; i<lastTreeBlockBegin[0] + 1; i++)
3783         {
3784         if (fgets (s, longestLineLength, fp) == NULL)
3785             {
3786             printf ("Error in function: %s at line: %d in file: %s", __func__, __LINE__, __FILE__);
3787             }
3788         }
3789 
3790     /* Calculate burnin */
3791     if (chainParams.relativeBurnin == YES)
3792         comptreeParams.burnin = (int)(chainParams.burninFraction * numTreesInLastBlock[0]);
3793     else
3794         comptreeParams.burnin = chainParams.chainBurnIn;
3795 
3796     /* Initialize sumtParams struct */
3797     numUniqueSplitsFound = numUniqueTreesFound = 0;
3798     sumtParams.runId = 0;
3799     strcpy(sumtParams.curFileName, comptreeParams.comptFileName1);
3800     sumtParams.tree = AllocatePolyTree (numTaxa);
3801     AllocatePolyTreePartitions (sumtParams.tree);
3802     sumtParams.numTreesEncountered = sumtParams.numTreesSampled = 0;
3803     sumtParams.numFileTrees = (int *) SafeCalloc (2*2+2*numTaxa, sizeof(int));
3804     sumtParams.numFileTreesSampled = sumtParams.numFileTrees + sumtParams.numRuns;
3805     sumtParams.order = sumtParams.numFileTrees + 2*sumtParams.numRuns;
3806     sumtParams.absentTaxa = sumtParams.numFileTrees + 2*sumtParams.numRuns + numTaxa;
3807     sumtParams.numTreesInLastBlock = numTreesInLastBlock[0];
3808     if (!sumtParams.numFileTrees)
3809         {
3810         MrBayesPrint ("%s   Problems allocating sumtParams.numFileTrees in DoSumt()\n", spacer);
3811         goto errorExit;
3812         }
3813     else
3814         memAllocs[ALLOC_SUMTPARAMS] = YES;
3815 
3816     /* ... and parse the file */
3817     expecting = Expecting(COMMAND);
3818     inTreesBlock = YES;
3819     ResetTranslateTable();
3820     for (i=0; i<lastTreeBlockEnd[0] - lastTreeBlockBegin[0] - 1; i++)
3821         {
3822         if (fgets (s, longestLineLength, fp) == NULL)
3823             {
3824             printf ("Error in function: %s at line: %d in file: %s", __func__, __LINE__, __FILE__);
3825             }
3826         /*MrBayesPrint ("%s", s);*/
3827         if (ParseCommand (s) == ERROR)
3828             goto errorExit;
3829         }
3830     inTreesBlock = NO;
3831     ResetTranslateTable();
3832 
3833     /* Check that at least one tree was read in. */
3834     if (sumtParams.numFileTreesSampled[0] <= 0)
3835         {
3836         MrBayesPrint ("%s   No trees read in\n", spacer);
3837         goto errorExit;
3838         }
3839 
3840     /* ... and close file */
3841     SafeFclose (&fp);
3842 
3843     /* Read file 2 for real */
3844     if ((fp = OpenTextFileR(comptreeParams.comptFileName2)) == NULL)
3845         goto errorExit;
3846 
3847     /* ...and fast forward to beginning of last tree block. */
3848     for (i=0; i<lastTreeBlockBegin[1] + 1; i++)
3849         {
3850         if (fgets (s, longestLineLength, fp) == NULL)
3851             {
3852             printf ("Error in function: %s at line: %d in file: %s", __func__, __LINE__, __FILE__);
3853             }
3854         }
3855 
3856     /* Renitialize sumtParams struct */
3857     sumtParams.runId = 1;
3858     strcpy (sumtParams.curFileName, comptreeParams.comptFileName2);
3859 
3860     /* Calculate burnin */
3861     if (chainParams.relativeBurnin == YES)
3862         comptreeParams.burnin = (int)(chainParams.burninFraction * numTreesInLastBlock[1]);
3863     else
3864         comptreeParams.burnin = chainParams.chainBurnIn;
3865 
3866     /* ... and parse the file */
3867     expecting = Expecting(COMMAND);
3868     inTreesBlock = YES;
3869     ResetTranslateTable();
3870     for (i=0; i<lastTreeBlockEnd[1] - lastTreeBlockBegin[1] - 1; i++)
3871         {
3872         if (fgets (s, longestLineLength, fp) == NULL)
3873             {
3874             printf ("Error in function: %s at line: %d in file: %s", __func__, __LINE__, __FILE__);
3875             }
3876         /*MrBayesPrint ("%s", s);*/
3877         if (ParseCommand (s) == ERROR)
3878             goto errorExit;
3879         }
3880     inTreesBlock = NO;
3881     ResetTranslateTable();
3882 
3883     /* Check that at least one tree was read in. */
3884     if (sumtParams.numFileTreesSampled[1] <= 0)
3885         {
3886         MrBayesPrint ("%s   No trees read in\n", spacer);
3887         goto errorExit;
3888         }
3889 
3890     /* ... and close file */
3891     SafeFclose (&fp);
3892 
3893     /* Now finish cheap status bar. */
3894     if (numAsterices < 80)
3895         for (i=0; i<80 - numAsterices; i++)
3896             MrBayesPrint ("*");
3897     MrBayesPrint ("\n\n");
3898 
3899     /* tell user how many trees were successfully read */
3900     MrBayesPrint ("%s   Read %d trees from last tree block of file \"%s\" (sampling %d of them)\n", spacer,
3901         sumtParams.numFileTrees[0],
3902         comptreeParams.comptFileName1,
3903         sumtParams.numFileTreesSampled[0]);
3904     MrBayesPrint ("%s   Read %d trees from last tree block of file \"%s\" (sampling %d of them)\n", spacer,
3905         sumtParams.numFileTrees[1],
3906         comptreeParams.comptFileName2,
3907         sumtParams.numFileTreesSampled[1]);
3908 
3909     /* Extract partition counter pointers */
3910     treeParts = (PartCtr **) SafeCalloc ((size_t)(numUniqueSplitsFound), sizeof(PartCtr *));
3911     i = 0;
3912     PartCtrUppass(partCtrRoot, treeParts, &i);
3913 
3914     /* Sort taxon partitions (clades, splits) ... */
3915     SortPartCtr (treeParts, 0, numUniqueSplitsFound-1);
3916 
3917     /* print to screen */
3918     MrBayesPrint ("                                                                                   \n");
3919     MrBayesPrint ("%s   General explanation:                                                          \n", spacer);
3920     MrBayesPrint ("                                                                                   \n");
3921     MrBayesPrint ("%s   In an unrooted tree, a taxon bipartition (split) is specified by removing a   \n", spacer);
3922     MrBayesPrint ("%s   branch, thereby dividing the species into those to the left and those to the  \n", spacer);
3923     MrBayesPrint ("%s   right of the branch. Here, taxa to one side of the removed branch are denoted \n", spacer);
3924     MrBayesPrint ("%s   '.' and those to the other side are denoted '*'. Specifically, the '.' symbol \n", spacer);
3925     MrBayesPrint ("%s   is used for the taxa on the same side as the outgroup.                        \n", spacer);
3926     MrBayesPrint ("                                                                                   \n");
3927     MrBayesPrint ("%s   In a rooted or clock tree, the '*' symbol is simply used to denote the taxa   \n", spacer);
3928     MrBayesPrint ("%s   that are included in a particular group (clade), that is, all the descendants \n", spacer);
3929     MrBayesPrint ("%s   of a particular branch in the tree.  Taxa that are not included are denoted   \n", spacer);
3930     MrBayesPrint ("%s   using the '.' symbol.                                                         \n", spacer);
3931     MrBayesPrint ("                                                                                   \n");
3932     MrBayesPrint ("%s   The output includes the ID of the encountered clades or splits (sorted from   \n", spacer);
3933     MrBayesPrint ("%s   highest to lowest probability), the bipartition or clade in '.*' format, \n", spacer);
3934     MrBayesPrint ("%s   number of times the bipartition or clade was observed in the first tree file  \n", spacer);
3935     MrBayesPrint ("%s   served in the first tree file, the number of times the bipartition was,       \n", spacer);
3936     MrBayesPrint ("%s   observed in the second tree file, the proportion of the time the bipartition  \n", spacer);
3937     MrBayesPrint ("%s   was found in the first tree file, and the proportion of the time the bi-      \n", spacer);
3938     MrBayesPrint ("%s   partition was found in the second tree file.                                  \n", spacer);
3939     MrBayesPrint ("                                                                                   \n");
3940     MrBayesPrint ("%s   List of taxa in bipartitions:                                                 \n", spacer);
3941     MrBayesPrint ("                                                                                   \n");
3942     j = 1;
3943     for (k=0; k<numTaxa; k++)
3944         {
3945         if (sumtParams.absentTaxa[k] == NO && taxaInfo[k].isDeleted == NO)
3946             {
3947             MrBayesPrint ("%s   %4d -- %s\n", spacer, j++, taxaNames[k]);
3948             }
3949         }
3950     MrBayesPrint ("                                                                                   \n");
3951     MrBayesPrint ("%s   List of taxon bipartitions found in tree files:                               \n\n", spacer);
3952 
3953     i = (int)(log10(sumtParams.numTreesSampled)) - 1;
3954     if (i<1)
3955         i = 1;
3956     j = sumtParams.numTaxa - 8;
3957     if (j < 1)
3958         j = 1;
3959     MrBayesPrint ("%s     ID -- Partition%*c  No1%*c  No2%*c  Freq1   Freq2\n",
3960         spacer, j, ' ', i, ' ', i, ' ');
3961 
3962     mask = SafeCalloc (sumtParams.BitsLongsNeeded, sizeof(BitsLong));
3963     for (i=0; i<sumtParams.numTaxa; i++)
3964         SetBit (i, mask);
3965     for (i=0; i<numUniqueSplitsFound; i++)
3966         {
3967         x = treeParts[i];
3968         if (IsBitSet(localOutGroup, x->partition) == YES && sumtParams.isRooted == NO)
3969             FlipBits(x->partition, sumtParams.BitsLongsNeeded, mask);
3970         if ((MrBFlt)x->totCount/(MrBFlt)sumtParams.numTreesSampled >= comptreeParams.minPartFreq)
3971             {
3972             MrBayesPrint ("%s   %4d -- ", spacer, i+1);
3973             ShowParts (stdout, x->partition, sumtParams.numTaxa);
3974 
3975             j = (int)(log10(sumtParams.numTreesSampled)) + 1;
3976             if (j < 3)
3977                 j = 3;
3978             MrBayesPrint ("   %*d   %*d   %1.3lf   %1.3lf\n",
3979             j, x->count[0], j, x->count[1],
3980             (MrBFlt)x->count[0]/(MrBFlt)sumtParams.numFileTreesSampled[0],
3981             (MrBFlt)x->count[1]/(MrBFlt)sumtParams.numFileTreesSampled[1]);
3982 
3983             MrBayesPrintf (fpParts, "%d\t%d\t%d\t%1.3lf\t%1.3lf\n",
3984             i+1, x->count[0], x->count[1],
3985             (MrBFlt)x->count[0]/(MrBFlt)sumtParams.numFileTreesSampled[0],
3986             (MrBFlt)x->count[1]/(MrBFlt)sumtParams.numFileTreesSampled[1]);
3987             }
3988         }
3989     free (mask);
3990 
3991     /* make a nifty graph plotting frequencies of clades found in the two tree files */
3992     MrBayesPrint ("                                                                                   \n");
3993     MrBayesPrint ("%s   Bivariate plot of clade probabilities:                                        \n", spacer);
3994     MrBayesPrint ("                                                                                   \n");
3995     MrBayesPrint ("%s   This graph plots the probabilities of clades found in file 1 (the x-axis)     \n", spacer);
3996     MrBayesPrint ("%s   against the probabilities of the same clades found in file 2 (the y-axis).    \n", spacer);
3997     MrBayesPrint ("                                                                                   \n");
3998     xInc = (MrBFlt) (1.0 / 80.0);
3999     yInc = (MrBFlt) (1.0 / 40.0);
4000     yUpper = 1.0;
4001     yLower = yUpper - yInc;
4002     for (yaxis=39; yaxis>=0; yaxis--)
4003         {
4004         xLower = 0.0;
4005         xUpper = xLower + xInc;
4006         for (xaxis=0; xaxis<80; xaxis++)
4007             {
4008             starHolder[xaxis] = 0;
4009             for (i=0; i<numUniqueSplitsFound; i++)
4010                 {
4011                 x = treeParts[i];
4012                 xProb = (MrBFlt)x->count[0]/(MrBFlt)sumtParams.numFileTreesSampled[0];
4013                 yProb = (MrBFlt)x->count[1]/(MrBFlt)sumtParams.numFileTreesSampled[1];
4014                 if ((xProb > xLower || (xProb == 0.0 && xaxis == 0)) && (xProb <= xUpper || (xProb == 1.0 && xaxis == 79))
4015                  && (yProb > yLower || (yProb == 0.0 && yaxis == 0)) && (yProb <= yUpper || (yProb == 1.0 && yaxis == 39)))
4016                     starHolder[xaxis] = 1;
4017                 }
4018             xLower += xInc;
4019             xUpper = xLower + xInc;
4020             }
4021 
4022         MrBayesPrint ("%s   ", spacer);
4023         for (xaxis=0; xaxis<80; xaxis++)
4024             {
4025             prCh = ' ';
4026             if ((xaxis == 0 && yaxis == 0) || (xaxis == 79 && yaxis == 39))
4027                 prCh = '+';
4028             else if ((xaxis == 0 && yaxis == 39) || (xaxis == 79 && yaxis == 0))
4029                 prCh = '+';
4030             else if ((yaxis == 0 || yaxis == 39) && xaxis > 0 && xaxis < 79)
4031                 prCh = '-';
4032             else if ((xaxis == 0 || xaxis == 79) && yaxis > 0 && yaxis < 39)
4033                 prCh = '|';
4034             if (starHolder[xaxis] == 1)
4035                 prCh = '*';
4036             MrBayesPrint ("%c", prCh);
4037             }
4038             if (yaxis == 39)
4039                 MrBayesPrint (" 1.00\n");
4040             else if (yaxis == 0)
4041                 MrBayesPrint (" 0.00\n");
4042             else
4043                 MrBayesPrint ("\n");
4044 
4045         yUpper -= yInc;
4046         yLower = yUpper - yInc;
4047         }
4048 
4049     MrBayesPrint ("%s   ^                                                                              ^\n", spacer);
4050     MrBayesPrint ("%s  0.00                                                                          1.00\n", spacer);
4051 
4052     /* get tree-to-tree distances: first allocate some space */
4053     minNumTrees = sumtParams.numFileTreesSampled[0];
4054     if (sumtParams.numFileTreesSampled[1] < minNumTrees)
4055         minNumTrees = sumtParams.numFileTreesSampled[1];
4056     dT1 = (MrBFlt *) SafeMalloc (3 * (size_t)minNumTrees * sizeof(MrBFlt));
4057     tree1 = AllocateFixedTree (sumtParams.numTaxa, sumtParams.isRooted);
4058     tree2 = AllocateFixedTree (sumtParams.numTaxa, sumtParams.isRooted);
4059     if (!dT1 || !tree1 || !tree2)
4060         {
4061         MrBayesPrint ("%s   Problem allocating topological distances\n", spacer);
4062         goto errorExit;
4063         }
4064     dT2 = dT1 + minNumTrees;
4065     dT3 = dT2 + minNumTrees;
4066 
4067     for (i=0; i<minNumTrees; i++)
4068         {
4069         if (sumtParams.isRooted == NO)
4070             {
4071             RetrieveUTree (tree1, packedTreeList[0][i].order, packedTreeList[0][i].brlens);
4072             RetrieveUTree (tree2, packedTreeList[1][i].order, packedTreeList[1][i].brlens);
4073             }
4074         else
4075             {
4076             RetrieveRTree (tree1, packedTreeList[0][i].order, packedTreeList[0][i].brlens);
4077             RetrieveRTree (tree2, packedTreeList[1][i].order, packedTreeList[1][i].brlens);
4078             }
4079         /* Allocate and set partitions now that we have a tree */
4080         if (i == 0)
4081             {
4082             AllocateTreePartitions(tree1);
4083             AllocateTreePartitions(tree2);
4084             }
4085         else
4086             {
4087             ResetTreePartitions(tree1);
4088             ResetTreePartitions(tree2);
4089             }
4090         CalculateTreeToTreeDistance (tree1, tree2, &d1, &d2, &d3);
4091         dT1[i] = d1;
4092         dT2[i] = d2;
4093         dT3[i] = d3;
4094         }
4095 
4096     for (i=0; i<minNumTrees; i++)
4097         {
4098         /*MrBayesPrint ("%s   %4d -- %lf %lf %lf\n", spacer, i+1, dT1[i], dT2[i], dT3[i]);*/
4099         if (sumtParams.brlensDef == YES)
4100             MrBayesPrintf (fpDists, "%d\t%lf\t%lf\t%lf\n", i+1, dT1[i], dT2[i], dT3[i]);
4101         else
4102             MrBayesPrintf (fpDists, "%d\t%lf\n", i+1, dT1[i]);
4103         }
4104 
4105     /* print x-y plot of log likelihood vs. generation */
4106     MrBayesPrint ("\n");
4107     MrBayesPrint ("%s   Rough plots of generation (x-axis) versus the measures of tree-   \n", spacer);
4108     MrBayesPrint ("%s   to-tree distances (y-axis).                                       \n", spacer);
4109     MrBayesPrint ("\n");
4110     MrBayesPrint ("%s   Distance(Robinson-Foulds):\n", spacer);
4111     MrBayesPrint ("\n");
4112     screenWidth = 60; /* don't change this without changing numY and meanY, declared above */
4113     screenHeigth = 15;
4114     minX = minY = 1000000000.0;
4115     maxX = maxY = -1000000000.0;
4116     for (i=0; i<minNumTrees; i++)
4117         {
4118         xVal = (MrBFlt) (i + comptreeParams.burnin);
4119         yVal = dT1[i];
4120         if (xVal < minX)
4121             minX = xVal;
4122         if (yVal < minY)
4123             minY = yVal;
4124         if (xVal > maxX)
4125             maxX = xVal;
4126         if (yVal > maxY)
4127             maxY = yVal;
4128         }
4129     for (i=0; i<screenWidth; i++)
4130         {
4131         numY[i] = 0;
4132         meanY[i] = 0.0;
4133         }
4134     for (i=0; i<minNumTrees; i++)
4135         {
4136         xVal = (MrBFlt) (i + comptreeParams.burnin);
4137         yVal = dT1[i];
4138         k = (int)(((xVal - minX) / (maxX - minX)) * screenWidth);
4139         if (k >= screenWidth)
4140             k = screenWidth - 1;
4141         meanY[k] += yVal;
4142         numY[k]++;
4143         }
4144     MrBayesPrint ("\n%s   +", spacer);
4145     for (i=0; i<screenWidth; i++)
4146         MrBayesPrint ("-");
4147     MrBayesPrint ("+ %1.2lf\n", maxY);
4148     for (j=screenHeigth-1; j>=0; j--)
4149         {
4150         MrBayesPrint ("%s   |", spacer);
4151         for (i=0; i<screenWidth; i++)
4152             {
4153             if (numY[i] > 0)
4154                 {
4155                 if (meanY[i] / numY[i] > (((maxY - minY)/screenHeigth)*j)+minY && meanY[i] / numY[i] <= (((maxY - minY)/screenHeigth)*(j+1))+minY)
4156                     MrBayesPrint ("*");
4157                 else
4158                     MrBayesPrint (" ");
4159                 }
4160             else
4161                 {
4162                 MrBayesPrint (" ");
4163                 }
4164             }
4165         MrBayesPrint ("|\n");
4166         }
4167     MrBayesPrint ("%s   +", spacer);
4168     for (i=0; i<screenWidth; i++)
4169         {
4170         if (numY[i] > 0 && meanY[i] / numY[i] <= minY)
4171             MrBayesPrint ("*");
4172         else if (i % (screenWidth/10) == 0 && i != 0)
4173             MrBayesPrint ("+");
4174         else
4175             MrBayesPrint ("-");
4176         }
4177     MrBayesPrint ("+ %1.2lf\n", minY);
4178     MrBayesPrint ("%s   ^", spacer);
4179     for (i=0; i<screenWidth; i++)
4180         MrBayesPrint (" ");
4181     MrBayesPrint ("^\n");
4182     MrBayesPrint ("%s   %1.0lf", spacer, minX);
4183     for (i=0; i<screenWidth; i++)
4184         MrBayesPrint (" ");
4185     MrBayesPrint ("%1.0lf\n\n", maxX);
4186 
4187     if (sumtParams.brlensDef == YES)
4188         {
4189         for (n=0; n<2; n++)
4190             {
4191             MrBayesPrint ("\n");
4192             if (n == 0)
4193                 MrBayesPrint ("%s   Distance(Robinson-Foulds with branch lengths):\n", spacer);
4194             else
4195                 MrBayesPrint ("%s   Distance(Robinson-Foulds with scaled branch lengths):\n", spacer);
4196             MrBayesPrint ("\n");
4197             screenWidth = 60; /* don't change this without changing numY and meanY, declared above */
4198             screenHeigth = 15;
4199             minX = minY = 1000000000.0;
4200             maxX = maxY = -1000000000.0;
4201             for (i=0; i<minNumTrees; i++)
4202                 {
4203                 xVal = (MrBFlt) (i + comptreeParams.burnin);
4204                 if (n == 0)
4205                     yVal = dT2[i];
4206                 else
4207                     yVal = dT3[i];
4208                 if (xVal < minX)
4209                     minX = xVal;
4210                 if (yVal < minY)
4211                     minY = yVal;
4212                 if (xVal > maxX)
4213                     maxX = xVal;
4214                 if (yVal > maxY)
4215                     maxY = yVal;
4216                 }
4217             for (i=0; i<screenWidth; i++)
4218                 {
4219                 numY[i] = 0;
4220                 meanY[i] = 0.0;
4221                 }
4222             for (i=0; i<minNumTrees; i++)
4223                 {
4224                 xVal = (MrBFlt) (i + comptreeParams.burnin);
4225                 if (n == 0)
4226                     yVal = dT2[i];
4227                 else
4228                     yVal = dT3[i];
4229                 k = (int)(((xVal - minX) / (maxX - minX)) * screenWidth);
4230                 if (k >= screenWidth)
4231                     k = screenWidth - 1;
4232                 meanY[k] += yVal;
4233                 numY[k]++;
4234                 }
4235             MrBayesPrint ("\n%s   +", spacer);
4236             for (i=0; i<screenWidth; i++)
4237                 MrBayesPrint ("-");
4238             MrBayesPrint ("+ %1.2lf\n", maxY);
4239             for (j=screenHeigth-1; j>=0; j--)
4240                 {
4241                 MrBayesPrint ("%s   |", spacer);
4242                 for (i=0; i<screenWidth; i++)
4243                     {
4244                     if (numY[i] > 0)
4245                         {
4246                         if (meanY[i] / numY[i] > (((maxY - minY)/screenHeigth)*j)+minY && meanY[i] / numY[i] <= (((maxY - minY)/screenHeigth)*(j+1))+minY)
4247                             MrBayesPrint ("*");
4248                         else
4249                             MrBayesPrint (" ");
4250                         }
4251                     else
4252                         {
4253                         MrBayesPrint (" ");
4254                         }
4255                     }
4256                 MrBayesPrint ("|\n");
4257                 }
4258             MrBayesPrint ("%s   +", spacer);
4259             for (i=0; i<screenWidth; i++)
4260                 {
4261                 if (numY[i] > 0 && meanY[i] / numY[i] <= minY)
4262                     MrBayesPrint ("*");
4263                 else if (i % (screenWidth/10) == 0 && i != 0)
4264                     MrBayesPrint ("+");
4265                 else
4266                     MrBayesPrint ("-");
4267                 }
4268             MrBayesPrint ("+ %1.2lf\n", minY);
4269             MrBayesPrint ("%s   ^", spacer);
4270             for (i=0; i<screenWidth; i++)
4271                 MrBayesPrint (" ");
4272             MrBayesPrint ("^\n");
4273             MrBayesPrint ("%s   %1.0lf", spacer, minX);
4274             for (i=0; i<screenWidth; i++)
4275                 MrBayesPrint (" ");
4276             MrBayesPrint ("%1.0lf\n\n", maxX);
4277             }
4278         }
4279 
4280     /* calculate average tree-to-tree distances */
4281     curTime = time(NULL);
4282     temporarySeed  = (RandLong)curTime;
4283     if (temporarySeed < 0)
4284         temporarySeed = -temporarySeed;
4285     sums[0] = sums[1] = sums[2] = 0.0;
4286     nSamples = 1000;
4287     for (n=0; n<nSamples; n++)
4288         {
4289         i = (int) RandomNumber(&temporarySeed) * minNumTrees;
4290         j = (int) RandomNumber(&temporarySeed) * minNumTrees;
4291         if (sumtParams.isRooted == NO)
4292             {
4293             RetrieveUTree (tree1, packedTreeList[0][i].order, packedTreeList[0][i].brlens);
4294             RetrieveUTree (tree2, packedTreeList[1][j].order, packedTreeList[1][j].brlens);
4295             }
4296         else /* if (sumtParams.isRooted == YES) */
4297             {
4298             RetrieveRTree (tree1, packedTreeList[0][i].order, packedTreeList[0][i].brlens);
4299             RetrieveRTree (tree2, packedTreeList[1][j].order, packedTreeList[1][j].brlens);
4300             }
4301         CalculateTreeToTreeDistance (tree1, tree2, &d1, &d2, &d3);
4302         sums[0] += d1;
4303         sums[1] += d2;
4304         sums[2] += d3;
4305         }
4306     MrBayesPrint ("%s   Mean tree-to-tree distances, based on %d trees randomly sampled from both files:\n\n", spacer, nSamples);
4307     MrBayesPrint ("%s                                 Mean(Robinson-Foulds) = %1.3lf\n", spacer, sums[0]/nSamples);
4308     if (sumtParams.brlensDef == YES)
4309         {
4310         MrBayesPrint ("%s             Mean(Robinson-Foulds with branch lengths) = %1.3lf\n", spacer, sums[1]/nSamples);
4311         MrBayesPrint ("%s      Mean(Robinson-Foulds with scaled branch lengths) = %1.3lf\n", spacer, sums[2]/nSamples);
4312         }
4313     MrBayesPrint ("\n");
4314 
4315     /* free memory and file pointers */
4316     free(s);
4317     free (dT1);
4318     FreeTree (tree1);
4319     FreeTree (tree2);
4320     if (memAllocs[ALLOC_PACKEDTREES] == YES)
4321         {
4322         for (i=0; i<numPackedTrees[0]+numPackedTrees[1]; i++)
4323             {
4324             free(packedTreeList[0][i].order);
4325             free(packedTreeList[0][i].brlens);
4326             }
4327         free(packedTreeList[0]);
4328         memAllocs[ALLOC_PACKEDTREES] = NO;
4329         }
4330 
4331     /* free sumtParams */
4332     FreeSumtParams();
4333 
4334     /* close files */
4335     SafeFclose (&fp);
4336     SafeFclose (&fpParts);
4337     SafeFclose (&fpDists);
4338 
4339     /* free pointer array to partitions, part and tree counters */
4340     free (treeParts);
4341     FreePartCtr (partCtrRoot);
4342     FreeTreeCtr (treeCtrRoot);
4343     partCtrRoot = NULL;
4344     treeCtrRoot = NULL;
4345 
4346     /* reset taxon set */
4347     ResetTaxonSet();
4348 
4349 #   if defined (MPI_ENABLED)
4350         }
4351 #   endif
4352 
4353     expecting = Expecting(COMMAND);
4354     inComparetreeCommand = NO;
4355     return (NO_ERROR);
4356 
4357     /* error exit */
4358     errorExit:
4359         if (s) free(s);
4360 
4361         /* free sumtParams */
4362         FreeSumtParams();
4363 
4364         free (dT1);
4365         FreeTree (tree1);
4366         FreeTree (tree2);
4367         if (memAllocs[ALLOC_PACKEDTREES] == YES)
4368             {
4369             for (i=0; i<numPackedTrees[0]+numPackedTrees[1]; i++)
4370                 {
4371                 free(packedTreeList[0][i].order);
4372                 free(packedTreeList[0][i].brlens);
4373                 }
4374             free(packedTreeList[0]);
4375             memAllocs[ALLOC_PACKEDTREES] = NO;
4376             }
4377 
4378         /* reset taxon set */
4379         ResetTaxonSet();
4380 
4381         /* free pointer array to partitions, part and tree counters */
4382         free (treeParts);
4383         FreePartCtr (partCtrRoot);
4384         FreeTreeCtr (treeCtrRoot);
4385         partCtrRoot = NULL;
4386         treeCtrRoot = NULL;
4387 
4388         SafeFclose (&fp);
4389         SafeFclose (&fpParts);
4390         SafeFclose (&fpDists);
4391         strcpy (spacer, "");
4392 
4393         expecting = Expecting(COMMAND);
4394         inComparetreeCommand = NO;
4395 
4396         return (ERROR);
4397 }
4398 
4399 
DoCompareTreeParm(char * parmName,char * tkn)4400 int DoCompareTreeParm (char *parmName, char *tkn)
4401 {
4402     int         tempI;
4403     MrBFlt      tempD;
4404     char        tempStr[100];
4405 
4406     if (expecting == Expecting(PARAMETER))
4407         {
4408         expecting = Expecting(EQUALSIGN);
4409         }
4410     else
4411         {
4412         if (!strcmp(parmName, "Xxxxxxxxxx"))
4413             {
4414             expecting  = Expecting(PARAMETER);
4415             expecting |= Expecting(SEMICOLON);
4416             }
4417         /* set Filename (comptreeParams.comptFileName1) *************************************************/
4418         else if (!strcmp(parmName, "Filename1"))
4419             {
4420             if (expecting == Expecting(EQUALSIGN))
4421                 {
4422                 expecting = Expecting(ALPHA);
4423                 readWord = YES;
4424                 }
4425             else if (expecting == Expecting(ALPHA))
4426                 {
4427                 strcpy (comptreeParams.comptFileName1, tkn);
4428                 MrBayesPrint ("%s   Setting comparetree filename 1 to %s\n", spacer, comptreeParams.comptFileName1);
4429                 expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
4430                 }
4431             else
4432                 return (ERROR);
4433             }
4434         /* set Filename (comptreeParams.comptFileName2) *************************************************/
4435         else if (!strcmp(parmName, "Filename2"))
4436             {
4437             if (expecting == Expecting(EQUALSIGN))
4438                 {
4439                 expecting = Expecting(ALPHA);
4440                 readWord = YES;
4441                 }
4442             else if (expecting == Expecting(ALPHA))
4443                 {
4444                 strcpy (comptreeParams.comptFileName2, tkn);
4445                 MrBayesPrint ("%s   Setting comparetree filename 2 to %s\n", spacer, comptreeParams.comptFileName2);
4446                 expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
4447                 }
4448             else
4449                 return (ERROR);
4450             }
4451         /* set Filename (comptreeParams.comptOutfile) ***************************************************/
4452         else if (!strcmp(parmName, "Outputname"))
4453             {
4454             if (expecting == Expecting(EQUALSIGN))
4455                 {
4456                 expecting = Expecting(ALPHA);
4457                 readWord = YES;
4458                 }
4459             else if (expecting == Expecting(ALPHA))
4460                 {
4461                 strcpy (comptreeParams.comptOutfile, tkn);
4462                 MrBayesPrint ("%s   Setting comparetree output file to %s\n", spacer, comptreeParams.comptOutfile);
4463                 expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
4464                 }
4465             else
4466                 return (ERROR);
4467             }
4468         /* set Relburnin (chainParams.relativeBurnin) ********************************************************/
4469         else if (!strcmp(parmName, "Relburnin"))
4470             {
4471             if (expecting == Expecting(EQUALSIGN))
4472                 expecting = Expecting(ALPHA);
4473             else if (expecting == Expecting(ALPHA))
4474                 {
4475                 if (IsArgValid(tkn, tempStr) == NO_ERROR)
4476                     {
4477                     if (!strcmp(tempStr, "Yes"))
4478                         chainParams.relativeBurnin = YES;
4479                     else
4480                         chainParams.relativeBurnin = NO;
4481                     }
4482                 else
4483                     {
4484                     MrBayesPrint ("%s   Invalid argument for Relburnin\n", spacer);
4485                     return (ERROR);
4486                     }
4487                 if (chainParams.relativeBurnin == YES)
4488                     MrBayesPrint ("%s   Using relative burnin (a fraction of samples discarded).\n", spacer);
4489                 else
4490                     MrBayesPrint ("%s   Using absolute burnin (a fixed number of samples discarded).\n", spacer);
4491                 expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
4492                 }
4493             else
4494                 {
4495                 //free (tempStr);
4496                 return (ERROR);
4497                 }
4498             }
4499         /* set Burnin (chainParams.chainBurnIn) *******************************************************/
4500         else if (!strcmp(parmName, "Burnin"))
4501             {
4502             if (expecting == Expecting(EQUALSIGN))
4503                 expecting = Expecting(NUMBER);
4504             else if (expecting == Expecting(NUMBER))
4505                 {
4506                 sscanf (tkn, "%d", &tempI);
4507                 chainParams.chainBurnIn = tempI;
4508                 MrBayesPrint ("%s   Setting burnin to %d\n", spacer, chainParams.chainBurnIn);
4509                 expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
4510                 }
4511             else
4512                 return (ERROR);
4513             }
4514         /* set Burninfrac (chainParams.burninFraction) ************************************************************/
4515         else if (!strcmp(parmName, "Burninfrac"))
4516             {
4517             if (expecting == Expecting(EQUALSIGN))
4518                 expecting = Expecting(NUMBER);
4519             else if (expecting == Expecting(NUMBER))
4520                 {
4521                 sscanf (tkn, "%lf", &tempD);
4522                 if (tempD < 0.01)
4523                     {
4524                     MrBayesPrint ("%s   Burnin fraction too low (< 0.01)\n", spacer);
4525                     return (ERROR);
4526                     }
4527                 if (tempD > 0.50)
4528                     {
4529                     MrBayesPrint ("%s   Burnin fraction too high (> 0.50)\n", spacer);
4530                     return (ERROR);
4531                     }
4532                 chainParams.burninFraction = tempD;
4533                 MrBayesPrint ("%s   Setting burnin fraction to %.2f\n", spacer, chainParams.burninFraction);
4534                 expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
4535                 }
4536             else
4537                 {
4538                 return (ERROR);
4539                 }
4540             }
4541         /* set Minpartfreq (comptreeParams.minPartFreq) *******************************************************/
4542         else if (!strcmp(parmName, "Minpartfreq"))
4543             {
4544             if (expecting == Expecting(EQUALSIGN))
4545                 expecting = Expecting(NUMBER);
4546             else if (expecting == Expecting(NUMBER))
4547                 {
4548                 sscanf (tkn, "%lf", &tempD);
4549                 comptreeParams.minPartFreq = tempD;
4550                 MrBayesPrint ("%s   Including partitions with probability greater than or equal to %lf in summary statistics\n", spacer, comptreeParams.minPartFreq);
4551                 expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
4552                 }
4553             else
4554                 return (ERROR);
4555             }
4556         else
4557             return (ERROR);
4558         }
4559 
4560     return (NO_ERROR);
4561 }
4562 
4563 
DoCompRefTree(void)4564 int DoCompRefTree (void)
4565 {
4566     /* Compare a tree file with the reference tree files to generate the SDSFs.
4567        Use parameters in CompareTree and MCMCP (lazy option) */
4568 
4569     char         outName[130], inName[130], inRefName[130], treeName[100], *lineBuf=NULL, *s;
4570     FILE         *fpTre=NULL, *fpOut=NULL;
4571     int          i, n, longestL=0, burnin, gen, nRefRun, nTre[2]={0}, skip;
4572     SumtFileInfo tFileInfo;
4573     Tree         *t;
4574 
4575 #   if defined (MPI_ENABLED)
4576     if (proc_id != 0)
4577         return NO_ERROR;
4578 #   endif
4579 
4580     /* Check that a data set has been read in. We check taxon names against those read in. */
4581     if (isTaxsetDef == NO)
4582         {
4583         MrBayesPrint ("%s   A matrix or set of taxon labels must be specified before compareref can be used\n", spacer);
4584         return (ERROR);
4585         }
4586 
4587     /* this is a hack to account for the comparing (0) and the reference (1) tree samples
4588        chainParams.numRuns is used in AddTreeToPartitionCounters to alloc mem correctly */
4589     nRefRun = chainParams.numRuns;
4590     chainParams.numRuns = 2;
4591 
4592     /* initialize */
4593     if ((t = AllocateTree (numLocalTaxa)) == NULL)
4594         {
4595         MrBayesPrint ("%s   Problem allocating diagn tree\n", spacer);
4596         goto errorExit;
4597         }
4598     if (SetUpPartitionCounters () == ERROR)
4599         goto errorExit;
4600     if ((chainParams.stat = (STATS *) SafeCalloc (numTopologies, sizeof (STATS))) == NULL)
4601         goto errorExit;
4602     else
4603         memAllocs[ALLOC_STATS] = YES;
4604 
4605     /* deal with the reference tree files */
4606     // for (k=0; k<numTopologies; k++)
4607     for (n=0; n<nRefRun; n++)
4608         {
4609         if (nRefRun == 1)
4610             sprintf (inRefName, "%s.t", comptreeParams.comptFileName2);
4611         else
4612             sprintf (inRefName, "%s.run%d.t", comptreeParams.comptFileName2, n+1);
4613         MrBayesPrint ("%s   Processing run %d in the reference trees\n", spacer, n+1);
4614 
4615         /* Examine each ref tree file, save info to tFileInfo */
4616         if (ExamineSumtFile(inRefName, &tFileInfo, treeName, &sumtParams.brlensDef) == ERROR)
4617             goto errorExit;
4618         if (longestL < tFileInfo.longestLineLength)
4619             {
4620             longestL = tFileInfo.longestLineLength;
4621             lineBuf = (char *) SafeRealloc (lineBuf, (size_t)longestL * sizeof(char));
4622             if (!lineBuf)
4623                 {
4624                 MrBayesPrint ("%s   Problem allocating string for reading tree file\n", spacer);
4625                 goto errorExit;
4626                 }
4627             }
4628 
4629         /* calculate burnin */
4630         if (chainParams.relativeBurnin == YES)
4631             burnin = (int)(chainParams.burninFraction * tFileInfo.numTreesInLastBlock);
4632         else
4633             burnin = chainParams.chainBurnIn;
4634         if (burnin >= tFileInfo.numTreesInLastBlock)
4635             {
4636             MrBayesPrint ("%s   Burnin should be smaller than the total number of trees\n", spacer);
4637             goto errorExit;
4638             }
4639 
4640         /* open the ref tree file */
4641         if ((fpTre = OpenTextFileR (inRefName)) == NULL)
4642             goto errorExit;
4643         /* ...and fast forward to beginning in last tree block */
4644         for (i=0; i <= tFileInfo.lastTreeBlockBegin; i++)
4645             {
4646             if (fgets(lineBuf, longestL-2, fpTre) == NULL)
4647                 goto errorExit;
4648             }
4649 
4650         /* process each ref tree */
4651         for (i=0; i < tFileInfo.numTreesInLastBlock; i++)
4652             {
4653             do {
4654                 if (fgets (lineBuf, longestL-2, fpTre) == NULL)
4655                     goto errorExit;
4656                 s = strtok (lineBuf, " ");
4657                 }
4658             while (strcmp (s, "tree") != 0);
4659 
4660             /* add reference trees to partition counters, discarding burnin */
4661             if (i < burnin) continue;
4662 
4663             s = strtok (NULL, ";");
4664             while (*s != '(')
4665                 s++;
4666             StripComments(s);
4667 
4668             if (ResetTopology (t, s) == ERROR)
4669                 goto errorExit;
4670             if (AddTreeToPartitionCounters (t, 0, 0) == ERROR)
4671                 goto errorExit;
4672             nTre[0]++;
4673             }
4674         MrBayesPrint ("%s   \t%d trees processed, %d trees discarded as burnin\n", spacer, tFileInfo.numTreesInLastBlock, burnin);
4675 
4676         /* close the tree file */
4677         SafeFclose (&fpTre);
4678         }
4679     /* end reference tree files */
4680     MrBayesPrint ("%s   \t%d reference trees in total from %d runs\n", spacer, nTre[0], nRefRun);
4681 
4682     MrBayesPrint ("%s   Processing the test run ...\n", spacer, n+1);
4683     /* open output file */
4684     strcpy (outName, comptreeParams.comptOutfile);
4685     strcat (outName, ".sdsf");
4686     if ((fpOut = OpenNewMBPrintFile (outName)) == NULL)
4687         goto errorExit;
4688     /* print stamp and header */
4689     if ((int)strlen(stamp) > 1)
4690         MrBayesPrintf (fpOut, "[ID: %s]\n", stamp);
4691     if (chainParams.diagnStat == AVGSTDDEV)
4692         MrBayesPrintf (fpOut, "Gen\tASDSF\n");
4693     else  // MAXSTDDEV
4694         MrBayesPrintf (fpOut, "Gen\tMSDSF\n");
4695 
4696     /* Examine the tree file to be compared, save info to tFileInfo */
4697     strcpy(inName, comptreeParams.comptFileName1);
4698     if (ExamineSumtFile(inName, &tFileInfo, treeName, &sumtParams.brlensDef) == ERROR)
4699         goto errorExit;
4700     if (longestL < tFileInfo.longestLineLength)
4701         {
4702         longestL = tFileInfo.longestLineLength;
4703         lineBuf = (char *) SafeRealloc (lineBuf, (size_t)longestL * sizeof(char));
4704         if (!lineBuf)
4705             {
4706             MrBayesPrint ("%s   Problem allocating string for reading tree file\n", spacer);
4707             goto errorExit;
4708             }
4709         }
4710 
4711     /* open the tree file to be compared */
4712     if ((fpTre = OpenTextFileR (inName)) == NULL)
4713         goto errorExit;
4714     /* ...and fast forward to beginning in last tree block */
4715     for (i=0; i <= tFileInfo.lastTreeBlockBegin; i++)
4716         {
4717         if (fgets(lineBuf, longestL-2, fpTre) == NULL)
4718             goto errorExit;
4719         }
4720 
4721     /* process each tree to be compared and print SDSF to file */
4722     skip = 1; // skip the first few trees (default 1)
4723     // skip = (int) (0.5 * tFileInfo.numTreesInLastBlock);
4724     for (i=0; i < tFileInfo.numTreesInLastBlock; i++)
4725         {
4726         do {
4727             if (fgets (lineBuf, longestL-2, fpTre) == NULL)
4728                 goto errorExit;
4729             s = strtok (lineBuf, " ");
4730             }
4731         while (strcmp (s, "tree") != 0);
4732 
4733         if (i < skip) continue;
4734 
4735         s = strtok (NULL, ";");
4736         gen = atoi(s+4);  // 4 is offset to get rid of "rep." in tree name
4737         while (*s != '(')
4738             s++;
4739         StripComments(s);
4740 
4741         /* add the tree to partition counters */
4742         if (ResetTopology (t, s) == ERROR)
4743             goto errorExit;
4744         if (AddTreeToPartitionCounters (t, 0, 1) == ERROR)
4745             goto errorExit;
4746         nTre[1]++;
4747 
4748         /* calculate and write stdev of split freq */
4749         CalcTopoConvDiagn2 (nTre);
4750         if (chainParams.stat[0].numPartitions == 0)
4751             {
4752             MrBayesPrintf (fpOut, "%d\tNA\n", gen);
4753             }
4754         else if (chainParams.diagnStat == AVGSTDDEV)
4755             {
4756             MrBayesPrintf (fpOut, "%d\t%lf\n", gen, chainParams.stat[0].avgStdDev);
4757             }
4758         else  // MAXSTDDEV
4759             {
4760             MrBayesPrintf (fpOut, "%d\t%lf\n", gen, chainParams.stat[0].max);
4761             }
4762         }
4763     MrBayesPrint ("%s   \t%d trees discarded, the last %d trees compared to the reference\n", spacer, skip, nTre[1]);
4764 
4765     /* change back to the actual numRuns, end of hack */
4766     chainParams.numRuns = nRefRun;
4767 
4768     /* close tree file */
4769     SafeFclose (&fpTre);
4770     /* close output file */
4771     SafeFclose (&fpOut);
4772     /* free memory */
4773     free(lineBuf);
4774     FreeTree (t);
4775     FreeChainMemory();
4776 
4777     return (NO_ERROR);
4778 
4779     /* error exit */
4780 errorExit:
4781     MrBayesPrint ("%s   Error in DoCompRefTree\n", spacer);
4782 
4783     chainParams.numRuns = nRefRun;
4784     SafeFclose (&fpTre);
4785     SafeFclose (&fpOut);
4786 
4787     FreeTree (t);
4788     FreeChainMemory();
4789     free(lineBuf);
4790 
4791     return (ERROR);
4792 }
4793 
4794 
4795 #if defined (PRINT_RATEMUL_CPP)
DELETE_ME_count_taxa(PolyNode * p)4796 int DELETE_ME_count_taxa(PolyNode *p)
4797 {
4798     int sum=0;
4799 
4800     if (p->left==NULL) {
4801         if (p->depth > 0.1)
4802             return 1;
4803         else
4804             return 0;
4805     }
4806 
4807     p=p->left;
4808     while (p != NULL) {
4809         sum+=DELETE_ME_count_taxa(p);
4810         p=p->sib;
4811     }
4812     return sum;
4813 }
4814 
4815 
DELETE_ME_dump_depth(PolyNode * p)4816 void DELETE_ME_dump_depth(PolyNode *p)
4817 {
4818     /*print depth of two taxa clade*/
4819     /*
4820     if (p->left != NULL && p->left->left == NULL && p->left->sib != NULL && p->left->sib->left == NULL){
4821         fprintf (rateMultfp,"%f\n",p->depth);
4822         }
4823     if (p->left != NULL && p->left->left == NULL && p->left->sib != NULL && p->left->sib->left == NULL){
4824         if (p->left->depth > 0.1 && p->left->sib->depth > 0.1)
4825             fprintf (rateMultfp,"%f\n",p->depth);
4826         }
4827     */
4828     /* print depth of three taxa clade */
4829     if (((p->left != NULL && p->left->left == NULL) && p->left->sib != NULL && p->left->sib->left != NULL &&  p->left->sib->left->left == NULL && p->left->sib->left->sib->left == NULL) ||
4830        (p->left != NULL && p->left->left != NULL && p->left->left->left == NULL && p->left->left->sib->left == NULL && (p->left->sib->left == NULL))) {
4831         if (DELETE_ME_count_taxa(p)==2)
4832             fprintf (rateMultfp,"%f\n",p->depth);
4833         }
4834 
4835     p=p->left;
4836     while (p != NULL) {
4837         DELETE_ME_dump_depth(p);
4838         p=p->sib;
4839     }
4840 }
4841 #endif
4842 
4843 
DoSumt(void)4844 int DoSumt (void)
4845 {
4846     int             i, j=0, k, n, len, longestName, treeNo, numTreePartsToPrint,
4847                     maxWidthID, maxWidthNumberPartitions, maxNumTaxa, tableWidth=0, unreliable, oneUnreliable,
4848                     longestHeader;
4849     MrBFlt          f, var_s, sum_s, stddev_s=0.0, sumsq_s, sumStdDev=0.0, maxStdDev=0.0, sumPSRF=0.0,
4850                     maxPSRF=0.0, avgStdDev=0.0, avgPSRF=0.0, min_s=0.0, max_s=0.0, numPSRFSamples=0, min;
4851     PartCtr         *x;
4852     char            *s=NULL, tempName[120], fileName[120], treeName[100], divString[100];
4853     char            *tempStr=NULL; /*not static because error ext is handeled*/
4854     int             tempStrLength;
4855     FILE            *fp=NULL;
4856     PartCtr         **treeParts=NULL,*tmp;
4857     SumtFileInfo    sumtFileInfo;
4858     Stat            theStats;
4859     BitsLong        *mask;
4860 
4861 #define SCREEN_WIDTH 80
4862 
4863 #   if defined (MPI_ENABLED)
4864     if (proc_id == 0)
4865         {
4866 #   endif
4867 
4868     /* Ensure that we read trees with sumt code and not user tree code */
4869     inSumtCommand = YES;
4870 
4871     /* set file pointers to NULL */
4872     fp = fpParts = fpTstat = fpVstat = fpCon = fpTrees = NULL;
4873 
4874     strcpy(treeName,"tree"); //in case if parameter is not specified in a .t file
4875 
4876     /* Check if there is anything to do */
4877     if (sumtParams.table == NO && sumtParams.summary == NO && sumtParams.showConsensus == NO)
4878         {
4879         MrBayesPrint ("%s   Nothing to do, all output parameters (Table, Summary, Consensus) set to 'NO'\n", spacer);
4880         goto errorExit;
4881         }
4882 
4883     SafeStrcpy(&tempStr, " ");
4884 
4885     /* Initialize sumtParams struct */
4886     sumtParams.numTaxa = 0;
4887     sumtParams.taxaNames = NULL;
4888     sumtParams.BitsLongsNeeded = 0;
4889     sumtParams.tree = AllocatePolyTree (numTaxa);
4890     sumtParams.nESets = 0;
4891     sumtParams.nBSets = 0;
4892     sumtParams.eSetName = NULL;
4893     sumtParams.bSetName = NULL;
4894     sumtParams.popSizeSet = NO;
4895     sumtParams.popSizeSetName = NULL;
4896     AllocatePolyTreePartitions (sumtParams.tree);
4897     sumtParams.numFileTrees = (int *) SafeCalloc (2*sumtParams.numRuns+2*numTaxa, sizeof(int));
4898     sumtParams.numFileTreesSampled = sumtParams.numFileTrees + sumtParams.numRuns;
4899     sumtParams.order = sumtParams.numFileTrees + 2*sumtParams.numRuns;
4900     sumtParams.absentTaxa = sumtParams.numFileTrees + 2*sumtParams.numRuns + numTaxa;
4901     if (!sumtParams.numFileTrees)
4902         {
4903         MrBayesPrint ("%s   Problems allocating sumtParams.numFileTrees in DoSumt()\n", spacer);
4904         goto errorExit;
4905         }
4906     else
4907         memAllocs[ALLOC_SUMTPARAMS] = YES;
4908 
4909     /* Make sure outgroup is set correctly */
4910 
4911     for (treeNo = 0; treeNo < sumtParams.numTrees; treeNo++)
4912         {
4913         /* initialize across-file tree and partition counters */
4914         sumtParams.numTreesSampled = sumtParams.numTreesEncountered = 0;
4915         numUniqueSplitsFound = numUniqueTreesFound = 0;
4916 
4917         /* initialize oneUnreliable && unreliable */
4918         oneUnreliable = unreliable = NO;
4919 
4920         /* initialize summary statistics */
4921         sumStdDev = 0.0;
4922         sumPSRF = 0.0;
4923         numPSRFSamples = 0;
4924         maxStdDev = 0.0;
4925         maxPSRF = 0.0;
4926 
4927         /* tell user we are ready to go */
4928         if (sumtParams.numTrees > 1)
4929             sprintf (fileName,"%s.tree%d", sumtParams.sumtFileName, treeNo+1);
4930         else
4931             strcpy (fileName, sumtParams.sumtFileName);
4932 
4933         if (sumtParams.numRuns == 1)
4934             MrBayesPrint ("%s   Summarizing trees in file \"%s.t\"\n", spacer, fileName);
4935         else if (sumtParams.numRuns == 2)
4936             MrBayesPrint ("%s   Summarizing trees in files \"%s.run1.t\" and \"%s.run2.t\"\n", spacer, fileName, fileName);
4937         else if (sumtParams.numRuns > 2)
4938             MrBayesPrint ("%s   Summarizing trees in files \"%s.run1.t\", \"%s.run2.t\",...,\"%s.run%d.t\"\n", spacer, fileName, fileName,fileName,sumtParams.numRuns);
4939 
4940         if (chainParams.relativeBurnin == YES)
4941             MrBayesPrint ("%s   Using relative burnin ('relburnin=yes'), discarding the first %.0f %% of sampled trees\n",
4942                 spacer, chainParams.burninFraction*100.0, chainParams.burninFraction);
4943         else
4944             MrBayesPrint ("%s   Using absolute burnin ('relburnin=no'), discarding the first %d sampled trees\n",
4945                 spacer, chainParams.chainBurnIn, chainParams.chainBurnIn);
4946 
4947         MrBayesPrint ("%s   Writing statistics to files %s.<parts|tstat|vstat|trprobs|con>\n", spacer, sumtParams.sumtOutfile);
4948 
4949         for (sumtParams.runId=0; sumtParams.runId < sumtParams.numRuns; sumtParams.runId++)
4950             {
4951             /* initialize tree counters */
4952             sumtParams.numFileTrees[sumtParams.runId] = sumtParams.numFileTreesSampled[sumtParams.runId] = 0;
4953 
4954             /* open binary file */
4955             if (sumtParams.numRuns == 1)
4956                 sprintf (tempName, "%s.t", fileName);
4957             else
4958                 sprintf (tempName, "%s.run%d.t", fileName, sumtParams.runId+1);
4959             strcpy(sumtParams.curFileName, tempName);
4960 
4961             /* tell user we are examining files if for the first run */
4962             if (sumtParams.runId == 0)
4963                 {
4964                 if (sumtParams.numRuns > 1 && sumtParams.numTrees > 1)
4965                     MrBayesPrint ("%s   Examining first file for tree %d ...\n", spacer, treeNo);
4966                 else if (sumtParams.numRuns > 1 && sumtParams.numTrees == 1)
4967                     MrBayesPrint ("%s   Examining first file ...\n", spacer);
4968                 else if (sumtParams.numRuns == 1 && sumtParams.numTrees > 1)
4969                     MrBayesPrint ("%s   Examining file for tree %d ...\n", spacer, treeNo);
4970                 else
4971                     MrBayesPrint ("%s   Examining file ...\n", spacer);
4972                 }
4973 
4974             /* examine file */
4975             if (ExamineSumtFile(tempName, &sumtFileInfo, treeName, &sumtParams.brlensDef) == ERROR)
4976                 goto errorExit;
4977 
4978             /* capture values */
4979             if (sumtParams.runId == 0)
4980 
4981             /* catch lack of sampled trees */
4982             if (chainParams.relativeBurnin == NO && chainParams.chainBurnIn > sumtFileInfo.numTreesInLastBlock)
4983                 {
4984                 MrBayesPrint ("%s   No trees are sampled as the burnin exceeds the number of trees in last block\n", spacer);
4985                 MrBayesPrint ("%s   Try setting burnin to a number less than %d\n", spacer, sumtFileInfo.numTreesInLastBlock);
4986                 goto errorExit;
4987                 }
4988 
4989             /* tell the user that everything is fine */
4990             if (sumtParams.runId == 0)
4991                 {
4992                 if (sumtFileInfo.numTreeBlocks == 1)
4993                     MrBayesPrint ("%s   Found one tree block in file \"%s\" with %d trees in last block\n",
4994                         spacer, tempName, sumtFileInfo.numTreesInLastBlock);
4995                 else
4996                     {
4997                     MrBayesPrint ("%s   Found %d tree blocks in file \"%s\" with %d trees in last block\n",
4998                         spacer, sumtFileInfo.numTreeBlocks, tempName, sumtFileInfo.numTreesInLastBlock);
4999                     MrBayesPrint ("%s   Only the %d trees in last tree block will be summarized\n", spacer, sumtFileInfo.numTreesInLastBlock);
5000                     }
5001                 sumtParams.numTreesInLastBlock = sumtFileInfo.numTreesInLastBlock;
5002                 if (sumtParams.numRuns > 1)
5003                     MrBayesPrint ("%s   Expecting the same number of trees in the last tree block of all files\n", spacer);
5004                 if (chainParams.relativeBurnin == NO)
5005                     sumtParams.burnin = chainParams.chainBurnIn;
5006                 else
5007                     sumtParams.burnin = (int) (sumtFileInfo.numTreesInLastBlock * chainParams.burninFraction);
5008                 }
5009             else
5010                 {
5011                 if (sumtFileInfo.numTreesInLastBlock != sumtParams.numFileTrees[0])
5012                     {
5013                     MrBayesPrint ("%s   Found %d trees in first file but %d trees in file \"%s\"\n", spacer,
5014                         sumtParams.numFileTrees[0],
5015                         sumtFileInfo.numTreesInLastBlock,
5016                         tempName);
5017                     goto errorExit;
5018                     }
5019                 }
5020 
5021             /* Now we read the file for real. First, allocate a string for reading the file... */
5022             if (sumtParams.runId == 0 && treeNo == 0)
5023                 {
5024                 s = (char *) SafeMalloc ((size_t)(sumtFileInfo.longestLineLength) * sizeof(char));
5025                 if (!s)
5026                     {
5027                     MrBayesPrint ("%s   Problem allocating string for reading sumt file\n", spacer);
5028                     goto errorExit;
5029                     }
5030                 }
5031             else
5032                 {
5033                 free (s);
5034                 s = (char *) SafeMalloc ((size_t)(sumtFileInfo.longestLineLength) * sizeof (char));
5035                 if (!s)
5036                     {
5037                     MrBayesPrint ("%s   Problem reallocating string for reading sumt file\n", spacer);
5038                     goto errorExit;
5039                     }
5040                 }
5041 
5042             /* ... open the file ... */
5043             if ((fp = OpenTextFileR(tempName)) == NULL)
5044                 goto errorExit;
5045 
5046             /* ...and fast forward to beginning of last tree block. */
5047             for (i=0; i<sumtFileInfo.lastTreeBlockBegin+1; i++)
5048                 {
5049                 if (fgets (s, sumtFileInfo.longestLineLength-2, fp) == NULL)
5050                     {
5051                     printf ("Error in function: %s at line: %d in file: %s", __func__, __LINE__, __FILE__);
5052                     }
5053                 }
5054 
5055 #   if defined (PRINT_RATEMUL_CPP)
5056             sprintf (tempName, "%s.ratemult", chainParams.chainFileName);
5057             if ((rateMultfp=OpenNewMBPrintFile (tempName)) == NULL)
5058                 {
5059                 printf ("Error oppening file: %s to write", tempName);
5060                 goto errorExit;
5061                 }
5062             fprintf (rateMultfp,"rateMult_CPP\n");
5063 #   endif
5064 
5065             /* Set up cheap status bar. */
5066             if (sumtParams.runId == 0)
5067                 {
5068                 if (sumtParams.numTrees > 1)
5069                     MrBayesPrint ("\n%s   Tree reading status for tree %d:\n\n", spacer, treeNo+1);
5070                 else
5071                     MrBayesPrint ("\n%s   Tree reading status:\n\n", spacer);
5072                 MrBayesPrint ("%s   0      10      20      30      40      50      60      70      80      90     100\n", spacer);
5073                 MrBayesPrint ("%s   v-------v-------v-------v-------v-------v-------v-------v-------v-------v-------v\n", spacer);
5074                 MrBayesPrint ("%s   *", spacer);
5075                 numAsterices = 0;
5076                 }
5077 
5078             /* ...and parse file, tree-by-tree. We are only parsing lines between the "begin trees" and "end" statements.
5079             We don't actually get those lines, however, but rather the lines between those statements. */
5080             expecting = Expecting(COMMAND);
5081             /* We skip the begin trees statement so we need to set up some variables here */
5082             inTreesBlock = YES;
5083             ResetTranslateTable();
5084             for (i=0; i<sumtFileInfo.lastTreeBlockEnd - sumtFileInfo.lastTreeBlockBegin - 1; i++)
5085                 {
5086                 if (fgets (s, sumtFileInfo.longestLineLength-2, fp) == NULL)
5087                     {
5088                     printf ("Error in function: %s at line: %d in file: %s", __func__, __LINE__, __FILE__);
5089                     }
5090                 /*MrBayesPrint ("%s", s);*/
5091                 if (ParseCommand (s) == ERROR)
5092                     goto errorExit;
5093                 }
5094             inTreesBlock = NO;
5095             ResetTranslateTable();
5096 
5097             /* Finish cheap status bar. */
5098             if (sumtParams.runId == sumtParams.numRuns - 1)
5099                 {
5100                 if (numAsterices < 80)
5101                     {
5102                     for (i=0; i<80 - numAsterices; i++)
5103                         MrBayesPrint ("*");
5104                     }
5105                 MrBayesPrint ("\n\n");
5106                 }
5107 
5108             /* print out information on absent and pruned taxa */
5109             if (sumtParams.runId == sumtParams.numRuns - 1 && treeNo == 0)
5110                 PrintSumtTaxaInfo ();
5111 
5112             /* tell user how many trees were successfully read */
5113             if (sumtParams.numRuns == 1)
5114                 MrBayesPrint ("%s   Read %d trees from last tree block (sampling %d of them)\n", spacer,
5115                     sumtParams.numTreesEncountered, sumtParams.numTreesSampled);
5116             else if (sumtParams.numRuns > 1)
5117                 {
5118                 if (sumtParams.runId != 0 && sumtParams.numFileTreesSampled[sumtParams.runId]!=sumtParams.numFileTreesSampled[0])
5119                     {
5120                     if (sumtParams.runId == sumtParams.numRuns - 1)
5121                         MrBayesPrint ("\n\n");
5122                     MrBayesPrint ("%s   Found %d post-burnin trees in the first file but %d post-burnin trees in file %d\n",
5123                             spacer,
5124                             sumtParams.numFileTreesSampled[0],
5125                             sumtParams.numFileTreesSampled[sumtParams.runId],
5126                             sumtParams.runId+1);
5127                     goto errorExit;
5128                     }
5129                 if (sumtParams.runId == sumtParams.numRuns - 1)
5130                     {
5131                     MrBayesPrint ("%s   Read a total of %d trees in %d files (sampling %d of them)\n", spacer,
5132                         sumtParams.numTreesEncountered,
5133                         sumtParams.numRuns, sumtParams.numTreesSampled);
5134                     MrBayesPrint ("%s      (Each file contained %d trees of which %d were sampled)\n", spacer,
5135                         sumtParams.numFileTrees[0],
5136                         sumtParams.numFileTreesSampled[0]);
5137                     }
5138                 }
5139 
5140             /* Check that at least one tree was read in. */
5141             if (sumtParams.numTreesSampled <= 0)
5142                 {
5143                 MrBayesPrint ("%s   No trees read in\n", spacer);
5144                 goto errorExit;
5145                 }
5146 
5147             SafeFclose (&fp);
5148             }   /* next run for this tree */
5149 
5150         /* Extract partition counter pointers */
5151         treeParts = (PartCtr **) SafeCalloc ((size_t)numUniqueSplitsFound, sizeof(PartCtr *));
5152         i = 0;
5153         PartCtrUppass(partCtrRoot, treeParts, &i);
5154 
5155         min = (sumtParams.minPartFreq * (sumtParams.numTreesSampled/sumtParams.numRuns));
5156         numTreePartsToPrint=numUniqueSplitsFound;
5157         for (i=0; i<numTreePartsToPrint;)
5158             {
5159             for (j=0; j<sumtParams.numRuns;j++)
5160                 {
5161                 if (treeParts[i]->count[j]>=min)
5162                     break;
5163                 }
5164             if (j==sumtParams.numRuns)
5165                 {
5166                 numTreePartsToPrint--;
5167                 tmp=treeParts[numTreePartsToPrint];
5168                 treeParts[numTreePartsToPrint]=treeParts[i];
5169                 treeParts[i]=tmp;
5170                 }
5171             else
5172                 {
5173                 i++;
5174                 }
5175             }
5176 
5177         /* Sort taxon partitions (clades, splits) ... */
5178         SortPartCtr (treeParts, 0, numTreePartsToPrint-1);
5179 
5180         /* Sort root and tips among those splits always present */
5181         SortTerminalPartCtr (treeParts, numUniqueSplitsFound);
5182 
5183         /* open output files for summary information (three files) */
5184         if (OpenSumtFiles (treeNo) == ERROR)
5185             goto errorExit;
5186 
5187         /* Print partitions to screen. */
5188         if (treeNo == 0)
5189             {
5190             longestName = 0;
5191             for (k=0; k<numTaxa; k++)
5192                 {
5193                 if (taxaInfo[k].isDeleted == NO && sumtParams.absentTaxa[k] == NO)
5194                     continue;
5195                 len = (int) strlen (taxaNames[k]);
5196                 if (len > longestName)
5197                     longestName = len;
5198                 }
5199             if (sumtParams.table == YES)
5200                 {
5201                 MrBayesPrint ("                                                                                   \n");
5202                 MrBayesPrint ("%s   General explanation:                                                          \n", spacer);
5203                 MrBayesPrint ("                                                                                   \n");
5204                 MrBayesPrint ("%s   In an unrooted tree, a taxon bipartition (split) is specified by removing a   \n", spacer);
5205                 MrBayesPrint ("%s   branch, thereby dividing the species into those to the left and those to the  \n", spacer);
5206                 MrBayesPrint ("%s   right of the branch. Here, taxa to one side of the removed branch are denoted \n", spacer);
5207                 MrBayesPrint ("%s   '.' and those to the other side are denoted '*'. Specifically, the '.' symbol \n", spacer);
5208                 MrBayesPrint ("%s   is used for the taxa on the same side as the outgroup.                        \n", spacer);
5209                 MrBayesPrint ("                                                                                   \n");
5210                 MrBayesPrint ("%s   In a rooted or clock tree, the tree is rooted using the model and not by      \n", spacer);
5211                 MrBayesPrint ("%s   reference to an outgroup. Each bipartition therefore corresponds to a clade,  \n", spacer);
5212                 MrBayesPrint ("%s   that is, a group that includes all the descendants of a particular branch in  \n", spacer);
5213                 MrBayesPrint ("%s   the tree.  Taxa that are included in each clade are denoted using '*', and    \n", spacer);
5214                 MrBayesPrint ("%s   taxa that are not included are denoted using the '.' symbol.                  \n", spacer);
5215                 MrBayesPrint ("                                                                                   \n");
5216                 MrBayesPrint ("%s   The output first includes a key to all the bipartitions with frequency larger \n", spacer);
5217                 MrBayesPrint ("%s   or equual to (Minpartfreq) in at least one run. Minpartfreq is a parameter to \n", spacer);
5218                 MrBayesPrint ("%s   sumt command and currently it is set to %1.2lf.  This is followed by a table  \n", spacer, sumtParams.minPartFreq);
5219                 MrBayesPrint ("%s   with statistics for the informative bipartitions (those including at least    \n", spacer);
5220                 MrBayesPrint ("%s   two taxa), sorted from highest to lowest probability. For each bipartition,   \n", spacer);
5221                 MrBayesPrint ("%s   the table gives the number of times the partition or split was observed in all\n", spacer);
5222                 MrBayesPrint ("%s   runs (#obs) and the posterior probability of the bipartition (Probab.), which \n", spacer);
5223                 MrBayesPrint ("%s   is the same as the split frequency. If several runs are summarized, this is   \n", spacer);
5224                 MrBayesPrint ("%s   followed by the minimum split frequency (Min(s)), the maximum frequency       \n", spacer);
5225                 MrBayesPrint ("%s   (Max(s)), and the standard deviation of frequencies (Stddev(s)) across runs.  \n", spacer);
5226                 MrBayesPrint ("%s   The latter value should approach 0 for all bipartitions as MCMC runs converge.\n", spacer);
5227                 MrBayesPrint ("                                                                                   \n");
5228                 MrBayesPrint ("%s   This is followed by a table summarizing branch lengths, node heights (if a    \n", spacer);
5229                 MrBayesPrint ("%s   clock model was used) and relaxed clock parameters (if a relaxed clock model  \n", spacer);
5230                 MrBayesPrint ("%s   was used). The mean, variance, and 95 %% credible interval are given for each \n", spacer);
5231                 MrBayesPrint ("%s   of these parameters. If several runs are summarized, the potential scale      \n", spacer);
5232                 MrBayesPrint ("%s   reduction factor (PSRF) is also given; it should approach 1 as runs converge. \n", spacer);
5233                 MrBayesPrint ("%s   Node heights will take calibration points into account, if such points were   \n", spacer);
5234                 MrBayesPrint ("%s   used in the analysis.                                                         \n", spacer);
5235                 MrBayesPrint ("%s                                                                                 \n", spacer);
5236                 MrBayesPrint ("%s   Note that Stddev may be unreliable if the partition is not present in all     \n", spacer);
5237                 MrBayesPrint ("%s   runs (the last column indicates the number of runs that sampled the partition \n", spacer);
5238                 MrBayesPrint ("%s   if more than one run is summarized). The PSRF is not calculated at all if     \n", spacer);
5239                 MrBayesPrint ("%s   the partition is not present in all runs.The PSRF is also sensitive to small  \n", spacer);
5240                 MrBayesPrint ("%s   sample sizes and it should only be considered a rough guide to convergence    \n", spacer);
5241                 MrBayesPrint ("%s   since some of the assumptions allowing one to interpret it as a true potential\n", spacer);
5242                 MrBayesPrint ("%s   scale reduction factor are violated in MrBayes.                               \n", spacer);
5243                 MrBayesPrint ("%s                                                                                 \n", spacer);
5244                 MrBayesPrint ("%s   List of taxa in bipartitions:                                                 \n", spacer);
5245                 MrBayesPrint ("                                                                                   \n");
5246                 j = 1;
5247                 for (k=0; k<numTaxa; k++)
5248                     {
5249                     if (taxaInfo[k].isDeleted == NO && sumtParams.absentTaxa[k] == NO)
5250                         {
5251                         MrBayesPrint ("%s   %4d -- %s\n", spacer, j++, taxaNames[k]);
5252                         }
5253                     }
5254                 }
5255             }
5256 
5257         if (sumtParams.numTrees > 1 && (sumtParams.table == YES || sumtParams.summary == YES))
5258             {
5259             MrBayesPrint ("\n\n");
5260             MrBayesPrint ("%s   Results for tree number %d\n", spacer, treeNo+1);
5261             MrBayesPrint ("%s   ==========================\n\n", spacer);
5262             }
5263 
5264         /* First print key to taxon bipartitions */
5265         if (sumtParams.table == YES)
5266             {
5267             MrBayesPrint ("\n");
5268             if (sumtParams.numTrees == 1)
5269                 MrBayesPrint ("%s   Key to taxon bipartitions (saved to file \"%s.parts\"):\n\n", spacer, sumtParams.sumtOutfile);
5270             else
5271                 MrBayesPrint ("%s   Key to taxon bipartitions (saved to file \"%s.tree%d.parts\"):\n\n", spacer,  sumtParams.sumtOutfile, treeNo+1);
5272             }
5273 
5274         /* calculate a couple of numbers that are handy to have */
5275         /*numTreePartsToPrint = 0;
5276         for (i=0; i<numUniqueSplitsFound; i++)
5277             {
5278             if ((MrBFlt)treeParts[i]->totCount/(MrBFlt)sumtParams.numTreesSampled >= sumtParams.minPartFreq)
5279                 numTreePartsToPrint++;
5280             }
5281             */
5282         maxWidthID = (int) (log10 (numTreePartsToPrint)) + 1;
5283         if (maxWidthID < 2)
5284             maxWidthID = 2;
5285         maxNumTaxa = SCREEN_WIDTH - 9;
5286 
5287         for (j=0; j<sumtParams.numTaxa; j+=maxNumTaxa)
5288             {
5289             /* print header to screen and to parts file simultaneously */
5290 
5291             /* first print header to screen */
5292             MrBayesPrint ("%s   ", spacer);
5293             if (j == 0)
5294                 MrBayesPrint ("%*s -- Partition\n", maxWidthID, "ID");
5295             else
5296                 MrBayesPrint ("%*s -- Partition (continued)\n", maxWidthID, "ID");
5297             tableWidth = maxWidthID + 4 + sumtParams.numTaxa;
5298             if (tableWidth > SCREEN_WIDTH)
5299                 tableWidth = SCREEN_WIDTH;
5300             MrBayesPrint ("%s   ", spacer);
5301             for (i=0; i<tableWidth; i++)
5302                 MrBayesPrint ("-");
5303             MrBayesPrint ("\n");
5304 
5305             /* now print header to file */
5306             MrBayesPrintf (fpParts, "ID\tPartition\n");
5307 
5308             /* now, show partitions that were found on screen; print to .parts file simultaneously */
5309             mask = SafeCalloc (sumtParams.BitsLongsNeeded, sizeof(BitsLong));
5310             for (i=0; i<sumtParams.numTaxa; i++)
5311                 SetBit (i, mask);
5312             for (i=0; i<numTreePartsToPrint; i++)
5313                 {
5314                 x = treeParts[i];
5315                 if (IsBitSet(localOutGroup, x->partition) == YES && sumtParams.isRooted == NO)
5316                     FlipBits(x->partition, sumtParams.BitsLongsNeeded, mask);
5317 
5318                 if ((NumBits(x->partition, sumtParams.BitsLongsNeeded) == numLocalTaxa || NumBits(x->partition, sumtParams.BitsLongsNeeded) == 0) && sumtParams.isClock == NO)
5319                     continue;
5320 
5321                 MrBayesPrint ("%s   %*d -- ", spacer, maxWidthID, i);
5322                 if (sumtParams.numTaxa <= maxNumTaxa)
5323                     ShowParts (stdout, x->partition, sumtParams.numTaxa);
5324                 else
5325                     {
5326                     if (sumtParams.numTaxa - j > maxNumTaxa)
5327                         ShowSomeParts (stdout, x->partition, j, maxNumTaxa);
5328                     else
5329                         ShowSomeParts (stdout, x->partition, j, sumtParams.numTaxa - j);
5330                     }
5331                 fflush(stdout);
5332                 MrBayesPrint ("\n");
5333 
5334                 MrBayesPrintf (fpParts, "%d\t", i);
5335                 ShowParts (fpParts, x->partition, sumtParams.numTaxa);
5336                 MrBayesPrintf (fpParts, "\n");
5337                 }
5338             free (mask);
5339 
5340             /* finish screen table */
5341             if (sumtParams.table == YES)
5342                 {
5343                 MrBayesPrint ("%s   ", spacer);
5344                 for (i=0; i<tableWidth; i++)
5345                     {
5346                     MrBayesPrint ("-");
5347                     }
5348                 MrBayesPrint ("\n");
5349                 if (oneUnreliable == YES)
5350                     {
5351                     MrBayesPrint ("%s   * The partition was not found in all runs so the values are unreliable\n\n", spacer);
5352                     }
5353                 else
5354                     {
5355                     MrBayesPrint ("\n");
5356                     }
5357                 }
5358             }
5359 
5360         /* Second, print statitistics for taxon bipartitions */
5361         if (sumtParams.table == YES)
5362             {
5363             if (sumtParams.isRooted == NO)
5364                 MrBayesPrint ("%s   Summary statistics for informative taxon bipartitions\n", spacer);
5365             else
5366                 MrBayesPrint ("%s   Summary statistics for informative taxon bipartitions (clades)\n", spacer);
5367             MrBayesPrint ("%s      (saved to file \"%s.tstat\"):\n\n", spacer, sumtParams.sumtOutfile);
5368             }
5369 
5370         /* calculate a couple of numbers that are handy to have */
5371         /*numTreePartsToPrint = 0;
5372         for (i=0; i<numUniqueSplitsFound; i++)
5373             {
5374             if ((MrBFlt)treeParts[i]->totCount/(MrBFlt)sumtParams.numTreesSampled >= sumtParams.minPartFreq)
5375                 numTreePartsToPrint++;
5376             }
5377             */
5378         maxWidthID = (int) (log10 (numTreePartsToPrint)) + 1;
5379         if (maxWidthID < 2)
5380             maxWidthID = 2;
5381         maxWidthNumberPartitions = (int) (log10 (treeParts[0]->totCount)) + 1;
5382         if (maxWidthNumberPartitions < 4)
5383             maxWidthNumberPartitions = 4;
5384 
5385         /* print header to screen and to parts file simultaneously */
5386         if (sumtParams.table == YES)
5387             {
5388             /* first print header to screen */
5389             MrBayesPrint ("%s   ", spacer);
5390             MrBayesPrint ("%*s   ", maxWidthID, "ID");
5391             tableWidth = maxWidthID + 3;
5392             MrBayesPrint ("#obs");
5393             tableWidth += 4;
5394             for (i=4; i<maxWidthNumberPartitions; i++)
5395                 {
5396                 MrBayesPrint (" ");
5397                 tableWidth++;
5398                 }
5399             MrBayesPrint ("    Probab.");
5400             tableWidth += 11;
5401             if (sumtParams.numRuns > 1)
5402                 {
5403                 MrBayesPrint ("     Sd(s)+ ");
5404                 MrBayesPrint ("     Min(s)      Max(s) ");
5405                 tableWidth += 36;
5406                 MrBayesPrint ("  Nruns ");
5407                 tableWidth += 8;
5408                 }
5409             MrBayesPrint ("\n%s   ", spacer);
5410             for (i=0; i<tableWidth; i++)
5411                 {
5412                 MrBayesPrint ("-");
5413                 }
5414             MrBayesPrint ("\n");
5415 
5416             /* now print header to file */
5417             if (sumtParams.numRuns > 1)
5418                 MrBayesPrintf (fpTstat, "ID\t#obs\tProbability(=s)\tStddev(s)\tMin(s)\tMax(s)\tNruns\n");
5419             else
5420                 MrBayesPrintf (fpTstat, "ID\t#obs\tProbability(=s)\n");
5421             }
5422 
5423         /* now, show informative partitions that were found on screen; print to .tstat file simultaneously */
5424         for (i=0; i<numTreePartsToPrint; i++)
5425             {
5426             x = treeParts[i];
5427 
5428             /* skip uninformative partitions */
5429             if (NumBits(x->partition, sumtParams.BitsLongsNeeded) <= 1 || NumBits(x->partition, sumtParams.BitsLongsNeeded) == sumtParams.numTaxa)
5430                 continue;
5431             if (NumBits(x->partition, sumtParams.BitsLongsNeeded) == sumtParams.numTaxa - 1 && sumtParams.isRooted == NO)
5432                 continue;
5433 
5434             if (sumtParams.table == YES)
5435                 {
5436                 MrBayesPrint ("%s   %*d", spacer, maxWidthID, i);
5437                 fflush(stdout);
5438                 MrBayesPrintf (fpTstat, "%d\t", i);
5439                 }
5440             if (sumtParams.numRuns > 1)
5441                 {
5442                 sum_s = 0.0;
5443                 sumsq_s = 0.0;
5444                 min_s = 1.0;
5445                 max_s = 0.0;
5446                 for (n=j=0; n<sumtParams.numRuns; n++)
5447                     {
5448                     if (x->count[n] > 0)
5449                         j++;
5450                     f = (MrBFlt) x->count[n] / (MrBFlt) sumtParams.numFileTreesSampled[n];
5451                     sum_s += f;
5452                     sumsq_s += f * f;
5453                     if (f < min_s)
5454                         min_s = f;
5455                     if (f  > max_s)
5456                         max_s = f;
5457                     }
5458                 var_s = sumsq_s - sum_s * sum_s / (MrBFlt) sumtParams.numRuns;
5459                 var_s /= (sumtParams.numRuns - 1);
5460                 if (var_s > 0.0)
5461                     stddev_s = sqrt (var_s);
5462                 else
5463                     stddev_s = 0.0;
5464                 if (j == sumtParams.numRuns)
5465                     unreliable = NO;
5466                 else
5467                     {
5468                     unreliable = YES;
5469                     oneUnreliable = YES;
5470                     }
5471                 }
5472             if (sumtParams.table == YES)
5473                 {
5474                 f = (MrBFlt) x->totCount / (MrBFlt) sumtParams.numTreesSampled;
5475                 MrBayesPrint ("  %*d    %1.6lf", maxWidthNumberPartitions, x->totCount, f);
5476                 MrBayesPrintf (fpTstat, "\t%d\t%s", x->totCount, MbPrintNum(f));
5477                 if (sumtParams.numRuns > 1)
5478                     {
5479                     MrBayesPrint ("    %1.6lf    %1.6lf    %1.6lf", stddev_s, min_s, max_s);
5480                     MrBayesPrint ("  %3d", j);
5481                     MrBayesPrintf (fpTstat, "\t%s", MbPrintNum(stddev_s));
5482                     MrBayesPrintf (fpTstat, "\t%s", MbPrintNum(min_s));
5483                     MrBayesPrintf (fpTstat, "\t%s", MbPrintNum(max_s));
5484                     MrBayesPrintf (fpTstat, "\t%d", j);
5485                     }
5486                 MrBayesPrintf (fpTstat, "\n");
5487                 if (unreliable == YES)
5488                     MrBayesPrint (" *\n");
5489                 else
5490                     MrBayesPrint ("\n");
5491                 sumStdDev += stddev_s;
5492                 if (stddev_s > maxStdDev)
5493                     maxStdDev = stddev_s;
5494                 }
5495             }
5496 
5497         /* finish screen table */
5498         if (sumtParams.table == YES)
5499             {
5500             MrBayesPrint ("%s   ", spacer);
5501             for (i=0; i<tableWidth; i++)
5502                 {
5503                 MrBayesPrint ("-");
5504                 }
5505             MrBayesPrint ("\n");
5506             if (sumtParams.numRuns > 1)
5507                 {
5508                 MrBayesPrint ("%s   + Convergence diagnostic (standard deviation of split frequencies)\n", spacer);
5509                 MrBayesPrint ("%s     should approach 0.0 as runs converge.\n\n", spacer);
5510                 }
5511             if (oneUnreliable == YES)
5512                 MrBayesPrint ("%s   * The partition was not found in all runs so the values are unreliable\n", spacer);
5513             }
5514 
5515         /* Third, print statitistics for branch and node parameters */
5516         if (sumtParams.table == YES)
5517             {
5518             MrBayesPrint ("\n");
5519             MrBayesPrint ("%s   Summary statistics for branch and node parameters\n", spacer);
5520             MrBayesPrint ("%s      (saved to file \"%s.vstat\"):\n", spacer, sumtParams.sumtOutfile);
5521             }
5522 
5523         if (sumtParams.table == YES)
5524             {
5525             /* calculate longest header */
5526             longestHeader = 9;  /* length of 'parameter' */
5527             i = (int)(log10(numTreePartsToPrint)) + 3;   /* length of partition specifier including [] */
5528             len = i + (int)(strlen(treeName)) + 2;   /* length of length{m}[n] or height{m}[n] */
5529             if (len > longestHeader)
5530                 longestHeader = len;
5531             for (j=0; j<sumtParams.nBSets; j++)
5532                 {
5533                 len = (int) strlen(sumtParams.tree->bSetName[j]) + 7 + i;
5534                 if (len > longestHeader)
5535                     longestHeader = len;
5536                 }
5537             for (j=0; j<sumtParams.nESets; j++)
5538                 {
5539                 len = (int) strlen(sumtParams.tree->eSetName[j]) + 8 + i;
5540                 if (len > longestHeader)
5541                     longestHeader = len;
5542                 }
5543             if (sumtParams.popSizeSet == YES)
5544                 {
5545                 len = (int) strlen(sumtParams.tree->popSizeSetName) + i;
5546                 if (len > longestHeader)
5547                     longestHeader = len;
5548                 }
5549 
5550             /* print the header rows */
5551             MrBayesPrint ("\n");
5552             if (sumtParams.HPD == NO)
5553                 MrBayesPrint ("%s   %*c                             95%% Cred. Interval\n", spacer, longestHeader, ' ');
5554             else
5555                 MrBayesPrint ("%s   %*c                              95%% HPD Interval\n", spacer, longestHeader, ' ');
5556             MrBayesPrint ("%s   %*c                            --------------------\n", spacer, longestHeader, ' ');
5557 
5558             MrBayesPrint ("%s   Parameter%*c     Mean       Variance     Lower       Upper       Median", spacer, longestHeader-9, ' ');
5559             tableWidth = 68 + longestHeader - 9;
5560             if (sumtParams.HPD == YES)
5561                 MrBayesPrintf (fpVstat, "Parameter\tMean\tVariance\tCredInt_Lower\tCredInt_Upper\tMedian", spacer, longestHeader-9, ' ');
5562             else
5563                 MrBayesPrintf (fpVstat, "Parameter\tMean\tVariance\tHPD_Lower\tHPD_Upper\tMedian", spacer, longestHeader-9, ' ');
5564             if (sumtParams.numRuns > 1)
5565                 {
5566                     MrBayesPrint ("     PSRF+  Nruns");
5567                 tableWidth += 17;
5568                 MrBayesPrintf (fpVstat, "\tPSRF\tNruns");
5569                 }
5570             MrBayesPrint ("\n");
5571             MrBayesPrintf (fpVstat, "\n");
5572 
5573             MrBayesPrint ("%s   ", spacer);
5574             for (j=0; j<tableWidth; j++)
5575                 {
5576                 MrBayesPrint ("-");
5577                 }
5578             MrBayesPrint ("\n");
5579 
5580             /* print lengths */
5581             strcpy (divString, treeName+4);
5582             for (i=1; i<numTreePartsToPrint; i++)
5583                 {
5584                 x = treeParts[i];
5585                 tempStrLength=(int)strlen(tempStr);
5586                 SafeSprintf (&tempStr,&tempStrLength, "length%s[%d]", divString, i);
5587 
5588                 GetSummary (x->length, sumtParams.numRuns, x->count, &theStats, sumtParams.HPD);
5589 
5590                 MrBayesPrint ("%s   %-*s  ", spacer, longestHeader, tempStr);
5591                 MrBayesPrintf (fpVstat, "%s", tempStr);
5592 
5593                 PrintSumtTableLine(sumtParams.numRuns, x->count, &theStats, &numPSRFSamples, &maxPSRF, &sumPSRF);
5594 
5595                 }
5596 
5597             /* print heights */
5598            if (sumtParams.isClock == YES)
5599                 {
5600                 strcpy (divString, treeName+4);
5601                 for (i=0; i<numTreePartsToPrint; i++)
5602                     {
5603                     x = treeParts[i];
5604                     tempStrLength=(int)strlen(tempStr);
5605                     SafeSprintf (&tempStr,&tempStrLength, "height%s[%d]", divString, i);
5606 
5607                     GetSummary (x->height, sumtParams.numRuns, x->count, &theStats, sumtParams.HPD);
5608 
5609                     MrBayesPrint ("%s   %-*s  ", spacer, longestHeader, tempStr);
5610                     MrBayesPrintf (fpVstat, "%s", tempStr);
5611 
5612                     PrintSumtTableLine(sumtParams.numRuns, x->count, &theStats, &numPSRFSamples, &maxPSRF, &sumPSRF);
5613                     }
5614                 }
5615 
5616             /* print ages */
5617             if (sumtParams.isCalibrated == YES)
5618                 {
5619                 strcpy (divString, treeName+4);
5620                 for (i=0; i<numTreePartsToPrint; i++)
5621                     {
5622                     x = treeParts[i];
5623                     tempStrLength=(int)strlen(tempStr);
5624                     SafeSprintf (&tempStr,&tempStrLength, "age%s[%d]", divString, i);
5625 
5626                     GetSummary (x->age, sumtParams.numRuns, x->count, &theStats, sumtParams.HPD);
5627 
5628                     MrBayesPrint ("%s   %-*s  ", spacer, longestHeader, tempStr);
5629                     MrBayesPrintf (fpVstat, "%s", tempStr);
5630 
5631                     PrintSumtTableLine(sumtParams.numRuns, x->count, &theStats, &numPSRFSamples, &maxPSRF, &sumPSRF);
5632                     }
5633                 }
5634 
5635             /* print effective branch lengths */
5636             if (sumtParams.isRelaxed == YES)
5637                 {
5638                 for (i=0; i<sumtParams.nBSets; i++)
5639                     {
5640                     for (j=1; j<numTreePartsToPrint; j++)
5641                         {
5642                         x = treeParts[j];
5643                         tempStrLength=(int)strlen(tempStr);
5644                         SafeSprintf (&tempStr,&tempStrLength, "%s_length[%d]", sumtParams.bSetName[i], j);
5645 
5646                         GetSummary (x->bLen[i], sumtParams.numRuns, x->count, &theStats, sumtParams.HPD);
5647 
5648                         MrBayesPrint ("%s   %-*s  ", spacer, longestHeader, tempStr);
5649                         MrBayesPrintf (fpVstat, "%s", tempStr);
5650 
5651                         PrintSumtTableLine(sumtParams.numRuns, x->count, &theStats, &numPSRFSamples, &maxPSRF, &sumPSRF);
5652                         }
5653                     for (j=1; j<numTreePartsToPrint; j++)
5654                         {
5655                         x = treeParts[j];
5656                         tempStrLength=(int)strlen(tempStr);
5657                         SafeSprintf (&tempStr,&tempStrLength, "%s_rate[%d]", sumtParams.bSetName[i], j);
5658 
5659                         GetSummary (x->bRate[i], sumtParams.numRuns, x->count, &theStats, sumtParams.HPD);
5660 
5661                         MrBayesPrint ("%s   %-*s  ", spacer, longestHeader, tempStr);
5662                         MrBayesPrintf (fpVstat, "%s", tempStr);
5663 
5664                         PrintSumtTableLine(sumtParams.numRuns, x->count, &theStats, &numPSRFSamples, &maxPSRF, &sumPSRF);
5665                         }
5666                     }
5667                 for (i=0; i<sumtParams.nESets; i++)
5668                     {
5669                     for (j=1; j<numTreePartsToPrint; j++)
5670                         {
5671                         x = treeParts[j];
5672                         tempStrLength=(int)strlen(tempStr);
5673                         SafeSprintf (&tempStr,&tempStrLength, "%s_nEvents[%d]", sumtParams.eSetName[i], j);
5674 
5675                         GetIntSummary (x->nEvents[i], sumtParams.numRuns, x->count, &theStats, sumtParams.HPD);
5676 
5677                         MrBayesPrint ("%s   %-*s  ", spacer, longestHeader, tempStr);
5678                         MrBayesPrintf (fpVstat, "%s", tempStr);
5679 
5680                         PrintSumtTableLine(sumtParams.numRuns, x->count, &theStats, &numPSRFSamples, &maxPSRF, &sumPSRF);
5681                         }
5682                     }
5683                 }
5684 
5685             /* print population size sets */
5686             if (sumtParams.popSizeSet == YES)
5687                 {
5688                 for (j=1; j<numTreePartsToPrint; j++)
5689                     {
5690                     x = treeParts[j];
5691                     tempStrLength=(int)strlen(tempStr);
5692                     SafeSprintf (&tempStr,&tempStrLength, "%s[%d]", sumtParams.popSizeSetName, j);
5693 
5694                     GetSummary (x->popSize, sumtParams.numRuns, x->count, &theStats, sumtParams.HPD);
5695 
5696                     MrBayesPrint ("%s   %-*s  ", spacer, longestHeader, tempStr);
5697                     MrBayesPrintf (fpVstat, "%s", tempStr);
5698 
5699                     PrintSumtTableLine(sumtParams.numRuns, x->count, &theStats, &numPSRFSamples, &maxPSRF, &sumPSRF);
5700                     }
5701                 }
5702 
5703             /* finish table */
5704             MrBayesPrint ("%s   ", spacer);
5705             for (j=0; j<tableWidth; j++)
5706                 MrBayesPrint ("-");
5707             MrBayesPrint ("\n");
5708 
5709             if (sumtParams.numRuns > 1)
5710                 {
5711                 MrBayesPrint ("%s   + Convergence diagnostic (PSRF = Potential Scale Reduction Factor; Gelman\n", spacer);
5712                 MrBayesPrint ("%s     and Rubin, 1992) should approach 1.0 as runs converge. NA is reported when\n", spacer);
5713                 MrBayesPrint ("%s     deviation of parameter values within all runs is 0 or when a parameter\n", spacer);
5714                 MrBayesPrint ("%s     value (a branch length, for instance) is not sampled in all runs.\n", spacer);
5715                 }
5716 
5717             if (oneUnreliable == YES)
5718                 {
5719                 MrBayesPrint ("%s   * The partition was not found in all runs so the values are unreliable.\n", spacer);
5720                 }
5721             MrBayesPrint ("\n\n");
5722             }
5723 
5724             /* Print branch parameters to file if requested */
5725             strcpy( divString, treeName+4);
5726             if (sumtParams.saveBrParams == YES && PrintBrParamsToFile (treeParts, numUniqueSplitsFound, treeNo, divString) == ERROR)
5727                 goto errorExit;
5728 
5729             /* Exclude trivial splits when calculating average standard deviation of split frequencies. */
5730             avgStdDev = sumStdDev / (numTreePartsToPrint-sumtParams.numTaxa-1);
5731             avgPSRF   = sumPSRF / numPSRFSamples;
5732 
5733             if (sumtParams.numRuns > 1 && sumtParams.summary == YES)
5734                 {
5735                 MrBayesPrint ("%s   Summary statistics for partitions with frequency >= %1.2lf in at least one run:\n", spacer, sumtParams.minPartFreq);
5736                 MrBayesPrint ("%s       Average standard deviation of split frequencies = %1.6lf\n", spacer, avgStdDev);
5737                 MrBayesPrint ("%s       Maximum standard deviation of split frequencies = %1.6lf\n", spacer, maxStdDev);
5738                 }
5739             if (sumtParams.brlensDef == YES && sumtParams.numRuns > 1 && sumtParams.summary == YES)
5740                 {
5741                 MrBayesPrint ("%s       Average PSRF for parameter values (excluding NA and >10.0) = %1.3lf\n", spacer, avgPSRF);
5742                 if (maxPSRF == 10)
5743                     MrBayesPrint ("%s       Maximum PSRF for parameter values = NA\n", spacer);
5744                 else
5745                     MrBayesPrint ("%s       Maximum PSRF for parameter values = %1.3lf\n", spacer, maxPSRF);
5746                 }
5747             MrBayesPrint ("\n");
5748 
5749         SortPartCtr (treeParts, 0, numUniqueSplitsFound-1); /* We sort again but this time we sort all partitions instead of just first numTreePartsToPrintNow */
5750         /* make the majority rule consensus tree */
5751         if (sumtParams.showConsensus == YES && ConTree (treeParts, numUniqueSplitsFound) == ERROR)
5752             goto errorExit;
5753 
5754         /* get probabilities of individual trees */
5755         if (TreeProb () == ERROR)
5756             goto errorExit;
5757 
5758         /* close files */
5759         SafeFclose (&fpParts);
5760         SafeFclose (&fpTstat);
5761         SafeFclose (&fpVstat);
5762         SafeFclose (&fpCon);
5763         SafeFclose (&fpTrees);
5764 
5765 #   if defined (PRINT_RATEMUL_CPP)
5766         SafeFclose (&rateMultfp);
5767 #   endif
5768 
5769         /* free pointer array to partitions */
5770         free (treeParts);
5771         treeParts = NULL;
5772         FreePartCtr (partCtrRoot);
5773         partCtrRoot = NULL;
5774         FreeTreeCtr (treeCtrRoot);
5775         treeCtrRoot = NULL;
5776         } /* next tree */
5777 
5778     /* free memory and file pointers */
5779     if (s) free(s);
5780     FreeSumtParams();
5781 
5782     /* reset numLocalTaxa and localOutGroup */
5783     ResetTaxonSet();
5784 
5785 #   if defined (MPI_ENABLED)
5786         }
5787 #   endif
5788 
5789     expecting = Expecting(COMMAND);
5790     inSumtCommand = NO;
5791     SAFEFREE (tempStr);
5792 
5793     return (NO_ERROR);
5794 
5795     /* error exit */
5796     errorExit:
5797         /* free sumtParams */
5798         if (s) free(s);
5799         FreeSumtParams();
5800 
5801         /* close files in case they are open*/
5802         SafeFclose (&fp);
5803         SafeFclose (&fpParts);
5804         SafeFclose (&fpTstat);
5805         SafeFclose (&fpVstat);
5806         SafeFclose (&fpCon);
5807         SafeFclose (&fpTrees);
5808 
5809 #   if defined (PRINT_RATEMUL_CPP)
5810         SafeFclose (&rateMultfp);
5811 #   endif
5812 
5813         /* free pointer array to partitions, part and tree counters */
5814         free (treeParts);
5815         FreePartCtr (partCtrRoot);
5816         FreeTreeCtr (treeCtrRoot);
5817         partCtrRoot = NULL;
5818         treeCtrRoot = NULL;
5819 
5820         /* reset taxon set */
5821         ResetTaxonSet();
5822 
5823         expecting = Expecting(COMMAND);
5824         inSumtCommand = NO;
5825         SAFEFREE (tempStr);
5826 
5827         return (ERROR);
5828 }
5829 
5830 
DoSumtParm(char * parmName,char * tkn)5831 int DoSumtParm (char *parmName, char *tkn)
5832 {
5833     int         tempI;
5834     MrBFlt      tempD;
5835     char        tempStr[100];
5836 
5837     if (defMatrix == NO)
5838         {
5839         MrBayesPrint ("%s   A matrix must be specified before sumt can be used\n", spacer);
5840         return (ERROR);
5841         }
5842 
5843     if (expecting == Expecting(PARAMETER))
5844         {
5845         expecting = Expecting(EQUALSIGN);
5846         }
5847     else
5848         {
5849         if (!strcmp(parmName, "Xxxxxxxxxx"))
5850             {
5851             expecting  = Expecting(PARAMETER);
5852             expecting |= Expecting(SEMICOLON);
5853             }
5854         /* set Filename (sumtParams.sumtFileName) ***************************************************/
5855         else if (!strcmp(parmName, "Filename"))
5856             {
5857             if (expecting == Expecting(EQUALSIGN))
5858                 {
5859                 expecting = Expecting(ALPHA);
5860                 readWord = YES;
5861                 }
5862             else if (expecting == Expecting(ALPHA))
5863                 {
5864                 if (strlen(tkn)>99)
5865                     {
5866                     MrBayesPrint ("%s   Maximum allowed length of file name is 99 characters. The given name:\n", spacer);
5867                     MrBayesPrint ("%s      '%s'\n", spacer,tkn);
5868                     MrBayesPrint ("%s   has %d characters.\n", spacer,strlen(tkn));
5869                     return (ERROR);
5870                     }
5871                 strcpy (sumtParams.sumtFileName, tkn);
5872                 strcpy(sumtParams.sumtOutfile, tkn);
5873                 MrBayesPrint ("%s   Setting sumt filename and outputname to %s\n", spacer, sumtParams.sumtFileName);
5874                 expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
5875                 }
5876             else
5877                 return (ERROR);
5878             }
5879         /* set Relburnin (chainParams.relativeBurnin) ********************************************************/
5880         else if (!strcmp(parmName, "Relburnin"))
5881             {
5882             if (expecting == Expecting(EQUALSIGN))
5883                 expecting = Expecting(ALPHA);
5884             else if (expecting == Expecting(ALPHA))
5885                 {
5886                 if (IsArgValid(tkn, tempStr) == NO_ERROR)
5887                     {
5888                     if (!strcmp(tempStr, "Yes"))
5889                         chainParams.relativeBurnin = YES;
5890                     else
5891                         chainParams.relativeBurnin = NO;
5892                     }
5893                 else
5894                     {
5895                     MrBayesPrint ("%s   Invalid argument for Relburnin\n", spacer);
5896                     return (ERROR);
5897                     }
5898                 if (chainParams.relativeBurnin == YES)
5899                     MrBayesPrint ("%s   Using relative burnin (a fraction of samples discarded).\n", spacer);
5900                 else
5901                     MrBayesPrint ("%s   Using absolute burnin (a fixed number of samples discarded).\n", spacer);
5902                 expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
5903                 }
5904             else
5905                 {
5906                 return (ERROR);
5907                 }
5908             }
5909         /* set Burnin (chainParams.chainBurnIn) ***********************************************************/
5910         else if (!strcmp(parmName, "Burnin"))
5911             {
5912             if (expecting == Expecting(EQUALSIGN))
5913                 expecting = Expecting(NUMBER);
5914             else if (expecting == Expecting(NUMBER))
5915                 {
5916                 sscanf (tkn, "%d", &tempI);
5917                 chainParams.chainBurnIn = tempI;
5918                 MrBayesPrint ("%s   Setting urn-in to %d\n", spacer, chainParams.chainBurnIn);
5919                 expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
5920                 }
5921             else
5922                 {
5923                 return (ERROR);
5924                 }
5925             }
5926         /* set Burninfrac (chainParams.burninFraction) ************************************************************/
5927         else if (!strcmp(parmName, "Burninfrac"))
5928             {
5929             if (expecting == Expecting(EQUALSIGN))
5930                 expecting = Expecting(NUMBER);
5931             else if (expecting == Expecting(NUMBER))
5932                 {
5933                 sscanf (tkn, "%lf", &tempD);
5934                 if (tempD < 0.01)
5935                     {
5936                     MrBayesPrint ("%s   Burnin fraction too low (< 0.01)\n", spacer);
5937                     return (ERROR);
5938                     }
5939                 if (tempD > 0.50)
5940                     {
5941                     MrBayesPrint ("%s   Burnin fraction too high (> 0.50)\n", spacer);
5942                     return (ERROR);
5943                     }
5944                 chainParams.burninFraction = tempD;
5945                 MrBayesPrint ("%s   Setting burnin fraction to %.2f\n", spacer, chainParams.burninFraction);
5946                 expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
5947                 }
5948             else
5949                 {
5950                 return (ERROR);
5951                 }
5952             }
5953         /* set Nruns (sumtParams.numRuns) *******************************************************/
5954         else if (!strcmp(parmName, "Nruns"))
5955             {
5956             if (expecting == Expecting(EQUALSIGN))
5957                 expecting = Expecting(NUMBER);
5958             else if (expecting == Expecting(NUMBER))
5959                 {
5960                 sscanf (tkn, "%d", &tempI);
5961                 if (tempI < 1)
5962                     {
5963                     MrBayesPrint ("%s   Nruns must be at least 1\n", spacer);
5964                     return (ERROR);
5965                     }
5966                 else
5967                     {
5968                     sumtParams.numRuns = tempI;
5969                     MrBayesPrint ("%s   Setting sumt nruns to %d\n", spacer, sumtParams.numRuns);
5970                     expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
5971                     }
5972                 }
5973             else
5974                 return (ERROR);
5975             }
5976         /* set Ntrees (sumtParams.numTrees) *******************************************************/
5977         else if (!strcmp(parmName, "Ntrees"))
5978             {
5979             if (expecting == Expecting(EQUALSIGN))
5980                 expecting = Expecting(NUMBER);
5981             else if (expecting == Expecting(NUMBER))
5982                 {
5983                 sscanf (tkn, "%d", &tempI);
5984                 if (tempI < 1)
5985                     {
5986                     MrBayesPrint ("%s   Ntrees must be at least 1\n", spacer);
5987                     return (ERROR);
5988                     }
5989                 else
5990                     {
5991                     sumtParams.numTrees = tempI;
5992                     MrBayesPrint ("%s   Setting sumt ntrees to %d\n", spacer, sumtParams.numTrees);
5993                     expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
5994                     }
5995                 }
5996             else
5997                 return (ERROR);
5998             }
5999         /* set Contype (sumtParams.sumtConType) *****************************************************/
6000         else if (!strcmp(parmName, "Contype"))
6001             {
6002             if (expecting == Expecting(EQUALSIGN))
6003                 expecting = Expecting(ALPHA);
6004             else if (expecting == Expecting(ALPHA))
6005                 {
6006                 if (IsArgValid(tkn, tempStr) == NO_ERROR)
6007                     {
6008                     strcpy (sumtParams.sumtConType, tempStr);
6009                     MrBayesPrint ("%s   Setting sumt contype to %s\n", spacer, sumtParams.sumtConType);
6010                     }
6011                 expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
6012                 }
6013             else
6014                 return (ERROR);
6015             }
6016         /* set Conformat (sumtParams.consensusFormat) *****************************************************/
6017         else if (!strcmp(parmName, "Conformat"))
6018             {
6019             if (expecting == Expecting(EQUALSIGN))
6020                 expecting = Expecting(ALPHA);
6021             else if (expecting == Expecting(ALPHA))
6022                 {
6023                 if (IsArgValid(tkn, tempStr) == NO_ERROR)
6024                     {
6025                     if (!strcmp(tempStr,"Figtree"))
6026                         {
6027                         MrBayesPrint ("%s   Setting sumt conformat to Figtree\n", spacer);
6028                         sumtParams.consensusFormat = FIGTREE;
6029                         }
6030                     else
6031                         {
6032                         MrBayesPrint ("%s   Setting sumt conformat to Simple\n", spacer);
6033                         sumtParams.consensusFormat = SIMPLE;
6034                         }
6035                     }
6036                 else
6037                     {
6038                     MrBayesPrint ("%s   Invalid argument for calctreeprobs\n", spacer);
6039                     return (ERROR);
6040                     }
6041                 expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
6042                 }
6043             else
6044                 return (ERROR);
6045             }
6046         /* set Calctreeprobs (sumtParams.calcTreeprobs) *********************************************/
6047         else if (!strcmp(parmName, "Calctreeprobs"))
6048             {
6049             if (expecting == Expecting(EQUALSIGN))
6050                 expecting = Expecting(ALPHA);
6051             else if (expecting == Expecting(ALPHA))
6052                 {
6053                 if (IsArgValid(tkn, tempStr) == NO_ERROR)
6054                     {
6055                     if (!strcmp(tempStr, "Yes"))
6056                         sumtParams.calcTreeprobs = YES;
6057                     else
6058                         sumtParams.calcTreeprobs = NO;
6059                     }
6060                 else
6061                     {
6062                     MrBayesPrint ("%s   Invalid argument for calctreeprobs\n", spacer);
6063                     return (ERROR);
6064                     }
6065                 if (sumtParams.calcTreeprobs == YES)
6066                     MrBayesPrint ("%s   Setting calctreeprobs to yes\n", spacer);
6067                 else
6068                     MrBayesPrint ("%s   Setting calctreeprobs to no\n", spacer);
6069                 expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
6070                 }
6071             else
6072                 return (ERROR);
6073             }
6074         /* set Showtreeprobs (sumtParams.showSumtTrees) *********************************************/
6075         else if (!strcmp(parmName, "Showtreeprobs"))
6076             {
6077             if (expecting == Expecting(EQUALSIGN))
6078                 expecting = Expecting(ALPHA);
6079             else if (expecting == Expecting(ALPHA))
6080                 {
6081                 if (IsArgValid(tkn, tempStr) == NO_ERROR)
6082                     {
6083                     if (!strcmp(tempStr, "Yes"))
6084                         sumtParams.showSumtTrees = YES;
6085                     else
6086                         sumtParams.showSumtTrees = NO;
6087                     }
6088                 else
6089                     {
6090                     MrBayesPrint ("%s   Invalid argument for showtreeprobs\n", spacer);
6091                     return (ERROR);
6092                     }
6093                 if (sumtParams.showSumtTrees == YES)
6094                     MrBayesPrint ("%s   Setting showtreeprobs to yes\n", spacer);
6095                 else
6096                     MrBayesPrint ("%s   Setting showtreeprobs to no\n", spacer);
6097                 expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
6098                 }
6099             else
6100                 return (ERROR);
6101             }
6102         /* set Hpd (sumpParams.HPD) ********************************************************/
6103         else if (!strcmp(parmName, "Hpd"))
6104             {
6105             if (expecting == Expecting(EQUALSIGN))
6106                 expecting = Expecting(ALPHA);
6107             else if (expecting == Expecting(ALPHA))
6108                 {
6109                 if (IsArgValid(tkn, tempStr) == NO_ERROR)
6110                     {
6111                     if (!strcmp(tempStr, "Yes"))
6112                         sumtParams.HPD = YES;
6113                     else
6114                         sumtParams.HPD = NO;
6115                     }
6116                 else
6117                     {
6118                     MrBayesPrint ("%s   Invalid argument for Hpd\n", spacer);
6119                     return (ERROR);
6120                     }
6121                 if (sumtParams.HPD == YES)
6122                     MrBayesPrint ("%s   Reporting 95 %% region of Highest Posterior Density (HPD).\n", spacer);
6123                 else
6124                     MrBayesPrint ("%s   Reporting median interval containing 95 %% of values.\n", spacer);
6125                 expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
6126                 }
6127             else
6128                 return (ERROR);
6129             }
6130         /* set Savebrparams (sumtParams.saveBrParams) *********************************************/
6131         else if (!strcmp(parmName, "Savebrparams"))
6132             {
6133             if (expecting == Expecting(EQUALSIGN))
6134                 expecting = Expecting(ALPHA);
6135             else if (expecting == Expecting(ALPHA))
6136                 {
6137                 if (IsArgValid(tkn, tempStr) == NO_ERROR)
6138                     {
6139                     if (!strcmp(tempStr, "Yes"))
6140                         sumtParams.saveBrParams = YES;
6141                     else
6142                         sumtParams.saveBrParams = NO;
6143                     }
6144                 else
6145                     {
6146                     MrBayesPrint ("%s   Invalid argument for savebrparams\n", spacer);
6147                     return (ERROR);
6148                     }
6149                 if (sumtParams.saveBrParams == YES)
6150                     MrBayesPrint ("%s   Setting savebrparams to yes\n", spacer);
6151                 else
6152                     MrBayesPrint ("%s   Setting savebrparams to no\n", spacer);
6153                 expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
6154                 }
6155             else
6156                 return (ERROR);
6157             }
6158         /* set Minbrparamfreq (sumtParams.minBrParamFreq) *******************************************************/
6159         else if (!strcmp(parmName, "Minbrparamfreq"))
6160             {
6161             if (expecting == Expecting(EQUALSIGN))
6162                 expecting = Expecting(NUMBER);
6163             else if (expecting == Expecting(NUMBER))
6164                 {
6165                 sscanf (tkn, "%lf", &tempD);
6166                 sumtParams.minBrParamFreq = tempD;
6167                 MrBayesPrint ("%s   Printing branch parameters to file for partitions with probability >= %lf\n", spacer, sumtParams.minBrParamFreq);
6168                 expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
6169                 }
6170             else
6171                 return (ERROR);
6172             }
6173         /* set Ordertaxa (sumtParams.orderTaxa) *********************************************/
6174         else if (!strcmp(parmName, "Ordertaxa"))
6175             {
6176             if (expecting == Expecting(EQUALSIGN))
6177                 expecting = Expecting(ALPHA);
6178             else if (expecting == Expecting(ALPHA))
6179                 {
6180                 if (IsArgValid(tkn, tempStr) == NO_ERROR)
6181                     {
6182                     if (!strcmp(tempStr, "Yes"))
6183                         sumtParams.orderTaxa = YES;
6184                     else
6185                         sumtParams.orderTaxa = NO;
6186                     }
6187                 else
6188                     {
6189                     MrBayesPrint ("%s   Invalid argument for ordertaxa\n", spacer);
6190                     return (ERROR);
6191                     }
6192                 if (sumtParams.orderTaxa == YES)
6193                     MrBayesPrint ("%s   Setting ordertaxa to yes\n", spacer);
6194                 else
6195                     MrBayesPrint ("%s   Setting ordertaxa to no\n", spacer);
6196                 expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
6197                 }
6198             else
6199                 return (ERROR);
6200             }
6201         /* set Outputname (sumtParams.sumtOutfile) *******************************************************/
6202         else if (!strcmp(parmName, "Outputname"))
6203             {
6204             if (expecting == Expecting(EQUALSIGN))
6205                 {
6206                 expecting = Expecting(ALPHA);
6207                 readWord = YES;
6208                 }
6209             else if (expecting == Expecting(ALPHA))
6210                 {
6211                 sscanf (tkn, "%s", tempStr);
6212                 strcpy (sumtParams.sumtOutfile, tempStr);
6213                 MrBayesPrint ("%s   Setting sumt output file name to \"%s\"\n", spacer, sumtParams.sumtOutfile);
6214                 expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
6215                 }
6216             else
6217                 return (ERROR);
6218             }
6219         /* set Table (sumtParams.table) ********************************************************/
6220         else if (!strcmp(parmName, "Table"))
6221             {
6222             if (expecting == Expecting(EQUALSIGN))
6223                 expecting = Expecting(ALPHA);
6224             else if (expecting == Expecting(ALPHA))
6225                 {
6226                 if (IsArgValid(tkn, tempStr) == NO_ERROR)
6227                     {
6228                     if (!strcmp(tempStr, "Yes"))
6229                         sumtParams.table = YES;
6230                     else
6231                         sumtParams.table = NO;
6232                     }
6233                 else
6234                     {
6235                     MrBayesPrint ("%s   Invalid argument for Table (valid arguments are 'yes' and 'no')\n", spacer);
6236                     return (ERROR);
6237                     }
6238                 if (sumtParams.table == YES)
6239                     MrBayesPrint ("%s   Setting sumt to compute table of partition frequencies\n", spacer);
6240                 else
6241                     MrBayesPrint ("%s   Setting sumt not to compute table of partition frequencies\n", spacer);
6242                 expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
6243                 }
6244             else
6245                 return (ERROR);
6246             }
6247         /* set Summary (sumtParams.summary) ********************************************************/
6248         else if (!strcmp(parmName, "Summary"))
6249             {
6250             if (expecting == Expecting(EQUALSIGN))
6251                 expecting = Expecting(ALPHA);
6252             else if (expecting == Expecting(ALPHA))
6253                 {
6254                 if (IsArgValid(tkn, tempStr) == NO_ERROR)
6255                     {
6256                     if (!strcmp(tempStr, "Yes"))
6257                         sumtParams.summary = YES;
6258                     else
6259                         sumtParams.summary = NO;
6260                     }
6261                 else
6262                     {
6263                     MrBayesPrint ("%s   Invalid argument for 'Summary' (valid arguments are 'yes' and 'no')\n", spacer);
6264                     return (ERROR);
6265                     }
6266                 if (sumtParams.summary == YES)
6267                     MrBayesPrint ("%s   Setting sumt to summary statistics\n", spacer);
6268                 else
6269                     MrBayesPrint ("%s   Setting sumt not to compute summary statistics\n", spacer);
6270                 expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
6271                 }
6272             else
6273                 return (ERROR);
6274             }
6275         /* set Consensus (sumtParams.showConsensus) ********************************************************/
6276         else if (!strcmp(parmName, "Consensus"))
6277             {
6278             if (expecting == Expecting(EQUALSIGN))
6279                 expecting = Expecting(ALPHA);
6280             else if (expecting == Expecting(ALPHA))
6281                 {
6282                 if (IsArgValid(tkn, tempStr) == NO_ERROR)
6283                     {
6284                     if (!strcmp(tempStr, "Yes"))
6285                         sumtParams.showConsensus = YES;
6286                     else
6287                         sumtParams.showConsensus = NO;
6288                     }
6289                 else
6290                     {
6291                     MrBayesPrint ("%s   Invalid argument for Consensus (valid arguments are 'yes' and 'no')\n", spacer);
6292                     return (ERROR);
6293                     }
6294                 if (sumtParams.showConsensus == YES)
6295                     MrBayesPrint ("%s   Setting sumt to show consensus trees\n", spacer);
6296                 else
6297                     MrBayesPrint ("%s   Setting sumt not to show consensus trees\n", spacer);
6298                 expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
6299                 }
6300             else
6301                 return (ERROR);
6302             }
6303         /* set Minpartfreq (sumtParams.minPartFreq) *******************************************************/
6304         else if (!strcmp(parmName, "Minpartfreq"))
6305             {
6306             if (expecting == Expecting(EQUALSIGN))
6307                 expecting = Expecting(NUMBER);
6308             else if (expecting == Expecting(NUMBER))
6309                 {
6310                 sscanf (tkn, "%lf", &tempD);
6311                 sumtParams.minPartFreq = tempD;
6312                 MrBayesPrint ("%s   Including partitions with probability greater than or equal to %lf in summary statistics\n", spacer, sumtParams.minPartFreq);
6313                 expecting = Expecting(PARAMETER) | Expecting(SEMICOLON);
6314                 }
6315             else
6316                 return (ERROR);
6317             }
6318         else
6319             return (ERROR);
6320         }
6321 
6322     return (NO_ERROR);
6323 }
6324 
6325 
DoSumtTree(void)6326 int DoSumtTree (void)
6327 {
6328     int             i, j, z, printEvery, nAstPerPrint, burnin;
6329     MrBFlt          x, y;
6330     PolyTree        *t;
6331     PolyNode        *p;
6332 
6333 #   if defined (PRINT_RATEMUL_CPP)
6334     /* get depths if relevant */
6335     if (sumtParams.tree->isClock)
6336         GetPolyDepths (sumtParams.tree);
6337     if (rateMultfp !=NULL && sumtParams.tree->root !=NULL)
6338         DELETE_ME_dump_depth(sumtParams.tree->root);
6339 #   endif
6340 
6341     /* increment number of trees read in */
6342     sumtParams.numFileTrees[sumtParams.runId]++;
6343     sumtParams.numTreesEncountered++;
6344 
6345     /*  update status bar */
6346     if (sumtParams.numTreesInLastBlock * sumtParams.numRuns < 80)
6347         {
6348         printEvery = 1;
6349         nAstPerPrint = 80 / (sumtParams.numTreesInLastBlock * sumtParams.numRuns);
6350         if (sumtParams.numTreesEncountered % printEvery == 0)
6351             {
6352             for (i=0; i<nAstPerPrint; i++)
6353                 {
6354                 MrBayesPrint ("*");
6355                 numAsterices++;
6356                 }
6357             }
6358         }
6359     else
6360         {
6361         x = (MrBFlt)(sumtParams.numTreesInLastBlock * sumtParams.numRuns) / (MrBFlt) (80);
6362         y = (MrBFlt)(sumtParams.numFileTrees[sumtParams.runId] + sumtParams.numTreesInLastBlock * sumtParams.runId) / x;
6363         z = (int)y;
6364         if (numAsterices < z)
6365             {
6366             MrBayesPrint ("*");
6367             numAsterices++;
6368             }
6369         }
6370 
6371     /* get burnin */
6372     if (inComparetreeCommand == YES)
6373         burnin = comptreeParams.burnin;
6374     else
6375         burnin = sumtParams.burnin;
6376 
6377     if (sumtParams.numFileTrees[sumtParams.runId] > burnin)
6378         {
6379         /* increment the number of trees sampled */
6380         sumtParams.numFileTreesSampled[sumtParams.runId]++;
6381         sumtParams.numTreesSampled++;
6382 
6383         /* get the tree we just read in */
6384         t = sumtParams.tree;
6385 
6386         /* move calculation root for nonrooted trees if necessary */
6387         MovePolyCalculationRoot (t, localOutGroup);
6388 
6389         /* check taxon set and outgroup */
6390         if (sumtParams.runId == 0 && sumtParams.numFileTreesSampled[0] == 1)
6391             {
6392             if (isTranslateDef == YES && isTranslateDiff == YES)
6393                 {
6394                 /* we are using a translate block with different taxa set (not all taxa) */
6395                 if (t->nNodes - t->nIntNodes != numTranslates)
6396                     {
6397                     MrBayesPrint ("%s   ERROR: Expected %d taxa; found %d taxa\n", spacer, numTranslates, sumtParams.numTaxa);
6398                     return (ERROR);
6399                     }
6400                 /* figure out which taxa are absent */
6401                 for (i=0; i<numTaxa; i++)
6402                     sumtParams.absentTaxa[i] = YES;
6403                 for (i=0; i<numTranslates; i++)
6404                     {
6405                     for (j=0; j<numTaxa; j++)
6406                         {
6407                         if (strcmp(transFrom[i], taxaNames[j]) == 0)
6408                             break;
6409                         }
6410                     if (j < numTaxa)
6411                         sumtParams.absentTaxa[j] = NO;
6412                     }
6413                 /* find local outgroup */
6414                 for (i=0; i<numTranslates; i++)
6415                     if (strcmp(transFrom[i], taxaNames[outGroupNum]) == 0)
6416                         break;
6417                 if (i == numTranslates)
6418                     localOutGroup = 0;      /* no previous outgroup assignment is valid */
6419                 else
6420                     localOutGroup = i;
6421                 }
6422             else
6423                 {
6424                 /* we are using the current taxa set */
6425                 for (i=0; i<numTaxa; i++)
6426                     sumtParams.absentTaxa[i] = YES;
6427                 for (i=0; i<t->nNodes; i++)
6428                     {
6429                     p = t->allDownPass[i];
6430                     if (p->left == NULL)
6431                         sumtParams.absentTaxa[p->index] = NO;
6432                     }
6433                 localOutGroup = 0;
6434                 for (i=j=0; i<numTaxa; i++)
6435                     {
6436                     if (sumtParams.absentTaxa[i] == NO && taxaInfo[i].isDeleted == NO)
6437                         {
6438                         if (i == outGroupNum)
6439                             localOutGroup = j;
6440                         j++;
6441                         }
6442                     }
6443                 }
6444 
6445             /* now we can safely prune the tree based on taxaInfo[].isDeleted */
6446             /* note that PrunePolyTree relies on labels to recognize tips */
6447             PrunePolyTree(t);
6448 
6449             /* reset tip and int node indices in case some taxa deleted */
6450             ResetTipIndices (t);
6451             ResetIntNodeIndices(t);
6452 
6453             /* set basic parameters */
6454             sumtParams.numTaxa = t->nNodes - t->nIntNodes;
6455             numLocalTaxa = sumtParams.numTaxa;
6456             sumtParams.BitsLongsNeeded = ((numLocalTaxa-1) / nBitsInALong) + 1;
6457             if (t->isRooted == YES)
6458                 sumtParams.orderLen = numLocalTaxa - 2;
6459             else
6460                 sumtParams.orderLen = numLocalTaxa - 3;
6461             }
6462         else
6463             {
6464             /* check whether we have some taxa that should not be in the tree */
6465             for (i=0; i<t->nNodes; i++)
6466                 {
6467                 p = t->allDownPass[i];
6468                 if (p->left == NULL && taxaInfo[p->index].isDeleted == NO && sumtParams.absentTaxa[p->index] == YES)
6469                     {
6470                     MrBayesPrint ("%s   Taxon %d should not be in sampled tree\n", spacer, p->index + 1);
6471                     return (ERROR);
6472                     }
6473                 }
6474 
6475             /* now we can safely prune the tree based on taxaInfo[].isDeleted */
6476             PrunePolyTree (t);
6477 
6478             /* reset tip and int node indices in case some taxa deleted */
6479             ResetTipIndices (t);
6480             ResetIntNodeIndices(t);
6481 
6482             /* check that all taxa are included */
6483             if (t->nNodes - t->nIntNodes != sumtParams.numTaxa)
6484                 {
6485                 MrBayesPrint ("%s   Expecting %d taxa but tree '%s' in file '%s' has %d taxa\n",
6486                     spacer, sumtParams.numTaxa, t->name, sumtParams.curFileName, t->nNodes-t->nIntNodes);
6487                 return ERROR;
6488                 }
6489             }
6490 
6491         if (sumtParams.runId == 0 && sumtParams.numFileTreesSampled[0] == 1)
6492             {
6493             /* harvest labels (can only be done safely after pruning) */
6494             for (i=0; i<sumtParams.numTaxa; i++)
6495                 {
6496                 for (j=0; j<t->nNodes; j++)
6497                     {
6498                     p = t->allDownPass[j];
6499                     if (p->index == i) {
6500                          if (strlen(p->label)>99)
6501                             {
6502                             MrBayesPrint ("%s   Taxon name %s is too long. Maximun 99 characters is allowed.\n", spacer, p->label);
6503                             return (ERROR);
6504                             }
6505                         AddString(&sumtParams.taxaNames, i, p->label);
6506                         }
6507                     }
6508                 }
6509             }
6510 
6511         /* check that tree agrees with template */
6512         if (sumtParams.numTreesSampled == 1)
6513             {
6514             sumtParams.brlensDef = t->brlensDef;
6515             sumtParams.isRooted = t->isRooted;
6516             sumtParams.isClock = t->isClock;
6517             sumtParams.isCalibrated = t->isCalibrated;
6518             sumtParams.isRelaxed = t->isRelaxed;
6519             sumtParams.nBSets = 0;
6520             sumtParams.nESets = 0;
6521             for (i=0; i<t->nBSets; i++)
6522                 AddString(&sumtParams.bSetName,sumtParams.nBSets++,t->bSetName[i]);
6523             for (i=0; i<t->nESets; i++)
6524                 AddString(&sumtParams.eSetName,sumtParams.nESets++,t->eSetName[i]);
6525             if (t->popSizeSet == YES)
6526                 {
6527                 sumtParams.popSizeSet = YES;
6528                 sumtParams.popSizeSetName = (char *) SafeCalloc (strlen(t->popSizeSetName)+1, sizeof(char));
6529                 strcpy(sumtParams.popSizeSetName, t->popSizeSetName);
6530                 }
6531             else
6532                 sumtParams.popSizeSet = NO;
6533             }
6534         else /* if (sumtParams.numTreesSampled > 1) */
6535             {
6536             if (sumtParams.brlensDef != t->brlensDef)
6537                 {
6538                 MrBayesPrint ("%s   Trees with and without branch lengths mixed\n", spacer);
6539                 return ERROR;
6540                 }
6541             if (sumtParams.isRooted != t->isRooted)
6542                 {
6543                 if (sumtParams.isRooted == YES)
6544                     MrBayesPrint ("%s   Expected rooted tree but tree '%s' in file '%s' is not rooted\n",
6545                         spacer, t->name, sumtParams.curFileName);
6546                 else if (sumtParams.isRooted == NO)
6547                     MrBayesPrint ("%s   Expected unrooted tree but tree '%s' in file '%s' is rooted\n",
6548                         spacer, t->name, sumtParams.curFileName);
6549                 return ERROR;
6550                 }
6551             if (sumtParams.isClock != t->isClock)
6552                 {
6553                 if (sumtParams.isClock == YES)
6554                     MrBayesPrint ("%s   Expected clock tree but tree '%s' in file '%s' is not clock\n",
6555                         spacer, t->name, sumtParams.curFileName);
6556                 else if (sumtParams.isClock == NO)
6557                     MrBayesPrint ("%s   Expected nonclock tree but tree '%s' in file '%s' is clock\n",
6558                         spacer, t->name, sumtParams.curFileName);
6559                 return ERROR;
6560                 }
6561             if (sumtParams.isCalibrated != t->isCalibrated)
6562                 {
6563                 if (sumtParams.isCalibrated == YES)
6564                     MrBayesPrint ("%s   Expected calibrated tree but tree '%s' in file '%s' is not calibrated\n",
6565                         spacer, t->name, sumtParams.curFileName);
6566                 else if (sumtParams.isCalibrated == NO)
6567                     MrBayesPrint ("%s   Expected noncalibrated tree but tree '%s' in file '%s' is calibrated\n",
6568                         spacer, t->name, sumtParams.curFileName);
6569                 return ERROR;
6570                 }
6571             if (inComparetreeCommand == NO && sumtParams.isRelaxed != t->isRelaxed)
6572                 {
6573                 if (sumtParams.isRelaxed == YES)
6574                     MrBayesPrint ("%s   Expected relaxed clock tree but tree '%s' in file '%s' is not relaxed\n",
6575                         spacer, t->name, sumtParams.curFileName);
6576                 else if (sumtParams.isRelaxed == NO)
6577                     MrBayesPrint ("%s   Expected unrooted tree but tree '%s' in file '%s' is rooted\n",
6578                         spacer, t->name, sumtParams.curFileName);
6579                 return ERROR;
6580                 }
6581             if (inComparetreeCommand == NO && (sumtParams.nESets != t->nESets || sumtParams.nBSets != t->nBSets))
6582                 {
6583                 MrBayesPrint ("%s   Tree '%s' in file '%s' does not have the expected relaxed clock parameters\n",
6584                         spacer, t->name, sumtParams.curFileName);
6585                 return ERROR;
6586                 }
6587             }
6588 
6589         /* set partitions for tree */
6590         ResetPolyTreePartitions(t);
6591 
6592         /* get depths if relevant */
6593         if (t->isClock)
6594             GetPolyDepths (t);
6595 
6596         /* get ages if relevant */
6597         if (t->isCalibrated)
6598             GetPolyAges (t);
6599 
6600         /* add partitions to counters */
6601         for (i=0; i<t->nNodes; i++)
6602             {
6603             p = t->allDownPass[i];
6604             partCtrRoot = AddSumtPartition (partCtrRoot, t, p, sumtParams.runId);
6605             }
6606 
6607         /* add the tree to relevant tree list */
6608         if (inSumtCommand == YES)
6609             {
6610             if (t->isRooted == YES)
6611                 StoreRPolyTopology (t, sumtParams.order);
6612             else /* if (sumtParams.isRooted == NO) */
6613                 StoreUPolyTopology (t, sumtParams.order);
6614             treeCtrRoot = AddSumtTree (treeCtrRoot, sumtParams.order);
6615             }
6616         else
6617             {
6618             i = sumtParams.numFileTreesSampled[sumtParams.runId] - 1;
6619             if (StoreSumtTree (packedTreeList[sumtParams.runId], i, t) == ERROR)
6620                 return (ERROR);
6621             }
6622 
6623         /* Display the tree nodes. */
6624 #       if 0
6625         ShowPolyNodes(t);
6626 #       endif
6627         }
6628 
6629     return (NO_ERROR);
6630 }
6631 
6632 
ExamineSumtFile(char * fileName,SumtFileInfo * sumtFileInfo,char * treeName,int * brlensDef)6633 int ExamineSumtFile (char *fileName, SumtFileInfo *sumtFileInfo, char *treeName, int *brlensDef)
6634 {
6635     int     i, foundBegin, lineTerm, inTreeBlock, blockErrors, inSumtComment, lineNum, numTreesInBlock,
6636             tokenType;
6637     char    sumtToken[100], *s, *sumtTokenP;
6638     FILE    *fp;
6639 
6640     /* open binary file */
6641     if ((fp = OpenBinaryFileR(fileName)) == NULL)
6642         return ERROR;
6643 
6644     /* find out what type of line termination is used for file 1 */
6645     lineTerm = LineTermType (fp);
6646     if (lineTerm != LINETERM_MAC && lineTerm != LINETERM_DOS && lineTerm != LINETERM_UNIX)
6647         {
6648         MrBayesPrint ("%s   Unknown line termination for file  \"%s\"\n", spacer, fileName);
6649         return ERROR;
6650         }
6651 
6652     /* find length of longest line in either file */
6653     sumtFileInfo->longestLineLength = LongestLine (fp);
6654     sumtFileInfo->longestLineLength += 10;
6655 
6656     /* allocate a string long enough to hold a line */
6657     s = (char *)SafeMalloc((size_t)(sumtFileInfo->longestLineLength) * sizeof(char));
6658     if (!s)
6659         {
6660         MrBayesPrint ("%s   Problem allocating string for examining file \"%s\"\n", spacer, fileName);
6661         return (ERROR);
6662         }
6663 
6664     /* close binary file */
6665     SafeFclose (&fp);
6666 
6667     foundBegin = inTreeBlock = blockErrors = inSumtComment = NO;
6668     lineNum = numTreesInBlock = 0;
6669     sumtFileInfo->numTreeBlocks = 0;
6670     sumtFileInfo->lastTreeBlockBegin = 0;
6671     sumtFileInfo->lastTreeBlockEnd = 0;
6672     sumtFileInfo->numTreesInLastBlock = 0;
6673 
6674     /* open text file */
6675     if ((fp = OpenTextFileR(fileName))==NULL)
6676         {
6677         MrBayesPrint ("%s   Could not read file \"%s\" in text mode \n", spacer, fileName);
6678         return (ERROR);
6679         }
6680 
6681     /* read file */
6682     while (fgets (s, sumtFileInfo->longestLineLength-2, fp) != NULL)
6683         {
6684         sumtTokenP = &s[0];
6685         do
6686             {
6687             if (GetToken (sumtToken, &tokenType, &sumtTokenP))
6688                 goto errorExit;
6689             if (IsSame("[", sumtToken) == SAME)
6690                 inSumtComment = YES;
6691             if (IsSame("]", sumtToken) == SAME)
6692                 inSumtComment = NO;
6693 
6694             if (inSumtComment == YES)
6695                 {
6696                 if (IsSame ("Param", sumtToken) == SAME)
6697                     {
6698                     /* extract the tree name */
6699                     if (GetToken (sumtToken, &tokenType, &sumtTokenP))   /* get the colon */
6700                         goto errorExit;
6701                     if (GetToken (sumtToken, &tokenType, &sumtTokenP))   /* get the tree name */
6702                         goto errorExit;
6703                     strcpy (treeName, sumtToken);
6704                     if (GetToken (sumtToken, &tokenType, &sumtTokenP))
6705                         goto errorExit;
6706                     while (IsSame("]", sumtToken) != SAME)
6707                         {
6708                         strcat (treeName, sumtToken);
6709                         if (GetToken (sumtToken, &tokenType, &sumtTokenP))
6710                             goto errorExit;
6711                         }
6712                     inSumtComment = NO;
6713                     }
6714                 }
6715             else /* if (inSumtComment == NO) */
6716                 {
6717                 if (foundBegin == YES)
6718                     {
6719                     if (IsSame("Trees", sumtToken) == SAME)
6720                         {
6721                         numTreesInBlock = 0;
6722                         inTreeBlock = YES;
6723                         foundBegin = NO;
6724                         sumtFileInfo->lastTreeBlockBegin = lineNum;
6725                         }
6726                     }
6727                 else
6728                     {
6729                     if (IsSame("Begin", sumtToken) == SAME)
6730                         {
6731                         if (foundBegin == YES)
6732                             {
6733                             MrBayesPrint ("%s   Found inappropriate \"Begin\" statement in file\n", spacer);
6734                             blockErrors = YES;
6735                             }
6736                         foundBegin = YES;
6737                         }
6738                     else if (IsSame("End", sumtToken) == SAME)
6739                         {
6740                         if (inTreeBlock == YES)
6741                             {
6742                             sumtFileInfo->numTreeBlocks++;
6743                             inTreeBlock = NO;
6744                             sumtFileInfo->lastTreeBlockEnd = lineNum;
6745                             }
6746                         else
6747                             {
6748                             MrBayesPrint ("%s   Found inappropriate \"End\" statement in file\n", spacer);
6749                             blockErrors = YES;
6750                             }
6751                         sumtFileInfo->numTreesInLastBlock = numTreesInBlock;
6752                         }
6753                     else if (IsSame("Tree", sumtToken) == SAME)
6754                         {
6755                         if (inTreeBlock == YES)
6756                             {
6757                             numTreesInBlock++;
6758                             if (numTreesInBlock == 1)
6759                                 {
6760                                 *brlensDef = NO;
6761                                 for (i=0; s[i]!='\0'; i++)
6762                                     {
6763                                     if (s[i] == ':')
6764                                         {
6765                                         *brlensDef = YES;
6766                                         break;
6767                                         }
6768                                     }
6769                                 }
6770                             }
6771                         else
6772                             {
6773                             MrBayesPrint ("%s   Found a \"Tree\" statement that is not in a tree block\n", spacer);
6774                             blockErrors = YES;
6775                             }
6776                         }
6777                     }
6778                 }
6779 
6780             } while (*sumtToken);
6781         lineNum++;
6782         }
6783 
6784     /* Now, check some aspects of the tree file, such as the number of tree blocks and whether they are properly terminated. */
6785     if (inTreeBlock == YES)
6786         {
6787         MrBayesPrint ("%s   Unterminated tree block in file %s. You probably need to\n", spacer, fileName);
6788         MrBayesPrint ("%s   add a new line to the end of the file with \"End;\" on it.\n", spacer);
6789         goto errorExit;
6790         }
6791     if (inSumtComment == YES)
6792         {
6793         MrBayesPrint ("%s   Unterminated comment in file %s\n", spacer, fileName);
6794         goto errorExit;
6795         }
6796     if (blockErrors == YES)
6797         {
6798         MrBayesPrint ("%s   Found formatting errors in file %s\n", spacer, fileName);
6799         goto errorExit;
6800         }
6801     if (sumtFileInfo->lastTreeBlockEnd < sumtFileInfo->lastTreeBlockBegin)
6802         {
6803         MrBayesPrint ("%s   Problem reading tree file %s\n", spacer, fileName);
6804         goto errorExit;
6805         }
6806     if (sumtFileInfo->numTreesInLastBlock <= 0)
6807         {
6808         MrBayesPrint ("%s   No trees were found in last tree block of file %s\n", spacer, fileName);
6809         goto errorExit;
6810         }
6811     free (s);
6812     return (NO_ERROR);
6813 
6814 errorExit:
6815     free (s);
6816     return (ERROR);
6817 }
6818 
6819 
6820 /* FreePartCtr: Recursively free partition counter nodes */
FreePartCtr(PartCtr * r)6821 void FreePartCtr (PartCtr *r)
6822 {
6823     int     i, j;
6824 
6825     if (r==NULL)
6826         return;
6827 
6828     FreePartCtr (r->left);
6829     FreePartCtr (r->right);
6830 
6831     /* free relaxed clock parameters: eRate, nEvents, bRate */
6832     if (sumtParams.nESets > 0)
6833         {
6834         for (i=0; i<sumtParams.nESets; i++)
6835             {
6836             for (j=0; j<sumtParams.numRuns; j++)
6837                 free (r->nEvents[i][j]);
6838             free (r->nEvents[i]);
6839             }
6840         free (r->nEvents);
6841         }
6842     if (sumtParams.nBSets > 0)
6843         {
6844         for (i=0; i<sumtParams.nBSets; i++)
6845             {
6846             for (j=0; j<sumtParams.numRuns; j++)
6847                 {
6848                 free (r->bLen [i][j]);
6849                 free (r->bRate[i][j]);
6850                 }
6851             free (r->bLen [i]);
6852             free (r->bRate[i]);
6853             }
6854         free (r->bLen);
6855         free (r->bRate);
6856         }
6857 
6858     /* free basic parameters */
6859     for (i=0; i<sumtParams.numRuns; i++)
6860         free (r->length[i]);
6861 
6862     free (r->length);
6863     free (r->count);
6864     free (r->partition);
6865     free (r);
6866     numUniqueSplitsFound--;
6867     r = NULL;
6868 }
6869 
6870 
6871 /* FreeSumtParams: Free parameters allocated in sumtParams struct */
FreeSumtParams(void)6872 void FreeSumtParams(void)
6873 {
6874     int     i;
6875 
6876     if (memAllocs[ALLOC_SUMTPARAMS] == YES)
6877         {
6878         for (i=0; i<sumtParams.numTaxa; i++)
6879             free(sumtParams.taxaNames[i]);
6880         free (sumtParams.taxaNames);
6881         sumtParams.taxaNames = NULL;
6882         if (sumtParams.numFileTrees) free (sumtParams.numFileTrees);
6883         sumtParams.numFileTrees = NULL;
6884         FreePolyTree (sumtParams.tree);
6885         sumtParams.tree = NULL;
6886         if (sumtParams.nBSets > 0)
6887             {
6888             for (i=0; i<sumtParams.nBSets; i++)
6889                 free(sumtParams.bSetName[i]);
6890             free (sumtParams.bSetName);
6891             sumtParams.bSetName = NULL;
6892             sumtParams.nBSets = 0;
6893             }
6894         if (sumtParams.nESets > 0)
6895             {
6896             for (i=0; i<sumtParams.nESets; i++)
6897                 free(sumtParams.eSetName[i]);
6898             free (sumtParams.eSetName);
6899             sumtParams.eSetName = NULL;
6900             sumtParams.nESets = 0;
6901             }
6902         if (sumtParams.popSizeSet == YES)
6903             {
6904             free (sumtParams.popSizeSetName);
6905             sumtParams.popSizeSetName = NULL;
6906             sumtParams.popSizeSet = NO;
6907             }
6908         memAllocs[ALLOC_SUMTPARAMS] = NO;
6909         }
6910 }
6911 
6912 
6913 /* FreeTreeCtr: Recursively free tree counter nodes */
FreeTreeCtr(TreeCtr * r)6914 void FreeTreeCtr (TreeCtr *r)
6915 {
6916     if (r==NULL)
6917         return;
6918 
6919     FreeTreeCtr (r->left);
6920     FreeTreeCtr (r->right);
6921 
6922     free (r->order);
6923     free (r);
6924     numUniqueTreesFound--;
6925     r = NULL;
6926 }
6927 
6928 
6929 /* Label: Calculate length of label and fill in char *label if not NULL */
Label(PolyNode * p,int addIndex,char * label,int maxLength)6930 int Label (PolyNode *p, int addIndex, char *label, int maxLength)
6931 {
6932     int     i, j0, j1, k, n, length, nameLength, index;
6933 
6934     if (p == NULL)
6935         return 0;
6936 
6937     /* first calculate length */
6938     if (inSumtCommand == YES && isTranslateDiff == NO)
6939         {
6940         for (index=i=0; index<numTaxa; index++)
6941             {
6942             if (sumtParams.absentTaxa[index] == YES || taxaInfo[index].isDeleted == YES)
6943                 continue;
6944             if (p->index == i)
6945                 break;
6946             else
6947                 i++;
6948             }
6949         }
6950     else
6951         index = p->index;
6952 
6953     if (addIndex != NO)
6954         length = (int)(strlen(p->label)) + 4 + (int)(log10(index+1));
6955     else
6956         length = (int)(strlen(p->label));
6957     length = (length > maxLength ? maxLength : length);
6958 
6959     /* fill in label if label != NULL */
6960     if (label != NULL)
6961         {
6962         if (addIndex != NO)
6963             nameLength = length - 4 - (int)(log10(index+1));
6964         else
6965             nameLength = length;
6966 
6967         for (i=0; i<nameLength-1; i++)
6968             label[i] = p->label[i];
6969         if ((int)strlen(p->label) > nameLength)
6970             label[i] = '~';
6971         else
6972             label[i] = p->label[i];
6973 
6974         if (addIndex != NO)
6975             {
6976             label[++i] = ' ';
6977             label[++i] = '(';
6978             n = index + 1;
6979             k = (int)(log10(n)) + 1;
6980             while (n != 0)
6981                 {
6982                 j0 = (int)(log10(n));
6983                 j1 = (int)(pow(10,j0));
6984                 label[++i] = '0' + n/j1;
6985                 n = n % j1;
6986                 k--;
6987                 }
6988             while (k!=0)
6989                 {
6990                 label[++i] = '0';
6991                 k--;
6992                 }
6993             label[++i] = ')';
6994             }
6995         label[++i] = '\0';
6996         }
6997 
6998     return length;
6999 }
7000 
7001 
OpenComptFiles(void)7002 int OpenComptFiles (void)
7003 {
7004     int         len, previousFiles, oldNoWarn, oldAutoOverwrite;
7005     char        pFilename[120], dFilename[120];
7006     FILE        *fpTemp;
7007 
7008     oldNoWarn = noWarn;
7009     oldAutoOverwrite = autoOverwrite;
7010 
7011     /* set file names */
7012     strcpy (pFilename, comptreeParams.comptOutfile);
7013     strcpy (dFilename, comptreeParams.comptOutfile);
7014     strcat (pFilename, ".pairs");
7015     strcat (dFilename, ".dists");
7016 
7017     /* one overwrite check for both files */
7018     previousFiles = NO;
7019     if (noWarn == NO)
7020         {
7021         if ((fpTemp = OpenTextFileR(pFilename)) != NULL)
7022             {
7023             previousFiles = YES;
7024             fclose(fpTemp);
7025             }
7026         if ((fpTemp = OpenTextFileR(dFilename)) != NULL)
7027             {
7028             previousFiles = YES;
7029             fclose(fpTemp);
7030             }
7031         if (previousFiles == YES)
7032             {
7033             MrBayesPrint("%s   There are previous compare results saved using the same filenames.\n", spacer);
7034             if (WantTo("Do you want to overwrite these results") == YES)
7035                 {
7036                 MrBayesPrint("\n");
7037                 noWarn = YES;
7038                 autoOverwrite = YES;
7039                 }
7040             else
7041                 {
7042                 MrBayesPrint("\n");
7043                 MrBayesPrint("%s   Please specify a different output file name before running the comparetree command.\n", spacer);
7044                 MrBayesPrint("%s      You can do that using 'comparetree outputfile=<name>'. You can also move or\n", spacer);
7045                 MrBayesPrint("%s      rename the old result files.\n", spacer);
7046                 return ERROR;
7047                 }
7048             }
7049         }
7050 
7051     if ((fpParts = OpenNewMBPrintFile (pFilename)) == NULL)
7052         {
7053         noWarn = oldNoWarn;
7054         autoOverwrite = oldAutoOverwrite;
7055         return ERROR;
7056         }
7057     if ((fpDists = OpenNewMBPrintFile (dFilename)) == NULL)
7058         {
7059         noWarn = oldNoWarn;
7060         autoOverwrite = oldAutoOverwrite;
7061         return ERROR;
7062         }
7063 
7064     /* Reset file flags */
7065     noWarn = oldNoWarn;
7066     autoOverwrite = oldAutoOverwrite;
7067 
7068     /* print unique identifiers to each file */
7069     len = (int) strlen (stamp);
7070     if (len > 1)
7071         {
7072         MrBayesPrintf (fpParts, "[ID: %s]\n", stamp);
7073         MrBayesPrintf (fpDists, "[ID: %s]\n", stamp);
7074         }
7075 
7076     return (NO_ERROR);
7077 }
7078 
7079 
OpenSumtFiles(int treeNo)7080 int OpenSumtFiles (int treeNo)
7081 {
7082     int         i, len,  oldNoWarn, oldAutoOverwrite, previousFiles;
7083     char        pFilename[145], sFilename[145], vFilename[145], cFilename[145], tFilename[145];
7084     FILE        *fpTemp;
7085 
7086     oldNoWarn = noWarn;
7087     oldAutoOverwrite = autoOverwrite;
7088 
7089     /* one overwrite check for all files */
7090     if (noWarn == NO && treeNo == 0)
7091         {
7092         previousFiles = NO;
7093         for (i=0; i<sumtParams.numTrees; i++)
7094             {
7095             if (sumtParams.numTrees > 1)
7096                 {
7097                 sprintf (pFilename, "%s.tree%d.parts", sumtParams.sumtOutfile, i+1);
7098                 sprintf (sFilename, "%s.tree%d.tstat", sumtParams.sumtOutfile, i+1);
7099                 sprintf (vFilename, "%s.tree%d.vstat", sumtParams.sumtOutfile, i+1);
7100                 sprintf (cFilename, "%s.tree%d.con.tre", sumtParams.sumtOutfile, i+1);
7101                 sprintf (tFilename, "%s.tree%d.trprobs", sumtParams.sumtOutfile, i+1);
7102                 }
7103             else
7104                 {
7105                 sprintf (pFilename, "%s.parts", sumtParams.sumtOutfile);
7106                 sprintf (sFilename, "%s.tstat", sumtParams.sumtOutfile);
7107                 sprintf (vFilename, "%s.vstat", sumtParams.sumtOutfile);
7108                 sprintf (cFilename, "%s.con.tre", sumtParams.sumtOutfile);
7109                 sprintf (tFilename, "%s.trprobs", sumtParams.sumtOutfile);
7110                 }
7111             if ((fpTemp = TestOpenTextFileR(pFilename)) != NULL)
7112                 {
7113                 previousFiles = YES;
7114                 fclose(fpTemp);
7115                 }
7116             if ((fpTemp = TestOpenTextFileR(sFilename)) != NULL)
7117                 {
7118                 previousFiles = YES;
7119                 fclose(fpTemp);
7120                 }
7121             if ((fpTemp = TestOpenTextFileR(vFilename)) != NULL)
7122                 {
7123                 previousFiles = YES;
7124                 fclose(fpTemp);
7125                 }
7126             if ((fpTemp = TestOpenTextFileR(cFilename)) != NULL)
7127                 {
7128                 previousFiles = YES;
7129                 fclose(fpTemp);
7130                 }
7131             if ((fpTemp = TestOpenTextFileR(tFilename)) != NULL)
7132                 {
7133                 previousFiles = YES;
7134                 fclose(fpTemp);
7135                 }
7136             if (previousFiles == YES)
7137                 {
7138                 MrBayesPrint("\n");
7139                 MrBayesPrint("%s   There are previous tree sample summaries saved using the same filenames.\n", spacer);
7140                 if (WantTo("Do you want to overwrite these results") == YES)
7141                     {
7142                     MrBayesPrint("\n");
7143                     noWarn = YES;
7144                     autoOverwrite = YES;
7145                     }
7146                 else
7147                     {
7148                     MrBayesPrint("\n");
7149                     MrBayesPrint("%s   Please specify a different output file name before running the sumt command.\n", spacer);
7150                     MrBayesPrint("%s      You can do that using 'sumt outputfile=<name>'. You can also move or\n", spacer);
7151                     MrBayesPrint("%s      rename the old result files.\n", spacer);
7152                     return ERROR;
7153                     }
7154                 }
7155             }
7156         }
7157 
7158     /* set file names */
7159     if (sumtParams.numTrees > 1)
7160         {
7161         sprintf (pFilename, "%s.tree%d.parts", sumtParams.sumtOutfile, treeNo+1);
7162         sprintf (sFilename, "%s.tree%d.tstat", sumtParams.sumtOutfile, treeNo+1);
7163         sprintf (vFilename, "%s.tree%d.vstat", sumtParams.sumtOutfile, treeNo+1);
7164         sprintf (cFilename, "%s.tree%d.con.tre", sumtParams.sumtOutfile, treeNo+1);
7165         sprintf (tFilename, "%s.tree%d.trprobs", sumtParams.sumtOutfile, treeNo+1);
7166         }
7167     else
7168         {
7169         sprintf (pFilename, "%s.parts", sumtParams.sumtOutfile);
7170         sprintf (sFilename, "%s.tstat", sumtParams.sumtOutfile);
7171         sprintf (vFilename, "%s.vstat", sumtParams.sumtOutfile);
7172         sprintf (cFilename, "%s.con.tre", sumtParams.sumtOutfile);
7173         sprintf (tFilename, "%s.trprobs", sumtParams.sumtOutfile);
7174         }
7175 
7176     /* open files checking for over-write as appropriate */
7177     if ((fpParts = OpenNewMBPrintFile(pFilename)) == NULL)
7178         return ERROR;
7179     if ((fpTstat = OpenNewMBPrintFile(sFilename)) == NULL)
7180         {
7181         SafeFclose (&fpParts);
7182         return ERROR;
7183         }
7184     if ((fpVstat = OpenNewMBPrintFile(vFilename)) == NULL)
7185         {
7186         SafeFclose (&fpParts);
7187         SafeFclose (&fpTstat);
7188         return ERROR;
7189         }
7190     if ((fpCon = OpenNewMBPrintFile(cFilename)) == NULL)
7191         {
7192         SafeFclose (&fpParts);
7193         SafeFclose (&fpTstat);
7194         SafeFclose (&fpVstat);
7195         return ERROR;
7196         }
7197     if (sumtParams.calcTreeprobs == YES)
7198         {
7199         if ((fpTrees = OpenNewMBPrintFile(tFilename)) == NULL)
7200             {
7201             SafeFclose (&fpParts);
7202             SafeFclose (&fpTstat);
7203             SafeFclose (&fpVstat);
7204             SafeFclose (&fpCon);
7205             return ERROR;
7206             }
7207         }
7208 
7209     /* print #NEXUS if appropriate */
7210     MrBayesPrintf (fpCon,   "#NEXUS\n");
7211     if (sumtParams.calcTreeprobs == YES)
7212         MrBayesPrintf (fpTrees, "#NEXUS\n");
7213 
7214     /* print unique identifiers to each file */
7215     len = (int) strlen (stamp);
7216     if (len > 1)
7217         {
7218         MrBayesPrintf (fpParts, "[ID: %s]\n", stamp);
7219         MrBayesPrintf (fpTstat, "[ID: %s]\n", stamp);
7220         MrBayesPrintf (fpVstat, "[ID: %s]\n", stamp);
7221         MrBayesPrintf (fpCon,   "[ID: %s]\n", stamp);
7222         if (sumtParams.calcTreeprobs == YES)
7223             MrBayesPrintf (fpTrees, "[ID: %s]\n", stamp);
7224         }
7225 
7226     /* Reset noWarn and autoOverwrite */
7227     if (treeNo == sumtParams.numTrees - 1)
7228         {
7229         noWarn = oldNoWarn;
7230         autoOverwrite = oldAutoOverwrite;
7231         }
7232 
7233     return (NO_ERROR);
7234 }
7235 
7236 
PartCtrUppass(PartCtr * r,PartCtr ** uppass,int * index)7237 void PartCtrUppass (PartCtr *r, PartCtr **uppass, int *index)
7238 {
7239     if (r != NULL)
7240         {
7241         uppass[(*index)++] = r;
7242 
7243         PartCtrUppass (r->left, uppass, index);
7244         PartCtrUppass (r->right, uppass, index);
7245         }
7246 }
7247 
7248 
7249 /* PrintBrParamsToFile: Print branach parameters to file */
PrintBrParamsToFile(PartCtr ** treeParts,int numTreeParts,int treeNo,char * divString)7250 int PrintBrParamsToFile (PartCtr **treeParts, int numTreeParts, int treeNo, char *divString)
7251 {
7252     int     i, j, numPartitions, min, treeSample, runNo;
7253     char    filename[145];
7254     PartCtr *x;
7255     FILE    *fp;
7256 
7257     /* set file name */
7258     if (sumtParams.numTrees > 1)
7259         sprintf (filename, "%s.tree%d.brparams", sumtParams.sumtOutfile, treeNo+1);
7260     else
7261         sprintf (filename, "%s.brparams", sumtParams.sumtOutfile);
7262     MrBayesPrint( "%s   Saving branch parameters to file \"%s\"\n", spacer, filename);
7263 
7264     /* Open file checking for over-write as appropriate */
7265     if ((fp = OpenNewMBPrintFile(filename)) == NULL)
7266         {
7267         MrBayesPrint ("\n");
7268         return ERROR;
7269         }
7270 
7271     /* count number of branch params to print */
7272     min = (sumtParams.minBrParamFreq * (sumtParams.numTreesSampled/sumtParams.numRuns));
7273     for (i=0; i<numTreeParts; i++)
7274         {
7275         if (treeParts[i]->totCount < min)
7276             break;
7277         }
7278     numPartitions = i;
7279 
7280     /* print header */
7281 
7282     /* -- header for branch lengths; NB! We skip the root branch length (i starts at 1) */
7283     for (i=1; i<numPartitions; ++i)
7284         {
7285         MrBayesPrintf (fp, "length%s[%d]", divString, i);
7286         if (i!=numPartitions-1)
7287             MrBayesPrintf (fp, "\t");
7288         }
7289 
7290     /* -- header for node heights */
7291     if (sumtParams.isClock == YES )
7292         {
7293         MrBayesPrintf (fp, "\t");
7294         for (i=0; i<numPartitions; i++)
7295             {
7296             MrBayesPrintf (fp, "height%s[%d]", divString, i);
7297             if (i!=numPartitions-1)
7298                 MrBayesPrintf (fp, "\t");
7299             }
7300         }
7301 
7302     /* -- header for node ages */
7303     if (sumtParams.isCalibrated == YES )
7304         {
7305         MrBayesPrintf (fp, "\t");
7306         for (i=0; i<numPartitions; i++)
7307             {
7308             MrBayesPrintf (fp, "age%s[%d]", divString, i);
7309             if (i!=numPartitions-1)
7310                 MrBayesPrintf (fp, "\t");
7311             }
7312         }
7313 
7314     /* -- header for effective branch lengths and branch rates; NB! We skip the root branch (j starts at 1) */
7315     if (sumtParams.isRelaxed == YES)
7316         {
7317         for (i=0; i<sumtParams.nBSets; i++)
7318             {
7319             MrBayesPrintf (fp, "\t");
7320             for (j=1; j<numPartitions; j++)
7321                 {
7322                 MrBayesPrintf (fp, "%s_length[%d]", sumtParams.bSetName[i], j);
7323                 MrBayesPrintf (fp, "\t");
7324                 }
7325             for (j=1; j<numPartitions; j++)
7326                 {
7327                 MrBayesPrintf (fp, "%s_rate[%d]", sumtParams.bSetName[i], j);
7328                 if (j!=numPartitions-1)
7329                     MrBayesPrintf (fp, "\t");
7330                 }
7331             }
7332         for (i=0; i<sumtParams.nESets; i++)
7333             {
7334             MrBayesPrintf (fp, "\t");
7335             for (j=1; j<numPartitions; j++)
7336                 {
7337                 MrBayesPrintf (fp, "%s_nEvents[%d]", sumtParams.eSetName[i], j);
7338                 if (j!=numPartitions-1)
7339                     MrBayesPrintf (fp, "\t");
7340                 }
7341             }
7342         }
7343 
7344     /* finalize header line */
7345     MrBayesPrintf (fp, "\n");
7346 
7347     /* print values */
7348     for (runNo=0; runNo<sumtParams.numRuns; runNo++)
7349         {
7350         for (treeSample=0; treeSample<sumtParams.numTreesSampled/sumtParams.numRuns; treeSample++)
7351             {
7352             /* print branch lengths */
7353             for (i=1; i<numPartitions; i++)
7354                 {
7355                 x = treeParts[i];
7356                 if (x->count[runNo] > treeSample)
7357                     MrBayesPrintf (fp, "%s", MbPrintNum (x->length[runNo][treeSample]));
7358                 else
7359                     MrBayesPrintf (fp, "NA");
7360                 if (i!=numPartitions-1)
7361                     MrBayesPrintf (fp, "\t");
7362                 }
7363             /* print node heights */
7364             if (sumtParams.isClock == YES)
7365                 {
7366                 MrBayesPrintf (fp, "\t");
7367                 for (i=0; i<numPartitions; i++)
7368                     {
7369                     x = treeParts[i];
7370                     if ( x->count[runNo] > treeSample )
7371                         MrBayesPrintf (fp, "%s", MbPrintNum (x->height[runNo][treeSample]));
7372                     else
7373                         MrBayesPrintf (fp, "NA");
7374                     if (i!=numPartitions-1)
7375                         MrBayesPrintf (fp, "\t");
7376                     }
7377                 }
7378             /* print node ages */
7379             if (sumtParams.isCalibrated == YES)
7380                 {
7381                 MrBayesPrintf (fp, "\t");
7382                 for (i=0; i<numPartitions; i++)
7383                     {
7384                     x = treeParts[i];
7385                     if ( x->count[runNo] > treeSample )
7386                         MrBayesPrintf (fp, "%s", MbPrintNum (x->age[runNo][treeSample]));
7387                     else
7388                         MrBayesPrintf (fp, "NA");
7389                     if (i!=numPartitions-1)
7390                         MrBayesPrintf (fp, "\t");
7391                     }
7392                 }
7393             /* print effective branch lengths */
7394             if (sumtParams.isRelaxed)
7395                 {
7396                 for (i=0; i<sumtParams.nBSets; i++)
7397                     {
7398                     MrBayesPrintf (fp, "\t");
7399                     for (j=1; j<numPartitions; j++)
7400                         {
7401                         x = treeParts[j];
7402                         if ( x->count[runNo] > treeSample )
7403                             MrBayesPrintf (fp, "%s", MbPrintNum (x->bLen[i][runNo][treeSample]));
7404                         else
7405                             MrBayesPrintf (fp, "NA");
7406                         MrBayesPrintf (fp, "\t");
7407                         }
7408                     for (j=1; j<numPartitions; j++)
7409                         {
7410                         x = treeParts[j];
7411                         if ( x->count[runNo] > treeSample )
7412                             MrBayesPrintf (fp, "%s", MbPrintNum (x->bRate[i][runNo][treeSample]));
7413                         else
7414                             MrBayesPrintf (fp, "NA");
7415                         if (j!=numPartitions-1)
7416                             MrBayesPrintf (fp, "\t");
7417                         }
7418                     }
7419                 for (i=0; i<sumtParams.nESets; i++)
7420                     {
7421                     MrBayesPrintf (fp, "\t");
7422                     for (j=1; j<numPartitions; j++)
7423                         {
7424                         x = treeParts[j];
7425                         if ( x->count[runNo] > treeSample )
7426                             MrBayesPrintf (fp, "%d", x->nEvents[i][runNo][treeSample]);
7427                         else
7428                             MrBayesPrintf (fp, "NA");
7429                         if (j!=numPartitions-1)
7430                             MrBayesPrintf (fp, "\t");
7431                         }
7432                     }
7433                 }
7434             MrBayesPrintf (fp, "\n");
7435             }   // next tree sample
7436         }   // next run
7437 
7438     MrBayesPrint("\n");
7439     return NO_ERROR;
7440 }
7441 
7442 
7443 /* PrintConTree: Print consensus tree in standard format readable by TreeView, Paup etc */
PrintConTree(FILE * fp,PolyTree * t)7444 void PrintConTree (FILE *fp, PolyTree *t)
7445 {
7446     MrBayesPrintf (fp, "   [Note: This tree contains information on the topology, \n");
7447     MrBayesPrintf (fp, "          branch lengths (if present), and the probability\n");
7448     MrBayesPrintf (fp, "          of the partition indicated by the branch.]\n");
7449     if (!strcmp(sumtParams.sumtConType, "Halfcompat"))
7450         MrBayesPrintf (fp, "   tree con_50_majrule = ");
7451     else
7452         MrBayesPrintf (fp, "   tree con_all_compat = ");
7453     WriteConTree (t->root, fp, YES);
7454     MrBayesPrintf (fp, ";\n");
7455     if (sumtParams.brlensDef == YES)
7456         {
7457         MrBayesPrintf (fp, "\n");
7458         MrBayesPrintf (fp, "   [Note: This tree contains information only on the topology\n");
7459         MrBayesPrintf (fp, "          and branch lengths (median of the posterior probability density).]\n");
7460         if (!strcmp(sumtParams.sumtConType, "Halfcompat"))
7461             MrBayesPrintf (fp, "   tree con_50_majrule = ");
7462         else
7463             MrBayesPrintf (fp, "   tree con_all_compat = ");
7464         WriteConTree (t->root, fp, NO);
7465         MrBayesPrintf (fp, ";\n");
7466         }
7467 }
7468 
7469 
7470 /* PrintFigTreeConTree: Print consensus tree in rich format for FigTree */
PrintFigTreeConTree(FILE * fp,PolyTree * t,PartCtr ** treeParts)7471 void PrintFigTreeConTree (FILE *fp, PolyTree *t, PartCtr **treeParts)
7472 {
7473     if (!strcmp(sumtParams.sumtConType, "Halfcompat"))
7474         MrBayesPrintf (fp, "   tree con_50_majrule = ");
7475     else
7476         MrBayesPrintf (fp, "   tree con_all_compat = ");
7477     if (t->isRooted == YES)
7478         MrBayesPrintf (fp, "[&R] ");
7479     else
7480         MrBayesPrintf (fp, "[&U] ");
7481 
7482     WriteFigTreeConTree (t->root, fp, treeParts);
7483     MrBayesPrintf (fp, ";\n");
7484 }
7485 
7486 
PrintFigTreeNodeInfo(FILE * fp,PartCtr * x,MrBFlt length)7487 void PrintFigTreeNodeInfo (FILE *fp, PartCtr *x, MrBFlt length)
7488 {
7489     int     i, postProbPercent, postProbSdPercent;
7490     MrBFlt  *support, mean, var, min, max;
7491     Stat    theStats;
7492 
7493     support = SafeCalloc (sumtParams.numRuns, sizeof(MrBFlt));
7494     for (i=0; i<sumtParams.numRuns; i++)
7495         {
7496         support[i] = (MrBFlt) x->count[i] / (MrBFlt) sumtParams.numFileTreesSampled[i];
7497         }
7498     if (sumtParams.numRuns > 1)
7499         {
7500         MeanVariance (support, sumtParams.numRuns, &mean, &var);
7501         Range (support, sumtParams.numRuns, &min, &max);
7502         postProbPercent = (int) (100.0*mean + 0.5);
7503         postProbSdPercent = (int) (100.0 * sqrt(var) + 0.5);
7504         fprintf (fp, "[&prob=%.8le,prob_stddev=%.8le,prob_range={%.8le,%.8le},prob(percent)=\"%d\",prob+-sd=\"%d+-%d\"",
7505             mean, sqrt(var), min, max, postProbPercent, postProbPercent, postProbSdPercent);
7506         }
7507     else
7508         {
7509         postProbPercent = (int) (100.0*support[0] + 0.5);
7510         fprintf (fp, "[&prob=%.8le,prob(percent)=\"%d\"", support[0], postProbPercent);
7511         }
7512     if (sumtParams.isClock == YES)
7513         {
7514         GetSummary (x->height, sumtParams.numRuns, x->count, &theStats, sumtParams.HPD);
7515         if (sumtParams.HPD == YES)
7516             fprintf (fp, ",height_mean=%.8le,height_median=%.8le,height_95%%HPD={%.8le,%.8le}", theStats.mean, theStats.median, theStats.lower, theStats.upper);
7517         else
7518             fprintf (fp, ",height_mean=%.8le,height_median=%.8le,height_95%%CredInt={%.8le,%.8le}", theStats.mean, theStats.median, theStats.lower, theStats.upper);
7519         }
7520     if (sumtParams.isCalibrated == YES)
7521         {
7522         GetSummary (x->age, sumtParams.numRuns, x->count, &theStats, sumtParams.HPD);
7523         if (sumtParams.HPD == YES)
7524             fprintf (fp, ",age_mean=%.8le,age_median=%.8le,age_95%%HPD={%.8le,%.8le}", theStats.mean, theStats.median, theStats.lower, theStats.upper);
7525         else
7526             fprintf (fp, ",age_mean=%.8le,age_median=%.8le,age_95%%CredInt={%.8le,%.8le}", theStats.mean, theStats.median, theStats.lower, theStats.upper);
7527         }
7528     fprintf (fp, "]");
7529     if (length >= 0.0)
7530         fprintf (fp, ":%s", MbPrintNum(length));
7531     if (sumtParams.brlensDef == YES)
7532         {
7533         GetSummary (x->length, sumtParams.numRuns, x->count, &theStats, sumtParams.HPD);
7534         if (sumtParams.HPD == YES)
7535             fprintf (fp, "[&length_mean=%.8le,length_median=%.8le,length_95%%HPD={%.8le,%.8le}", theStats.mean, theStats.median, theStats.lower, theStats.upper);
7536         else
7537             fprintf (fp, "[&length_mean=%.8le,length_median=%.8le,length_95%%CredInt={%.8le,%.8le}", theStats.mean, theStats.median, theStats.lower, theStats.upper);
7538         }
7539     if (sumtParams.isClock == YES && sumtParams.isRelaxed == YES)
7540         {
7541         for (i=0; i<sumtParams.nBSets; i++)
7542             {
7543             GetSummary (x->bLen[i], sumtParams.numRuns, x->count, &theStats, sumtParams.HPD);
7544             if (sumtParams.HPD == YES)
7545                 fprintf (fp, ",effectivebrlen%s_mean=%lf,effectivebrlen%s_median=%lf,effectivebrlen%s_95%%HPD={%lf,%lf}",
7546                     sumtParams.tree->bSetName[i], theStats.mean,
7547                     sumtParams.tree->bSetName[i], theStats.median,
7548                     sumtParams.tree->bSetName[i], theStats.lower,
7549                     theStats.upper);
7550             else
7551                 fprintf (fp, ",effectivebrlen%s_mean=%lf,effectivebrlen%s_median=%lf,effectivebrlen%s_95%%CredInt={%lf,%lf}",
7552                     sumtParams.tree->bSetName[i], theStats.mean,
7553                     sumtParams.tree->bSetName[i], theStats.median,
7554                     sumtParams.tree->bSetName[i], theStats.lower,
7555                     theStats.upper);
7556             GetSummary (x->bRate[i], sumtParams.numRuns, x->count, &theStats, sumtParams.HPD);
7557             if (sumtParams.HPD == YES)
7558                 fprintf (fp, ",rate%s_mean=%lf,rate%s_median=%lf,rate%s_95%%HPD={%lf,%lf}",
7559                     sumtParams.tree->bSetName[i], theStats.mean,
7560                     sumtParams.tree->bSetName[i], theStats.median,
7561                     sumtParams.tree->bSetName[i], theStats.lower,
7562                     theStats.upper);
7563             else
7564                 fprintf (fp, ",rate%s_mean=%lf,rate%s_median=%lf,rate%s_95%%CredInt={%lf,%lf}",
7565                     sumtParams.tree->bSetName[i], theStats.mean,
7566                     sumtParams.tree->bSetName[i], theStats.median,
7567                     sumtParams.tree->bSetName[i], theStats.lower,
7568                     theStats.upper);
7569             }
7570         for (i=0; i<sumtParams.nESets; i++)
7571             {
7572             GetIntSummary (x->nEvents[i], sumtParams.numRuns, x->count, &theStats, sumtParams.HPD);
7573             if (sumtParams.HPD == YES)
7574                 fprintf (fp, ",nEvents%s_mean=%lf,nEvents%s_median=%lf,nEvents%s_95%%HPD={%lf,%lf}",
7575                     sumtParams.tree->eSetName[i], theStats.mean,
7576                     sumtParams.tree->eSetName[i], theStats.median,
7577                     sumtParams.tree->eSetName[i], theStats.lower,
7578                     theStats.upper);
7579             else
7580                 fprintf (fp, ",nEvents%s_mean=%lf,nEvents%s_median=%lf,nEvents%s_95%%CredInt={%lf,%lf}",
7581                     sumtParams.tree->eSetName[i], theStats.mean,
7582                     sumtParams.tree->eSetName[i], theStats.median,
7583                     sumtParams.tree->eSetName[i], theStats.lower,
7584                     theStats.upper);
7585             }
7586         }
7587     if (sumtParams.brlensDef == YES)
7588         fprintf (fp, "]");
7589 
7590     free (support);
7591 }
7592 
7593 
PrintSumtTableLine(int numRuns,int * rowCount,Stat * theStats,MrBFlt * numPSRFSamples,MrBFlt * maxPSRF,MrBFlt * sumPSRF)7594 void PrintSumtTableLine(int numRuns, int *rowCount, Stat *theStats, MrBFlt *numPSRFSamples, MrBFlt *maxPSRF, MrBFlt *sumPSRF)
7595 {
7596     int j,k;
7597 
7598     MrBayesPrint ("%10.6lf  %10.6lf  %10.6lf  %10.6lf  %10.6lf", theStats->mean, theStats->var, theStats->lower, theStats->upper, theStats->median);
7599 
7600     MrBayesPrintf (fpVstat, "\t%s", MbPrintNum(theStats->mean));
7601     MrBayesPrintf (fpVstat, "\t%s", MbPrintNum(theStats->var));
7602     MrBayesPrintf (fpVstat, "\t%s", MbPrintNum(theStats->lower));
7603     MrBayesPrintf (fpVstat, "\t%s", MbPrintNum(theStats->upper));
7604     MrBayesPrintf (fpVstat, "\t%s", MbPrintNum(theStats->median));
7605 
7606     if (numRuns > 1)
7607         {
7608         for (j=k=0; j<numRuns; j++)
7609             if (rowCount[j] > 0)
7610                 k++;
7611 
7612         if (theStats->PSRF < 0.0)
7613             {
7614             MrBayesPrint ("     NA    %3d", k);
7615             MrBayesPrintf (fpVstat, "\tNA\t%d", k);
7616             }
7617         else
7618             {
7619             if (theStats->PSRF > 10.0)
7620                 {
7621                 MrBayesPrint ("    >10.0  %3d", k);
7622                 MrBayesPrintf (fpVstat, "\tNA\t%d", k);
7623                 (*maxPSRF) = 10.0;
7624                 }
7625             else
7626                 {
7627                 MrBayesPrint ("  %7.3lf  %3d", theStats->PSRF, k);
7628                 MrBayesPrintf (fpVstat, "\t%s\t%d", MbPrintNum(theStats->PSRF), k);
7629                 (*sumPSRF) += theStats->PSRF;
7630                 (*numPSRFSamples)++;
7631                 if (theStats->PSRF > *maxPSRF)
7632                     (*maxPSRF) = theStats->PSRF;
7633                 }
7634             }
7635 
7636         if (k != numRuns)
7637             MrBayesPrint (" *");
7638         }
7639 
7640     MrBayesPrint ("\n");
7641     MrBayesPrintf (fpVstat, "\n");
7642 }
7643 
7644 
7645 /* PrintSumtTaxaInfo: Print information on pruned and absent taxa */
PrintSumtTaxaInfo(void)7646 void PrintSumtTaxaInfo (void)
7647 {
7648     int     i, j, lineWidth, numExcludedTaxa, len;
7649     char    tempStr[100];
7650 
7651     /* print out information on absent taxa */
7652     numExcludedTaxa = 0;
7653     for (i=0; i<numTaxa; i++)
7654         if (sumtParams.absentTaxa[i] == YES)
7655             numExcludedTaxa++;
7656 
7657     if (numExcludedTaxa > 0)
7658         {
7659         if (numExcludedTaxa == 1)
7660             MrBayesPrint ("%s   The following taxon was absent from trees:\n", spacer);
7661         else
7662             MrBayesPrint ("%s   The following %d taxa were absent from trees:\n", spacer, numExcludedTaxa);
7663         MrBayesPrint ("%s      ", spacer);
7664         j = lineWidth = 0;
7665         for (i=0; i<numTaxa; i++)
7666             {
7667             if (sumtParams.absentTaxa[i] == YES)
7668                 {
7669                 j++;
7670                 strcpy (tempStr, taxaNames[i]);
7671                 len = (int) strlen(tempStr);
7672                 lineWidth += len+2;
7673                 if (lineWidth > 60)
7674                     {
7675                     MrBayesPrint ("\n%s      ", spacer);
7676                     lineWidth = 0;
7677                     }
7678                 if (numExcludedTaxa == 1)
7679                     MrBayesPrint ("%s\n", tempStr);
7680                 else if (numExcludedTaxa == 2 && j == 1)
7681                     MrBayesPrint ("%s ", tempStr);
7682                 else if (j == numExcludedTaxa)
7683                     MrBayesPrint ("and %s\n", tempStr);
7684                 else
7685                     MrBayesPrint ("%s, ", tempStr);
7686                 }
7687             }
7688         MrBayesPrint ("\n");
7689         }
7690 
7691     /* print out information on pruned taxa */
7692     numExcludedTaxa = 0;
7693     for (i=0; i<numTaxa; i++)
7694         if (taxaInfo[i].isDeleted == YES && sumtParams.absentTaxa[i] == NO)
7695             numExcludedTaxa++;
7696 
7697     if (numExcludedTaxa > 0)
7698         {
7699         if (numExcludedTaxa == 1)
7700             MrBayesPrint ("%s   The following taxon was pruned from trees:\n", spacer);
7701         else
7702             MrBayesPrint ("%s   The following %d taxa were pruned from trees:\n", spacer, numExcludedTaxa);
7703         MrBayesPrint ("%s      ", spacer);
7704         j = lineWidth = 0;
7705         for (i=0; i<numTaxa; i++)
7706             {
7707             if (taxaInfo[i].isDeleted == YES && sumtParams.absentTaxa[i] == NO)
7708                 {
7709                 j++;
7710                 strcpy (tempStr, taxaNames[i]);
7711                 len = (int) strlen(tempStr);
7712                 lineWidth += len+2;
7713                 if (lineWidth > 60)
7714                     {
7715                     MrBayesPrint ("\n%s      ", spacer);
7716                     lineWidth = 0;
7717                     }
7718                 if (numExcludedTaxa == 1)
7719                     MrBayesPrint ("%s\n", tempStr);
7720                 else if (numExcludedTaxa == 2 && j == 1)
7721                     MrBayesPrint ("%s ", tempStr);
7722                 else if (j == numExcludedTaxa)
7723                     MrBayesPrint ("and %s\n", tempStr);
7724                 else
7725                     MrBayesPrint ("%s, ", tempStr);
7726                 }
7727             }
7728         MrBayesPrint ("\n");
7729         }
7730 }
7731 
7732 
7733 /* Range: Determine range for a vector of MrBFlt values */
Range(MrBFlt * vals,int nVals,MrBFlt * min,MrBFlt * max)7734 void Range (MrBFlt *vals, int nVals, MrBFlt *min, MrBFlt *max)
7735 {
7736     SortMrBFlt (vals, 0, nVals-1);
7737 
7738     *min  = vals[0];
7739     *max  = vals[nVals-1];
7740 }
7741 
7742 
7743 /* ResetTaxonSet: Reset included taxa and local outgroup number */
ResetTaxonSet(void)7744 void ResetTaxonSet (void)
7745 {
7746     int     i, j;
7747 
7748     /* reset numLocalTaxa and localOutGroup */
7749     localOutGroup = 0;
7750     numLocalTaxa = 0;
7751     for (i=j=0; i<numTaxa; i++)
7752         {
7753         if (taxaInfo[i].isDeleted == NO)
7754             {
7755             if (i == outGroupNum)
7756                 localOutGroup = numLocalTaxa;
7757             numLocalTaxa++;
7758             }
7759         }
7760 }
7761 
7762 
ResetTranslateTable(void)7763 void ResetTranslateTable (void)
7764 {
7765     int i;
7766 
7767     for (i=0; i<numTranslates; i++)
7768         {
7769         free (transFrom[i]);
7770         free (transTo[i]);
7771         }
7772     free (transFrom);
7773     free (transTo);
7774     transFrom = NULL;
7775     transTo = NULL;
7776     numTranslates = 0;
7777     isTranslateDef = NO;
7778     isTranslateDiff = NO;
7779 }
7780 
7781 
ShowConPhylogram(FILE * fp,PolyTree * t,int screenWidth)7782 int ShowConPhylogram (FILE *fp, PolyTree *t, int screenWidth)
7783 {
7784     int             i, j, k, nLines, from, to, treeWidth=0, barLength, printExponential,
7785                     precision, width, newPos, curPos, nTimes, numSpaces, maxLabelLength;
7786     char            *printLine, *markLine, temp[30], *label;
7787     MrBFlt          scale, f, scaleBar;
7788     PolyNode        *p, *q;
7789 
7790     /* set max label length */
7791     maxLabelLength = 20;
7792 
7793     /* allocate space for label, printLine and markLine */
7794     printLine = (char *) SafeCalloc ((2*screenWidth+2),sizeof(char));
7795     label = (char *) SafeCalloc (maxLabelLength+1, sizeof(char));
7796     if (!printLine || !label)
7797         return ERROR;
7798     markLine = printLine + screenWidth + 1;
7799 
7800     /* calculate scale */
7801     scale = 0.0;
7802     t->root->f = 0.0;
7803     for (i=t->nNodes-2; i>=0; i--)
7804         {
7805         p = t->allDownPass[i];
7806         /* find distance to root in relevant units */
7807         if (sumtParams.isClock == YES && sumtParams.isCalibrated == NO)
7808             p->f = t->root->depth - p->depth;
7809         else if (sumtParams.isClock == YES && sumtParams.isCalibrated == YES)
7810             p->f = t->root->age - p->age;
7811         else
7812             p->f = p->anc->f + p->length;
7813         if (p->left == NULL)
7814             {
7815             f = p->f / (screenWidth - Label(p,YES,NULL,maxLabelLength) - 2);
7816             if (f > scale)
7817                 {
7818                 scale = f;
7819                 treeWidth = screenWidth - Label(p,YES,NULL,maxLabelLength) - 2;
7820                 }
7821             }
7822         }
7823 
7824     /* calculate x coordinates */
7825     for (i=0; i<t->nNodes; i++)
7826         {
7827         p = t->allDownPass[i];
7828         p->x = (int) (0.5 + (p->f / scale));
7829         }
7830 
7831     /* calculate y coordinates and lines to print */
7832     for (i=nLines=0; i<t->nNodes; i++)
7833         {
7834         p = t->allDownPass[i];
7835         if (p->left != NULL)
7836             {
7837             /* internal node */
7838             for (q=p->left->sib; q->sib!=NULL; q=q->sib)
7839                 ;
7840             p->y = (int) (0.5 + ((p->left->y + q->y) / 2.0));
7841             }
7842         else
7843             {
7844             /* terminal node */
7845             p->y = nLines;
7846             nLines += 2;
7847             }
7848         }
7849 
7850     /* print tree line by line */
7851 
7852     for (i=0; i<nLines; i++)
7853         {
7854         MrBayesPrint ("%s   ", spacer);
7855         /* empty printLine */
7856         for (j=0; j<screenWidth; j++)
7857             {
7858             printLine[j] = ' ';
7859             }
7860         printLine[j]='\0';
7861 
7862         for (j=0; j<t->nNodes; j++)
7863             {
7864             p = t->allDownPass[j];
7865             if (p->y != i)
7866                 continue;
7867 
7868             /* this branch should be printed */
7869             /* add branch */
7870             if (p->anc == NULL)
7871                 {
7872                 /* this is the root of the whole tree */
7873                 printLine[p->x] = '+';
7874                 }
7875             else
7876                 {
7877                 /* this is an ordinary branch */
7878                 to = p->x;
7879                 from = p->anc->x;
7880                 for (k=from+1; k<=to; k++)
7881                     printLine[k] = '-';
7882                 if (p == p->anc->left)
7883                     {
7884                     if (markLine[from] == 0)
7885                         printLine[from] = '/';
7886                     else
7887                         printLine[from] = '|';
7888                     markLine[from] ++;
7889                     }
7890                 else if (p->sib == NULL)
7891                     {
7892                     if (markLine[from] == 1)
7893                         printLine[from] = '\\';
7894                     else
7895                         printLine[from] = '|';
7896                     markLine[from] --;
7897                     }
7898                 if (p->left!=NULL)
7899                     {
7900                     if (from != to)
7901                         printLine[to] = '+';
7902                     else
7903                         printLine[to] = '|';
7904                     }
7905                 else
7906                     {
7907                     /* add label if the branch is terminal */
7908                     Label(p,YES,label,maxLabelLength);
7909                     sprintf (printLine+to+2,"%s", label);
7910                     }
7911                 }
7912             }
7913 
7914         /* check for cross branches */
7915         for (j=0; j<screenWidth; j++)
7916             {
7917             if (markLine[j] >= 1 && printLine[j] == ' ')
7918                 printLine[j] = '|';
7919             }
7920         MrBayesPrintf (fp, "%s\n",printLine);
7921         }
7922 
7923     /* print scale */
7924     k = (int) (floor (log10 (scale * 80)));
7925     scaleBar = pow (10, k);
7926     barLength = (int) (scaleBar / scale);
7927     if (barLength > 80)
7928         {
7929         barLength /= 10;
7930         scaleBar /= 10.0;
7931         }
7932     else if (barLength > 40)
7933         {
7934         barLength /= 5;
7935         scaleBar /= 5.0;
7936         }
7937     else if (barLength > 16)
7938         {
7939         barLength /= 2;
7940         scaleBar /= 2.0;
7941         }
7942 
7943     if (t->isClock == YES)
7944         {
7945         MrBayesPrint ("%s   ", spacer);
7946         for (i=0; i<treeWidth; i++)
7947             printLine[i] = '-';
7948         nTimes = (int) (treeWidth / (scaleBar / scale));
7949         for (i=0; i<=nTimes; i++)
7950             printLine[treeWidth - (int)(i*scaleBar/scale)] = '|';
7951         MrBayesPrint ("%s\n", printLine);
7952 
7953         MrBayesPrint ("%s   ", spacer);
7954         f = treeWidth * scale;
7955         if (f >= 1000.0 || f < 0.10)
7956             {
7957             printExponential = YES;
7958             precision = 0;
7959             }
7960         else
7961             {
7962             printExponential = NO;
7963             precision = 2 - (int) (log10 (f));
7964             }
7965 
7966         curPos = 0;
7967         f = nTimes * scaleBar;
7968         while (curPos < treeWidth)
7969             {
7970             /* print the number */
7971             if (printExponential == YES)
7972                 sprintf (temp, "%.2e", f);
7973             else
7974                 sprintf (temp, "%.*lf", precision, f);
7975 
7976             /* room to print ? if so, print */
7977             width = (int) strlen (temp);
7978             newPos = treeWidth - (int) (nTimes * (scaleBar / scale));
7979             numSpaces = newPos - width / 2 - curPos;
7980             if (numSpaces >= 0 || (numSpaces >= -2 && curPos == 0))
7981                 {
7982                 while (numSpaces > 0)
7983                     {
7984                     printLine[curPos++] = ' ';
7985                     numSpaces--;
7986                     }
7987                 for (i=0; temp[i]!='\0'; i++)
7988                     printLine[curPos++] = temp[i];
7989                 }
7990 
7991             /* get new number */
7992             f -= scaleBar;
7993             nTimes--;
7994             }
7995 
7996         MrBayesPrint ("%s\n", printLine);
7997 
7998         if (sumtParams.isCalibrated == YES)
7999             MrBayesPrint ("\n%s   [User-defined time units]\n\n", spacer);
8000         else
8001             MrBayesPrint ("\n%s   [Expected changes per site]\n\n", spacer);
8002         }
8003     else
8004         {
8005         MrBayesPrintf (fp, "%s   |", spacer);
8006         for (i=0; i<barLength-1; i++)
8007             MrBayesPrintf (fp, "-");
8008         MrBayesPrintf (fp, "| %1.3lf expected changes per site\n\n", scaleBar);
8009         }
8010 
8011     free (printLine);
8012 
8013     return NO_ERROR;
8014 }
8015 
8016 
ShowConTree(FILE * fp,PolyTree * t,int screenWidth,int showSupport)8017 int ShowConTree (FILE *fp, PolyTree *t, int screenWidth, int showSupport)
8018 {
8019     int             i, j, k, treeWidth, minBranchLength, maxWidth, isTreeDivided,
8020                     printWidth, nLines, nodesToBePrinted, from, to, maxLabelLength,
8021                     maxLength;
8022     char            *printLine, *markLine, temp[20], *label;
8023     PolyNode        *p=NULL, *q;
8024 
8025     maxLength = 20;         /* max length of label */
8026     minBranchLength = 5;    /* min length of branch in tree */
8027     isTreeDivided = NO;
8028 
8029     /* allocate space for printLine, markLine and label */
8030     printLine = (char *) SafeCalloc (maxLength+1+(2*screenWidth+2),sizeof(char));
8031     if (!printLine)
8032         return ERROR;
8033     markLine = printLine + screenWidth + 1;
8034     label = markLine + screenWidth + 1;
8035 
8036     /* get fresh internal node indices */
8037     k = t->nNodes - t->nIntNodes;
8038     for (i=0; i<t->nIntNodes; i++)
8039         {
8040         p = t->intDownPass[i];
8041         p->index = k++;
8042         }
8043 
8044     /* calculate max length of labels including taxon index number */
8045     maxLabelLength = 0;
8046     for (i=0; i<t->nNodes; i++)
8047         {
8048         p = t->allDownPass[i];
8049         if (p->left == NULL)
8050             {
8051             j = Label(p,YES,NULL,maxLength);
8052             if (j > maxLabelLength)
8053                 maxLabelLength = j;
8054             }
8055         }
8056 
8057     /* make sure label can hold an interior node index number */
8058     j = (int) (3.0 + log10((MrBFlt)t->nNodes));
8059     maxLabelLength = (maxLabelLength > j ? maxLabelLength : j);
8060 
8061     /* calculate remaining screen width for tree
8062        and maxWidth in terms of branches */
8063     treeWidth = screenWidth - maxLabelLength - 1;
8064     maxWidth = treeWidth / minBranchLength;
8065 
8066     /* unmark whole tree */
8067     for (i=0; i<t->nNodes; i++)
8068         t->allDownPass[i]->mark = 0;
8069     nodesToBePrinted = t->nNodes;
8070 
8071     while (nodesToBePrinted > 0)
8072         {
8073         /* count depth of nodes in unprinted tree */
8074         for (i=0; i<t->nNodes; i++)
8075             {
8076             p = t->allDownPass[i];
8077             if (p->mark == 0)   /* the node has not been printed yet */
8078                 {
8079                 p->x = 0;
8080                 /* if it is an interior node in the tree that will be printed
8081                    compute the depth of the node */
8082                 if (p->left != NULL && p->left->mark == 0)
8083                     {
8084                     for (q = p->left; q!=NULL; q=q->sib)
8085                         {
8086                         if (q->x > p->x)
8087                             p->x = q->x;
8088                         }
8089                     p->x++;
8090                     /* break when root of print subtree has been found */
8091                     if (p->x >= maxWidth)
8092                         break;
8093                     }
8094                 }
8095             }
8096 
8097         /* if internal node then find largest nonprinted subtree among descendant nodes */
8098         if (p->anc != NULL)
8099             {
8100             for (q=p->left; q!=NULL; q=q->sib)
8101                 {
8102                 if (q->x == p->x - 1 && q->mark == 0)
8103                     p = q;
8104                 }
8105             MrBayesPrintf (fp, "%s   Subtree rooted at node %d:\n\n", spacer, p->index);
8106             isTreeDivided = YES;
8107             }
8108         else if (isTreeDivided == YES)
8109             MrBayesPrintf (fp, "%s   Root part of tree:\n\n", spacer);
8110 
8111         /* mark subtree for printing and
8112            translate x coordinates from depth to position */
8113         if (p->anc == NULL)
8114             printWidth = p->x;
8115         else
8116             printWidth = p->x + 1;
8117         p->mark = 1;
8118         p->x = (int) (treeWidth - 0.5 - ((treeWidth - 1) * (p->x / (MrBFlt) printWidth)));
8119         for (i=t->nNodes-2; i>=0; i--)
8120             {
8121             p = t->allDownPass[i];
8122             if (p->mark == 0 && p->anc->mark == 1)
8123                 {
8124                 p->mark = 1;
8125                 p->x = (int) (treeWidth - 0.5 - ((treeWidth - 1) * (p->x / (MrBFlt) printWidth)));
8126                 }
8127             }
8128 
8129         /* calculate y coordinates of nodes to be printed and lines to print */
8130         for (i=nLines=0; i<t->nNodes; i++)
8131             {
8132             p = t->allDownPass[i];
8133             if (p->mark == 1)
8134                 {
8135                 if (p->left != NULL && p->left->mark == 1)
8136                     {
8137                     /* internal node */
8138                     for (q=p->left->sib; q->sib!=NULL; q=q->sib)
8139                         ;
8140                     p->y = (int) (0.5 + ((p->left->y + q->y) / 2.0));
8141                     }
8142                 else
8143                     {
8144                     /* terminal node */
8145                     p->y = nLines;
8146                     nLines += 2;
8147                     }
8148                 }
8149             }
8150 
8151         /* print subtree line by line */
8152         for (i=0; i<nLines; i++)
8153             {
8154             MrBayesPrintf (fp, "%s   ", spacer);
8155             /* empty printLine */
8156             for (j=0; j<screenWidth; j++)
8157                 {
8158                 printLine[j] = ' ';
8159                 }
8160             printLine[j]='\0';
8161 
8162             for (j=0; j<t->nNodes; j++)
8163                 {
8164                 p = t->allDownPass[j];
8165                 if (p->mark != 1 || p->y != i)
8166                     continue;
8167 
8168                 /* this branch should be printed
8169                    add label if the branch is terminal in tree to be printed */
8170                 if (p->left == NULL)
8171                     {
8172                     Label (p,YES,label,maxLength);
8173                     sprintf (printLine+treeWidth+1,"%s", label);
8174                     }
8175                 else if (p->left->mark == 2)
8176                     sprintf (printLine+treeWidth+1,"(%d)", p->index);
8177 
8178                 /* add branch */
8179                 if (p->anc == NULL)
8180                     {
8181                     /* this is the root of the whole tree */
8182                     printLine[p->x] = '+';
8183                     nodesToBePrinted--;
8184                     }
8185                 else if (p->anc->mark == 0)
8186                     {
8187                     /* this is a root of a subtree
8188                        this branch will have to be printed again so do
8189                        not decrease nodesToBePrinted */
8190                     to = p->x;
8191                     from = 0;
8192                     for (k=from; k<to; k++)
8193                         printLine[k] = '-';
8194                     printLine[to] = '+';
8195                     if (showSupport == YES)
8196                         sprintf (temp, "%d", (int) (p->support*100.0 + 0.5));
8197                     else
8198                         *temp='\0';
8199                     from = (int)(from + 1.5 + ((to - from - 1 - strlen(temp)) / 2.0));
8200                     for (k=0; temp[k]!='\0'; k++)
8201                         printLine[from++] = temp[k];
8202                     }
8203                 else
8204                     {
8205                     /* this is an ordinary branch */
8206                     to = p->x;
8207                     from = p->anc->x;
8208                     for (k=from+1; k<=to; k++)
8209                         printLine[k] = '-';
8210                     if (p == p->anc->left)
8211                         {
8212                         printLine[from] = '/';
8213                         markLine[from] = 1;
8214                         }
8215                     else if (p->sib == NULL)
8216                         {
8217                         printLine[from] = '\\';
8218                         markLine[from] = 0;
8219                         }
8220                     if (p->left!=NULL && p->left->mark!=2)
8221                         {
8222                         printLine[to] = '+';
8223                         if (showSupport == YES)
8224                             sprintf (temp, "%d", (int) (p->support*100.0 + 0.5));
8225                         else
8226                             *temp='\0';
8227                         from = (int)(from + 1.5 + ((to - from - 1 - strlen(temp)) / 2.0));
8228                         for (k=0; temp[k]!='\0'; k++)
8229                             printLine[from++] = temp[k];
8230                         }
8231                     nodesToBePrinted--;
8232                     }
8233                 }
8234 
8235             /* check for cross branches */
8236             for (j=0; j<treeWidth; j++)
8237                 {
8238                 if (markLine[j] == 1 && printLine[j] == ' ')
8239                     printLine[j] = '|';
8240                 }
8241 
8242             MrBayesPrintf (fp, "%s\n",printLine);
8243             }
8244 
8245         /* mark printed branches */
8246         for (i=0; i<t->nNodes; i++)
8247             {
8248             p = t->allDownPass[i];
8249             if (p->mark == 1)
8250                 {
8251                 if (p->anc == NULL)
8252                     p->mark = 2;
8253                 else if (p->anc->mark == 0)
8254                     p->mark = 0;    /* this branch will have to be printed again */
8255                 else
8256                     p->mark = 2;
8257                 }
8258             }
8259 
8260         }   /* next subtree */
8261 
8262     free (printLine);
8263 
8264     return NO_ERROR;
8265 }
8266 
8267 
ShowParts(FILE * fp,BitsLong * p,int nTaxaToShow)8268 void ShowParts (FILE *fp, BitsLong *p, int nTaxaToShow)
8269 {
8270     int         i;
8271     BitsLong    x, y, bitsLongOne;
8272 
8273     bitsLongOne = 1;
8274 
8275     for (i=0; i<nTaxaToShow; i++)
8276         {
8277         y = p[i / nBitsInALong];
8278         x = bitsLongOne << (i % nBitsInALong);
8279         if ((x & y) == 0)
8280             MrBayesPrintf (fp, ".");
8281         else
8282             MrBayesPrintf (fp, "*");
8283         }
8284 }
8285 
8286 
ShowSomeParts(FILE * fp,BitsLong * p,int offset,int nTaxaToShow)8287 void ShowSomeParts (FILE *fp, BitsLong *p, int offset, int nTaxaToShow)
8288 {
8289     int         i;
8290     BitsLong    x, y, bitsLongOne;
8291 
8292     bitsLongOne = 1;
8293 
8294     for (i=offset; i<offset+nTaxaToShow; i++)
8295         {
8296         y = p[i / nBitsInALong];
8297         x = bitsLongOne << (i % nBitsInALong);
8298         if ((x & y) == 0)
8299             MrBayesPrintf (fp, ".");
8300         else
8301             MrBayesPrintf (fp, "*");
8302         }
8303 }
8304 
8305 
SortPartCtr(PartCtr ** item,int left,int right)8306 void SortPartCtr (PartCtr **item, int left, int right)
8307 {
8308     register int    i, j;
8309     PartCtr         *tempPartCtr;
8310     int             x;
8311 
8312     assert (left >= 0);
8313     assert (right >= 0);
8314 
8315     i = left;
8316     j = right;
8317     x = item[(left+right)/2]->totCount;
8318     do
8319         {
8320         while (item[i]->totCount > x && i < right)
8321             i++;
8322         while (x > item[j]->totCount && j > left)
8323             j--;
8324         if (i <= j)
8325             {
8326             tempPartCtr = item[i];
8327             item[i] = item[j];
8328             item[j] = tempPartCtr;
8329 
8330             i++;
8331             j--;
8332             }
8333         } while (i <= j);
8334     if (left < j)
8335         SortPartCtr (item, left, j);
8336     if (i < right)
8337         SortPartCtr (item, i, right);
8338 }
8339 
8340 
SortTerminalPartCtr(PartCtr ** item,int len)8341 void SortTerminalPartCtr (PartCtr **item, int len)
8342 {
8343     register int    i, j, maxCount;
8344     PartCtr         *temp;
8345 
8346     maxCount = item[0]->totCount;
8347 
8348     /* put root first */
8349     for (i=0; item[i]->totCount == maxCount; i++)
8350         if (NumBits(item[i]->partition, sumtParams.BitsLongsNeeded) == sumtParams.numTaxa)
8351             break;
8352 
8353     if (i!=0)
8354         {
8355         temp = item[0];
8356         item[0] = item[i];
8357         item[i] = temp;
8358         }
8359 
8360     /* then find terminals in index order */
8361     for (i=1; i<=sumtParams.numTaxa; i++)
8362         {
8363         for (j=i; item[j]->totCount == maxCount && j<len; j++)
8364             if (NumBits(item[j]->partition, sumtParams.BitsLongsNeeded) == 1 &&
8365                 FirstTaxonInPartition(item[j]->partition, sumtParams.BitsLongsNeeded) == i-1)
8366                 break;
8367 
8368         if (j!=i)
8369             {
8370             temp = item[i];
8371             item[i] = item[j];
8372             item[j] = temp;
8373             }
8374         }
8375 }
8376 
8377 
SortTreeCtr(TreeCtr ** item,int left,int right)8378 void SortTreeCtr (TreeCtr **item, int left, int right)
8379 {
8380     register int    i, j;
8381     TreeCtr         *tempTreeCtr;
8382     int             x;
8383 
8384     i = left;
8385     j = right;
8386     x = item[(left+right)/2]->count;
8387     do
8388         {
8389         while (item[i]->count > x && i < right)
8390             i++;
8391         while (x > item[j]->count && j > left)
8392             j--;
8393         if (i <= j)
8394             {
8395             tempTreeCtr = item[i];
8396             item[i] = item[j];
8397             item[j] = tempTreeCtr;
8398 
8399             i++;
8400             j--;
8401             }
8402         } while (i <= j);
8403     if (left < j)
8404         SortTreeCtr (item, left, j);
8405     if (i < right)
8406         SortTreeCtr (item, i, right);
8407 }
8408 
8409 
8410 /* StoreSumtTree: Store tree in treeList in packed format */
StoreSumtTree(PackedTree * treeList,int index,PolyTree * t)8411 int StoreSumtTree (PackedTree *treeList, int index, PolyTree *t)
8412 {
8413     int orderLen, numBrlens;
8414 
8415     assert (treeList[index].brlens == NULL);
8416     assert (treeList[index].order == NULL);
8417 
8418     /* get tree dimensions */
8419     numBrlens = t->nNodes - 1;
8420     orderLen = t->nIntNodes - 1;
8421 
8422     /* allocate space */
8423     treeList[index].brlens = (MrBFlt *) SafeCalloc (numBrlens, sizeof(MrBFlt));
8424     treeList[index].order  = (int *) SafeCalloc (orderLen, sizeof(MrBFlt));
8425     if (!treeList[index].order || !treeList[index].brlens)
8426         {
8427         MrBayesPrint ("%s   Could not store packed representation of tree '%s'\n", spacer, t->name);
8428         return (ERROR);
8429         }
8430 
8431     /* store tree */
8432     if (t->isRooted == YES)
8433         StoreRPolyTree (t, treeList[index].order, treeList[index].brlens);
8434     else
8435         StoreUPolyTree (t, treeList[index].order, treeList[index].brlens);
8436 
8437     return (NO_ERROR);
8438 }
8439 
8440 
8441 /* TreeCtrUppass: extract TreeCtr nodes in uppass sequence */
TreeCtrUppass(TreeCtr * r,TreeCtr ** uppass,int * index)8442 void TreeCtrUppass (TreeCtr *r, TreeCtr **uppass, int *index)
8443 {
8444     if (r != NULL)
8445         {
8446         uppass[(*index)++] = r;
8447 
8448         TreeCtrUppass (r->left, uppass, index);
8449         TreeCtrUppass (r->right, uppass, index);
8450         }
8451 }
8452 
8453 
TreeProb(void)8454 int TreeProb (void)
8455 {
8456     int         i, num, nInSets[5];
8457     MrBFlt      treeProb, cumTreeProb;
8458     TreeCtr     **trees;
8459     Tree        *theTree;
8460 
8461     /* check if we need to do this */
8462     if (sumtParams.calcTreeprobs == NO)
8463         return (NO_ERROR);
8464 
8465     MrBayesPrint ("%s   Calculating tree probabilities...\n\n", spacer);
8466 
8467     /* allocate space for tree counters and trees */
8468     trees = (TreeCtr **) SafeCalloc ((size_t)numUniqueTreesFound, sizeof(TreeCtr *));
8469     theTree = AllocateTree (sumtParams.numTaxa);
8470     if (!trees || !theTree)
8471         {
8472         MrBayesPrint ("%s   Problem allocating trees or theTree in TreeProb\n", spacer);
8473         return (ERROR);
8474         }
8475 
8476     /* extract trees */
8477     i = 0;
8478     TreeCtrUppass (treeCtrRoot, trees, &i);
8479 
8480     /* sort trees */
8481     SortTreeCtr (trees, 0, numUniqueTreesFound-1);
8482 
8483     /* set basic params in receiving tree */
8484     theTree->isRooted = sumtParams.isRooted;
8485     if (theTree->isRooted)
8486         {
8487         theTree->nNodes = 2 * sumtParams.numTaxa;
8488         theTree->nIntNodes = sumtParams.numTaxa - 1;
8489         }
8490     else
8491         {
8492         theTree->nNodes = 2 * sumtParams.numTaxa - 2;
8493         theTree->nIntNodes = sumtParams.numTaxa - 2;
8494         }
8495 
8496     /* show tree data */
8497     cumTreeProb = 0.0;
8498     nInSets[0] = nInSets[1] = nInSets[2] = nInSets[3] = nInSets[4] = 0;
8499     for (num=0; num<numUniqueTreesFound; num++)   /* loop over all of the trees that were found */
8500         {
8501         /* get probability of tree */
8502         treeProb = (MrBFlt)trees[num]->count / (MrBFlt)sumtParams.numTreesSampled;
8503         cumTreeProb += treeProb;
8504         if (cumTreeProb >= 0.0 && cumTreeProb < 0.5)
8505             nInSets[0]++;
8506         else if (cumTreeProb >= 0.5 && cumTreeProb < 0.9)
8507             nInSets[1]++;
8508         else if (cumTreeProb >= 0.9 && cumTreeProb < 0.95)
8509             nInSets[2]++;
8510         else if (cumTreeProb >= 0.95 && cumTreeProb < 0.99)
8511             nInSets[3]++;
8512         else
8513             nInSets[4]++;
8514 
8515         /* draw tree to stdout */
8516         if (theTree->isRooted == YES)
8517             RetrieveRTopology (theTree, trees[num]->order);
8518         else
8519             RetrieveUTopology (theTree, trees[num]->order);
8520         if (sumtParams.showSumtTrees == YES)
8521             {
8522             MrBayesPrint ("\n%s   Tree %d (p = %1.3lf, P = %1.3lf):\n\n", spacer, num+1, treeProb, cumTreeProb);
8523             ShowTree (theTree);
8524             }
8525 
8526         /* draw tree to file */
8527         if (num == 0)
8528             {
8529             MrBayesPrintf (fpTrees, "[This file contains the trees that were found during the MCMC\n");
8530             MrBayesPrintf (fpTrees, "search, sorted by posterior probability. \"p\" indicates the\n");
8531             MrBayesPrintf (fpTrees, "posterior probability of the tree whereas \"P\" indicates the\n");
8532             MrBayesPrintf (fpTrees, "cumulative posterior probability.]\n\n");
8533             MrBayesPrintf (fpTrees, "begin trees;\n");
8534             MrBayesPrintf (fpTrees, "   translate\n");
8535             for (i=0; i<sumtParams.numTaxa; i++)
8536                 {
8537                 if (i == sumtParams.numTaxa - 1)
8538                     MrBayesPrintf (fpTrees, "   %2d %s;\n", i+1, sumtParams.taxaNames[i]);
8539                 else
8540                     MrBayesPrintf (fpTrees, "   %2d %s,\n", i+1, sumtParams.taxaNames[i]);
8541                 }
8542             }
8543         MrBayesPrintf (fpTrees, "   tree tree_%d [p = %1.3lf, P = %1.3lf] = [&W %1.6lf] ", num+1, treeProb, cumTreeProb, treeProb);
8544         WriteTopologyToFile (fpTrees, theTree->root->left, theTree->isRooted);
8545         MrBayesPrintf (fpTrees, ";\n");
8546         if (num == numUniqueTreesFound - 1)
8547             MrBayesPrintf (fpTrees, "end;\n");
8548         }
8549 
8550     /* print out general information on credible sets of trees */
8551     i = nInSets[0] + nInSets[1] + nInSets[2] + nInSets[3] + nInSets[4];
8552     MrBayesPrint ("%s   Credible sets of trees (%d tree%s sampled):\n", spacer, i, i > 1 ? "s" : "");
8553     i = nInSets[0] + 1;
8554     if (i > 1)
8555         MrBayesPrint ("%s      50 %% credible set contains %d trees\n", spacer, i);
8556     i += nInSets[1];
8557     if (i > 1)
8558         MrBayesPrint ("%s      90 %% credible set contains %d trees\n", spacer, i);
8559     i += nInSets[2];
8560     if (i > 1)
8561         MrBayesPrint ("%s      95 %% credible set contains %d trees\n", spacer, i);
8562     i += nInSets[3];
8563     MrBayesPrint ("%s      99 %% credible set contains %d tree%s\n\n", spacer, i, i > 1 ? "s" : "");
8564 
8565     /* free memory */
8566     free (trees);
8567 
8568     return (NO_ERROR);
8569 }
8570 
8571 
WriteConTree(PolyNode * p,FILE * fp,int showSupport)8572 void WriteConTree (PolyNode *p, FILE *fp, int showSupport)
8573 {
8574     PolyNode        *q;
8575 
8576     if (p->anc != NULL)
8577         if (p->anc->left == p)
8578             fprintf (fp, "(");
8579 
8580     for (q = p->left; q != NULL; q = q->sib)
8581         {
8582         if (q->anc->left != q) /* Note that q->anc always exists (it is p) */
8583             fprintf (fp, ",");
8584         WriteConTree (q, fp, showSupport);
8585         }
8586     if (p->left == NULL)
8587         {
8588         if (sumtParams.brlensDef == YES)
8589             {
8590             if (sumtParams.isClock == NO)
8591                 fprintf (fp, "%d:%s", p->index+1, MbPrintNum(p->length));
8592             else
8593                 fprintf (fp, "%d:%s", p->index+1, MbPrintNum(p->anc->depth - p->depth));
8594             }
8595         else
8596             fprintf (fp, "%d", p->index+1);
8597         }
8598 
8599     if (p->sib == NULL && p->anc != NULL)
8600         {
8601         if (p->anc->anc != NULL)
8602             {
8603             if (sumtParams.brlensDef == YES && showSupport == NO)
8604                 {
8605                 if (sumtParams.isClock == NO)
8606                     fprintf (fp, "):%s", MbPrintNum(p->anc->length));
8607                 else
8608                     fprintf (fp, "):%s", MbPrintNum(p->anc->anc->depth - p->anc->depth));
8609                 }
8610             else if (sumtParams.brlensDef == NO && showSupport == YES)
8611                 fprintf (fp, ")%1.3lf", p->anc->support);
8612             else if (sumtParams.brlensDef == YES && showSupport == YES)
8613                 {
8614                 if (sumtParams.isClock == NO)
8615                     fprintf (fp, ")%1.3lf:%s", p->anc->support, MbPrintNum(p->anc->length));
8616                 else
8617                     fprintf (fp, ")%1.3lf:%s", p->anc->support, MbPrintNum(p->anc->anc->depth - p->anc->depth));
8618                 }
8619             else
8620                 fprintf (fp, ")");
8621             }
8622         else
8623             fprintf (fp, ")");
8624         }
8625 }
8626 
8627 
8628 /* WriteFigTreeConTree: Include rich information for each node in a consensus tree */
WriteFigTreeConTree(PolyNode * p,FILE * fp,PartCtr ** treeParts)8629 void WriteFigTreeConTree (PolyNode *p, FILE *fp, PartCtr **treeParts)
8630 {
8631     PolyNode        *q;
8632 
8633     if (p->left == NULL)
8634         {
8635         fprintf (fp, "%d", p->index+1);
8636         if (sumtParams.isClock == NO)
8637             PrintFigTreeNodeInfo(fp, treeParts[p->partitionIndex], p->length);
8638         else if (sumtParams.isCalibrated == YES)
8639             PrintFigTreeNodeInfo(fp, treeParts[p->partitionIndex], p->anc->age - p->age);
8640         else
8641             PrintFigTreeNodeInfo(fp, treeParts[p->partitionIndex], p->anc->depth - p->depth);
8642         }
8643     else
8644         {
8645         fprintf  (fp, "(");
8646         for (q = p->left; q != NULL; q = q->sib)
8647             {
8648             WriteFigTreeConTree (q, fp, treeParts);
8649             if (q->sib != NULL)
8650                 fprintf (fp, ",");
8651             }
8652         fprintf (fp, ")");
8653         if (p->partitionIndex >= 0 && p->partitionIndex < numUniqueSplitsFound)
8654             {
8655             if (p->anc == NULL)
8656                 {
8657                 if (sumtParams.isClock == YES)
8658                     PrintFigTreeNodeInfo(fp,treeParts[p->partitionIndex], -1.0);
8659                 }
8660             else if (sumtParams.isClock == NO)
8661                 PrintFigTreeNodeInfo(fp, treeParts[p->partitionIndex], p->length);
8662             else if (sumtParams.isCalibrated == YES)
8663                 PrintFigTreeNodeInfo(fp, treeParts[p->partitionIndex], p->anc->age - p->age);
8664             else
8665                 PrintFigTreeNodeInfo(fp, treeParts[p->partitionIndex], p->anc->depth - p->depth);
8666             }
8667         }
8668 }
8669 
8670