/*
* MrBayes 2.0
*
* John P. Huelsenbeck
* Department of Biology
* University of Rochester
* Rochester, NY 14627
*
* johnh@brahms.biology.rochester.edu
*
* Fredrik Ronquist
* Dept. Systematic Zoology
* Evolutionary Biology Centre
* Uppsala University
* Norbyv. 18D, SE-752 36 Uppsala, Sweden
*
* fredrik.ronquist@ebc.uu.se
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <string.h>
#include <ctype.h>
#include "jph.h"
#include "tree.h"
#include "mcmc.h"
#include "command.h"
#include "gamma.h"
#include "linalg.h"
#include "matrices.h"
#include "complex.h"
#define MORPH
#if defined (MORPH)
#define NUM_ALLOCS 45
#else
#define NUM_ALLOCS 44
#endif
#define ALLOC_KAPPA 0
#define ALLOC_SUBPARAMS 1
#define ALLOC_BASEFREQS 2
#define ALLOC_GAMMA_SHAPE 3
#define ALLOC_SITE_RATES 4
#define ALLOC_UNSCALED_SITE_RATES 5
#define ALLOC_NSITES_IN_PART 6
#define ALLOC_MATRIX 7
#define ALLOC_N_SITE_PATS 8
#define ALLOC_PART_ID 9
#define ALLOC_NODES 10
#define ALLOC_ROOT 11
#define ALLOC_ALLDOWNPASS 12
#define ALLOC_INTDOWNPASS 13
#define ALLOC_CLUPDATE_FLAG 14
#define ALLOC_COND_LIKES 15
#define ALLOC_COND_SCALER 16
#define ALLOC_DISTANCES 17
#define ALLOC_TREE_HEIGHT 18
#define ALLOC_ANC_STATES 19
#define ALLOC_TEMP_ANC_STATES 20
#define ALLOC_PAT_IDS 21
#define ALLOC_SP_RATE 22
#define ALLOC_EX_RATE 23
#define ALLOC_OMEGA 24
#define ALLOC_PUR 25
#define ALLOC_NEU 26
#define ALLOC_POS 27
#define ALLOC_AUTO_GAMMA 28
#define ALLOC_AUTO_GAMMA2 29
#define ALLOC_LAG 30
#define ALLOC_INV_P 31
#define ALLOC_SWITCH_RATE 32
#define ALLOC_SWITCH_PI 33
#define ALLOC_GC1 34
#define ALLOC_GC2 35
#define ALLOC_FRAC_A 36
#define ALLOC_FRAC_G 37
#define ALLOC_LN_SITE_SCALER 38
#define ALLOC_SCALER_UPDATE_FLAG 39
#define ALLOC_TERM_STATES 40
#define ALLOC_TI_PROBS 41
#define ALLOC_TI_FLAGS 42
#define ALLOC_STATE_SET 43
#if defined (MORPH)
#define ALLOC_BETA 44
#endif
#define MAX_PROPOSAL_SIZE 33
#if defined (MORPH)
#define NUM_PROPOSAL_TYPES 24
#else
#define NUM_PROPOSAL_TYPES 23
#endif
#define CHANGE_QMAT 0
#define CHANGE_BASEFREQS 1
#define CHANGE_GAMMA_SHAPE 2
#define CHANGE_SITE_RATES 3
#define CHANGE_UNROOT_LOCAL 4
#define CHANGE_CLOCK_LOCAL 5
#define CHANGE_CLOCK_TIME_LOCAL 6
#define CHANGE_TREE_HEIGHT 7
#define CHANGE_WORM 8
#define CHANGE_NODE_TIME 9
#define CHANGE_BD_PARAMS 10
#define CHANGE_OMEGA 11
#define CHANGE_OMEGA_PROBS 12
#define CHANGE_AUTO_CORR 13
#define CHANGE_LAG 14
#define CHANGE_TREE_SPR 15
#define CHANGE_INV_P 16
#define CHANGE_SWITCH_RATE 17
#define CHANGE_UNROOT_TBR 18
#define CHANGE_GCSWITCH 19
#define CHANGE_TREE_FTBR 20
#define CHANGE_BRLEN 21
#define CHANGE_ERASER 22
#if defined (MORPH)
#define CHANGE_BETA_SHAPE 23
#endif
#define LIKE_EPSILON 1.0e-300
#define BRLEN_EPSILON 1.0e-8
#define RESCALE_FREQ 5
#define MAX_COVARIATES 20000
#define A 0
#define C 1
#define G 2
#define T 3
#define AA 0
#define AC 1
#define AG 2
#define AT 3
#define CA 4
#define CC 5
#define CG 6
#define CT 7
#define GA 8
#define GC 9
#define GG 10
#define GT 11
#define TA 12
#define TC 13
#define TG 14
#define TT 15
#define ROOTED 0
#define UNROOTED 1
#define SCREENWIDTH 60
#define SCREENWIDTH2 61
#undef DEBUG_START_TREE
#undef DEBUG_LOCAL
#undef DEBUG_LOCAL_CLOCK
#undef DEBUG_LOCAL_TIME_CLOCK
#undef SHOW_MOVE_WORM
#undef DEBUG_SPR
#undef DEBUG_TBR
#undef DEBUG_FTBR
#undef DEBUG_BRLENMOVE
#undef DEBUG_INITCONDLIKES
#undef TOPOLOGY_MOVE_STATS
#undef DEBUG_LNLIKEBIN
#undef TRANSLATE_TO_AA
#define SUPER_FAST
#define SMART_TI_PROBS
/*-pac- #define MORPH //NB! MORPH also defined earlier in this file to fix #define statements */
void BetaBreaks (double alpha, double beta, double *values, double *probs, int K);
double BetaCf (double a, double b, double x);
double BetaQuantile (double alpha, double beta, double x);
int BuildStartingTree (int numTaxa, int numChars, long int *seed, int showStartTree);
void CalcCijk (double *c_ijk, int n, double **u, double **v);
void CalcPij (double *c_ijk, int n, double *eigenValues, double v, double r, double **p);
void CalcPFSij (double *c_ijk, int n, double *eigenValues, double v, double r, double **p, double **f_p, double **s_p);
# if defined (SMART_TI_PROBS)
int CalcTransitionProbs (int whichState, int whichChain, int numRateCats);
int CalcTransAA (int whichState, int whichChain, int numRateCats);
int CalcTransCodon (int whichState, int whichChain);
int CalcTransCovarion (int whichState, int whichChain, int numRateCats);
int CalcTransDNA (int whichState, int whichChain, int numRateCats);
# endif
int CheckConstraints (void);
int ComplexChangeMatrix (double *eigenValues, double *eigvalsImag, complex **Ceigvecs,
complex **CinverseEigvecs, int n, double **p, double t, double r);
int ComplexDerivativesMatrix (double *eigenValues, double *eigvalsImag, complex **Ceigvecs,
complex **CinverseEigvecs, int n, double **f, double **s, double t, double r);
int CompressMatrix (int *numTaxa, int *numChars);
int CompressMatrixPars (int *numTaxa, int *numChars);
void CopyConditionalLikelihoods (int from, int to, int whichChain, int numTaxa, int numChars, int numRateCats);
void CopyTree (int from, int to, int whichChain);
void DirichletRandomVariable (double *alp, double *z, int n, long int *seed);
void FreeMemory (void);
double GetTreeLength (int whichState, int whichChain);
int GetDistances (int numTaxa, int numChars);
void GetDownPassSeq (TreeNode *p, int whichTree, int whichChain, int numTaxa, int *i, int *j);
int GetEigens (int n, double **q, double *eigenValues, double *eigvalsImag, double **eigvecs,
double **inverseEigvecs, complex **Ceigvecs, complex **CinverseEigvecs);
void GetEmpiricalAAFreqs (void);
void GetEmpiricalBaseFreqs (void);
void GetPossibleAAs (int nucCode, int nuc[]);
void GetPossibleNucs (int nucCode, int nuc[]);
void GetTempDownPassSeq (TreeNode *p, int *i, TreeNode **dp);
void HkyChangeMat (double **ch_prob, double time, double k, double r, double piA, double piC, double piG, double piT);
void HkyFirstMat (double **ch_prob, double time, double k, double r, double piA, double piC, double piG, double piT);
void HkySecondMat (double **ch_prob, double time, double k, double r, double piA, double piC, double piG, double piT);
double IncompleteBetaFunction (double alpha, double beta, double x);
int InitializeConditionalLikes (int numTaxa, int numChars, int numRateCats);
int InitializeTipStates (int numTaxa, int numChars);
int InitTiMatrix (double m[3][3], double x, double y, double z, double pPurifying, double pNeutral, double pPositive, int model);
int IsKink (TreeNode *p);
int IsLeaf (TreeNode *p);
int LnBDPrior (int whichState, int whichChain, int numTaxa, double *prob);
double LnGamma (double alp);
int LnLike (int whichState, int whichChain, int numChars, int numRateCats, double *lnL, int refreshScalers);
int LnLikeAA (int whichState, int whichChain, int numChars, int numRateCats, double *lnL, int refreshScalers);
int LnLikeCodon (int whichState, int whichChain, int numChars, double *lnL, int refreshScalers);
int LnLikeCovarion (int whichState, int whichChain, int numChars, int numRateCats, double *lnL, int refreshScalers);
int LnLikeDNA (int whichState, int whichChain, int numChars, int numRateCats, double *lnL, int refreshScalers);
int LnLikeRestriction (int whichState, int whichChain, int numChars, int numRateCats, double *lnL, int refreshScalers);
int LnLikeStandardBin (int whichState, int whichChain, int numChars, int numRateCats, double *lnL, int refreshScalers);
int LnLikeStandardMk (int whichState, int whichChain, int numChars, int numRateCats, double *lnL, int refreshScalers);
double lnP1 (double t, double l, double m, double r);
double lnVt (double t, double l, double m, double r);
int MarkovChain (int numTaxa, int numChars, int numRateCats, long int *seed);
int MarkovChainPars (int numTaxa, int numChars, long int *seed);
void MarkPathDown (TreeNode *p, TreeNode *q);
int Move_ChangeAutoCorr (int proposedState, int whichChain, long int *seed, double *lnPriorRatio);
int Move_ChangeBaseFreqs (int proposedState, int whichChain, long int *seed, double *lnPriorRatio, double *lnProposalRatio);
int Move_ChangeBetaShape (int proposedState, int whichChain, long int *seed, double *lnPriorRatio);
int Move_ChangeBD (int proposedState, int whichChain, long int *seed);
int Move_ChangeBrLen (int proposedState, int whichChain, long int *seed, double *lnProposalRatio, double *lnPriorRatio);
int Move_ChangeClockWithLocal (int numTaxa, int proposedState, int whichChain, long int *seed, double *lnProposalRatio, double *lnPriorRatio);
int Move_ChangeEraser (int numTaxa, int proposedState, int whichChain, long int *seed, double *lnProposalRatio, double *lnPriorRatio);
int Move_ChangeGammaShape (int proposedState, int whichChain, long int *seed, double *lnPriorRatio);
int Move_ChangeGCSwitch (int proposedState, int whichChain, long int *seed, double *lnPriorRatio, double *lnProposalRatio);
int Move_ChangeLag (int proposedState, int whichChain, long int *seed, double *lnPriorRatio, double *lnProposalRatio);
int Move_ChangeNNI (int numTaxa, int proposedState, int whichChain, long int *seed);
int Move_ChangeQMatrix (int proposedState, int whichChain, long int *seed, double *lnPriorRatio);
int Move_ChangeSiteRates (int proposedState, int whichChain, long int *seed, double *lnPriorRatio);
int Move_ChangeNodeTime (int numTaxa, int proposedState, int whichChain, long int *seed, double *lnProposalRatio, double *lnPriorRatio);
int Move_ChangeOmega (int proposedState, int whichChain, long int *seed, double *lnPriorRatio);
int Move_ChangeOmegaProbs (int proposedState, int whichChain, long int *seed, double *lnPriorRatio, double *lnProposalRatio);
int Move_ChangePropInv (int proposedState, int whichChain, long int *seed, double *lnPriorRatio);
int Move_ChangeSwitchRate (int proposedState, int whichChain, long int *seed, double *lnPriorRatio);
int Move_ChangeTimeClockWithLocal (int numTaxa, int proposedState, int whichChain, long int *seed, double *lnProposalRatio, double *lnPriorRatio);
int Move_ChangeTreeHeight (int proposedState, int whichChain, long int *seed, double *lnProposalRatio);
int Move_ChangeUnrootedWithLocal (int numTaxa, int proposedState, int whichChain, long int *seed, double *lnProposalRatio, double *lnPriorRatio);
int Move_SingleWorm (int numTaxa, int proposedState, int whichChain, long int *seed, double *lnProposalRatio, double *lnPriorRatio);
int Move_ChangeUnrootedWithSPR (int numTaxa, int proposedState, int whichChain, long int *seed, double *lnProposalRatio, double *lnPriorRatio);
int Move_ChangeTBR (int numTaxa, int proposedState, int whichChain, long int *seed, double *lnProposalRatio, double *lnPriorRatio);
int Move_ChangeFTBR (int numTaxa, int proposedState, int whichChain, long int *seed, double *lnProposalRatio, double *lnPriorRatio);
int NumAdjacentMarked (TreeNode *p);
FILE *OpenFile(char *filename, int isNexus);
double ParsimonyLength (int whichState, int whichChain, int numChars);
int PerturnStartingTree (int numTaxa, long int *seed);
int PrepareOutputFiles (void);
int PrepareParsOutputFiles (void);
int PrintAncStatesAA (int whichState, int whichChain, int numChars, int numRateCats, int whichGen);
int PrintAncStatesDNA (int whichState, int whichChain, int numChars, int numRateCats, int whichGen);
int PrintPosSelProbs (int whichState, int whichChain, int numChars, int numRateCats, int whichGen);
int PrintRateFactors (int whichState, int whichChain, int numChars, int numRateCats, int whichGen);
int PrintStatesToFile (int n, int coldId, int whichState, double logLike, double *constrainedNodes, double *calibratedNodes);
int ProposeNewState (long int *seed);
double RandomNumber (long int *seed);
double RndGamma (double s, long int *seed);
double RndGamma1 (double s, long int *seed);
double RndGamma2 (double s, long int *seed);
int SetAARates (void);
void SetCode (void);
int SetModel (int *numRateCats);
int SetAAQMatrix (double **a, int whichTree, int whichChain);
int SetCodonQMatrix (double **a, int whichTree, int whichChain, double nonsyn, double kap);
int SetCodonSwitchQMatrix (double **a, int whichTree, int whichChain, double nonsyn, double kap, double sr);
int SetAACovQMatrix (double **a, int whichTree, int whichChain, double r);
int SetDNACovQMatrix (double **a, int whichTree, int whichChain, double r);
int SetGCSwitchQMatrix (double **a, int whichTree, int whichChain, double r);
int SetQMatrix (double **a, int whichTree, int whichChain);
# if defined (SMART_TI_PROBS)
int SetUpTransitionProbs (int numRateCats);
# endif
int SetUpTrees (int numTaxa);
int ShowStartTree (TreeNode *r, int nt, int isThisTreeRooted);
#if defined (TRANSLATE_TO_AA)
void TranslateToAA (void);
# endif
void UpDateAllCls (int whichState, int whichChain);
void UpDateAllTIs (int whichState, int whichChain);
char WhichAA (int x);
void WriteTreeToFile (TreeNode *p, FILE *fp, int showBrlens);
void WriteTreeToScreen (TreeNode *p, int showBrlens);
int YesNo (void);
static int nStates, nst, isStartingTreeRandom, allocatedMemory[NUM_ALLOCS], *nSitesInPartition,
*matrix, *numSitesOfPat, *partitionId, treeModel, intNodeNum, localOutgroup,
numNodes, numIntNodes, *clUpdateFlag, *patternId, nSampled, *numCovEvents, aaJones[20][20],
aaDayhoff[20][20], codon[64], transCodon[64], codonNucs[64][3], *lag, nExcluded,
numDummyChars, numBetaCats, *scalerUpdateFlag;
#if defined (TRANSLATE_TO_AA)
static int treatAsAA; // temporary solution, should be declared as global instead
#endif
static unsigned int *stateSet;
static double *kappa, *subParams, *baseFreq, *alpha, relProposalProbs[NUM_PROPOSAL_TYPES], *rateCorrelation,
chainMins[NUM_PROPOSAL_TYPES], chainMaxs[NUM_PROPOSAL_TYPES],
*scaledRates, *unscaledRates, *condLike, *distances, *treeHeight, *clScaler, *ancStatesProbs,
*tempStateProbs, *covInvariable, *covLambda, *spRate, *exRate, *posSelProbs, *rateCorrelation2,
dayhoffPi[20], jonesPi[20], *omega, *probPur, *probNeu, *probPos, *invP, *rateFactors,
*switchRate, *switchPi, *rateProbs, *gc1, *gc2, *fracA, *fracG, *lnSiteScaler, EigValexp[200];
static char proposalName[NUM_PROPOSAL_TYPES][MAX_PROPOSAL_SIZE] =
{"changes to Q matrix",
"changes to base frequencies",
"changes to gamma shape",
"changes to site rates",
"changes to tree (stochastic NNI)",
"changes to clock tree",
"changes to tree",
"changes to tree height",
"changes to tree (one worm)",
"changes to node time",
"changes to bd parameters",
"changes to omega",
"changes to omega probabilities",
"changes to auto correlation",
"changes to lag",
"changes to tree (stochastic SPR)",
"changes to proportion invariant",
"changes to covarion parameter",
"changes to tree (TBR1)",
"changes to GC swith parameters",
"changes to tree (TBR2)",
"changes to a branch length",
"changes to tree (eraser)",
"changes to beta/dirichlet shape"};
static TreeNode *nodes, **root, *tempNodes, **intNodeDownPassSeq, **allNodesDownPassSeq;
FILE *tFile, *pFile, *bpFile;
extern int nTaxa, nChar, *origDataMatrix, dataType, isUserTreeDefined, isTreeRooted,
numChains, *excludedTaxa, *excludedSites, isPartitionDefined, nPartitions, *sitePartitions,
nRateCats, enforceConstraints, enforceCalibrations, inferAncStates, *constraints, nConstraints,
*calibrations, nCalibrations, outgroupNum, nGen, printFreq, sampleFreq, saveBrlens, autoclose,
nPerturbations, userBrlensDef, aaModelType, saveAncFiles, enforceCodonModel, aaCode,
inferPoseSel, lagNumber, inferRates, useCovarion, mcmcBurn, cycleFreq, calcPseudoBf, useParsCriterion;
extern long int randomSeed;
extern double tRatio, revRates[6], nonRevRates[12], qmatprExp, qmatprUni[2], basefreqprDir,
shape, shapeprUni[2], shapeprExp, siteRates[50], siterateprExp, siterateprUni[2],
brlenprExp, brlenprUni[2], chainTemp, calibrationTimes[32][2], seqErrorProb,
speciationRate, extinctionRate, samplingFraction, omegaRatio, omegaprUni[2], omegaprExp,
lagprUni[2], lagprExp, qMatWinProp, piAlphaProp, rateWinProp, tuningProp, clockTuneProp, timeTuneProp, mTuneProp,
extendPProp, wormTuneProp, bdWinProp, omegaWinProp, rhoWinProp, omegaAlphaProp, invSlideProp,
switchWinProp, alphaWinProp, nodeTimeTuneProp, reconLimProp, tbrExtendPProp, tbrTuneProp,
blTuneProp, statefreqprDir, moveRates[100];
extern char startingTreeModel[20], subModel[20], baseFreqModel[20], ratesModel[20],
qmatprModel[20], basefreqprModel[20], shapeModel[20], shapeprModel[20],
defPartitionName[50], partitionName[50], siterateprModel[20], clockModel[20], covarionModelType[20],
brlenprModel[20], *taxonLabels, calibrationLabels[32][100], constraintLabels[32][100],
outFile[100], codonModelType[20], omegaRatioModel[20], omegaprModel[20], lagModel[20],
lagprModel[20], codingType[20], stateFreqPrModel[20];
extern TreeNode *userTree, *userTreeRoot;
# if defined (TOPOLOGY_MOVE_STATS)
int gTopologyHasChanged, gNodeMoves, nAcceptedTopology[NUM_PROPOSAL_TYPES],
nProposedTopology[NUM_PROPOSAL_TYPES], nProposedNodes[NUM_PROPOSAL_TYPES],
nAcceptedNodes[NUM_PROPOSAL_TYPES];
# endif
# if defined (MORPH)
double pObserved, *statefreqP;
# endif
// termState: vector with terminal state code, multiplied with 4 to give suitable index
// isPartAmbig: flag signalling if terminal is partly ambiguous for some sites
# if defined (SUPER_FAST)
int *termState, *isPartAmbig;
# endif
# if defined (SMART_TI_PROBS)
int *updateTiFlag, nodeTiSize;
double *transitionProbs;
# endif
void BetaBreaks (double alpha, double beta, double *values, double *probs, int K)
{
int i;
double r, quantile, lower, upper;
r = (1.0 / K) * 0.5;
lower = 0.0;
upper = (1.0 / K);
r = (upper - lower) * 0.5 + lower;
for (i=0; i<K; i++)
{
quantile = BetaQuantile (alpha, beta, r);
values[i] = quantile;
probs[i] = upper - lower;
lower += (1.0/K);
upper += (1.0/K);
r += (1.0/K);
}
# if 0
for (i=0; i<K; i++)
{
printf ("%4d %lf %lf\n", i, values[i], probs[i]);
}
# endif
}
double BetaCf (double a, double b, double x)
{
int m, m2;
double aa, c, d, del, h, qab, qam, qap;
qab = a + b;
qap = a + 1.0;
qam = a - 1.0;
c = 1.0;
d = 1.0 - qab * x / qap;
if (fabs(d) < (1.0e-30))
d = (1.0e-30);
d = 1.0 / d;
h = d;
for (m=1; m<=100; m++)
{
m2 = 2 * m;
aa = m * (b-m) * x / ((qam+m2) * (a+m2));
d = 1.0 + aa * d;
if (fabs(d) < (1.0e-30))
d = (1.0e-30);
c = 1.0 + aa / c;
if (fabs(c) < (1.0e-30))
c = (1.0e-30);
d = 1.0 / d;
h *= d * c;
aa = -(a+m) * (qab+m) * x / ((a+m2) * (qap+m2));
d = 1.0 + aa * d;
if (fabs(d) < (1.0e-30))
d = (1.0e-30);
c = 1.0 + aa / c;
if (fabs(c) < (1.0e-30))
c = (1.0e-30);
d = 1.0 / d;
del = d * c;
h *= del;
if (fabs(del - 1.0) < (3.0e-7))
break;
}
if (m > 100)
{
printf ("Error in BetaCf.\n");
exit (-1);
}
return (h);
}
double BetaQuantile (double alpha, double beta, double x)
{
int i, stopIter, direction, nswitches;
double curPos, curFraction, increment;
i = nswitches = 0;
curPos = 0.5;
stopIter = NO;
increment = 0.25;
curFraction = IncompleteBetaFunction (alpha, beta, curPos);
if (curFraction > x)
direction = DOWN;
else
direction = UP;
while (stopIter == NO)
{
curFraction = IncompleteBetaFunction (alpha, beta, curPos);
if (curFraction > x && direction == DOWN)
{
/* continue going down */
while (curPos - increment <= 0.0)
{
increment /= 2.0;
}
curPos -= increment;
}
else if (curFraction > x && direction == UP)
{
/* switch directions, and go down */
nswitches++;
direction = DOWN;
while (curPos - increment <= 0.0)
{
increment /= 2.0;
}
increment /= 2.0;
curPos -= increment;
}
else if (curFraction < x && direction == UP)
{
/* continue going up */
while (curPos + increment >= 1.0)
{
increment /= 2.0;
}
curPos += increment;
}
else if (curFraction < x && direction == DOWN)
{
/* switch directions, and go up */
nswitches++;
direction = UP;
while (curPos + increment >= 1.0)
{
increment /= 2.0;
}
increment /= 2.0;
curPos += increment;
}
else
{
stopIter = YES;
}
if (i > 1000 || nswitches > 20)
stopIter = YES;
i++;
}
return (curPos);
}
int BuildStartingTree (int numTaxa, int numChars, long int *seed, int showStartTree)
{
int i, j, k, n, tSize, nNodes, nTips, nInts, nextTip, nextInt,
nPotentialPlaces, whichNode, consistentNode, uniqueBipart1[32],
uniqueBipart2[32], isMarked, nId, nLftId, nRhtId, nAncId, nUserNodes, tempLength;
unsigned int conLft, conRht, conAnc, conNde, conNum1, conNum2, *localConstraints, *localCalibrations;
double treeLength, sum, oldestAbove, oldestBelow;
TreeNode *p, *a, *b, *c, *d, *e, **availTips, **availInts, **tempDP, *tempRoot,
**potentialPlaces, *lft, *m1, *m2, *um1, *um2, *out;
if (enforceConstraints == YES || enforceCalibrations == YES)
{
if (CheckConstraints () == NO)
{
printf ("\n ERROR: Constraints and/or calibrations are inconsistent with a single tree\n");
FreeMemory ();
return (ERROR);
}
}
printf (" Making starting trees\n");
if (treeModel == ROOTED)
{
tSize = 2*numTaxa;
printf (" Starting tree(s) are rooted\n");
}
else if (treeModel == UNROOTED)
{
tSize = 2*numTaxa-2;
printf (" Starting tree(s) are unrooted\n");
}
else
{
printf ("\n ERROR: Cannot decide if the tree is rooted or unrooted\n");
FreeMemory ();
return (ERROR);
}
/* allocate memory for nodes */
nodes = (TreeNode *)malloc(sizeof(TreeNode) * numChains * 2 * tSize);
if (!nodes)
{
printf ("\n ERROR: Could not allocate nodes\n");
FreeMemory ();
return (ERROR);
}
else
allocatedMemory[ALLOC_NODES] = YES;
root = (TreeNode **)malloc(sizeof(TreeNode *) * numChains * 2);
if (!root)
{
printf ("\n ERROR: Could not allocate root\n");
FreeMemory ();
return (ERROR);
}
else
allocatedMemory[ALLOC_ROOT] = YES;
printf (" Allocated memory for trees\n");
/* set the tree pointers to null */
for (i=0; i<numChains*2*tSize; i++)
{
nodes[i].left = NULL;
nodes[i].right = NULL;
nodes[i].anc = NULL;
nodes[i].index = -1;
nodes[i].length = 0.0;
nodes[i].nodeTime = 0.0;
nodes[i].isConstrained = NO;
nodes[i].isCalibrated = NO;
for (j=0; j<99; j++)
nodes[i].label[j] = ' ';
nodes[i].label[99] = '\0';
for (j=0; j<99; j++)
nodes[i].calibrationName[j] = ' ';
nodes[i].calibrationName[99] = '\0';
for (j=0; j<99; j++)
nodes[i].constraintName[j] = ' ';
nodes[i].constraintName[99] = '\0';
}
availTips = (TreeNode **)malloc(sizeof(TreeNode *) * nTaxa);
if (!availTips)
{
printf ("\n ERROR: Could not allocate availTips\n");
FreeMemory ();
return (ERROR);
}
availInts = (TreeNode **)malloc(sizeof(TreeNode *) * nTaxa);
if (!availInts)
{
printf ("\n ERROR: Could not allocate availInts\n");
free (availTips);
FreeMemory ();
return (ERROR);
}
tempDP = (TreeNode **)malloc(sizeof(TreeNode *) * 2*nTaxa);
if (!tempDP)
{
printf ("\n ERROR: Could not allocate tempDP\n");
free (availTips);
free (availInts);
FreeMemory ();
return (ERROR);
}
potentialPlaces = (TreeNode **)malloc(sizeof(TreeNode *) * 2*nTaxa);
if (!potentialPlaces)
{
printf ("\n ERROR: Could not allocate potentialPlaces\n");
free (availTips);
free (availInts);
free (tempDP);
FreeMemory ();
return (ERROR);
}
tempNodes = (TreeNode *)malloc(sizeof(TreeNode) * 2*nTaxa);
if (!tempNodes)
{
printf ("\n ERROR: Could not allocate tempNodes\n");
free (availTips);
free (availInts);
free (tempDP);
free (potentialPlaces);
FreeMemory ();
return (ERROR);
}
localConstraints = (unsigned int *)malloc(sizeof(unsigned int) * nTaxa);
if (!localConstraints)
{
printf ("\n ERROR: Could not allocate localConstraints\n");
free (availTips);
free (availInts);
free (tempDP);
free (potentialPlaces);
free (tempNodes);
FreeMemory ();
return (ERROR);
}
localCalibrations = (unsigned int *)malloc(sizeof(unsigned int) * nTaxa);
if (!localCalibrations)
{
printf ("\n ERROR: Could not allocate localCalibrations\n");
free (availTips);
free (availInts);
free (tempDP);
free (potentialPlaces);
free (tempNodes);
free (localConstraints);
FreeMemory ();
return (ERROR);
}
/* set up constraints */
if (enforceConstraints == YES)
{
printf (" Setting up constraints\n");
/* look for unique constraints and remove them */
for (i=0; i<nTaxa; i++)
localConstraints[i] = (unsigned int)constraints[i];
for (i=0; i<nConstraints; i++)
uniqueBipart1[i] = 0;
for (i=0; i<nConstraints; i++)
{
conNde = (unsigned int)pow(2.0, (double)i);
for (j=0; j<nTaxa; j++)
{
if (excludedTaxa[j] == NO)
{
conLft = conNde & (unsigned int)constraints[j];
if (conNde == conLft)
uniqueBipart1[i]++;
}
}
if (uniqueBipart1[i] <= 1)
{
for (j=0; j<nTaxa; j++)
{
conLft = conNde & (unsigned int)constraints[j];
if (conNde == conLft)
localConstraints[j] -= conNde;
}
}
# if defined (DEBUG_START_TREE)
printf ("Taxon bipartition %d found %d times for this constraint\n", conNde, uniqueBipart1[i]);
# endif
}
# if defined (DEBUG_START_TREE)
printf ("cons: ");
for (i=0; i<nTaxa; i++)
{
if (excludedTaxa[i] == NO)
printf ("%2d ", localConstraints[i]);
}
printf ("\n");
# endif
}
/* set up calibrations */
if (enforceCalibrations == YES)
{
printf (" Setting up calibrations\n");
/* look for unique calibrations and remove them */
for (i=0; i<nTaxa; i++)
localCalibrations[i] = (unsigned int)calibrations[i];
for (i=0; i<nCalibrations; i++)
uniqueBipart2[i] = 0;
for (i=0; i<nCalibrations; i++)
{
conNde = (unsigned int)pow(2.0, (double)i);
for (j=0; j<nTaxa; j++)
{
if (excludedTaxa[j] == NO)
{
conLft = conNde & (unsigned int)calibrations[j];
if (conNde == conLft)
uniqueBipart2[i]++;
}
}
if (uniqueBipart2[i] <= 1)
{
for (j=0; j<nTaxa; j++)
{
conLft = conNde & (unsigned int)calibrations[j];
if (conNde == conLft)
localCalibrations[j] -= conNde;
}
}
# if defined (DEBUG_START_TREE)
printf ("Taxon bipartition %d found %d times for this calibration\n", conNde, uniqueBipart2[i]);
# endif
}
# if defined (DEBUG_START_TREE)
printf ("cals: ");
for (i=0; i<nTaxa; i++)
{
if (excludedTaxa[i] == NO)
printf ("%2d ", localCalibrations[i]);
}
printf ("\n");
# endif
}
if (!strcmp(startingTreeModel, "random"))
{
/* random tree(s) start chain */
printf (" Starting tree(s) are random\n");
for (n=0; n<numChains; n++)
{
/* set everything to null */
for (i=0; i<2*numTaxa; i++)
{
tempNodes[i].left = NULL;
tempNodes[i].right = NULL;
tempNodes[i].anc = NULL;
tempNodes[i].index = -1;
tempNodes[i].length = 0.0;
for (j=0; j<100; j++)
tempNodes[i].label[j] = ' ';
}
/* set up available nodes */
j = 0;
for (i=0; i<nTaxa; i++)
{
if (excludedTaxa[i] == NO)
{
p = &tempNodes[j];
availTips[j] = p;
p->index = j;
p->memoryIndex = j;
if (enforceConstraints == YES)
p->constraints = localConstraints[i];
if (enforceCalibrations == YES)
p->calibrations = localCalibrations[i];
k = 0;
while (taxonLabels[i*100+k] != '|')
{
p->label[k] = taxonLabels[i*100+k];
k++;
}
p->label[k] = '\0';
j++;
}
}
k = 0;
for (i=numTaxa; i<2*numTaxa; i++)
{
p = &tempNodes[j];
availInts[k] = p;
p->index = j;
p->memoryIndex = j;
j++;
k++;
}
/* set up initial split at base with two taxa */
a = availTips[0];
b = availTips[1];
c = availInts[0];
d = availInts[1];
a->anc = b->anc = c;
c->left = a;
c->right = b;
c->anc = d;
d->left = c;
tempRoot = d;
nNodes = 4;
nTips = 2;
nInts = 2;
nextTip = 2;
nextInt = 2;
if (enforceConstraints == YES)
{
for (i=0; i<nConstraints; i++)
{
uniqueBipart1[i] = YES;
conNde = (unsigned int)pow(2.0, (double)i);
conLft = conNde & a->constraints;
conRht = conNde & b->constraints;
if (conLft == conNde)
uniqueBipart1[i] = NO;
if (conRht == conNde)
uniqueBipart1[i] = NO;
}
# if defined (DEBUG_START_TREE)
printf ("unique bipartitions: ");
for (i=0; i<nConstraints; i++)
printf ("%d ", uniqueBipart1[i]);
printf ("\n");
# endif
}
if (enforceCalibrations == YES)
{
for (i=0; i<nCalibrations; i++)
{
uniqueBipart2[i] = YES;
conNde = (unsigned int)pow(2.0, (double)i);
conLft = conNde & a->calibrations;
conRht = conNde & b->calibrations;
if (conLft == conNde)
uniqueBipart2[i] = NO;
if (conRht == conNde)
uniqueBipart2[i] = NO;
}
# if defined (DEBUG_START_TREE)
printf ("unique bipartitions: ");
for (i=0; i<nCalibrations; i++)
printf ("%d ", uniqueBipart2[i]);
printf ("\n");
# endif
}
while (nTips < numTaxa)
{
# if defined (DEBUG_START_TREE)
printf ("intermediate tree\n");
ShowNodes (tempRoot, 2, YES);
//ShowStartTree (tempRoot, nTips, YES);
# endif
/* get down pass sequence for partial tree */
i = 0;
GetTempDownPassSeq (tempRoot, &i, tempDP);
if (enforceConstraints == YES)
{
for (i=0; i<nNodes; i++)
{
p = tempDP[i];
if (p->left != NULL && p->right != NULL)
{
conLft = p->left->constraints;
conRht = p->right->constraints;
conNde = conLft & conRht;
p->constraints = conNde;
}
else if (p->left != NULL && p->right == NULL && p->anc == NULL)
p->constraints = 0;
# if defined (DEBUG_START_TREE)
printf ("%4d -- %d\n", p->index, p->constraints);
# endif
}
}
if (enforceCalibrations == YES)
{
for (i=0; i<nNodes; i++)
{
p = tempDP[i];
if (p->left != NULL && p->right != NULL)
{
conLft = p->left->calibrations;
conRht = p->right->calibrations;
conNde = conLft & conRht;
p->calibrations = conNde;
}
else if (p->left != NULL && p->right == NULL && p->anc == NULL)
p->calibrations = 0;
# if defined (DEBUG_START_TREE)
printf ("%4d -- %d\n", p->index, p->calibrations);
# endif
}
}
/* make list of acceptable nodes */
a = availTips[nextTip];
# if defined (DEBUG_START_TREE)
printf ("adding taxon %s\n", a->label);
# endif
if (enforceConstraints == YES)
{
conNum1 = a->constraints;
for (j=0; j<nConstraints; j++)
{
conNde = conNum1 & (int)pow(2.0, (double)j);
if (conNde > 0 && uniqueBipart1[j] == YES)
{
conNum1 -= (int)pow(2.0, (double)j);
uniqueBipart1[j] = NO;
}
}
# if defined (DEBUG_START_TREE)
printf ("conNum1 = %d\n", conNum1);
# endif
}
if (enforceCalibrations == YES)
{
conNum2 = a->calibrations;
for (j=0; j<nCalibrations; j++)
{
conNde = conNum2 & (int)pow(2.0, (double)j);
if (conNde > 0 && uniqueBipart2[j] == YES)
{
conNum2 -= (int)pow(2.0, (double)j);
uniqueBipart2[j] = NO;
}
}
# if defined (DEBUG_START_TREE)
printf ("conNum2 = %d\n", conNum2);
# endif
}
nPotentialPlaces = 0;
if (enforceConstraints == YES || enforceCalibrations == YES)
{
for (i=0; i<nNodes; i++)
{
p = tempDP[i];
if (p->anc != NULL)
{
consistentNode = YES;
if (enforceConstraints == YES)
{
for (j=0; j<nConstraints; j++)
{
conLft = p->constraints & (int)pow(2.0, (double)j);
conRht = p->anc->constraints & (int)pow(2.0, (double)j);
conNde = conNum1 & (int)pow(2.0, (double)j);
if (conNde != conLft && conNde != conRht)
consistentNode = NO;
}
}
if (enforceCalibrations == YES)
{
for (j=0; j<nCalibrations; j++)
{
conLft = p->calibrations & (int)pow(2.0, (double)j);
conRht = p->anc->calibrations & (int)pow(2.0, (double)j);
conNde = conNum2 & (int)pow(2.0, (double)j);
if (conNde != conLft && conNde != conRht)
consistentNode = NO;
}
}
if (consistentNode == YES)
potentialPlaces[nPotentialPlaces++] = p;
}
}
}
else
{
for (i=0; i<nNodes; i++)
{
p = tempDP[i];
if (p->anc != NULL)
potentialPlaces[nPotentialPlaces++] = p;
}
}
# if defined (DEBUG_START_TREE)
printf ("potential nodes = ");
for (i=0; i<nPotentialPlaces; i++)
{
p = potentialPlaces[i];
printf ("%d ", p->index);
}
printf ("\n");
# endif
if (nPotentialPlaces <= 0)
{
free (availTips);
free (availInts);
free (tempDP);
free (potentialPlaces);
free (tempNodes);
free (localConstraints);
free (localCalibrations);
printf ("\n ERROR: Could not add tip to tree\n");
return (ERROR);
}
/* randomly choose node from acceptable list */
whichNode = (int)(RandomNumber (seed) * nPotentialPlaces);
p = potentialPlaces[whichNode];
/* add next tip taxon to tree */
b = availInts[nextInt];
c = p->anc;
if (c->left == p)
{
b->anc = c;
b->left = p;
b->right = a;
c->left = b;
a->anc = b;
p->anc = b;
}
else
{
b->anc = c;
b->left = a;
b->right = p;
c->right = b;
a->anc = b;
p->anc = b;
}
/* increment nTips, etc. */
nTips++;
nInts++;
nextTip++;
nextInt++;
nNodes += 2;
}
/* clean tree up */
if (treeModel == UNROOTED)
{
i = 0;
GetTempDownPassSeq (tempRoot, &i, tempDP);
isMarked = NO;
for (i=0; i<nNodes; i++)
{
p = tempDP[i];
if (p->left == NULL && p->right == NULL)
{
if (p->index == localOutgroup)
{
p->marked = YES;
isMarked = YES;
}
else
p->marked = NO;
}
else if (p->left != NULL && p->right != NULL && p->anc != NULL)
{
if (p->left->marked == YES || p->right->marked == YES)
p->marked = YES;
else
p->marked = NO;
}
else
{
p->marked = YES;
}
}
if (isMarked == NO)
{
printf ("\n ERROR: Could not find outgroup taxon\n");
free (availTips);
free (availInts);
free (tempDP);
free (potentialPlaces);
free (tempNodes);
free (localConstraints);
free (localCalibrations);
return (ERROR);
}
lft = tempRoot->left;
while (lft->left->index != localOutgroup && lft->right->index != localOutgroup)
{
if (lft->left->marked == YES && lft->right->marked == NO)
{
m1 = lft->left;
um1 = lft->right;
if (m1->left != NULL && m1->right != NULL)
{
if (m1->left->marked == YES)
{
m2 = m1->left;
um2 = m1->right;
}
else
{
m2 = m1->right;
um2 = m1->left;
}
lft->left = m2;
lft->right = m1;
m2->anc = lft;
m1->left = um2;
m1->right = um1;
m1->anc = lft;
um1->anc = m1;
um2->anc = m1;
m1->marked = NO;
}
else
{
printf ("\n ERROR: Rooting routine is lost\n");
free (availTips);
free (availInts);
free (tempDP);
free (potentialPlaces);
free (tempNodes);
free (localConstraints);
free (localCalibrations);
return (ERROR);
}
}
else if (lft->left->marked == NO && lft->right->marked == YES)
{
m1 = lft->right;
um1 = lft->left;
if (m1->left != NULL && m1->right != NULL)
{
if (m1->left->marked == YES)
{
m2 = m1->left;
um2 = m1->right;
}
else
{
m2 = m1->right;
um2 = m1->left;
}
lft->left = m1;
lft->right = m2;
m2->anc = lft;
m1->left = um1;
m1->right = um2;
m1->anc = lft;
um1->anc = m1;
um2->anc = m1;
m1->marked = NO;
}
else
{
printf ("\n ERROR: Rooting routine is lost\n");
free (availTips);
free (availInts);
free (tempDP);
free (potentialPlaces);
free (tempNodes);
free (localConstraints);
free (localCalibrations);
return (ERROR);
}
}
else
{
printf (" ERROR: Rooting routine is lost\n");
free (availTips);
free (availInts);
free (tempDP);
free (potentialPlaces);
free (tempNodes);
free (localConstraints);
free (localCalibrations);
return (ERROR);
}
}
/* make certain outgroup is to the right of the root */
if (tempRoot->left->left->index == localOutgroup)
{
m1 = tempRoot->left->left;
m2 = tempRoot->left->right;
lft = tempRoot->left;
lft->left = m2;
lft->right = m1;
}
/* now, take outgroup and make it point down */
m1 = tempRoot;
m2 = tempRoot->left;
lft = tempRoot->left->left;
out = tempRoot->left->right;
lft->anc = out;
out->left = lft;
out->right = NULL;
out->anc = NULL;
m1->left = NULL;
m2->left = NULL;
m1->right = NULL;
m2->right = NULL;
m1->anc = NULL;
m2->anc = NULL;
tempRoot = out;
}
i = numTaxa;
if (treeModel == UNROOTED)
FinishTree (tempRoot, &i, NO);
else
FinishTree (tempRoot, &i, YES);
# if defined (DEBUG_START_TREE)
printf ("final tree for chain %d (before copy)\n",n);
ShowNodes (tempRoot, 2, YES);
//ShowStartTree (tempRoot, nTips, YES);
# endif
/* copy this tree into nodes */
i = 0;
GetTempDownPassSeq (tempRoot, &i, tempDP);
for (i=0; i<tSize; i++)
{
p = tempDP[i];
nId = p->index;
a = &nodes[n*2*tSize+nId];
a->index = nId;
a->memoryIndex = nId;
a->length = 0.1; /* TEMP: May decide to use different starting branch lengths later */
if (p->left != NULL)
{
nLftId = p->left->index;
b = &nodes[n*2*tSize+nLftId];
a->left = b;
}
else
a->left = NULL;
if (p->right != NULL)
{
nRhtId = p->right->index;
c = &nodes[n*2*tSize+nRhtId];
a->right = c;
}
else
a->right = NULL;
if (p->anc != NULL)
{
nAncId = p->anc->index;
d = &nodes[n*2*tSize+nAncId];
a->anc = d;
}
else
a->anc = NULL;
if (a->left == NULL && a->right == NULL)
strcpy (a->label, p->label);
if (treeModel == UNROOTED && a->left != NULL && a->right == NULL && a->anc == NULL)
strcpy (a->label, p->label);
}
nId = tempRoot->index;
root[n*2+0] = &nodes[n*2*tSize+nId];
# if defined (DEBUG_START_TREE)
printf ("final tree for chain %d (copied version)\n",n);
ShowNodes (root[n*2+0], 2, YES);
//ShowStartTree (tempRoot, nTips, YES);
# endif
}
}
else
{
/* user tree starts chain */
printf (" Starting tree(s) are user-specified\n");
if (treeModel == ROOTED && isTreeRooted == NO)
{
printf (" Rooting user tree\n");
if (RootTree (userTreeRoot) == ERROR)
{
FreeMemory ();
free (availTips);
free (availInts);
free (tempDP);
free (potentialPlaces);
free (tempNodes);
free (localConstraints);
free (localCalibrations);
return (ERROR);
}
isTreeRooted = YES;
}
else if (treeModel == UNROOTED && isTreeRooted == YES)
{
printf (" Derooting user tree\n");
if (DerootTree (userTreeRoot) == ERROR)
{
FreeMemory ();
free (availTips);
free (availInts);
free (tempDP);
free (potentialPlaces);
free (tempNodes);
free (localConstraints);
free (localCalibrations);
return (ERROR);
}
isTreeRooted = NO;
}
for (n=0; n<numChains; n++)
{
/* get down pass for user tree */
i = 0;
GetTempDownPassSeq (userTreeRoot, &i, tempDP);
if (isTreeRooted == YES)
{
nNodes = 2*numTaxa;
nUserNodes = 2*nTaxa;
}
else
{
nNodes = 2*numTaxa-2;
nUserNodes = 2*nTaxa-2;
}
/* read user tree into temporary nodes */
for (i=0; i<2*nTaxa; i++)
{
tempNodes[i].left = NULL;
tempNodes[i].right = NULL;
tempNodes[i].anc = NULL;
tempNodes[i].index = -1;
tempNodes[i].length = 0.0;
for (j=0; j<100; j++)
tempNodes[i].label[j] = ' ';
}
for (i=0; i<nUserNodes; i++)
{
p = tempDP[i];
nId = p->index;
a = &tempNodes[nId];
a->index = nId;
a->memoryIndex = nId;
a->length = p->length;
if (p->left != NULL)
{
nLftId = p->left->index;
b = &tempNodes[nLftId];
a->left = b;
}
else
a->left = NULL;
if (p->right != NULL)
{
nRhtId = p->right->index;
c = &tempNodes[nRhtId];
a->right = c;
}
else
a->right = NULL;
if (p->anc != NULL)
{
nAncId = p->anc->index;
d = &tempNodes[nAncId];
a->anc = d;
}
else
a->anc = NULL;
if (a->left == NULL && a->right == NULL)
strcpy (a->label, p->label);
if (treeModel == UNROOTED && a->left != NULL && a->right == NULL && a->anc == NULL)
strcpy (a->label, p->label);
}
nId = userTreeRoot->index;
tempRoot = &tempNodes[nId];
/* delete unused nodes from temporary nodes*/
i = 0;
GetTempDownPassSeq (tempRoot, &i, tempDP);
for (i=0; i<nUserNodes; i++)
{
p = tempDP[i];
p->marked = NO;
if (p->left == NULL && p->right == NULL && p->anc != NULL && excludedTaxa[p->index] == YES)
{
p->marked = YES;
}
else if (p->left != NULL && p->right == NULL && p->anc == NULL)
{
if (isTreeRooted == NO && excludedTaxa[p->index] == YES)
{
p->marked = YES;
}
}
}
for (i=0; i<nUserNodes; i++)
{
p = tempDP[i];
if (p->marked == YES)
{
if (p->anc != NULL)
{
b = p->anc;
if (b->left == p)
a = b->right;
else
a = b->left;
c = b->anc;
if (c->left == b)
c->left = a;
else
c->right = a;
a->anc = c;
a->length += b->length;
p->anc = p->left = p->right = NULL;
b->anc = b->left = b->right = NULL;
p->marked = NO;
b->marked = NO;
}
else
{
/* first rotate tree so that left, left is a tip */
a = p->left;
b = a->left;
while (b->left != NULL && b->right != NULL)
{
c = b->left;
d = b->right;
e = a->right;
c->anc = a;
a->left = c;
a->right = b;
b->left = d;
b->right = e;
b->anc = a;
d->anc = e->anc = b;
e->length += b->length;
b->length = c->length / 2.0;
c->length = b->length;
a = p->left;
b = a->left;
}
if (treeModel == ROOTED)
ShowNodes (tempRoot, 2, YES);
else
ShowNodes (tempRoot, 2, NO);
/* now that the tree is rotated around the root, remove the root */
a = p->left;
b = a->left;
c = a->right;
c->anc = b;
c->length += b->length;
b->left = c;
b->right = b->anc = NULL;
a->left = a->right = a->anc = NULL;
p->left = p->right = p->anc = NULL;
tempRoot = b;
}
}
}
/* if constraints are enforced, check that the user tree is consistent with the constraints */
i = 0;
GetTempDownPassSeq (tempRoot, &i, tempDP);
if (enforceConstraints == YES)
{
for (j=0; j<nConstraints; j++)
{
/* downpass first */
for (i=0; i<tSize; i++)
{
p = tempDP[i];
if (p->left == NULL && p->right == NULL && p->anc != NULL)
{
conLft = (unsigned int)pow(2.0, (double)j);
nId = 0;
for (k=0; k<nTaxa; k++)
{
if (excludedTaxa[k] == NO)
{
if (nId == p->index)
break;
nId++;
}
}
conNde = conLft & (unsigned int)constraints[k];
if (conNde > 0)
p->constraints = 2;
else
p->constraints = 1;
}
else if (p->left != NULL && p->right != NULL && p->anc != NULL)
{
conLft = p->left->constraints;
conRht = p->right->constraints;
conNde = conLft & conRht;
if (conNde == 0)
p->constraints = conLft | conRht;
else
p->constraints = conNde;
}
else
{
if (treeModel == UNROOTED)
{
conLft = (unsigned int)pow(2.0, (double)j);
nId = 0;
for (k=0; k<nTaxa; k++)
{
if (excludedTaxa[k] == NO)
{
if (nId == p->index)
break;
nId++;
}
}
conNde = conLft & (unsigned int)constraints[k];
if (conNde > 0)
p->constraints = 2;
else
p->constraints = 1;
}
else
p->constraints = 0;
}
}
/* now pass up tree and count changes */
consistentNode = 0;
for (i=tSize-1; i>=0; i--)
{
p = tempDP[i];
if (p->left != NULL && p->right != NULL && p->anc != NULL)
{
conLft = p->constraints;
conRht = p->anc->constraints;
conNde = conLft & conRht;
if (conNde > 0)
p->constraints = conNde;
}
if (p->anc != NULL)
{
if (p->anc->anc == NULL)
{
if (p->constraints != p->anc->constraints && treeModel == UNROOTED)
consistentNode++;
}
else
{
if (p->constraints != p->anc->constraints)
consistentNode++;
}
}
}
if (consistentNode > 1)
{
printf ("\n ERROR: User tree is inconsistent with the specied constraints\n");
free (availTips);
free (availInts);
free (tempDP);
free (potentialPlaces);
free (tempNodes);
free (localConstraints);
free (localCalibrations);
return (ERROR);
}
}
}
/* if calibrations are enforced, check that the user tree is consistent with the constraints */
if (enforceCalibrations == YES)
{
for (j=0; j<nCalibrations; j++)
{
/* downpass first */
for (i=0; i<tSize; i++)
{
p = tempDP[i];
if (p->left == NULL && p->right == NULL && p->anc != NULL)
{
conLft = (unsigned int)pow(2.0, (double)j);
nId = 0;
for (k=0; k<nTaxa; k++)
{
if (excludedTaxa[k] == NO)
{
if (nId == p->index)
break;
nId++;
}
}
conNde = conLft & (unsigned int)calibrations[k];
if (conNde > 0)
p->calibrations = 2;
else
p->calibrations = 1;
}
else if (p->left != NULL && p->right != NULL && p->anc != NULL)
{
conLft = p->left->calibrations;
conRht = p->right->calibrations;
conNde = conLft & conRht;
if (conNde == 0)
p->calibrations = conLft | conRht;
else
p->calibrations = conNde;
}
else
{
if (treeModel == UNROOTED)
{
conLft = (unsigned int)pow(2.0, (double)j);
nId = 0;
for (k=0; k<nTaxa; k++)
{
if (excludedTaxa[k] == NO)
{
if (nId == p->index)
break;
nId++;
}
}
conNde = conLft & (unsigned int)calibrations[k];
if (conNde > 0)
p->calibrations = 2;
else
p->calibrations = 1;
}
else
p->calibrations = 0;
}
}
/* now pass up tree and count changes */
consistentNode = 0;
for (i=tSize-1; i>=0; i--)
{
p = tempDP[i];
if (p->left != NULL && p->right != NULL && p->anc != NULL)
{
conLft = p->calibrations;
conRht = p->anc->calibrations;
conNde = conLft & conRht;
if (conNde > 0)
p->calibrations = conNde;
}
if (p->anc != NULL)
{
if (p->anc->anc == NULL)
{
if (p->calibrations != p->anc->calibrations && treeModel == UNROOTED)
consistentNode++;
}
else
{
if (p->calibrations != p->anc->calibrations)
consistentNode++;
}
}
}
if (consistentNode > 1)
{
printf ("\n ERROR: User tree is inconsistent with the specied calibrations\n");
free (availTips);
free (availInts);
free (tempDP);
free (potentialPlaces);
free (tempNodes);
free (localConstraints);
free (localCalibrations);
return (ERROR);
}
}
}
/* relabel nodes */
i = 0;
GetTempDownPassSeq (tempRoot, &i, tempDP);
if (treeModel == ROOTED)
nUserNodes = 2*numTaxa;
else
nUserNodes = 2*numTaxa-2;
for (i=0; i<nUserNodes; i++)
{
p = tempDP[i];
if (p->left == NULL && p->right == NULL && p->anc != NULL)
{
k = 0;
for (j=0; j<p->index; j++)
{
if (excludedTaxa[j] == NO)
k++;
}
p->index = k;
}
else if (p->left != NULL && p->right == NULL && p->anc == NULL)
{
if (treeModel == UNROOTED)
{
k = 0;
for (j=0; j<p->index; j++)
{
if (excludedTaxa[j] == NO)
k++;
}
p->index = k;
}
}
}
i = numTaxa;
if (treeModel == UNROOTED)
FinishTree (tempRoot, &i, NO);
else
FinishTree (tempRoot, &i, YES);
/* copy tree into nodes */
for (i=0; i<tSize; i++)
{
p = tempDP[i];
nId = p->index;
a = &nodes[n*2*tSize+nId];
a->index = nId;
a->memoryIndex = nId;
a->length = p->length;
if (p->left != NULL)
{
nLftId = p->left->index;
b = &nodes[n*2*tSize+nLftId];
a->left = b;
}
else
a->left = NULL;
if (p->right != NULL)
{
nRhtId = p->right->index;
c = &nodes[n*2*tSize+nRhtId];
a->right = c;
}
else
a->right = NULL;
if (p->anc != NULL)
{
nAncId = p->anc->index;
d = &nodes[n*2*tSize+nAncId];
a->anc = d;
}
else
a->anc = NULL;
if (a->left == NULL && a->right == NULL)
strcpy (a->label, p->label);
if (treeModel == UNROOTED && a->left != NULL && a->right == NULL && a->anc == NULL)
strcpy (a->label, p->label);
}
nId = tempRoot->index;
root[n*2+0] = &nodes[n*2*tSize+nId];
# if defined (DEBUG_START_TREE)
printf ("final tree for chain %d (copied version)\n",n);
if (treeModel == ROOTED)
ShowNodes (root[n*2+0], 2, YES);
else
ShowNodes (root[n*2+0], 2, NO);
//ShowStartTree (tempRoot, nTips, YES);
# endif
}
}
# if defined (DEBUG_START_TREE)
printf ("tidying up trees\n");
# endif
/* tidy up trees, assigning constraints, calibrations, and branch lengths */
printf (" Setting branch lengths\n");
for (n=0; n<numChains; n++)
{
i = 0;
GetTempDownPassSeq (root[n*2+0], &i, tempDP);
/* set constraints */
if (enforceConstraints == YES)
{
for (j=0; j<tSize; j++)
{
p = tempDP[j];
p->constraints = 0;
p->isConstrained = NO;
p->constraintNum = 0;
}
for (i=0; i<nConstraints; i++)
{
for (j=0; j<tSize; j++)
{
p = tempDP[j];
p->constraints = 0;
}
conNde = (unsigned int)pow(2.0, (double)i);
for (j=0; j<tSize; j++)
{
p = tempDP[j];
if (p->left == NULL && p->right == NULL && p->anc != NULL)
{
nId = 0;
for (k=0; k<nTaxa; k++)
{
if (excludedTaxa[k] == NO)
{
if (nId == p->index)
break;
nId++;
}
}
conLft = conNde & (unsigned int)constraints[k];
if (conNde == conLft)
p->constraints = conNde;
else
p->constraints = 0;
}
else if (p->left != NULL && p->right == NULL && p->anc == NULL && treeModel == UNROOTED)
{
nId = 0;
for (k=0; k<nTaxa; k++)
{
if (excludedTaxa[k] == NO)
{
if (nId == p->index)
break;
nId++;
}
}
conLft = conNde & (unsigned int)constraints[k];
if (conNde == conLft)
p->constraints = conNde;
else
p->constraints = 0;
}
}
/* pass down */
for (j=0; j<tSize; j++)
{
p = tempDP[j];
if (p->left != NULL && p->right != NULL && p->anc != NULL)
{
conLft = p->left->constraints;
conRht = p->right->constraints;
conNum1 = conLft & conRht;
if (conNum1 == conNde)
p->constraints = conNde;
}
}
/* pass up */
for (j=tSize-1; j>=0; j--)
{
p = tempDP[j];
if (p->left != NULL && p->right != NULL && p->anc != NULL)
{
conAnc = p->anc->constraints;
conLft = p->left->constraints;
conRht = p->right->constraints;
conNum1 = conAnc & conLft;
conNum2 = conAnc & conRht;
if (conNum1 == conNde || conNum2 == conNde)
p->constraints = conNde;
}
}
/* assign constraints */
for (j=0; j<tSize; j++)
{
p = tempDP[j];
if (p->anc != NULL)
{
if (p->constraints == conNde && p->anc->constraints == 0)
{
p->isConstrained = YES;
p->constraintNum = i+1;
k = 0;
while (constraintLabels[p->constraintNum-1][k] != '|' && k < 99)
{
p->constraintName[k] = constraintLabels[p->constraintNum-1][k];
k++;
}
p->constraintName[k] = '\0';
}
else if (p->anc->constraints == conNde && p->constraints == 0)
{
p->anc->isConstrained = YES;
p->anc->constraintNum = i+1;
k = 0;
while (constraintLabels[p->anc->constraintNum-1][k] != '|' && k < 99)
{
p->anc->constraintName[k] = constraintLabels[p->anc->constraintNum-1][k];
k++;
}
p->anc->constraintName[k] = '\0';
}
}
else
{
if (p->constraints == conNde && p->left->constraints == 0 && treeModel == UNROOTED)
{
p->isConstrained = YES;
p->constraintNum = i+1;
k = 0;
while (constraintLabels[p->constraintNum-1][k] != '|' && k < 99)
{
p->constraintName[k] = constraintLabels[p->constraintNum-1][k];
k++;
}
p->constraintName[k] = '\0';
}
}
}
}
# if 0
for (j=0; j<tSize; j++)
{
p = tempDP[j];
if (p->isConstrained == YES)
printf ("%2d %4d -- %d (%s)\n", conNde, p->index, p->constraintNum, p->constraintName);
else
printf ("%2d %4d --\n", conNde, p->index);
}
# endif
}
/* set calibrations */
if (enforceCalibrations == YES)
{
for (j=0; j<tSize; j++)
{
p = tempDP[j];
p->calibrations = 0;
p->isCalibrated = NO;
p->calibrationNum = 0;
p->calTime[0] = p->calTime[1] = 0.0;
}
for (i=0; i<nCalibrations; i++)
{
for (j=0; j<tSize; j++)
{
p = tempDP[j];
p->calibrations = 0;
}
conNde = (unsigned int)pow(2.0, (double)i);
for (j=0; j<tSize; j++)
{
p = tempDP[j];
if (p->left == NULL && p->right == NULL && p->anc != NULL)
{
nId = 0;
for (k=0; k<nTaxa; k++)
{
if (excludedTaxa[k] == NO)
{
if (nId == p->index)
break;
nId++;
}
}
conLft = conNde & (unsigned int)calibrations[k];
if (conNde == conLft)
p->calibrations = conNde;
else
p->calibrations = 0;
}
else if (p->left != NULL && p->right == NULL && p->anc == NULL && treeModel == UNROOTED)
{
nId = 0;
for (k=0; k<nTaxa; k++)
{
if (excludedTaxa[k] == NO)
{
if (nId == p->index)
break;
nId++;
}
}
conLft = conNde & (unsigned int)calibrations[k];
if (conNde == conLft)
p->calibrations = conNde;
else
p->calibrations = 0;
}
}
/* pass down */
for (j=0; j<tSize; j++)
{
p = tempDP[j];
if (p->left != NULL && p->right != NULL && p->anc != NULL)
{
conLft = p->left->calibrations;
conRht = p->right->calibrations;
conNum1 = conLft & conRht;
if (conNum1 == conNde)
p->calibrations = conNde;
}
}
/* pass up */
for (j=tSize-1; j>=0; j--)
{
p = tempDP[j];
if (p->left != NULL && p->right != NULL && p->anc != NULL)
{
conAnc = p->anc->calibrations;
conLft = p->left->calibrations;
conRht = p->right->calibrations;
conNum1 = conAnc & conLft;
conNum2 = conAnc & conRht;
if (conNum1 == conNde || conNum2 == conNde)
p->calibrations = conNde;
}
}
/* assign calibrations */
for (j=0; j<tSize; j++)
{
p = tempDP[j];
if (p->anc != NULL)
{
if (p->calibrations == conNde && p->anc->calibrations == 0)
{
p->isCalibrated = YES;
p->calibrationNum = i+1;
k = 0;
while (calibrationLabels[p->calibrationNum-1][k] != '|' && k < 99)
{
p->calibrationName[k] = calibrationLabels[p->calibrationNum-1][k];
k++;
}
p->calibrationName[k] = '\0';
p->calTime[0] = calibrationTimes[p->calibrationNum-1][0];
p->calTime[1] = calibrationTimes[p->calibrationNum-1][1];
}
else if (p->anc->calibrations == conNde && p->calibrations == 0)
{
p->anc->isCalibrated = YES;
p->anc->calibrationNum = i+1;
k = 0;
while (calibrationLabels[p->anc->calibrationNum-1][k] != '|' && k < 99)
{
p->anc->calibrationName[k] = calibrationLabels[p->anc->calibrationNum-1][k];
k++;
}
p->anc->calibrationName[k] = '\0';
p->anc->calTime[0] = calibrationTimes[p->calibrationNum-1][0];
p->anc->calTime[1] = calibrationTimes[p->calibrationNum-1][1];
}
}
else
{
if (p->calibrations == conNde && p->left->calibrations == 0 && treeModel == UNROOTED)
{
p->isCalibrated = YES;
p->calibrationNum = i+1;
k = 0;
while (calibrationLabels[p->calibrationNum-1][k] != '|' && k < 99)
{
p->calibrationName[k] = calibrationLabels[p->calibrationNum-1][k];
k++;
}
p->calibrationName[k] = '\0';
p->calTime[0] = calibrationTimes[p->calibrationNum-1][0];
p->calTime[1] = calibrationTimes[p->calibrationNum-1][1];
}
}
}
}
# if 0
for (j=0; j<tSize; j++)
{
p = tempDP[j];
if (p->isCalibrated == YES)
printf ("%2d %4d -- %d (%s) (%lf %lf)\n", conNde, p->index, p->calibrationNum, p->calibrationName, p->calTime[0], p->calTime[1]);
else
printf ("%2d %4d --\n", conNde, p->index);
}
# endif
}
/* set branch lengths */
/* get parsimony tree length */
treeLength = 0.0;
sum = 0.0;
for (i=0; i<numChars; i++)
{
tempLength = 0;
for (j=0; j<tSize; j++)
{
p = tempDP[j];
if (p->left == NULL && p->right == NULL && p->anc != NULL)
{
p->farrisSet = matrix[pos(p->index,i,numChars)];
}
else if (p->left != NULL && p->right != NULL && p->anc != NULL)
{
conLft = p->left->farrisSet;
conRht = p->right->farrisSet;
conNde = conLft & conRht;
if (conNde == 0)
{
conNde = conLft | conRht;
tempLength++;
}
p->farrisSet = conNde;
}
else
{
if (treeModel == UNROOTED)
{
p->farrisSet = matrix[pos(p->index,i,numChars)];
conLft = p->left->farrisSet;
conRht = p->farrisSet;
conNde = conLft & conRht;
if (conNde == 0)
{
tempLength++;
}
}
}
}
sum += (double)numSitesOfPat[i];
treeLength += tempLength * numSitesOfPat[i];
}
if (treeLength <= 0.0)
treeLength = 0.01;
else
treeLength /= sum;
//printf ("tree length = %lf\n", treeLength);
if (treeModel == UNROOTED)
{
if (!strcmp(startingTreeModel, "random") || (!strcmp(startingTreeModel, "user") && userBrlensDef == NO))
{
sum = 0.0;
for (j=0; j<tSize; j++)
{
p = tempDP[j];
if (p->anc != NULL)
{
p->length = RandomNumber (seed);
sum += p->length;
}
}
for (j=0; j<tSize; j++)
{
p = tempDP[j];
if (p->anc != NULL)
p->length /= treeLength;
}
}
}
else
{
if (!strcmp(clockModel, "relaxed") || !strcmp(clockModel, "strict"))
{
if (enforceCalibrations == YES)
{
/* get node times under the clock constraint with calibrations*/
for (j=0; j<tSize; j++)
{
p = tempDP[j];
if (p->left == NULL && p->right == NULL && p->anc != NULL)
{
if (p->isCalibrated == YES)
{
p->nodeTime = p->calTime[0];
}
else
p->nodeTime = 0.0;
}
else if (p->left != NULL && p->right != NULL && p->anc != NULL)
{
oldestAbove = p->left->nodeTime;
if (p->right->nodeTime > oldestAbove)
oldestAbove = p->right->nodeTime;
if (p->isCalibrated == YES)
{
if (oldestAbove > p->calTime[0] + p->calTime[1])
{
printf ("\n ERROR: Inconsistent times for calibrations\n");
free (availTips);
free (availInts);
free (tempDP);
free (potentialPlaces);
free (tempNodes);
free (localConstraints);
free (localCalibrations);
return (ERROR);
}
else if (oldestAbove > p->calTime[0] && oldestAbove < p->calTime[0] + p->calTime[1])
{
p->nodeTime = oldestAbove + 0.0001;
}
else
{
p->nodeTime = p->calTime[0];
}
}
else
{
p->nodeTime = oldestAbove + 0.0001;
}
}
}
for (i=0; i<10; i++)
{
for (j=0; j<tSize; j++)
{
p = tempDP[j];
if (p->anc != NULL)
{
if (p->isCalibrated == NO)
{
if (p->left == NULL && p->right == NULL && p->anc != NULL)
{
oldestAbove = 0.0;
}
else
{
oldestAbove = p->left->nodeTime;
if (p->right->nodeTime > oldestAbove)
oldestAbove = p->right->nodeTime;
}
if (p->anc->anc != NULL)
oldestBelow = p->anc->nodeTime;
else
oldestBelow = 2 * p->nodeTime;
if (p->left != NULL && p->right != NULL)
p->nodeTime = oldestAbove + (oldestBelow - oldestAbove) * RandomNumber(seed);
}
}
}
}
if (GetDistances (numTaxa, numChars) == ERROR)
{
printf ("\n ERROR: Could not calculate distances\n");
free (availTips);
free (availInts);
free (tempDP);
free (potentialPlaces);
free (tempNodes);
free (localConstraints);
free (localCalibrations);
return (ERROR);
}
else
allocatedMemory[ALLOC_DISTANCES] = YES;
sum = 0.0;
for (i=0; i<numTaxa-1; i++)
for (j=i; j<numTaxa; j++)
if (distances[pos(i,j,numTaxa)] > sum)
sum = distances[pos(i,j,numTaxa)];
free (distances);
allocatedMemory[ALLOC_DISTANCES] = NO;
//treeHeight[n*2+0] = sum * 0.5;
treeHeight[n*2+0] = 0.0005; /* TEMP */
for (j=0; j<tSize; j++)
{
p = tempDP[j];
if (p->anc != NULL)
{
if (p->anc->anc != NULL)
{
p->length = treeHeight[n*2+0] * (p->anc->nodeTime - p->nodeTime);
if (p->length < BRLEN_EPSILON)
p->length = BRLEN_EPSILON;
}
else
{
p->length = 0.0;
}
}
else
{
p->length = 0.0;
}
}
}
else
{
/* get node times under the clock constraint without calibrations*/
for (j=0; j<tSize; j++)
{
p = tempDP[j];
if (p->left == NULL && p->right == NULL && p->anc != NULL)
{
p->nodeTime = 0.0;
}
else if (p->left != NULL && p->right != NULL && p->anc != NULL)
{
oldestAbove = p->left->nodeTime;
if (p->right->nodeTime > oldestAbove)
oldestAbove = p->right->nodeTime;
p->nodeTime = oldestAbove + 0.0001;
}
}
sum = root[n*2+0]->left->nodeTime;
for (j=0; j<tSize; j++)
{
p = tempDP[j];
if (p->anc != NULL)
p->nodeTime /= sum;
}
if (GetDistances (numTaxa, numChars) == ERROR)
{
printf ("\n ERROR: Could not calculate distances\n");
free (availTips);
free (availInts);
free (tempDP);
free (potentialPlaces);
free (tempNodes);
free (localConstraints);
free (localCalibrations);
return (ERROR);
}
else
allocatedMemory[ALLOC_DISTANCES] = YES;
sum = 0.0;
for (i=0; i<numTaxa-1; i++)
for (j=i; j<numTaxa; j++)
if (distances[pos(i,j,numTaxa)] > sum)
sum = distances[pos(i,j,numTaxa)];
free (distances);
allocatedMemory[ALLOC_DISTANCES] = NO;
sum *= 0.5;
for (j=0; j<tSize; j++)
{
p = tempDP[j];
if (p->anc != NULL)
{
if (p->anc->anc != NULL)
p->length = sum * (p->anc->nodeTime - p->nodeTime);
else
p->length = 0.0;
}
else
p->length = 0.0;
}
}
}
else
{
if (!strcmp(startingTreeModel, "random") || (!strcmp(startingTreeModel, "user") && userBrlensDef == NO))
{
sum = 0.0;
for (j=0; j<tSize; j++)
{
p = tempDP[j];
if (p->anc != NULL)
{
if (p->anc->anc != NULL)
{
p->length = RandomNumber (seed);
sum += p->length;
}
}
}
for (j=0; j<tSize; j++)
{
p = tempDP[j];
if (p->anc != NULL)
if (p->anc->anc != NULL)
p->length /= treeLength;
}
}
}
}
# if 0
if (treeModel == ROOTED)
{
printf ("nodes for rooted tree:\n");
ShowNodes (root[n*2+0], 2, YES);
//ShowStartTree (root[n*2+0], numTaxa, YES);
}
else
{
printf ("nodes for unrooted tree:\n");
ShowNodes (root[n*2+0], 2, NO);
//ShowStartTree (root[n*2+0], numTaxa, NO);
}
# endif
}
if (showStartTree == YES)
{
for (n=0; n<numChains; n++)
{
printf ("\n Starting tree for chain %d:\n", n+1);
if (treeModel == ROOTED)
{
ShowNodes (root[n*2+0], 2, YES);
//ShowStartTree (root[n*2+0], numTaxa, YES);
}
else
{
ShowNodes (root[n*2+0], 2, NO);
//ShowStartTree (root[n*2+0], numTaxa, NO);
}
}
}
# if 0
for (n=0; n<numChains; n++)
{
printf ("\n Starting tree for chain %d:\n", n+1);
if (treeModel == ROOTED)
{
ShowNodes (root[n*2+0], 2, YES);
}
else
{
ShowNodes (root[n*2+0], 2, NO);
}
}
# endif
free (availTips);
free (availInts);
free (tempDP);
free (potentialPlaces);
free (tempNodes);
free (localConstraints);
free (localCalibrations);
return (NO_ERROR);
}
void CalcCijk (double *c_ijk, int n, double **u, double **v)
{
register int i, j, k;
double *pc;
/* precalculate values for faster matrix mult in GTRChangeMatrix and GTRDerivatives */
pc = c_ijk;
for (i=0; i<n; i++)
for (j=0; j<n; j++)
for (k=0; k<n; k++)
*pc++ = u[i][k] * v[k][j]; /* (note: pc = &c[i][j][k]) */
}
void CalcPij (double *c_ijk, int n, double *eigenValues, double v, double r, double **p)
{
register int i, j, k;
double vr, *ptr, *g, sum;
vr = v * r;
g = EigValexp;
for (k=0; k<n; k++)
*g++ = exp(*eigenValues++ * vr);
ptr = c_ijk;
for(i=0; i<n; i++)
{
for(j=0; j<n; j++)
{
g = EigValexp;
sum = 0.0;
for(k=0; k<n; k++)
sum += (*ptr++) * (*g++);
p[i][j] = (sum < 0.0) ? 0.0 : sum;
}
}
# if 0
printf ("v = %lf, r = %lf\n", v, r);
for (i=0; i<n; i++)
{
for (j=0; j<n; j++)
{
printf ("%1.3lf ", p[i][j]);
}
printf ("\n");
}
printf ("\n");
# endif
}
void CalcPFSij (double *c_ijk, int n, double *eigenValues, double v, double r, double **p, double **f_p, double **s_p)
{
int i, j, k;
/* P(t) = U * exp{Root*t} * V */
for (i=0; i<n; i++)
{
for (j=0; j<n; j++)
{
p[i][j] = f_p[i][j] = s_p[i][j] = 0.0;
for (k=0; k<n; k++)
{
p[i][j] += c_ijk[i*n*n+j*n+k]*exp(eigenValues[k]*v*r);
f_p[i][j] += c_ijk[i*n*n+j*n+k]*eigenValues[k]*r*exp(eigenValues[k]*v*r);
s_p[i][j] += c_ijk[i*n*n+j*n+k]*eigenValues[k]*eigenValues[k]*r*r*exp(eigenValues[k]*v*r);
}
if (p[i][j] < 0.0)
p[i][j] = 0.0;
}
}
}
#if defined (SMART_TI_PROBS)
int CalcTransitionProbs (int whichState, int whichChain, int numRateCats)
{
if ((dataType == DNA || dataType == RNA) && enforceCodonModel == NO)
{
if (useCovarion == NO)
{
if (CalcTransDNA (whichState, whichChain, numRateCats) == ERROR)
{
return (ERROR);
}
}
else
{
if (CalcTransCovarion (whichState, whichChain, numRateCats) == ERROR)
{
return (ERROR);
}
}
}
else if ((dataType == DNA || dataType == RNA) && enforceCodonModel == YES)
{
if (useCovarion == NO)
{
if (CalcTransCodon (whichState, whichChain) == ERROR)
{
return (ERROR);
}
}
else
{
return (ERROR);
}
}
else if (dataType == PROTEIN)
{
if (useCovarion == NO)
{
if (CalcTransAA (whichState, whichChain, numRateCats) == ERROR)
{
return (ERROR);
}
}
else
{
if (CalcTransCovarion (whichState, whichChain, numRateCats) == ERROR)
{
return (ERROR);
}
}
}
else if (dataType == RESTRICTION)
{
if (useCovarion == NO)
{
}
else
{
return (ERROR);
}
}
else if (dataType == STANDARD)
{
if (useCovarion == NO)
{
}
else
{
return (ERROR);
}
}
else
return (ERROR);
return (NO_ERROR);
}
int CalcTransAA (int whichState, int whichChain, int numRateCats)
{
register int i, j, k, m, index;
int n, lnStates, lnStatesCubed, nRates, lnPartitions, lnumRateCats, isComplex,
allNodesPointer, allNodesStop, nForOneState;
double **probs, *catFreq, *catRate, *partRate,
**q, *eigenValues, *eigvalsImag, **eigvecs, **inverseEigvecs, *c_ijk,
correlation, **markovTi, theRate, bs[20], *ptr;
complex **Ceigvecs, **CinverseEigvecs;
TreeNode *p;
allNodesPointer = whichChain*2*numNodes + whichState*numNodes;
allNodesStop = allNodesPointer + numNodes;
/* standard 4 X 4 model of DNA substitution ***************************************************************************/
lnStates = 20;
lnStatesCubed = 8000;
/* base frequencies */
index = whichChain*2*lnStates + whichState*lnStates;
for (i=0; i<lnStates; i++)
bs[i] = baseFreq[index + i];
/* allocate memory for transition probabilities along a single branch */
probs = psdmatrix (lnStates);
/* get eigenvalues and eigenvectors */
q = psdmatrix (lnStates);
eigenValues = (double *)malloc((size_t) (2 * lnStates * sizeof(double)));
if (!eigenValues)
{
printf ("\n ERROR: Problem allocating eigenValues and eigvalsImag.\n");
goto error_exit;
}
eigvalsImag = eigenValues + lnStates;
eigvecs = psdmatrix (lnStates);
inverseEigvecs = psdmatrix (lnStates);
Ceigvecs = pscmatrix (lnStates);
CinverseEigvecs = pscmatrix (lnStates);
if (SetAAQMatrix (q, whichState, whichChain) == ERROR)
goto error_exit;
isComplex = GetEigens (lnStates, q, eigenValues, eigvalsImag, eigvecs, inverseEigvecs, Ceigvecs, CinverseEigvecs);
if (isComplex == NO)
{
c_ijk = (double *)malloc((size_t) (lnStatesCubed * sizeof(double)));
if (!c_ijk)
{
printf ("\n ERROR: Problem allocating c_ijk.\n");
goto error_exit;
}
CalcCijk (c_ijk, lnStates, eigvecs, inverseEigvecs);
}
/* how many rates are there? */
if (!strcmp(ratesModel, "sitespec") || !strcmp(ratesModel, "ssgamma") || !strcmp(ratesModel, "ssadgamma"))
lnPartitions = nPartitions;
else
lnPartitions = 1;
if (!strcmp(ratesModel, "equal") || !strcmp(ratesModel, "sitespec"))
lnumRateCats = 1;
else
lnumRateCats = numRateCats;
nRates = lnPartitions * lnumRateCats;
/* allocate memory for rate and rate category frequencies */
catFreq = (double *)malloc((size_t) ((2 * lnumRateCats + lnPartitions) * sizeof(double)));
if (!catFreq)
{
printf ("\n ERROR: Problem allocating space for rate multipliers and rate category freqs.\n");
goto error_exit;
}
catRate = catFreq + lnumRateCats;
partRate = catRate + lnumRateCats;
/* fill in rate categories with frequencies and rates */
if (!strcmp(ratesModel,"gamma") || !strcmp(ratesModel, "ssgamma"))
{
DiscreteGamma (catFreq, catRate, alpha[whichChain*2 + whichState], alpha[whichChain*2 + whichState], lnumRateCats, 0);
}
else if (!strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "ssadgamma"))
{
markovTi = psdmatrix (lnumRateCats);
AutodGamma (markovTi, catFreq, catRate, &correlation, alpha[whichChain*2 + whichState], rateCorrelation[whichChain*2 + whichState], lnumRateCats);
}
else if (!strcmp(ratesModel, "invgamma"))
{
DiscreteGamma (catFreq, catRate, alpha[whichChain*2 + whichState], alpha[whichChain*2 + whichState], lnumRateCats-1, 0);
catRate[lnumRateCats-1] = 0.0;
catFreq[lnumRateCats-1] = invP[whichChain*2 + whichState];
for (i=0; i<lnumRateCats-1; i++)
{
catRate[i] *= 1.0 / (1.0 - invP[whichChain*2 + whichState]);
catFreq[i] *= (1.0 - invP[whichChain*2 + whichState]);
}
}
else if (!strcmp(ratesModel, "invariant"))
{
catRate[0] = 0.0;
catRate[1] = 1.0 / (1.0 - invP[whichChain*2 + whichState]);
catFreq[0] = invP[whichChain*2 + whichState];
catFreq[1] = 1.0 - invP[whichChain*2 + whichState];
}
else { // "sitespec" or "equal"
catRate[0] = 1.0;
catFreq[0] = 1.0;
}
/* initialize partition rates, if appropriate */
if (lnPartitions > 1)
{
for (i=0; i<lnPartitions; i++)
partRate[i] = scaledRates[whichChain*2*lnPartitions + whichState*lnPartitions + i];
}
else
partRate[0] = 1.0;
/* calculate transtition probabilities */
nForOneState = numNodes*nodeTiSize;
for (n=allNodesPointer; n<allNodesStop; n++)
{
p = allNodesDownPassSeq[n];
updateTiFlag[p->index] = NO;
if (p->anc != NULL)
{
if ((p->anc->anc != NULL || (p->anc->anc == NULL && treeModel == UNROOTED)) && p->upDateTi == YES)
{
p->upDateTi = NO;
updateTiFlag[p->index] = YES;
ptr = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (p->index)*nodeTiSize);
for (m=index=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
theRate = partRate[m] * catRate[k];
if (isComplex == NO)
CalcPij (c_ijk, lnStates, eigenValues, p->length, theRate, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, lnStates, probs, p->length, theRate) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<lnStates; i++)
for (j=0; j<lnStates; j++)
ptr[index++] = probs[i][j];
}
}
}
}
}
/* free memory */
free_psdmatrix (probs);
free (catFreq);
if (!strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "ssadgamma"))
free_psdmatrix(markovTi);
free_psdmatrix (q);
free (eigenValues);
free_psdmatrix (eigvecs);
free_psdmatrix (inverseEigvecs);
free_pscmatrix (Ceigvecs);
free_pscmatrix (CinverseEigvecs);
if (isComplex != YES)
free (c_ijk);
return (NO_ERROR);
error_exit:
return (ERROR);
}
int CalcTransCodon (int whichState, int whichChain)
{
register int i, j, k, index;
int n, lnStates, lnStatesSquared, lnStatesCube, nOmegaCats, isComplex,
allNodesPointer, allNodesStop, nForOneState, index1;
double **probs, **q, *eigenValues, *eigvalsImag, **eigvecs, **inverseEigvecs, *c_ijk,
*bs, *ptr;
complex **Ceigvecs, **CinverseEigvecs;
TreeNode *p;
allNodesPointer = whichChain*2*numNodes + whichState*numNodes;
allNodesStop = allNodesPointer + numNodes;
/* number of states */
if (!strcmp(codonModelType, "covny98"))
lnStates = 3 * nStates;
else
lnStates = nStates;
lnStatesSquared = lnStates * lnStates;
lnStatesCube = lnStatesSquared * lnStates;
/* load codon frequencies */
bs = (double *)malloc((size_t) (lnStates * sizeof(double)));
if (!bs)
{
printf ("\n ERROR: Problem allocating bs.\n");
goto error_exit;
}
index = whichChain*2*nStates + whichState*nStates;
if (!strcmp(codonModelType, "covny98"))
{
k = 0;
for (i=0; i<nStates; i++)
{
bs[k] = baseFreq[index + i] * probPur[whichChain*2 + whichState];
k++;
}
for (i=0; i<nStates; i++)
{
bs[k] = baseFreq[index + i] * probNeu[whichChain*2 + whichState];
k++;
}
for (i=0; i<nStates; i++)
{
bs[k] = baseFreq[index + i] * probPos[whichChain*2 + whichState];
k++;
}
}
else
{
for (i=0; i<nStates; i++)
bs[i] = baseFreq[index + i];
}
/* how many different omega categories */
if (!strcmp(codonModelType, "ny98") || !strcmp(codonModelType, "ac1ny98") || !strcmp(codonModelType, "ac2ny98"))
nOmegaCats = 3;
else
nOmegaCats = 1;
/* allocate memory for transition probabilities along a single branch */
probs = psdmatrix (lnStates);
/* allocate memory for eigenvalues and eigenvectors */
q = psdmatrix (lnStates);
eigenValues = (double *)malloc((size_t) (2 * lnStates * sizeof(double)));
if (!eigenValues)
{
printf ("\n ERROR: Problem allocating eigenValues and eigvalsImag.\n");
goto error_exit;
}
eigvalsImag = eigenValues + lnStates;
c_ijk = (double *)malloc((size_t) (lnStatesCube * sizeof(double)));
if (!c_ijk)
{
printf ("\n ERROR: Problem allocating c_ijk.\n");
goto error_exit;
}
eigvecs = psdmatrix (lnStates);
inverseEigvecs = psdmatrix (lnStates);
Ceigvecs = pscmatrix (lnStates);
CinverseEigvecs = pscmatrix (lnStates);
/* get eigenvalues and eigenvectors for covarion matrices */
nForOneState = numNodes*nodeTiSize;
index1 = whichChain*2*nForOneState + whichState*nForOneState;
/* always calculate at least one transition matrix */
if (!strcmp(codonModelType, "covny98"))
{
if (SetCodonSwitchQMatrix (q, whichState, whichChain, omega[whichChain*2 + whichState], kappa[whichChain*2 + whichState], switchRate[whichChain*4 + whichState*2 + 0]) == ERROR)
goto error_exit;
}
else
{
if (SetCodonQMatrix (q, whichState, whichChain, omega[whichChain*2 + whichState], kappa[whichChain*2 + whichState]) == ERROR)
goto error_exit;
}
isComplex = GetEigens (lnStates, q, eigenValues, eigvalsImag, eigvecs, inverseEigvecs, Ceigvecs, CinverseEigvecs);
if (isComplex == NO)
{
CalcCijk (c_ijk, lnStates, eigvecs, inverseEigvecs);
}
for (n=allNodesPointer; n<allNodesStop; n++)
{
p = allNodesDownPassSeq[n];
if (p->anc != NULL)
{
if ((p->anc->anc != NULL || (p->anc->anc == NULL && treeModel == UNROOTED)) && p->upDateTi == YES)
{
ptr = transitionProbs + (index1 + (p->index)*nodeTiSize);
if (isComplex == NO)
CalcPij (c_ijk, lnStates, eigenValues, p->length, 1.0, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, lnStates, probs, p->length, 1.0) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
index = 0;
for (i=0; i<lnStates; i++)
for (j=0; j<lnStates; j++)
ptr[index++] = probs[i][j];
}
}
}
/* here if Nielsen and Yang like model is used */
if (!strcmp(codonModelType, "ny98") || !strcmp(codonModelType, "ac1ny98") || !strcmp(codonModelType, "ac2ny98"))
{
/* strong purifying selection */
if (SetCodonQMatrix (q, whichState, whichChain, 0.0, kappa[whichChain*2 + whichState]) == ERROR)
goto error_exit;
isComplex = GetEigens (lnStates, q, eigenValues, eigvalsImag, eigvecs, inverseEigvecs, Ceigvecs, CinverseEigvecs);
if (isComplex == NO)
{
CalcCijk (c_ijk, lnStates, eigvecs, inverseEigvecs);
}
for (n=allNodesPointer; n<allNodesStop; n++)
{
p = allNodesDownPassSeq[n];
if (p->anc != NULL)
{
if ((p->anc->anc != NULL || (p->anc->anc == NULL && treeModel == UNROOTED)) && p->upDateTi == YES)
{
ptr = transitionProbs + (index1 + (p->index)*nodeTiSize + lnStatesSquared);
if (isComplex == NO)
CalcPij (c_ijk, lnStates, eigenValues, p->length, 1.0, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, lnStates, probs, p->length, 1.0) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
index = 0;
for (i=0; i<lnStates; i++)
for (j=0; j<lnStates; j++)
ptr[index++] = probs[i][j];
}
}
}
/* neutral class */
if (SetCodonQMatrix (q, whichState, whichChain, 1.0, kappa[whichChain*2 + whichState]) == ERROR)
goto error_exit;
isComplex = GetEigens (lnStates, q, eigenValues, eigvalsImag, eigvecs, inverseEigvecs, Ceigvecs, CinverseEigvecs);
if (isComplex == NO)
{
CalcCijk (c_ijk, lnStates, eigvecs, inverseEigvecs);
}
for (n=allNodesPointer; n<allNodesStop; n++)
{
p = allNodesDownPassSeq[n];
if (p->anc != NULL)
{
if ((p->anc->anc != NULL || (p->anc->anc == NULL && treeModel == UNROOTED)) && p->upDateTi == YES)
{
ptr = transitionProbs + (index1 + (p->index)*nodeTiSize + 2*lnStatesSquared);
if (isComplex == NO)
CalcPij (c_ijk, lnStates, eigenValues, p->length, 1.0, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, lnStates, probs, p->length, 1.0) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
index = 0;
for (i=0; i<lnStates; i++)
for (j=0; j<lnStates; j++)
ptr[index++] = probs[i][j];
}
}
}
}
/* update flags */
for (n=allNodesPointer; n<allNodesStop; n++)
{
p = allNodesDownPassSeq[n];
updateTiFlag[p->index] = NO;
if (p->anc != NULL)
{
if ((p->anc->anc != NULL || (p->anc->anc == NULL && treeModel == UNROOTED)) && p->upDateTi == YES)
{
p->upDateTi = NO;
updateTiFlag[p->index] = YES;
}
}
}
/* free memory */
free (bs);
free_psdmatrix (probs);
free_psdmatrix (q);
free (eigenValues);
free (c_ijk);
free_psdmatrix (eigvecs);
free_psdmatrix (inverseEigvecs);
free_pscmatrix (Ceigvecs);
free_pscmatrix (CinverseEigvecs);
return (NO_ERROR);
error_exit:
return (ERROR);
}
int CalcTransCovarion (int whichState, int whichChain, int numRateCats)
{
register int i, j, k, m, b, index;
int n, lnStates, lnStatesSquared, lnStatesCube, nRates, lnPartitions, lnumRateCats, isComplex,
allNodesPointer, allNodesStop, nForOneState, index1, index2;
double **probs, *catFreq, *catRate, *partRate,
**q, *eigenValues, *eigvalsImag, **eigvecs, **inverseEigvecs, *c_ijk,
correlation, **markovTi, *bs, *ptr, s01, s10, prob0, prob1;
complex **Ceigvecs, **CinverseEigvecs;
TreeNode *p;
allNodesPointer = whichChain*2*numNodes + whichState*numNodes;
allNodesStop = allNodesPointer + numNodes;
/* twice nStates because matrix is doubled */
lnStates = 2 * nStates;
lnStatesSquared = lnStates * lnStates;
lnStatesCube = lnStates * lnStatesSquared;
/* load base frequencies */
index = whichChain*2*lnStates + whichState*lnStates;
index1 = whichChain*4 + whichState*2;
index2 = whichChain*2 + whichState;
bs = (double *)malloc((size_t) (lnStates * sizeof(double)));
if (!bs)
{
printf ("\n ERROR: Problem allocating bs.\n");
goto error_exit;
}
if (!strcmp(covarionModelType, "ts98"))
{
k = 0;
for (j=0; j<2; j++)
{
for (i=0; i<nStates; i++)
{
bs[k] = baseFreq[whichChain*2*nStates + whichState*nStates + i] * switchPi[whichChain*4 + whichState*2 + j];
k++;
}
}
}
else if (!strcmp(covarionModelType, "gcswitch"))
{
s01 = switchRate[index1 + 0];
s10 = switchRate[index1 + 1];
prob0 = s10 / (s01+s10);
prob1 = s01 / (s01+s10);
bs[0] = (1.0 - gc1[index2]) * (fracA[index2]) * prob0;
bs[1] = (gc1[index2]) * (1.0 - fracG[index2]) * prob0;
bs[2] = (gc1[index2]) * (fracG[index2]) * prob0;
bs[3] = (1.0 - gc1[index2]) * (1.0 - fracA[index2]) * prob0;
bs[4] = (1.0 - gc2[index2]) * (fracA[index2]) * prob1;
bs[5] = (gc2[index2]) * (1.0 - fracG[index2]) * prob1;
bs[6] = (gc2[index2]) * (fracG[index2]) * prob1;
bs[7] = (1.0 - gc2[index2]) * (1.0 - fracA[index2]) * prob1;
}
/* how many different rates? */
if (!strcmp(ratesModel, "sitespec") || !strcmp(ratesModel, "ssgamma") || !strcmp(ratesModel, "ssadgamma"))
lnPartitions = nPartitions;
else
lnPartitions = 1;
if (!strcmp(ratesModel, "equal") || !strcmp(ratesModel, "sitespec"))
lnumRateCats = 1;
else
lnumRateCats = numRateCats;
nRates = lnPartitions * lnumRateCats;
/* allocate memory for transition probabilities along a single branch */
probs = psdmatrix (lnStates);
/* allocate memory for rate and rate category frequencies */
catFreq = (double *)malloc((size_t) ((2 * lnumRateCats + lnPartitions) * sizeof(double)));
if (!catFreq)
{
printf ("\n ERROR: Problem allocating space for rate multipliers and rate category freqs.\n");
goto error_exit;
}
catRate = catFreq + lnumRateCats;
partRate = catRate + lnumRateCats;
/* fill in rate categories with frequencies and rates by dividing the */
if (!strcmp(ratesModel,"gamma")|| !strcmp(ratesModel, "ssgamma"))
{
DiscreteGamma (catFreq, catRate, alpha[whichChain*2 + whichState], alpha[whichChain*2 + whichState], lnumRateCats, 0);
}
else if (!strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "ssadgamma"))
{
markovTi = psdmatrix (lnumRateCats);
AutodGamma (markovTi, catFreq, catRate, &correlation, alpha[whichChain*2 + whichState], rateCorrelation[whichChain*2 + whichState], lnumRateCats);
}
else if (!strcmp(ratesModel, "invgamma"))
{
DiscreteGamma (catFreq, catRate, alpha[whichChain*2 + whichState], alpha[whichChain*2 + whichState], lnumRateCats-1, 0);
catRate[lnumRateCats-1] = 0.0;
catFreq[lnumRateCats-1] = invP[whichChain*2 + whichState];
for (i=0; i<lnumRateCats-1; i++)
{
catRate[i] *= 1.0 / (1.0 - invP[whichChain*2 + whichState]);
catFreq[i] *= (1.0 - invP[whichChain*2 + whichState]);
}
}
else if (!strcmp(ratesModel, "invariant"))
{
catRate[0] = 0.0;
catRate[1] = 1.0 / (1.0 - invP[whichChain*2 + whichState]);
catFreq[0] = invP[whichChain*2 + whichState];
catFreq[1] = 1.0 - invP[whichChain*2 + whichState];
}
else {
catRate[0] = 1.0;
catFreq[0] = 1.0;
}
/* initialize partition rates, if appropriate */
if (lnPartitions > 1)
{
for (i=0; i<lnPartitions; i++)
partRate[i] = scaledRates[whichChain*2*lnPartitions + whichState*lnPartitions + i];
}
else
partRate[0] = 1.0;
/* allocate memory for eigenvalues and eigenvectors */
q = psdmatrix (lnStates);
eigenValues = (double *)malloc((size_t) (2 * lnStates * sizeof(double)));
if (!eigenValues)
{
printf ("\n ERROR: Problem allocating eigenValues and eigvalsImag.\n");
goto error_exit;
}
eigvalsImag = eigenValues + lnStates;
c_ijk = (double *)malloc((size_t) (lnStatesCube * sizeof(double)));
if (!c_ijk)
{
printf ("\n ERROR: Problem allocating c_ijk.\n");
goto error_exit;
}
eigvecs = psdmatrix (lnStates);
inverseEigvecs = psdmatrix (lnStates);
Ceigvecs = pscmatrix (lnStates);
CinverseEigvecs = pscmatrix (lnStates);
/* get eigenvalues and eigenvectors for covarion matrices */
nForOneState = numNodes*nodeTiSize;
for (m=b=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
if (dataType == DNA || dataType == RNA)
{
if (!strcmp(covarionModelType, "ts98"))
{
if (SetDNACovQMatrix (q, whichState, whichChain, catRate[k]*partRate[m]) == ERROR)
goto error_exit;
}
else if (!strcmp(covarionModelType, "gcswitch"))
{
if (SetGCSwitchQMatrix (q, whichState, whichChain, catRate[k]*partRate[m]) == ERROR)
goto error_exit;
}
else
{
goto error_exit;
}
}
else
{
if (SetAACovQMatrix (q, whichState, whichChain, catRate[k]*partRate[m]) == ERROR)
goto error_exit;
}
isComplex = GetEigens (lnStates, q, eigenValues, eigvalsImag, eigvecs, inverseEigvecs, Ceigvecs, CinverseEigvecs);
if (isComplex == NO)
{
CalcCijk (c_ijk, lnStates, eigvecs, inverseEigvecs);
}
index1 = whichChain*2*nForOneState + whichState*nForOneState;
for (n=allNodesPointer; n<allNodesStop; n++)
{
p = allNodesDownPassSeq[n];
if (p->anc != NULL)
{
if ((p->anc->anc != NULL || (p->anc->anc == NULL && treeModel == UNROOTED)) && p->upDateTi == YES)
{
ptr = transitionProbs + (index1 + (p->index)*nodeTiSize + b*lnStatesSquared);
if (isComplex == NO)
CalcPij (c_ijk, lnStates, eigenValues, p->length, 1.0, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, lnStates, probs, p->length, 1.0) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
index = 0;
for (i=0; i<lnStates; i++)
for (j=0; j<lnStates; j++)
ptr[index++] = probs[i][j];
}
}
}
b++;
}
}
/* update flags */
for (n=allNodesPointer; n<allNodesStop; n++)
{
p = allNodesDownPassSeq[n];
updateTiFlag[p->index] = NO;
if (p->anc != NULL)
{
if ((p->anc->anc != NULL || (p->anc->anc == NULL && treeModel == UNROOTED)) && p->upDateTi == YES)
{
p->upDateTi = NO;
updateTiFlag[p->index] = YES;
}
}
}
/* free memory */
free (bs);
free (catFreq);
free_psdmatrix (probs);
free_psdmatrix (q);
free (eigenValues);
free (c_ijk);
free_psdmatrix (eigvecs);
free_psdmatrix (inverseEigvecs);
free_pscmatrix (Ceigvecs);
free_pscmatrix (CinverseEigvecs);
if (!strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "ssadgamma"))
free_psdmatrix(markovTi);
return (NO_ERROR);
error_exit:
return (ERROR);
}
int CalcTransDNA (int whichState, int whichChain, int numRateCats)
{
register int i, j, k, m, index;
int n, lnStates, lnStatesCubed, nRates, lnPartitions, lnumRateCats, isComplex,
allNodesPointer, allNodesStop, nForOneState;
double **probs, *catFreq, *catRate, *partRate, lkappa,
**q, *eigenValues, *eigvalsImag, **eigvecs, **inverseEigvecs, *c_ijk,
correlation, **markovTi, theRate, bs[4], *ptr;
complex **Ceigvecs, **CinverseEigvecs;
TreeNode *p;
allNodesPointer = whichChain*2*numNodes + whichState*numNodes;
allNodesStop = allNodesPointer + numNodes;
/* standard 4 X 4 model of DNA substitution ***************************************************************************/
lnStates = 4;
lnStatesCubed = 64;
/* base frequencies */
index = whichChain*2*nStates + whichState*nStates;
bs[A] = baseFreq[index + A];
bs[C] = baseFreq[index + C];
bs[G] = baseFreq[index + G];
bs[T] = baseFreq[index + T];
/* allocate memory for transition probabilities along a single branch */
probs = psdmatrix (lnStates);
/* find kappa if nst == 1 or nst == 2 */
if (nst == 1)
lkappa = 1.0;
else if (nst == 2)
lkappa = kappa[whichChain*2 + whichState];
/* get eigenvalues and eigenvectors if nst=6 or nst=12 */
if (nst == 6 || nst == 12)
{
q = psdmatrix (lnStates);
eigenValues = (double *)malloc((size_t) (2 * lnStates * sizeof(double)));
if (!eigenValues)
{
printf ("\n ERROR: Problem allocating eigenValues and eigvalsImag.\n");
goto error_exit;
}
eigvalsImag = eigenValues + lnStates;
eigvecs = psdmatrix (lnStates);
inverseEigvecs = psdmatrix (lnStates);
Ceigvecs = pscmatrix (lnStates);
CinverseEigvecs = pscmatrix (lnStates);
if (SetQMatrix (q, whichState, whichChain) == ERROR)
goto error_exit;
isComplex = GetEigens (lnStates, q, eigenValues, eigvalsImag, eigvecs, inverseEigvecs, Ceigvecs, CinverseEigvecs);
if (isComplex == NO)
{
c_ijk = (double *)malloc((size_t) (lnStatesCubed * sizeof(double)));
if (!c_ijk)
{
printf ("\n ERROR: Problem allocating c_ijk.\n");
goto error_exit;
}
CalcCijk (c_ijk, lnStates, eigvecs, inverseEigvecs);
}
}
/* how many rates are there? */
if (!strcmp(ratesModel, "sitespec") || !strcmp(ratesModel, "ssgamma") || !strcmp(ratesModel, "ssadgamma"))
lnPartitions = nPartitions;
else
lnPartitions = 1;
if (!strcmp(ratesModel, "equal") || !strcmp(ratesModel, "sitespec"))
lnumRateCats = 1;
else
lnumRateCats = numRateCats;
nRates = lnPartitions * lnumRateCats;
/* allocate memory for rate and rate category frequencies */
catFreq = (double *)malloc((size_t) ((2 * lnumRateCats + lnPartitions) * sizeof(double)));
if (!catFreq)
{
printf ("\n ERROR: Problem allocating space for rate multipliers and rate category freqs.\n");
goto error_exit;
}
catRate = catFreq + lnumRateCats;
partRate = catRate + lnumRateCats;
/* fill in rate categories with frequencies and rates by dividing the */
if (!strcmp(ratesModel,"gamma") || !strcmp(ratesModel, "ssgamma"))
{
DiscreteGamma (catFreq, catRate, alpha[whichChain*2 + whichState], alpha[whichChain*2 + whichState], lnumRateCats, 0);
}
else if (!strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "ssadgamma"))
{
markovTi = psdmatrix (lnumRateCats);
AutodGamma (markovTi, catFreq, catRate, &correlation, alpha[whichChain*2 + whichState], rateCorrelation[whichChain*2 + whichState], lnumRateCats);
}
else if (!strcmp(ratesModel, "invgamma"))
{
DiscreteGamma (catFreq, catRate, alpha[whichChain*2 + whichState], alpha[whichChain*2 + whichState], lnumRateCats-1, 0);
catRate[lnumRateCats-1] = 0.0;
catFreq[lnumRateCats-1] = invP[whichChain*2 + whichState];
for (i=0; i<lnumRateCats-1; i++)
{
catRate[i] *= 1.0 / (1.0 - invP[whichChain*2 + whichState]);
catFreq[i] *= (1.0 - invP[whichChain*2 + whichState]);
}
}
else if (!strcmp(ratesModel, "invariant"))
{
catRate[0] = 0.0;
catRate[1] = 1.0 / (1.0 - invP[whichChain*2 + whichState]);
catFreq[0] = invP[whichChain*2 + whichState];
catFreq[1] = 1.0 - invP[whichChain*2 + whichState];
}
else { // "sitespec" or "equal"
catRate[0] = 1.0;
catFreq[0] = 1.0;
}
/* initialize partition rates, if appropriate */
if (lnPartitions > 1)
{
for (i=0; i<lnPartitions; i++)
partRate[i] = scaledRates[whichChain*2*lnPartitions + whichState*lnPartitions + i];
}
else
partRate[0] = 1.0;
/* calculate transtition probabilities */
nForOneState = numNodes*nodeTiSize;
for (n=allNodesPointer; n<allNodesStop; n++)
{
p = allNodesDownPassSeq[n];
updateTiFlag[p->index] = NO;
if (p->anc != NULL)
{
if ((p->anc->anc != NULL || (p->anc->anc == NULL && treeModel == UNROOTED)) && p->upDateTi == YES)
{
//printf (" updating %d\n", p->index);
p->upDateTi = NO;
updateTiFlag[p->index] = YES;
ptr = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (p->index)*nodeTiSize);
if (nst == 1 || nst == 2)
{
for (m=index=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
theRate = partRate[m] * catRate[k];
/* calculate transition probabilities for left branch */
HkyChangeMat (probs, p->length, lkappa, theRate, bs[A], bs[C], bs[G], bs[T]);
for (i=0; i<lnStates; i++)
for (j=0; j<lnStates; j++)
ptr[index++] = probs[i][j];
}
}
}
else // nst == 6 or nst == 12
{
for (m=index=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
theRate = partRate[m] * catRate[k];
// calculate transition probabilities for left branch
if (isComplex == NO)
CalcPij (c_ijk, lnStates, eigenValues, p->length, theRate, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, lnStates, probs, p->length, theRate) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<lnStates; i++)
for (j=0; j<lnStates; j++)
ptr[index++] = probs[i][j];
}
}
}
}
}
}
/* free memory */
free_psdmatrix (probs);
free (catFreq);
if (!strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "ssadgamma"))
free_psdmatrix(markovTi);
if (nst == 6 || nst == 12)
{
free_psdmatrix (q);
free (eigenValues);
free_psdmatrix (eigvecs);
free_psdmatrix (inverseEigvecs);
free_pscmatrix (Ceigvecs);
free_pscmatrix (CinverseEigvecs);
if (isComplex != YES)
free (c_ijk);
}
return (NO_ERROR);
error_exit:
return (ERROR);
}
#endif
int CheckConstraints (void)
{
int i, j, k, x, y, consAreConsistent, n1, n2, iCon, jCon,
foundLft, foundRht, nLftOverlap, nRhtOverlap, nBothOverlap;
unsigned int lftPart, rhtPart, conNde;
consAreConsistent = YES;
n1 = nConstraints;
n2 = nCalibrations;
if (enforceConstraints == YES && enforceCalibrations == YES)
{
for (i=0; i<n1+n2-1; i++)
{
if (i < n1)
{
x = i;
iCon = YES;
}
else
{
x = i - n1;
iCon = NO;
}
for (j=i+1; j<n1+n2; j++)
{
if (j < n1)
{
y = j;
jCon = YES;
}
else
{
y = j - n1;
jCon = NO;
}
//printf ("Comparing %d (%d) to %d (%d)\n", x, iCon, y, jCon);
nBothOverlap = nLftOverlap = nRhtOverlap = 0;
for (k=0; k<nTaxa; k++)
{
if (excludedTaxa[k] == NO)
{
if (iCon == YES)
lftPart = constraints[k];
else
lftPart = calibrations[k];
if (jCon == YES)
rhtPart = constraints[k];
else
rhtPart = calibrations[k];
conNde = lftPart & (unsigned int)pow(2.0, (double)x);
if (conNde > 0)
foundLft = YES;
else
foundLft = NO;
conNde = rhtPart & (unsigned int)pow(2.0, (double)y);
if (conNde > 0)
foundRht = YES;
else
foundRht = NO;
if (foundLft == YES && foundRht == YES)
nBothOverlap++;
if (foundLft == YES && foundRht == NO)
nRhtOverlap++;
else if (foundLft == NO && foundRht == YES)
nLftOverlap++;
}
}
//printf (" nlftover = %d nrhtover = %d\n", nLftOverlap, nRhtOverlap);
if (nBothOverlap > 0 && nLftOverlap > 0 && nRhtOverlap > 0)
{
consAreConsistent = NO;
return (consAreConsistent);
}
}
}
}
else if (enforceConstraints == YES && enforceCalibrations == NO)
{
for (i=0; i<n1-1; i++)
{
x = i;
for (j=i+1; j<n1; j++)
{
y = j;
//printf ("Comparing %d (%d) to %d (%d)\n", x, iCon, y, jCon);
nBothOverlap = nLftOverlap = nRhtOverlap = 0;
for (k=0; k<nTaxa; k++)
{
if (excludedTaxa[k] == NO)
{
lftPart = constraints[k];
rhtPart = constraints[k];
conNde = lftPart & (unsigned int)pow(2.0, (double)x);
if (conNde > 0)
foundLft = YES;
else
foundLft = NO;
conNde = rhtPart & (unsigned int)pow(2.0, (double)y);
if (conNde > 0)
foundRht = YES;
else
foundRht = NO;
if (foundLft == YES && foundRht == YES)
nBothOverlap++;
if (foundLft == YES && foundRht == NO)
nRhtOverlap++;
else if (foundLft == NO && foundRht == YES)
nLftOverlap++;
}
}
//printf (" nlftover = %d nrhtover = %d\n", nLftOverlap, nRhtOverlap);
if (nBothOverlap > 0 && nLftOverlap > 0 && nRhtOverlap > 0)
{
consAreConsistent = NO;
return (consAreConsistent);
}
}
}
}
else if (enforceConstraints == NO && enforceCalibrations == YES)
{
for (i=0; i<n1-1; i++)
{
x = i;
for (j=i+1; j<n1; j++)
{
y = j;
//printf ("Comparing %d (%d) to %d (%d)\n", x, iCon, y, jCon);
nBothOverlap = nLftOverlap = nRhtOverlap = 0;
for (k=0; k<nTaxa; k++)
{
if (excludedTaxa[k] == NO)
{
lftPart = calibrations[k];
rhtPart = calibrations[k];
conNde = lftPart & (unsigned int)pow(2.0, (double)x);
if (conNde > 0)
foundLft = YES;
else
foundLft = NO;
conNde = rhtPart & (unsigned int)pow(2.0, (double)y);
if (conNde > 0)
foundRht = YES;
else
foundRht = NO;
if (foundLft == YES && foundRht == YES)
nBothOverlap++;
if (foundLft == YES && foundRht == NO)
nRhtOverlap++;
else if (foundLft == NO && foundRht == YES)
nLftOverlap++;
}
}
//printf (" nlftover = %d nrhtover = %d\n", nLftOverlap, nRhtOverlap);
if (nBothOverlap > 0 && nLftOverlap > 0 && nRhtOverlap > 0)
{
consAreConsistent = NO;
return (consAreConsistent);
}
}
}
}
return (consAreConsistent);
}
int ComplexChangeMatrix (double *eigenValues, double *eigvalsImag, complex **Ceigvecs, complex **CinverseEigvecs, int n, double **p, double t, double r)
{
int i, j, k, rc;
complex **Cwork;
rc = NO_ERROR;
Cwork = pscmatrix(n);
for(i=0; i<n; i++)
{
for(j=0; j<n; j++)
{
Cwork[i][j].re = 0.0;
Cwork[i][j].im = 0.0;
for(k = 0; k < n; k++)
{
Cwork[i][j] = Cadd(Cwork[i][j], Cmul(Ceigvecs[i][k], Cmul(CinverseEigvecs[k][j], Cexp(RCmul(t*r, Complex(eigenValues[k], eigvalsImag[k]))))));
}
}
}
for(i=0; i<n; i++)
{
for(j=0; j<n; j++)
{
p[i][j] = Cwork[i][j].re;
if (p[i][j] < 0.0)
p[i][j] = 0.0;
if(fabs(Cwork[i][j].im) > 0.1)
{
printf ("i = %lf\n", Cwork[i][j].im);
rc = ERROR;
}
}
}
free_pscmatrix (Cwork);
return (rc);
}
int ComplexDerivativesMatrix (double *eigenValues, double *eigvalsImag, complex **Ceigvecs, complex **CinverseEigvecs, int n, double **f, double **s, double t, double r)
{
int i, j, k, rc;
complex ceval, **Cwork1, **Cwork2, rate;
rc = NO_ERROR;
rate.re = r;
rate.im = 0.0;
Cwork1 = pscmatrix(n);
Cwork2 = pscmatrix(n);
for(i=0; i<n; i++)
{
for(j=0; j<n; j++)
{
Cwork1[i][j].re = Cwork2[i][j].re = 0.0;
Cwork1[i][j].im = Cwork2[i][j].im = 0.0;
for(k = 0; k < n; k++)
{
ceval = Complex(eigenValues[k], eigvalsImag[k]);
Cwork1[i][j] = Cadd(Cwork1[i][j], Cmul(rate, Cmul(Ceigvecs[i][k], Cmul(CinverseEigvecs[k][j], Cmul(ceval, Cexp(RCmul(t * r, ceval)))))));
Cwork2[i][j] = Cadd(Cwork2[i][j], Cmul(rate, Cmul(rate, Cmul(Ceigvecs[i][k], Cmul(CinverseEigvecs[k][j], Cmul(ceval, Cmul(ceval, Cexp(RCmul(t * r, ceval)))))))));
}
}
}
for(i=0; i<n; i++)
{
for(j=0; j<n; j++)
{
f[i][j] = Cwork1[i][j].re;
s[i][j] = Cwork2[i][j].re;
if(fabs(Cwork1[i][j].im) > 0.000000000001 || fabs(Cwork2[i][j].im) > 0.000000000001)
{
rc = ERROR;
}
}
}
free_pscmatrix (Cwork1);
free_pscmatrix (Cwork2);
return (rc);
}
int CompressMatrix (int *numTaxa, int *numChars)
{
int i, j, k, *numOfThisPat, isSame, nPat, nt, siteNum, taxNum, *tempMatrix, *tempNumSitePats, *tempPartId, nOnes, nTwos;
#if defined (MORPH)
int index;
#endif
nExcluded = 0;
for (i=0; i<nChar; i++)
if (excludedSites[i] == YES)
nExcluded++;
numDummyChars = 0;
if ((dataType == DNA || dataType == RNA) && enforceCodonModel == YES)
{
printf (" Compressing codon matrix\n");
/* 61 X 61 substitution model */
if (nChar % 3 != 0)
{
printf ("\n ERROR: Number of sites in data matrix must be divisable\n");
printf (" by 3 for codon models.\n");
FreeMemory ();
return (ERROR);
}
patternId = (int *)malloc((size_t) ((nChar / 3) * sizeof(int)));
if (!patternId)
{
printf ("ERROR: Problem allocating patternId\n");
return (ERROR);
}
else
allocatedMemory[ALLOC_PAT_IDS] = YES;
for (i=0; i<nChar/3; i++)
patternId[i] = -1;
numOfThisPat = (int *)malloc((size_t) ((nChar / 3) * sizeof(int)));
if (!numOfThisPat)
{
printf ("\n ERROR: Problem allocating numOfThisPat.\n");
FreeMemory ();
return (ERROR);
}
for (i=0; i<nChar/3; i++)
{
if (excludedSites[i*3] == YES || excludedSites[i*3+1] == YES || excludedSites[i*3+2] == YES)
numOfThisPat[i] = 0;
else
numOfThisPat[i] = 1;
}
siteNum = 0;
for (i=0; i<(nChar/3)-1; i++)
{
if (numOfThisPat[i] > 0)
{
patternId[i] = siteNum;
for (j=i+1; j<(nChar/3); j++)
{
if (numOfThisPat[j] > 0)
{
isSame = YES;
for (k=0; k<nTaxa; k++)
{
if (excludedTaxa[k] == NO && origDataMatrix[k*nChar+i*3] != origDataMatrix[k*nChar+j*3])
isSame = NO;
if (excludedTaxa[k] == NO && origDataMatrix[k*nChar+i*3+1] != origDataMatrix[k*nChar+j*3+1])
isSame = NO;
if (excludedTaxa[k] == NO && origDataMatrix[k*nChar+i*3+2] != origDataMatrix[k*nChar+j*3+2])
isSame = NO;
}
if (isSame == YES)
{
numOfThisPat[i]++;
numOfThisPat[j] = 0;
patternId[j] = patternId[i] = siteNum;
}
}
}
siteNum++;
}
}
if (patternId[nChar/3 - 1] == -1)
patternId[nChar/3 - 1] = siteNum++;
# if 0
k = 0;
for (i=0; i<nChar/3; i++)
{
k++;
printf ("%4d -- ", k);
for (j=0; j<nTaxa; j++)
{
printf ("%2d ", origDataMatrix[j*nChar + i*3]);
printf ("%2d ", origDataMatrix[j*nChar + i*3+1]);
printf ("%2d ", origDataMatrix[j*nChar + i*3+2]);
}
printf (" -- %d %d\n", patternId[i], numOfThisPat[i]);
}
# endif
nPat = 0;
for (i=0; i<nChar/3; i++)
{
if (numOfThisPat[i] > 0)
nPat++;
}
nt = 0;
for (j=0; j<nTaxa; j++)
{
if (excludedTaxa[j] == NO)
nt++;
}
printf (" Data matrix has %d taxa and %d site patterns\n", nt, nPat);
(*numTaxa) = nt;
(*numChars) = nPat;
matrix = (int *)malloc((size_t) (nt * nPat * 3 * sizeof(int)));
if (!matrix)
{
printf ("\n ERROR: Problem allocating matrix.\n");
FreeMemory ();
free (numOfThisPat);
return (ERROR);
}
else
allocatedMemory[ALLOC_MATRIX] = YES;
numSitesOfPat = (int *)malloc((size_t) (nPat * sizeof(int)));
if (!numSitesOfPat)
{
printf ("\n ERROR: Problem allocating numSitesOfPat.\n");
FreeMemory ();
free (numOfThisPat);
return (ERROR);
}
else
allocatedMemory[ALLOC_N_SITE_PATS] = YES;
partitionId = (int *)malloc((size_t) (nPat * sizeof(int)));
if (!partitionId)
{
printf ("\n ERROR: Problem allocating partitionId.\n");
FreeMemory ();
free (numOfThisPat);
return (ERROR);
}
else
allocatedMemory[ALLOC_PART_ID] = YES;
for (i=0; i<nPat; i++)
partitionId[i] = 0;
siteNum = 0;
for (i=0; i<nChar/3; i++)
{
if (numOfThisPat[i] > 0)
{
numSitesOfPat[siteNum] = numOfThisPat[i];
taxNum = 0;
for (j=0; j<nTaxa; j++)
{
if (excludedTaxa[j] == NO)
{
matrix[pos(taxNum,siteNum*3, (*numChars)*3)] = origDataMatrix[j*nChar+i*3];
matrix[pos(taxNum,siteNum*3+1,(*numChars)*3)] = origDataMatrix[j*nChar+i*3+1];
matrix[pos(taxNum,siteNum*3+2,(*numChars)*3)] = origDataMatrix[j*nChar+i*3+2];
taxNum++;
}
}
siteNum++;
}
}
free (numOfThisPat);
# if 0
for (i=0; i<(*numChars); i++)
{
printf ("%4d -- ", i+1);
for (j=0; j<(*numTaxa); j++)
{
printf ("%2d ", matrix[pos(j,i*3, (*numChars)*3)]);
printf ("%2d ", matrix[pos(j,i*3+1,(*numChars)*3)]);
printf ("%2d ", matrix[pos(j,i*3+2,(*numChars)*3)]);
}
printf ("-- %3d %3d\n", numSitesOfPat[i], partitionId[i]);
}
# endif
}
else if (((dataType == DNA || dataType == RNA) && enforceCodonModel == NO) || dataType == PROTEIN)
{
printf (" Compressing data matrix\n");
/* 4 X 4 or 20 X 20 substitution model */
patternId = (int *)malloc((size_t) (nChar * sizeof(int)));
if (!patternId)
{
printf ("ERROR: Problem allocating patternId\n");
return (ERROR);
}
else
allocatedMemory[ALLOC_PAT_IDS] = YES;
for (i=0; i<nChar; i++)
patternId[i] = -1;
if (!strcmp(ratesModel, "sitespec") || !strcmp(ratesModel, "ssgamma") || !strcmp(ratesModel, "ssadgamma"))
{
/* compress for site-specific rates */
numOfThisPat = (int *)malloc((size_t) (nChar * sizeof(int)));
if (!numOfThisPat)
{
printf ("\n ERROR: Problem allocating numOfThisPat.\n");
FreeMemory ();
return (ERROR);
}
for (i=0; i<nChar; i++)
{
if (excludedSites[i] == YES)
numOfThisPat[i] = 0;
else
numOfThisPat[i] = 1;
}
siteNum = 0;
for (i=0; i<nChar-1; i++)
{
if (numOfThisPat[i] > 0)
{
patternId[i] = siteNum;
for (j=i+1; j<nChar; j++)
{
if (numOfThisPat[j] > 0)
{
isSame = YES;
for (k=0; k<nTaxa; k++)
{
if (excludedTaxa[k] == NO && origDataMatrix[k*nChar+i] != origDataMatrix[k*nChar+j])
{
isSame = NO;
}
}
if (isSame == YES && sitePartitions[i] == sitePartitions[j])
{
numOfThisPat[i]++;
numOfThisPat[j] = 0;
patternId[j] = siteNum;
}
}
}
siteNum++;
}
}
if (patternId[nChar - 1] == -1)
patternId[nChar - 1] = siteNum++;
nPat = 0;
for (i=0; i<nChar; i++)
{
if (numOfThisPat[i] > 0)
nPat++;
}
nt = 0;
for (j=0; j<nTaxa; j++)
{
if (excludedTaxa[j] == NO)
nt++;
}
printf (" Data matrix has %d taxa and %d site patterns\n", nt, nPat);
(*numTaxa) = nt;
(*numChars) = nPat;
matrix = (int *)malloc((size_t) (nt * nPat * sizeof(int)));
if (!matrix)
{
printf ("\n ERROR: Problem allocating matrix.\n");
FreeMemory ();
free (numOfThisPat);
return (ERROR);
}
else
allocatedMemory[ALLOC_MATRIX] = YES;
numSitesOfPat = (int *)malloc((size_t) (nPat * sizeof(int)));
if (!numSitesOfPat)
{
printf ("\n ERROR: Problem allocating numSitesOfPat.\n");
FreeMemory ();
free (numOfThisPat);
return (ERROR);
}
else
allocatedMemory[ALLOC_N_SITE_PATS] = YES;
partitionId = (int *)malloc((size_t) (nPat * sizeof(int)));
if (!partitionId)
{
printf ("\n ERROR: Problem allocating partitionId.\n");
FreeMemory ();
free (numOfThisPat);
return (ERROR);
}
else
allocatedMemory[ALLOC_PART_ID] = YES;
siteNum = 0;
for (i=0; i<nChar; i++)
{
if (numOfThisPat[i] > 0)
{
patternId[i] = siteNum;
taxNum = 0;
for (j=0; j<nTaxa; j++)
{
if (excludedTaxa[j] == NO)
{
matrix[pos(taxNum,siteNum,(*numChars))] = origDataMatrix[j*nChar+i];
taxNum++;
}
}
numSitesOfPat[siteNum] = numOfThisPat[i];
partitionId[siteNum] = sitePartitions[i] - 1;
if (sitePartitions[i] - 1 < 0 && sitePartitions[i] >= nPartitions)
{
printf ("\n ERROR: Invalid partition ID.\n");
free (numOfThisPat);
FreeMemory ();
return (ERROR);
}
siteNum++;
}
}
free (numOfThisPat);
}
else
{
/* compress for other types of rate models */
numOfThisPat = (int *)malloc((size_t) (nChar * sizeof(int)));
if (!numOfThisPat)
{
printf ("\n ERROR: Problem allocating numOfThisPat.\n");
FreeMemory ();
return (ERROR);
}
for (i=0; i<nChar; i++)
{
if (excludedSites[i] == YES)
numOfThisPat[i] = 0;
else
numOfThisPat[i] = 1;
}
siteNum = 0;
for (i=0; i<nChar-1; i++)
{
if (numOfThisPat[i] > 0)
{
patternId[i] = siteNum;
for (j=i+1; j<nChar; j++)
{
if (numOfThisPat[j] > 0)
{
isSame = YES;
for (k=0; k<nTaxa; k++)
{
if (excludedTaxa[k] == NO && origDataMatrix[k*nChar+i] != origDataMatrix[k*nChar+j])
{
isSame = NO;
}
}
if (isSame == YES)
{
numOfThisPat[i]++;
numOfThisPat[j] = 0;
patternId[j] = patternId[i] = siteNum;
}
}
}
siteNum++;
}
}
if (patternId[nChar - 1] == -1)
patternId[nChar - 1] = siteNum++;
nPat = 0;
for (i=0; i<nChar; i++)
{
if (numOfThisPat[i] > 0)
nPat++;
}
nt = 0;
for (j=0; j<nTaxa; j++)
{
if (excludedTaxa[j] == NO)
nt++;
}
printf (" Data matrix has %d taxa and %d site patterns\n", nt, nPat);
(*numTaxa) = nt;
(*numChars) = nPat;
matrix = (int *)malloc((size_t) (nt * nPat * sizeof(int)));
if (!matrix)
{
printf ("\n ERROR: Problem allocating matrix.\n");
FreeMemory ();
free (numOfThisPat);
return (ERROR);
}
else
allocatedMemory[ALLOC_MATRIX] = YES;
numSitesOfPat = (int *)malloc((size_t) (nPat * sizeof(int)));
if (!numSitesOfPat)
{
printf ("\n ERROR: Problem allocating numSitesOfPat.\n");
FreeMemory ();
free (numOfThisPat);
return (ERROR);
}
else
allocatedMemory[ALLOC_N_SITE_PATS] = YES;
partitionId = (int *)malloc((size_t) (nPat * sizeof(int)));
if (!partitionId)
{
printf ("\n ERROR: Problem allocating partitionId.\n");
FreeMemory ();
free (numOfThisPat);
return (ERROR);
}
else
allocatedMemory[ALLOC_PART_ID] = YES;
siteNum = 0;
for (i=0; i<nChar; i++)
{
if (numOfThisPat[i] > 0)
{
taxNum = 0;
for (j=0; j<nTaxa; j++)
{
if (excludedTaxa[j] == NO)
{
matrix[pos(taxNum,siteNum,(*numChars))] = origDataMatrix[j*nChar+i];
taxNum++;
}
}
numSitesOfPat[siteNum] = numOfThisPat[i];
partitionId[siteNum] = 0;
siteNum++;
}
}
free (numOfThisPat);
}
# if 0
for (i=0; i<(*numChars); i++)
{
printf ("%4d -- ", i+1);
for (j=0; j<(*numTaxa); j++)
{
printf ("%2d ", matrix[pos(j,i,(*numChars))]);
}
printf ("-- %3d %3d\n", numSitesOfPat[i], partitionId[i]);
}
# endif
}
else if (dataType == RESTRICTION)
{
printf (" Compressing data matrix\n");
/* 2 X 2 substitution model */
patternId = (int *)malloc((size_t) (nChar * sizeof(int)));
if (!patternId)
{
printf ("ERROR: Problem allocating patternId\n");
return (ERROR);
}
else
allocatedMemory[ALLOC_PAT_IDS] = YES;
for (i=0; i<nChar; i++)
patternId[i] = -1;
numOfThisPat = (int *)malloc((size_t) (nChar * sizeof(int)));
if (!numOfThisPat)
{
printf ("\n ERROR: Problem allocating numOfThisPat.\n");
FreeMemory ();
return (ERROR);
}
for (i=0; i<nChar; i++)
{
if (excludedSites[i] == YES)
numOfThisPat[i] = 0;
else
numOfThisPat[i] = 1;
}
siteNum = 0;
for (i=0; i<nChar-1; i++)
{
if (numOfThisPat[i] > 0)
{
patternId[i] = siteNum;
for (j=i+1; j<nChar; j++)
{
if (numOfThisPat[j] > 0)
{
isSame = YES;
for (k=0; k<nTaxa; k++)
{
if (excludedTaxa[k] == NO && origDataMatrix[k*nChar+i] != origDataMatrix[k*nChar+j])
{
isSame = NO;
}
}
if (isSame == YES)
{
numOfThisPat[i]++;
numOfThisPat[j] = 0;
patternId[j] = patternId[i] = siteNum;
}
}
}
siteNum++;
}
}
if (patternId[nChar - 1] == -1)
patternId[nChar - 1] = siteNum++;
nPat = 0;
for (i=0; i<nChar; i++)
{
if (numOfThisPat[i] > 0)
nPat++;
}
nt = 0;
for (j=0; j<nTaxa; j++)
{
if (excludedTaxa[j] == NO)
nt++;
}
printf (" Data matrix has %d taxa and %d site patterns\n", nt, nPat);
(*numTaxa) = nt;
(*numChars) = nPat;
matrix = (int *)malloc((size_t) (nt * nPat * sizeof(int)));
if (!matrix)
{
printf ("\n ERROR: Problem allocating matrix.\n");
FreeMemory ();
free (numOfThisPat);
return (ERROR);
}
else
allocatedMemory[ALLOC_MATRIX] = YES;
numSitesOfPat = (int *)malloc((size_t) (nPat * sizeof(int)));
if (!numSitesOfPat)
{
printf ("\n ERROR: Problem allocating numSitesOfPat.\n");
FreeMemory ();
free (numOfThisPat);
return (ERROR);
}
else
allocatedMemory[ALLOC_N_SITE_PATS] = YES;
partitionId = (int *)malloc((size_t) (nPat * sizeof(int)));
if (!partitionId)
{
printf ("\n ERROR: Problem allocating partitionId.\n");
FreeMemory ();
free (numOfThisPat);
return (ERROR);
}
else
allocatedMemory[ALLOC_PART_ID] = YES;
siteNum = 0;
for (i=0; i<nChar; i++)
{
if (numOfThisPat[i] > 0)
{
taxNum = 0;
for (j=0; j<nTaxa; j++)
{
if (excludedTaxa[j] == NO)
{
matrix[pos(taxNum,siteNum,(*numChars))] = origDataMatrix[j*nChar+i];
taxNum++;
}
}
numSitesOfPat[siteNum] = numOfThisPat[i];
partitionId[siteNum] = 0;
siteNum++;
}
}
if (!strcmp(codingType, "variable") || !strcmp(codingType, "noabsence") || !strcmp(codingType, "nopresence"))
{
printf (" Adding dummy %s character(s)\n", codingType);
tempMatrix = (int *)malloc((size_t) (nt * nPat * sizeof(int)));
if (!tempMatrix)
{
printf ("\n ERROR: Problem allocating tempMatrix.\n");
FreeMemory ();
free (numOfThisPat);
return (ERROR);
}
tempNumSitePats = (int *)malloc((size_t) (nPat * sizeof(int)));
if (!tempNumSitePats)
{
printf ("\n ERROR: Problem allocating tempNumSitePats.\n");
FreeMemory ();
free (numOfThisPat);
return (ERROR);
}
tempPartId = (int *)malloc((size_t) (nPat * sizeof(int)));
if (!tempPartId)
{
printf ("\n ERROR: Problem allocating tempPartId.\n");
FreeMemory ();
free (numOfThisPat);
return (ERROR);
}
for (i=0; i<nPat; i++)
{
for (j=0; j<nTaxa; j++)
{
tempMatrix[pos(j,i,(*numChars))] = matrix[pos(j,i,(*numChars))];
}
tempNumSitePats[i] = numSitesOfPat[i];
tempPartId[i] = partitionId[i];
}
free (matrix);
free (numSitesOfPat);
free (partitionId);
allocatedMemory[ALLOC_MATRIX] = NO;
allocatedMemory[ALLOC_N_SITE_PATS] = NO;
allocatedMemory[ALLOC_PART_ID] = NO;
if (!strcmp(codingType, "variable"))
numDummyChars = 2;
else if (!strcmp(codingType, "noabsence") || !strcmp(codingType, "nopresence"))
numDummyChars = 1;
matrix = (int *)malloc((size_t) (nt * (nPat+numDummyChars) * sizeof(int)));
if (!matrix)
{
printf ("\n ERROR: Problem allocating matrix.\n");
FreeMemory ();
free (numOfThisPat);
return (ERROR);
}
else
allocatedMemory[ALLOC_MATRIX] = YES;
numSitesOfPat = (int *)malloc((size_t) ((nPat+numDummyChars) * sizeof(int)));
if (!numSitesOfPat)
{
printf ("\n ERROR: Problem allocating numSitesOfPat.\n");
FreeMemory ();
free (numOfThisPat);
return (ERROR);
}
else
allocatedMemory[ALLOC_N_SITE_PATS] = YES;
partitionId = (int *)malloc((size_t) ((nPat+numDummyChars) * sizeof(int)));
if (!partitionId)
{
printf ("\n ERROR: Problem allocating partitionId.\n");
FreeMemory ();
free (numOfThisPat);
return (ERROR);
}
else
allocatedMemory[ALLOC_PART_ID] = YES;
for (i=0; i<nPat; i++)
{
for (j=0; j<nTaxa; j++)
{
matrix[pos(j,i+numDummyChars,(*numChars)+numDummyChars)] = tempMatrix[pos(j,i,(*numChars))];
}
numSitesOfPat[i+numDummyChars] = tempNumSitePats[i];
partitionId[i+numDummyChars] = tempPartId[i];
}
nPat += numDummyChars;
(*numChars) = nPat;
if (!strcmp(codingType, "variable"))
{
numSitesOfPat[0] = 0;
partitionId[0] = 0;
numSitesOfPat[1] = 0;
partitionId[1] = 0;
for (j=0; j<nTaxa; j++)
{
matrix[pos(j,0,(*numChars))] = 1;
matrix[pos(j,1,(*numChars))] = 2;
}
}
else
{
numSitesOfPat[0] = 0;
partitionId[0] = 0;
for (j=0; j<nTaxa; j++)
{
if (!strcmp(codingType, "noabsence"))
matrix[pos(j,0,(*numChars))] = 1;
else if (!strcmp(codingType, "nopresence"))
matrix[pos(j,0,(*numChars))] = 2;
}
}
free (tempMatrix);
free (tempNumSitePats);
free (tempPartId);
/* check to see if the dummy characters are present elsewhere */
for (i=numDummyChars; i<nPat; i++)
{
nOnes = nTwos = 0;
for (j=0; j<nTaxa; j++)
{
if (matrix[pos(j,i,(*numChars))] == 1)
nOnes++;
else if (matrix[pos(j,i,(*numChars))] == 2)
nTwos++;
}
if (nOnes == nTaxa && (!strcmp(codingType, "variable") || !strcmp(codingType, "noabsence")))
{
printf ("\n Warning: Not expecting all absence characters with this coding (%d).\n", i-numDummyChars+1);
printf ("\n Continue with chain? (yes/no): ");
if (YesNo() == YES)
{
printf (" Continuing with chain, even if it is not a good idea... \n\n");
break;
}
else
{
FreeMemory ();
free (numOfThisPat);
return (ERROR);
}
}
else if (nTwos == nTaxa && (!strcmp(codingType, "variable") || !strcmp(codingType, "nopresence")))
{
printf ("\n Warning: Not expecting all presence characters with this coding (%d).\n", i-numDummyChars+1);
printf ("\n Continue with chain? (yes/no): ");
if (YesNo() == YES)
{
printf (" Continuing with chain, even if it is not a good idea... \n\n");
break;
}
else
{
FreeMemory ();
free (numOfThisPat);
return (ERROR);
}
}
}
}
free (numOfThisPat);
# if 0
for (i=0; i<(*numChars); i++)
{
printf ("%4d -- ", i+1);
for (j=0; j<(*numTaxa); j++)
{
printf ("%d", matrix[pos(j,i,(*numChars))]);
}
printf ("-- %3d %3d\n", numSitesOfPat[i], partitionId[i]);
}
# endif
}
else if (dataType == STANDARD)
{
printf (" Compressing data matrix\n");
/* 2 X 2 substitution model */
patternId = (int *)malloc((size_t) (nChar * sizeof(int)));
if (!patternId)
{
printf ("ERROR: Problem allocating patternId\n");
return (ERROR);
}
else
allocatedMemory[ALLOC_PAT_IDS] = YES;
for (i=0; i<nChar; i++)
patternId[i] = -1;
numOfThisPat = (int *)malloc((size_t) (nChar * sizeof(int)));
if (!numOfThisPat)
{
printf ("\n ERROR: Problem allocating numOfThisPat.\n");
FreeMemory ();
return (ERROR);
}
for (i=0; i<nChar; i++)
{
if (excludedSites[i] == YES)
numOfThisPat[i] = 0;
else
numOfThisPat[i] = 1;
}
siteNum = 0;
for (i=0; i<nChar-1; i++)
{
if (numOfThisPat[i] > 0)
{
patternId[i] = siteNum;
for (j=i+1; j<nChar; j++)
{
if (numOfThisPat[j] > 0)
{
isSame = YES;
for (k=0; k<nTaxa; k++)
{
if (excludedTaxa[k] == NO && origDataMatrix[k*nChar+i] != origDataMatrix[k*nChar+j])
{
isSame = NO;
}
}
# if !defined (MORPH)
if (isSame == YES/* && isSame == NO*/) /* NOTE: I am simply fooling the compression part of the algorithm */
/* so that no compression occurs. */
# else
if (isSame == YES)
# endif
{
numOfThisPat[i]++;
numOfThisPat[j] = 0;
patternId[j] = patternId[i] = siteNum;
}
}
}
siteNum++;
}
}
if (patternId[nChar - 1] == -1)
patternId[nChar - 1] = siteNum++;
nPat = 0;
for (i=0; i<nChar; i++)
{
if (numOfThisPat[i] > 0)
nPat++;
}
nt = 0;
for (j=0; j<nTaxa; j++)
{
if (excludedTaxa[j] == NO)
nt++;
}
printf (" Data matrix has %d taxa and %d site patterns\n", nt, nPat);
(*numTaxa) = nt;
(*numChars) = nPat;
matrix = (int *)malloc((size_t) (nt * nPat * sizeof(int)));
if (!matrix)
{
printf ("\n ERROR: Problem allocating matrix.\n");
FreeMemory ();
free (numOfThisPat);
return (ERROR);
}
else
allocatedMemory[ALLOC_MATRIX] = YES;
numSitesOfPat = (int *)malloc((size_t) (nPat * sizeof(int)));
if (!numSitesOfPat)
{
printf ("\n ERROR: Problem allocating numSitesOfPat.\n");
FreeMemory ();
free (numOfThisPat);
return (ERROR);
}
else
allocatedMemory[ALLOC_N_SITE_PATS] = YES;
partitionId = (int *)malloc((size_t) (nPat * sizeof(int)));
if (!partitionId)
{
printf ("\n ERROR: Problem allocating partitionId.\n");
FreeMemory ();
free (numOfThisPat);
return (ERROR);
}
else
allocatedMemory[ALLOC_PART_ID] = YES;
siteNum = 0;
for (i=0; i<nChar; i++)
{
if (numOfThisPat[i] > 0)
{
taxNum = 0;
for (j=0; j<nTaxa; j++)
{
if (excludedTaxa[j] == NO)
{
matrix[pos(taxNum,siteNum,(*numChars))] = origDataMatrix[j*nChar+i];
taxNum++;
}
}
numSitesOfPat[siteNum] = numOfThisPat[i];
partitionId[siteNum] = 0;
siteNum++;
}
}
if (!strcmp(codingType, "variable") || !strcmp(codingType, "informative"))
{
#if defined (MORPH)
printf (" Adding dummy characters that are not %s\n", codingType);
#else
printf (" Adding dummy %s character(s)\n", codingType);
#endif
tempMatrix = (int *)malloc((size_t) (nt * nPat * sizeof(int)));
if (!tempMatrix)
{
printf ("\n ERROR: Problem allocating tempMatrix.\n");
FreeMemory ();
free (numOfThisPat);
return (ERROR);
}
tempNumSitePats = (int *)malloc((size_t) (nPat * sizeof(int)));
if (!tempNumSitePats)
{
printf ("\n ERROR: Problem allocating tempNumSitePats.\n");
FreeMemory ();
free (numOfThisPat);
return (ERROR);
}
tempPartId = (int *)malloc((size_t) (nPat * sizeof(int)));
if (!tempPartId)
{
printf ("\n ERROR: Problem allocating tempPartId.\n");
FreeMemory ();
free (numOfThisPat);
return (ERROR);
}
for (i=0; i<nPat; i++)
{
for (j=0; j<nTaxa; j++)
{
tempMatrix[pos(j,i,(*numChars))] = matrix[pos(j,i,(*numChars))];
}
tempNumSitePats[i] = numSitesOfPat[i];
tempPartId[i] = partitionId[i];
}
free (matrix);
free (numSitesOfPat);
free (partitionId);
allocatedMemory[ALLOC_MATRIX] = NO;
allocatedMemory[ALLOC_N_SITE_PATS] = NO;
allocatedMemory[ALLOC_PART_ID] = NO;
if (!strcmp(codingType, "variable"))
numDummyChars = 2;
else if (!strcmp(codingType, "informative"))
#if !defined (MORPH)
numDummyChars = 1; /* this will be 2 + 2*ntax when properly implemented */
#else
numDummyChars = 2 + 2*nTaxa;
#endif
matrix = (int *)malloc((size_t) (nt * (nPat+numDummyChars) * sizeof(int)));
if (!matrix)
{
printf ("\n ERROR: Problem allocating matrix.\n");
FreeMemory ();
free (numOfThisPat);
return (ERROR);
}
else
allocatedMemory[ALLOC_MATRIX] = YES;
numSitesOfPat = (int *)malloc((size_t) ((nPat+numDummyChars) * sizeof(int)));
if (!numSitesOfPat)
{
printf ("\n ERROR: Problem allocating numSitesOfPat.\n");
FreeMemory ();
free (numOfThisPat);
return (ERROR);
}
else
allocatedMemory[ALLOC_N_SITE_PATS] = YES;
partitionId = (int *)malloc((size_t) ((nPat+numDummyChars) * sizeof(int)));
if (!partitionId)
{
printf ("\n ERROR: Problem allocating partitionId.\n");
FreeMemory ();
free (numOfThisPat);
return (ERROR);
}
else
allocatedMemory[ALLOC_PART_ID] = YES;
for (i=0; i<nPat; i++)
{
for (j=0; j<nTaxa; j++)
{
matrix[pos(j,i+numDummyChars,(*numChars)+numDummyChars)] = tempMatrix[pos(j,i,(*numChars))];
}
numSitesOfPat[i+numDummyChars] = tempNumSitePats[i];
partitionId[i+numDummyChars] = tempPartId[i];
}
nPat += numDummyChars;
(*numChars) = nPat;
#if defined (MORPH)
index = 0;
if (!strcmp(codingType, "variable") || !strcmp(codingType, "informative"))
{
// put in constant patterns
for (k=0; k<2; k++)
{
numSitesOfPat[index] = 0;
partitionId[index] = 0;
for (j=0; j<nTaxa; j++)
matrix[j*(*numChars)+index] = k + 1;
index++;
}
}
if (!strcmp(codingType, "informative"))
{
// put in uninformative patterns
for (k=0; k<2; k++)
{
for (i=0; i< nTaxa; i++)
{
numSitesOfPat[index] = 0;
partitionId[index] = 0;
for (j=0; j<nTaxa; j++)
{
if(j == i)
matrix[j*(*numChars)+index] = (k + 1) ^ 3;
else
matrix[j*(*numChars)+index] = k + 1;
}
index++;
}
}
}
#endif
free (tempMatrix);
free (tempNumSitePats);
free (tempPartId);
# if defined (MORPH)
/* check to see if the dummy characters are present elsewhere */
if (!strcmp(codingType, "variable"))
index = nTaxa;
else if (!strcmp (codingType, "informative"))
index = nTaxa - 1;
else
index = nTaxa + 1;
for (i=numDummyChars; i<nPat; i++)
{
nOnes = nTwos = 0;
for (j=0; j<nTaxa; j++)
{
if (matrix[pos(j,i,(*numChars))] == 1)
nOnes++;
else if (matrix[pos(j,i,(*numChars))] == 2)
nTwos++;
}
if (nOnes >= index || nTwos >= index)
{
printf ("\n Warning: Not expecting this character pattern under the chosen coding (%d).\n", i-numDummyChars+1);
printf ("\n Continue with chain? (yes/no): ");
if (YesNo() == YES)
{
printf (" Continuing with chain, even if it is not a good idea... \n\n");
break;
}
else
{
FreeMemory ();
free (numOfThisPat);
return (ERROR);
}
}
}
# else
/* check to see if the dummy characters are present elsewhere */
for (i=numDummyChars; i<nPat; i++)
{
nOnes = nTwos = 0;
for (j=0; j<nTaxa; j++)
{
if (matrix[pos(j,i,(*numChars))] == 1)
nOnes++;
else if (matrix[pos(j,i,(*numChars))] == 2)
nTwos++;
}
if (nOnes == nTaxa && !strcmp(codingType, "variable"))
{
printf ("\n Warning: Not expecting all absence characters with this coding (%d).\n", i-numDummyChars+1);
printf ("\n Continue with chain? (yes/no): ");
if (YesNo() == YES)
{
printf (" Continuing with chain, even if it is not a good idea... \n\n");
break;
}
else
{
FreeMemory ();
free (numOfThisPat);
return (ERROR);
}
}
if (nTwos == nTaxa && !strcmp(codingType, "variable"))
{
printf ("\n Warning: Not expecting all presence characters with this coding (%d).\n", i-numDummyChars+1);
printf ("\n Continue with chain? (yes/no): ");
if (YesNo() == YES)
{
printf (" Continuing with chain, even if it is not a good idea... \n\n");
break;
}
else
{
FreeMemory ();
free (numOfThisPat);
return (ERROR);
}
}
}
#endif
}
free (numOfThisPat);
# if 0
for (i=0; i<(*numChars); i++)
{
printf ("%4d -- ", i+1);
for (j=0; j<(*numTaxa); j++)
{
printf ("%d", matrix[pos(j,i,(*numChars))]);
}
printf ("-- %3d %3d\n", numSitesOfPat[i], partitionId[i]);
}
# endif
}
else
{
printf ("\n ERROR: Unknown datatype when compressing.\n");
FreeMemory ();
return (ERROR);
}
return (NO_ERROR);
}
int CompressMatrixPars (int *numTaxa, int *numChars)
{
int i, j, k, *numOfThisPat, isSame, nPat, nt, siteNum, taxNum;
nExcluded = 0;
for (i=0; i<nChar; i++)
if (excludedSites[i] == YES)
nExcluded++;
numDummyChars = 0;
if ((dataType == DNA || dataType == RNA) && enforceCodonModel == YES)
{
printf ("ERROR: Codon models not supported with parsimony criterion.\n");
return (ERROR);
}
else if (((dataType == DNA || dataType == RNA) && enforceCodonModel == NO) || dataType == PROTEIN)
{
nStates = 4;
if (dataType == PROTEIN)
nStates = 20;
printf (" Compressing data matrix\n");
/* 4 X 4 or 20 X 20 substitution model */
patternId = (int *)malloc((size_t) (nChar * sizeof(int)));
if (!patternId)
{
printf ("ERROR: Problem allocating patternId\n");
return (ERROR);
}
else
allocatedMemory[ALLOC_PAT_IDS] = YES;
for (i=0; i<nChar; i++)
patternId[i] = -1;
/* compress for other types of rate models */
numOfThisPat = (int *)malloc((size_t) (nChar * sizeof(int)));
if (!numOfThisPat)
{
printf ("\n ERROR: Problem allocating numOfThisPat.\n");
FreeMemory ();
return (ERROR);
}
for (i=0; i<nChar; i++)
{
if (excludedSites[i] == YES)
numOfThisPat[i] = 0;
else
numOfThisPat[i] = 1;
}
siteNum = 0;
for (i=0; i<nChar-1; i++)
{
if (numOfThisPat[i] > 0)
{
patternId[i] = siteNum;
for (j=i+1; j<nChar; j++)
{
if (numOfThisPat[j] > 0)
{
isSame = YES;
for (k=0; k<nTaxa; k++)
{
if (excludedTaxa[k] == NO && origDataMatrix[k*nChar+i] != origDataMatrix[k*nChar+j])
{
isSame = NO;
}
}
if (isSame == YES)
{
numOfThisPat[i]++;
numOfThisPat[j] = 0;
patternId[j] = patternId[i] = siteNum;
}
}
}
siteNum++;
}
}
if (patternId[nChar - 1] == -1)
patternId[nChar - 1] = siteNum++;
nPat = 0;
for (i=0; i<nChar; i++)
{
if (numOfThisPat[i] > 0)
nPat++;
}
nt = 0;
for (j=0; j<nTaxa; j++)
{
if (excludedTaxa[j] == NO)
nt++;
}
printf (" Data matrix has %d taxa and %d site patterns\n", nt, nPat);
(*numTaxa) = nt;
(*numChars) = nPat;
matrix = (int *)malloc((size_t) (nt * nPat * sizeof(int)));
if (!matrix)
{
printf ("\n ERROR: Problem allocating matrix.\n");
FreeMemory ();
free (numOfThisPat);
return (ERROR);
}
else
allocatedMemory[ALLOC_MATRIX] = YES;
numSitesOfPat = (int *)malloc((size_t) (nPat * sizeof(int)));
if (!numSitesOfPat)
{
printf ("\n ERROR: Problem allocating numSitesOfPat.\n");
FreeMemory ();
free (numOfThisPat);
return (ERROR);
}
else
allocatedMemory[ALLOC_N_SITE_PATS] = YES;
partitionId = (int *)malloc((size_t) (nPat * sizeof(int)));
if (!partitionId)
{
printf ("\n ERROR: Problem allocating partitionId.\n");
FreeMemory ();
free (numOfThisPat);
return (ERROR);
}
else
allocatedMemory[ALLOC_PART_ID] = YES;
siteNum = 0;
for (i=0; i<nChar; i++)
{
if (numOfThisPat[i] > 0)
{
taxNum = 0;
for (j=0; j<nTaxa; j++)
{
if (excludedTaxa[j] == NO)
{
matrix[pos(taxNum,siteNum,(*numChars))] = origDataMatrix[j*nChar+i];
taxNum++;
}
}
numSitesOfPat[siteNum] = numOfThisPat[i];
partitionId[siteNum] = 0;
siteNum++;
}
}
free (numOfThisPat);
# if 0
for (i=0; i<(*numChars); i++)
{
printf ("%4d -- ", i+1);
for (j=0; j<(*numTaxa); j++)
{
printf ("%2d ", matrix[pos(j,i,(*numChars))]);
}
printf ("-- %3d %3d\n", numSitesOfPat[i], partitionId[i]);
}
# endif
}
else if (dataType == RESTRICTION)
{
nStates = 2;
printf (" Compressing data matrix\n");
/* 2 X 2 substitution model */
patternId = (int *)malloc((size_t) (nChar * sizeof(int)));
if (!patternId)
{
printf ("ERROR: Problem allocating patternId\n");
return (ERROR);
}
else
allocatedMemory[ALLOC_PAT_IDS] = YES;
for (i=0; i<nChar; i++)
patternId[i] = -1;
numOfThisPat = (int *)malloc((size_t) (nChar * sizeof(int)));
if (!numOfThisPat)
{
printf ("\n ERROR: Problem allocating numOfThisPat.\n");
FreeMemory ();
return (ERROR);
}
for (i=0; i<nChar; i++)
{
if (excludedSites[i] == YES)
numOfThisPat[i] = 0;
else
numOfThisPat[i] = 1;
}
siteNum = 0;
for (i=0; i<nChar-1; i++)
{
if (numOfThisPat[i] > 0)
{
patternId[i] = siteNum;
for (j=i+1; j<nChar; j++)
{
if (numOfThisPat[j] > 0)
{
isSame = YES;
for (k=0; k<nTaxa; k++)
{
if (excludedTaxa[k] == NO && origDataMatrix[k*nChar+i] != origDataMatrix[k*nChar+j])
{
isSame = NO;
}
}
if (isSame == YES)
{
numOfThisPat[i]++;
numOfThisPat[j] = 0;
patternId[j] = patternId[i] = siteNum;
}
}
}
siteNum++;
}
}
if (patternId[nChar - 1] == -1)
patternId[nChar - 1] = siteNum++;
nPat = 0;
for (i=0; i<nChar; i++)
{
if (numOfThisPat[i] > 0)
nPat++;
}
nt = 0;
for (j=0; j<nTaxa; j++)
{
if (excludedTaxa[j] == NO)
nt++;
}
printf (" Data matrix has %d taxa and %d site patterns\n", nt, nPat);
(*numTaxa) = nt;
(*numChars) = nPat;
matrix = (int *)malloc((size_t) (nt * nPat * sizeof(int)));
if (!matrix)
{
printf ("\n ERROR: Problem allocating matrix.\n");
FreeMemory ();
free (numOfThisPat);
return (ERROR);
}
else
allocatedMemory[ALLOC_MATRIX] = YES;
numSitesOfPat = (int *)malloc((size_t) (nPat * sizeof(int)));
if (!numSitesOfPat)
{
printf ("\n ERROR: Problem allocating numSitesOfPat.\n");
FreeMemory ();
free (numOfThisPat);
return (ERROR);
}
else
allocatedMemory[ALLOC_N_SITE_PATS] = YES;
partitionId = (int *)malloc((size_t) (nPat * sizeof(int)));
if (!partitionId)
{
printf ("\n ERROR: Problem allocating partitionId.\n");
FreeMemory ();
free (numOfThisPat);
return (ERROR);
}
else
allocatedMemory[ALLOC_PART_ID] = YES;
siteNum = 0;
for (i=0; i<nChar; i++)
{
if (numOfThisPat[i] > 0)
{
taxNum = 0;
for (j=0; j<nTaxa; j++)
{
if (excludedTaxa[j] == NO)
{
matrix[pos(taxNum,siteNum,(*numChars))] = origDataMatrix[j*nChar+i];
taxNum++;
}
}
numSitesOfPat[siteNum] = numOfThisPat[i];
partitionId[siteNum] = 0;
siteNum++;
}
}
free (numOfThisPat);
# if 0
for (i=0; i<(*numChars); i++)
{
printf ("%4d -- ", i+1);
for (j=0; j<(*numTaxa); j++)
{
printf ("%d", matrix[pos(j,i,(*numChars))]);
}
printf ("-- %3d %3d\n", numSitesOfPat[i], partitionId[i]);
}
# endif
}
else if (dataType == STANDARD)
{
nStates = 2;
printf (" Compressing data matrix\n");
/* 2 X 2 substitution model */
patternId = (int *)malloc((size_t) (nChar * sizeof(int)));
if (!patternId)
{
printf ("ERROR: Problem allocating patternId\n");
return (ERROR);
}
else
allocatedMemory[ALLOC_PAT_IDS] = YES;
for (i=0; i<nChar; i++)
patternId[i] = -1;
numOfThisPat = (int *)malloc((size_t) (nChar * sizeof(int)));
if (!numOfThisPat)
{
printf ("\n ERROR: Problem allocating numOfThisPat.\n");
FreeMemory ();
return (ERROR);
}
for (i=0; i<nChar; i++)
{
if (excludedSites[i] == YES)
numOfThisPat[i] = 0;
else
numOfThisPat[i] = 1;
}
siteNum = 0;
for (i=0; i<nChar-1; i++)
{
if (numOfThisPat[i] > 0)
{
patternId[i] = siteNum;
for (j=i+1; j<nChar; j++)
{
if (numOfThisPat[j] > 0)
{
isSame = YES;
for (k=0; k<nTaxa; k++)
{
if (excludedTaxa[k] == NO && origDataMatrix[k*nChar+i] != origDataMatrix[k*nChar+j])
{
isSame = NO;
}
}
if (isSame == YES/* && isSame == NO*/) /* NOTE: I am simply fooling the compression part of the algorithm */
{ /* so that no compression occurs. */
numOfThisPat[i]++;
numOfThisPat[j] = 0;
patternId[j] = patternId[i] = siteNum;
}
}
}
siteNum++;
}
}
if (patternId[nChar - 1] == -1)
patternId[nChar - 1] = siteNum++;
nPat = 0;
for (i=0; i<nChar; i++)
{
if (numOfThisPat[i] > 0)
nPat++;
}
nt = 0;
for (j=0; j<nTaxa; j++)
{
if (excludedTaxa[j] == NO)
nt++;
}
printf (" Data matrix has %d taxa and %d site patterns\n", nt, nPat);
(*numTaxa) = nt;
(*numChars) = nPat;
matrix = (int *)malloc((size_t) (nt * nPat * sizeof(int)));
if (!matrix)
{
printf ("\n ERROR: Problem allocating matrix.\n");
FreeMemory ();
free (numOfThisPat);
return (ERROR);
}
else
allocatedMemory[ALLOC_MATRIX] = YES;
numSitesOfPat = (int *)malloc((size_t) (nPat * sizeof(int)));
if (!numSitesOfPat)
{
printf ("\n ERROR: Problem allocating numSitesOfPat.\n");
FreeMemory ();
free (numOfThisPat);
return (ERROR);
}
else
allocatedMemory[ALLOC_N_SITE_PATS] = YES;
partitionId = (int *)malloc((size_t) (nPat * sizeof(int)));
if (!partitionId)
{
printf ("\n ERROR: Problem allocating partitionId.\n");
FreeMemory ();
free (numOfThisPat);
return (ERROR);
}
else
allocatedMemory[ALLOC_PART_ID] = YES;
siteNum = 0;
for (i=0; i<nChar; i++)
{
if (numOfThisPat[i] > 0)
{
taxNum = 0;
for (j=0; j<nTaxa; j++)
{
if (excludedTaxa[j] == NO)
{
matrix[pos(taxNum,siteNum,(*numChars))] = origDataMatrix[j*nChar+i];
taxNum++;
}
}
numSitesOfPat[siteNum] = numOfThisPat[i];
partitionId[siteNum] = 0;
siteNum++;
}
}
free (numOfThisPat);
# if 0
for (i=0; i<(*numChars); i++)
{
printf ("%4d -- ", i+1);
for (j=0; j<(*numTaxa); j++)
{
printf ("%d", matrix[pos(j,i,(*numChars))]);
}
printf ("-- %3d %3d\n", numSitesOfPat[i], partitionId[i]);
}
# endif
}
else
{
printf ("\n ERROR: Unknown datatype when compressing.\n");
FreeMemory ();
return (ERROR);
}
return (NO_ERROR);
}
void CopyConditionalLikelihoods (int from, int to, int whichChain, int numTaxa, int numChars, int numRateCats)
{
register int c, i, s, oneMatSize, kTimesC, nLocalStates;
double *clTo, *clFrom, *scTo, *scFrom;
if ((dataType == DNA || dataType == RNA) && enforceCodonModel == YES)
{
if (!strcmp(codonModelType, "covny98"))
nLocalStates = 3 * nStates;
else
nLocalStates = nStates;
}
else
{
if (useCovarion == YES)
nLocalStates = 2 * nStates;
else
nLocalStates = nStates;
}
oneMatSize = numNodes * numChars * numRateCats * numBetaCats * nLocalStates;
kTimesC = nLocalStates * numRateCats * numBetaCats;
/* copy conditional likelihoods */
for (i=numTaxa; i<numNodes; i++)
{
if (clUpdateFlag[i] == YES)
{
clTo = &condLike[whichChain*2*oneMatSize + to*oneMatSize + i*numChars*kTimesC];
clFrom = &condLike[whichChain*2*oneMatSize + from*oneMatSize + i*numChars*kTimesC];
for (c=0; c<numChars; c++, *(clTo+=kTimesC), *(clFrom+=kTimesC))
{
for (s=0; s<kTimesC; s++)
clTo[s] = clFrom[s];
}
clUpdateFlag[i] = NO;
}
}
/* copy node scalers */
for (i=0; i<numIntNodes; i++)
{
if (scalerUpdateFlag[i] == YES)
{
scTo = &clScaler[whichChain*2*numIntNodes*numChars + to*numIntNodes*numChars + i*numChars];
scFrom = &clScaler[whichChain*2*numIntNodes*numChars + from*numIntNodes*numChars + i*numChars];
for (c=0; c<numChars; c++)
{
scTo[c] = scFrom[c];
}
scalerUpdateFlag[i] = NO;
}
}
// copy lnSiteScaler
// will almost always be touched, so always update
scTo = &lnSiteScaler[whichChain*2*numChars + to*numChars];
scFrom = &lnSiteScaler[whichChain*2*numChars + from*numChars];
for (i=0; i<numChars; i++)
{
scTo[i] = scFrom[i];
}
# if defined (SMART_TI_PROBS)
for (i=0; i<numNodes; i++)
{
if (updateTiFlag[i] == YES)
{
scTo = &transitionProbs[whichChain*2*numNodes*nodeTiSize + to*numNodes*nodeTiSize + i*nodeTiSize];
scFrom = &transitionProbs[whichChain*2*numNodes*nodeTiSize + from*numNodes*nodeTiSize + i*nodeTiSize];
for (s=0; s<nodeTiSize; s++)
scTo[s] = scFrom[s];
}
updateTiFlag[i] = NO;
}
# endif
}
void CopyTree (int from, int to, int whichChain)
{
int i, iA, iL, iR;
TreeNode *p, *pA, *pL, *pR, *q, *qA, *qL, *qR, *r;
r = root[whichChain*2+from];
for (i=0; i<numNodes; i++)
{
/* get from pointers */
p = nodes + (whichChain*2*numNodes + from * numNodes + i);
if (p->anc != NULL)
{
pA = p->anc;
iA = pA->memoryIndex;
}
if (p->left != NULL)
{
pL = p->left;
iL = pL->memoryIndex;
}
if (p->right != NULL)
{
pR = p->right;
iR = pR->memoryIndex;
}
/* to pointers should be offset sizeOfTree from from pointers */
q = nodes + (whichChain*2*numNodes + to * numNodes + i);
if (p->anc != NULL)
{
qA = nodes + (whichChain*2*numNodes + to * numNodes + iA);
q->anc = qA;
}
else
{
q->anc = NULL;
}
if (p->left != NULL)
{
qL = nodes + (whichChain*2*numNodes + to * numNodes + iL);
q->left = qL;
}
else
{
q->left = NULL;
}
if (p->right != NULL)
{
qR = nodes + (whichChain*2*numNodes + to * numNodes + iR);
q->right = qR;
}
else
{
q->right = NULL;
}
q->memoryIndex = p->memoryIndex;
q->index = p->index;
q->upDateCl = p->upDateCl;
q->marked = p->marked;
q->x = p->x;
q->y = p->y;
q->constraints = p->constraints;
q->calibrations = p->calibrations;
q->scaler = p->scaler;
q->scalerNode = p->scalerNode;
q->flag = p->flag;
q->isCalibrated = p->isCalibrated;
q->isConstrained = p->isConstrained;
q->constraintNum = p->constraintNum;
q->calibrationNum = p->calibrationNum;
q->farrisSet = p->farrisSet;
q->length = p->length;
q->nodeTime = p->nodeTime;
q->calTime[0] = p->calTime[0];
q->calTime[1] = p->calTime[1];
q->scalerIndex = p->scalerIndex;
# if defined (SMART_TI_PROBS)
q->upDateTi = p->upDateTi;
# endif
strcpy (q->label, p->label);
strcpy (q->calibrationName, p->calibrationName);
strcpy (q->constraintName, p->constraintName);
if (p == r)
root[whichChain*2 + to] = q;
}
for (i=0; i<numIntNodes; i++)
{
p = intNodeDownPassSeq[whichChain*2*numIntNodes + from * numIntNodes + i];
q = nodes + (whichChain*2*numNodes + to * numNodes + p->memoryIndex);
intNodeDownPassSeq[whichChain*2*numIntNodes + to * numIntNodes + i] = q;
}
for (i=0; i<numNodes; i++)
{
p = allNodesDownPassSeq[whichChain*2*numNodes + from * numNodes + i];
q = nodes + (whichChain*2*numNodes + to * numNodes + p->memoryIndex);
allNodesDownPassSeq[whichChain*2*numNodes + to * numNodes + i] = q;
}
if (allocatedMemory[ALLOC_TREE_HEIGHT] == YES)
treeHeight[whichChain*2 + to] = treeHeight[whichChain*2 + from];
if (allocatedMemory[ALLOC_KAPPA] == YES)
kappa[whichChain*2 + to] = kappa[whichChain*2 + from];
if (allocatedMemory[ALLOC_OMEGA] == YES)
omega[whichChain*2 + to] = omega[whichChain*2 + from];
if (allocatedMemory[ALLOC_PUR] == YES)
probPur[whichChain*2 + to] = probPur[whichChain*2 + from];
if (allocatedMemory[ALLOC_NEU] == YES)
probNeu[whichChain*2 + to] = probNeu[whichChain*2 + from];
if (allocatedMemory[ALLOC_POS] == YES)
probPos[whichChain*2 + to] = probPos[whichChain*2 + from];
if (allocatedMemory[ALLOC_GAMMA_SHAPE] == YES)
alpha[whichChain*2 + to] = alpha[whichChain*2 + from];
if (allocatedMemory[ALLOC_INV_P] == YES)
invP[whichChain*2 + to] = invP[whichChain*2 + from];
if (allocatedMemory[ALLOC_AUTO_GAMMA] == YES)
rateCorrelation[whichChain*2 + to] = rateCorrelation[whichChain*2 + from];
if (allocatedMemory[ALLOC_AUTO_GAMMA2] == YES)
{
for (i=0; i<2; i++)
rateCorrelation2[whichChain*4 + to*2 + i] = rateCorrelation2[whichChain*4 + from*2 + i];
}
if (allocatedMemory[ALLOC_LAG] == YES)
lag[whichChain*2 + to] = lag[whichChain*2 + from];
if (allocatedMemory[ALLOC_SUBPARAMS] == YES)
{
for (i=0; i<nst; i++)
subParams[whichChain*2*nst + to*nst + i] = subParams[whichChain*2*nst + from*nst + i];
}
if (allocatedMemory[ALLOC_BASEFREQS] == YES)
{
for (i=0; i<nStates; i++)
baseFreq[whichChain*2*nStates + to*nStates + i] = baseFreq[whichChain*2*nStates + from*nStates + i];
}
if (allocatedMemory[ALLOC_UNSCALED_SITE_RATES] == YES)
{
for (i=0; i<nPartitions; i++)
unscaledRates[whichChain*2*nPartitions + to*nPartitions + i] = unscaledRates[whichChain*2*nPartitions + from*nPartitions + i];
}
if (allocatedMemory[ALLOC_SITE_RATES] == YES)
{
for (i=0; i<nPartitions; i++)
scaledRates[whichChain*2*nPartitions + to*nPartitions + i] = scaledRates[whichChain*2*nPartitions + from*nPartitions + i];
}
if (allocatedMemory[ALLOC_SP_RATE] == YES)
spRate[whichChain*2 + to] = spRate[whichChain*2 + from];
if (allocatedMemory[ALLOC_EX_RATE] == YES)
exRate[whichChain*2 + to] = exRate[whichChain*2 + from];
if (allocatedMemory[ALLOC_SWITCH_RATE] == YES)
{
for (i=0; i<2; i++)
switchRate[whichChain*2*2 + to*2 + i] = switchRate[whichChain*2*2 + from*2 + i];
}
if (allocatedMemory[ALLOC_SWITCH_PI] == YES)
{
for (i=0; i<2; i++)
switchPi[whichChain*2*2 + to*2 + i] = switchPi[whichChain*2*2 + from*2 + i];
}
if (allocatedMemory[ALLOC_GC1] == YES)
gc1[whichChain*2 + to] = gc1[whichChain*2 + from];
if (allocatedMemory[ALLOC_GC2] == YES)
gc2[whichChain*2 + to] = gc2[whichChain*2 + from];
if (allocatedMemory[ALLOC_FRAC_A] == YES)
fracA[whichChain*2 + to] = fracA[whichChain*2 + from];
if (allocatedMemory[ALLOC_FRAC_G] == YES)
fracG[whichChain*2 + to] = fracG[whichChain*2 + from];
if (allocatedMemory[ALLOC_BETA] == YES)
statefreqP[whichChain*2 + to] = statefreqP[whichChain*2 + from];
}
void DirichletRandomVariable (double *alp, double *z, int n, long int *seed)
{
int i;
double sum;
sum = 0.0;
for(i=0; i<n; i++)
{
z[i] = RndGamma (alp[i], seed) / 1.0;
sum += z[i];
}
for(i=0; i<n; i++)
z[i] /= sum;
}
void FreeMemory (void)
{
if (allocatedMemory[ALLOC_KAPPA] == YES)
{
free (kappa);
allocatedMemory[ALLOC_KAPPA] = NO;
}
if (allocatedMemory[ALLOC_SUBPARAMS] == YES)
{
free (subParams);
allocatedMemory[ALLOC_SUBPARAMS] = NO;
}
if (allocatedMemory[ALLOC_BASEFREQS] == YES)
{
free (baseFreq);
allocatedMemory[ALLOC_BASEFREQS] = NO;
}
if (allocatedMemory[ALLOC_GAMMA_SHAPE] == YES)
{
free (alpha);
allocatedMemory[ALLOC_GAMMA_SHAPE] = NO;
}
if (allocatedMemory[ALLOC_SITE_RATES] == YES)
{
free (scaledRates);
allocatedMemory[ALLOC_SITE_RATES] = NO;
}
if (allocatedMemory[ALLOC_UNSCALED_SITE_RATES] == YES)
{
free (unscaledRates);
allocatedMemory[ALLOC_UNSCALED_SITE_RATES] = NO;
}
if (allocatedMemory[ALLOC_NSITES_IN_PART] == YES)
{
free (nSitesInPartition);
allocatedMemory[ALLOC_NSITES_IN_PART] = NO;
}
if (allocatedMemory[ALLOC_MATRIX] == YES)
{
free (matrix);
allocatedMemory[ALLOC_MATRIX] = NO;
}
if (allocatedMemory[ALLOC_N_SITE_PATS] == YES)
{
free (numSitesOfPat);
allocatedMemory[ALLOC_N_SITE_PATS] = NO;
}
if (allocatedMemory[ALLOC_PART_ID] == YES)
{
free (partitionId);
allocatedMemory[ALLOC_PART_ID] = NO;
}
if (allocatedMemory[ALLOC_NODES] == YES)
{
free (nodes);
allocatedMemory[ALLOC_NODES] = NO;
}
if (allocatedMemory[ALLOC_ROOT] == YES)
{
free (root);
allocatedMemory[ALLOC_ROOT] = NO;
}
if (allocatedMemory[ALLOC_ALLDOWNPASS] == YES)
{
free (allNodesDownPassSeq);
allocatedMemory[ALLOC_ALLDOWNPASS] = NO;
}
if (allocatedMemory[ALLOC_INTDOWNPASS] == YES)
{
free (intNodeDownPassSeq);
allocatedMemory[ALLOC_INTDOWNPASS] = NO;
}
if (allocatedMemory[ALLOC_CLUPDATE_FLAG] == YES)
{
free (clUpdateFlag);
allocatedMemory[ALLOC_CLUPDATE_FLAG] = NO;
}
if (allocatedMemory[ALLOC_COND_LIKES] == YES)
{
free (condLike);
allocatedMemory[ALLOC_COND_LIKES] = NO;
}
if (allocatedMemory[ALLOC_COND_SCALER] == YES)
{
free (clScaler);
allocatedMemory[ALLOC_COND_SCALER] = NO;
}
if (allocatedMemory[ALLOC_DISTANCES] == YES)
{
free (distances);
allocatedMemory[ALLOC_DISTANCES] = NO;
}
if (allocatedMemory[ALLOC_TREE_HEIGHT] == YES)
{
free (treeHeight);
allocatedMemory[ALLOC_TREE_HEIGHT] = NO;
}
if (allocatedMemory[ALLOC_ANC_STATES] == YES)
{
free (ancStatesProbs);
allocatedMemory[ALLOC_ANC_STATES] = NO;
}
if (allocatedMemory[ALLOC_TEMP_ANC_STATES] == YES)
{
free (tempStateProbs);
allocatedMemory[ALLOC_TEMP_ANC_STATES] = NO;
}
if (allocatedMemory[ALLOC_PAT_IDS] == YES)
{
free (patternId);
allocatedMemory[ALLOC_PAT_IDS] = NO;
}
if (allocatedMemory[ALLOC_SP_RATE] == YES)
{
free (spRate);
allocatedMemory[ALLOC_SP_RATE] = NO;
}
if (allocatedMemory[ALLOC_EX_RATE] == YES)
{
free (exRate);
allocatedMemory[ALLOC_EX_RATE] = NO;
}
if (allocatedMemory[ALLOC_OMEGA] == YES)
{
free (omega);
allocatedMemory[ALLOC_OMEGA] = NO;
}
if (allocatedMemory[ALLOC_PUR] == YES)
{
free (probPur);
allocatedMemory[ALLOC_PUR] = NO;
}
if (allocatedMemory[ALLOC_NEU] == YES)
{
free (probNeu);
allocatedMemory[ALLOC_NEU] = NO;
}
if (allocatedMemory[ALLOC_POS] == YES)
{
free (probPos);
allocatedMemory[ALLOC_POS] = NO;
}
if (allocatedMemory[ALLOC_AUTO_GAMMA] == YES)
{
free (rateCorrelation);
allocatedMemory[ALLOC_AUTO_GAMMA] = NO;
}
if (allocatedMemory[ALLOC_AUTO_GAMMA2] == YES)
{
free (rateCorrelation2);
allocatedMemory[ALLOC_AUTO_GAMMA2] = NO;
}
if (allocatedMemory[ALLOC_LAG] == YES)
{
free (lag);
allocatedMemory[ALLOC_LAG] = NO;
}
if (allocatedMemory[ALLOC_INV_P] == YES)
{
free (invP);
allocatedMemory[ALLOC_INV_P] = NO;
}
if (allocatedMemory[ALLOC_SWITCH_RATE] == YES)
{
free (switchRate);
allocatedMemory[ALLOC_SWITCH_RATE] = NO;
}
if (allocatedMemory[ALLOC_SWITCH_PI] == YES)
{
free (switchPi);
allocatedMemory[ALLOC_SWITCH_PI] = NO;
}
if (allocatedMemory[ALLOC_GC1] == YES)
{
free (gc1);
allocatedMemory[ALLOC_GC1] = NO;
}
if (allocatedMemory[ALLOC_GC2] == YES)
{
free (gc2);
allocatedMemory[ALLOC_GC2] = NO;
}
if (allocatedMemory[ALLOC_FRAC_A] == YES)
{
free (fracA);
allocatedMemory[ALLOC_FRAC_A] = NO;
}
if (allocatedMemory[ALLOC_FRAC_G] == YES)
{
free (fracG);
allocatedMemory[ALLOC_FRAC_G] = NO;
}
if (allocatedMemory[ALLOC_LN_SITE_SCALER] == YES)
{
free (lnSiteScaler);
allocatedMemory[ALLOC_LN_SITE_SCALER] = NO;
}
if (allocatedMemory[ALLOC_SCALER_UPDATE_FLAG] == YES)
{
free (scalerUpdateFlag);
allocatedMemory[ALLOC_SCALER_UPDATE_FLAG] = NO;
}
# if defined (SUPER_FAST)
if (allocatedMemory[ALLOC_TERM_STATES] == YES)
{
free (isPartAmbig);
allocatedMemory[ALLOC_TERM_STATES] = NO;
}
# endif
# if defined (SMART_TI_PROBS)
if (allocatedMemory[ALLOC_TI_PROBS] == YES)
{
free (transitionProbs);
allocatedMemory[ALLOC_TI_PROBS] = NO;
}
if (allocatedMemory[ALLOC_TI_FLAGS] == YES)
{
free (updateTiFlag);
allocatedMemory[ALLOC_TI_FLAGS] = NO;
}
# endif
if (allocatedMemory[ALLOC_STATE_SET] == YES)
{
free (stateSet);
allocatedMemory[ALLOC_STATE_SET] = NO;
}
#if defined (MORPH)
if (allocatedMemory[ALLOC_BETA] == YES)
{
free (statefreqP);
allocatedMemory[ALLOC_BETA] = NO;
}
#endif
}
double GetTreeLength (int whichState, int whichChain)
{
int i;
double sum;
TreeNode *p;
sum = 0.0;
for (i=0; i<numNodes; i++)
{
p = allNodesDownPassSeq[whichChain*2*numNodes + whichState*numNodes + i];
if (p->anc != NULL)
{
if (p->anc->anc != NULL)
sum += p->length;
else if (treeModel == UNROOTED)
sum += p->length;
}
}
return (sum);
}
int GetDistances (int numTaxa, int numChars)
{
int i, j, k, x, y;
double nSame, nDiff, d, p;
distances = (double *)malloc(sizeof(double) * numTaxa * numTaxa);
if (!distances)
{
printf ("\n ERROR: Could not allocate distances\n");
FreeMemory ();
return (ERROR);
}
else
allocatedMemory[ALLOC_DISTANCES] = YES;
x = 0;
for (i=0; i<nTaxa; i++)
{
if (excludedTaxa[i] == NO)
{
y = 0;
for (j=0; j<nTaxa; j++)
{
if (excludedTaxa[j] == NO)
{
/* get distance for taxa x and y */
if (x == y)
distances[pos(x,y,numTaxa)] = 0.0;
else
{
nSame = nDiff = 0.0;
for (k=0; k<numChars; k++)
{
if ((matrix[pos(x,k,numChars)] == 1 || matrix[pos(x,k,numChars)] == 2 || matrix[pos(x,k,numChars)] == 4 ||
matrix[pos(x,k,numChars)] == 8) &&
(matrix[pos(y,k,numChars)] == 1 || matrix[pos(y,k,numChars)] == 2 || matrix[pos(y,k,numChars)] == 4 ||
matrix[pos(y,k,numChars)] == 8))
{
if (matrix[pos(x,k,numChars)] == matrix[pos(y,k,numChars)])
nSame += (double)numSitesOfPat[k];
else
nDiff += (double)numSitesOfPat[k];
}
}
p = (nDiff/(nSame+nDiff));
if (p >= 0.74999)
d = 9.999999999;
else
d = -0.75 * log (1.0 - (4.0/3.0) * p);
distances[pos(x,y,numTaxa)] = d;
}
y++;
}
}
x++;
}
}
for (i=0; i<numTaxa; i++)
distances[pos(i,i,numTaxa)] = 0.0;
# if 0
printf ("Jukes-Cantor (1969) distance matrix:\n");
for (i=0; i<numTaxa; i++)
{
for (j=0; j<numTaxa; j++)
printf ("%1.4lf ", distances[pos(i,j,numTaxa)]);
printf ("\n");
}
printf ("\n");
# endif
return (NO_ERROR);
}
void GetDownPassSeq (TreeNode *p, int whichTree, int whichChain, int numTaxa, int *i, int *j)
{
if (p != NULL)
{
GetDownPassSeq (p->left, whichTree, whichChain, numTaxa, i, j);
GetDownPassSeq (p->right, whichTree, whichChain, numTaxa, i, j);
if (p->left != NULL && p->right != NULL && p->anc != NULL)
{
intNodeDownPassSeq[whichChain*2*numIntNodes + whichTree*numIntNodes + (*i)++] = p;
allNodesDownPassSeq[whichChain*2*numNodes + whichTree*numNodes + (*j)++] = p;
}
else if (p->left == NULL && p->right == NULL && p->anc != NULL)
{
allNodesDownPassSeq[whichChain*2*numNodes + whichTree*numNodes + (*j)++] = p;
}
else if (p->left != NULL && p->right == NULL && p->anc == NULL)
{
allNodesDownPassSeq[whichChain*2*numNodes + whichTree*numNodes + (*j)++] = p;
}
}
}
int GetEigens (int n, double **q, double *eigenValues, double *eigvalsImag, double **eigvecs, double **inverseEigvecs, complex **Ceigvecs, complex **CinverseEigvecs)
{
int i, j, rc, *iwork, isComplex;
double **mwork, *dwork;
complex **Cwork, *Ccol;
/* allocate memory */
dwork = (double *)malloc((size_t) (n * sizeof(double)));
iwork = (int *)malloc((size_t) (n * sizeof(int)));
/* calculate eigenvalues and eigenvectors */
isComplex = NO;
rc = EigenRealGeneral (n, q, eigenValues, eigvalsImag, eigvecs, iwork, dwork);
if (rc != NO_ERROR)
{
if (rc == RC_COMPLEX_EVAL)
{
isComplex = YES;
}
}
/* invert U = eigenvectors (InvertMatrix destroys its input matrix, so copy U to temp) */
if (isComplex == NO)
{
mwork = psdmatrix (n);
copy_psdmatrix (eigvecs, mwork, n);
InvertMatrix (mwork, n, dwork, iwork, inverseEigvecs);
free_psdmatrix (mwork);
}
else
{
for(i=0; i<n; i++)
{
if (eigvalsImag[i] == 0.0)
{
for(j=0; j<n; j++)
{
Ceigvecs[j][i].re = eigvecs[j][i];
Ceigvecs[j][i].im = 0.0;
}
}
else if (eigvalsImag[i] > 0.0)
{
for (j=0; j<n; j++)
{
Ceigvecs[j][i].re = eigvecs[j][i];
Ceigvecs[j][i].im = eigvecs[j][i + 1];
}
}
else if (eigvalsImag[i] < 0.0)
{
for (j=0; j<n; j++)
{
Ceigvecs[j][i].re = eigvecs[j][i-1];
Ceigvecs[j][i].im = -eigvecs[j][i];
}
}
}
Ccol = (complex *)malloc((size_t) (n * sizeof(complex)));
Cwork = pscmatrix (n);
copy_pscmatrix (Ceigvecs, Cwork, n);
ComplexInvertMatrix (Cwork, n, dwork, iwork, CinverseEigvecs, Ccol);
free (Ccol);
free_pscmatrix (Cwork);
}
free (dwork);
free (iwork);
return (isComplex);
}
void GetEmpiricalAAFreqs (void)
{
int i, j, k, m, aa[20], chain;
double freq[20], sum, sumAA[20];
for (i=0; i<20; i++)
freq[i] = 0.05;
for (k=0; k<8; k++)
{
for (i=0; i<20; i++)
sumAA[i] = 0.0;
for (i=0; i<nTaxa; i++)
{
if (excludedTaxa[i] == NO)
{
for (j=0; j<nChar; j++)
{
if (excludedSites[j] == NO)
{
GetPossibleAAs (origDataMatrix[i*nChar+j], aa);
sum = 0.0;
for (m=0; m<20; m++)
sum += freq[m] * aa[m];
for (m=0; m<20; m++)
sumAA[m] += freq[m] * aa[m] / sum;
}
}
}
}
sum = 0.0;
for (m=0; m<20; m++)
sum += sumAA[m];
for (m=0; m<20; m++)
freq[m] = sumAA[m] / sum;
}
for (chain=0; chain<numChains; chain++)
{
for (m=0; m<20; m++)
{
baseFreq[chain*8 + 0*nStates + m] = freq[m];
baseFreq[chain*8 + 1*nStates + m] = freq[m];
}
}
}
void GetEmpiricalBaseFreqs (void)
{
int i, j, k, nuc[4], chain;
double freqA, freqC, freqG, freqT, sum, sumA, sumC, sumG, sumT;
freqA = 0.25;
freqC = 0.25;
freqG = 0.25;
freqT = 0.25;
for (k=0; k<8; k++)
{
sumA = 0.0;
sumC = 0.0;
sumG = 0.0;
sumT = 0.0;
for (i=0; i<nTaxa; i++)
{
if (excludedTaxa[i] == NO)
{
for (j=0; j<nChar; j++)
{
if (excludedSites[j] == NO)
{
GetPossibleNucs (origDataMatrix[i*nChar+j], nuc);
sum = freqA * nuc[0];
sum += freqC * nuc[1];
sum += freqG * nuc[2];
sum += freqT * nuc[3];
sumA += freqA * nuc[0] / sum;
sumC += freqC * nuc[1] / sum;
sumG += freqG * nuc[2] / sum;
sumT += freqT * nuc[3] / sum;
}
}
}
}
sum = sumA + sumC + sumG + sumT;
freqA = sumA / sum;
freqC = sumC / sum;
freqG = sumG / sum;
freqT = sumT / sum;
}
for (chain=0; chain<numChains; chain++)
{
baseFreq[chain*8 + 0*nStates + A] = freqA;
baseFreq[chain*8 + 0*nStates + C] = freqC;
baseFreq[chain*8 + 0*nStates + G] = freqG;
baseFreq[chain*8 + 0*nStates + T] = freqT;
baseFreq[chain*8 + 1*nStates + A] = freqA;
baseFreq[chain*8 + 1*nStates + C] = freqC;
baseFreq[chain*8 + 1*nStates + G] = freqG;
baseFreq[chain*8 + 1*nStates + T] = freqT;
}
}
void GetPossibleAAs (int aaCode, int aa[])
{
int m;
for (m=0; m<20; m++)
aa[m] = 0;
if (aaCode > 0 && aaCode <= 20)
aa[aaCode-1] = 1;
else
{
for (m=0; m<20; m++)
aa[m] = 1;
}
# if 0
printf ("%2d -- ", aaCode);
for (m=0; m<20; m++)
printf("%d", aa[m]);
printf ("\n");
# endif
}
void GetPossibleNucs (int nucCode, int nuc[])
{
if (nucCode == 1)
{
nuc[0] = 1;
nuc[1] = 0;
nuc[2] = 0;
nuc[3] = 0;
}
else if (nucCode == 2)
{
nuc[0] = 0;
nuc[1] = 1;
nuc[2] = 0;
nuc[3] = 0;
}
else if (nucCode == 3)
{
nuc[0] = 1;
nuc[1] = 1;
nuc[2] = 0;
nuc[3] = 0;
}
else if (nucCode == 4)
{
nuc[0] = 0;
nuc[1] = 0;
nuc[2] = 1;
nuc[3] = 0;
}
else if (nucCode == 5)
{
nuc[0] = 1;
nuc[1] = 0;
nuc[2] = 1;
nuc[3] = 0;
}
else if (nucCode == 6)
{
nuc[0] = 0;
nuc[1] = 1;
nuc[2] = 1;
nuc[3] = 0;
}
else if (nucCode == 7)
{
nuc[0] = 1;
nuc[1] = 1;
nuc[2] = 1;
nuc[3] = 0;
}
else if (nucCode == 8)
{
nuc[0] = 0;
nuc[1] = 0;
nuc[2] = 0;
nuc[3] = 1;
}
else if (nucCode == 9)
{
nuc[0] = 1;
nuc[1] = 0;
nuc[2] = 0;
nuc[3] = 1;
}
else if (nucCode == 10)
{
nuc[0] = 0;
nuc[1] = 1;
nuc[2] = 0;
nuc[3] = 1;
}
else if (nucCode == 11)
{
nuc[0] = 1;
nuc[1] = 1;
nuc[2] = 0;
nuc[3] = 1;
}
else if (nucCode == 12)
{
nuc[0] = 0;
nuc[1] = 0;
nuc[2] = 1;
nuc[3] = 1;
}
else if (nucCode == 13)
{
nuc[0] = 1;
nuc[1] = 0;
nuc[2] = 1;
nuc[3] = 1;
}
else if (nucCode == 14)
{
nuc[0] = 0;
nuc[1] = 1;
nuc[2] = 1;
nuc[3] = 1;
}
else if (nucCode == 15)
{
nuc[0] = 1;
nuc[1] = 1;
nuc[2] = 1;
nuc[3] = 1;
}
}
void GetTempDownPassSeq (TreeNode *p, int *i, TreeNode **dp)
{
if (p != NULL)
{
GetTempDownPassSeq (p->left, i, dp);
GetTempDownPassSeq (p->right, i, dp);
dp[(*i)++] = p;
}
}
void HkyChangeMat (double **ch_prob, double time, double k, double r, double piA, double piC, double piG, double piT)
{
int i, j;
double t, u, w, x, y, z, beta, bigPi_j[4], pij, bigPij, pis[4];
/* rescale beta */
pis[0] = piA;
pis[1] = piC;
pis[2] = piG;
pis[3] = piT;
beta = 0.5 / ((piA + piG)*(piC + piT) + k*((piA*piG) + (piC*piT)));
bigPi_j[0] = piA + piG;
bigPi_j[1] = piC + piT;
bigPi_j[2] = piA + piG;
bigPi_j[3] = piC + piT;
t = time * r;
for (i=0; i<4; i++)
{
for (j=0; j<4; j++)
{
bigPij = bigPi_j[j];
pij = pis[j];
u = 1.0/bigPij - 1.0;
w = -beta * (1.0 + bigPij * (k - 1.0));
x = exp(-beta * t);
y = exp(w * t);
z = (bigPij - pij) / bigPij;
if (i == j)
ch_prob[i][j] = pij + pij * u * x + z * y;
else if ((i == 0 && j == 2) || (i == 2 && j == 0) || (i == 1 && j == 3) || (i == 3 && j == 1))
ch_prob[i][j] = pij + pij * u * x - (pij/bigPij) * y;
else
ch_prob[i][j] = pij * (1.0 - x);
}
}
# if 0
printf ("Change probabilities (HKY 85, v = %lf):\n", time);
for (i=0; i<4; i++)
{
for (j=0; j<4; j++)
{
printf ("%lf ", ch_prob[i][j]);
}
printf ("\n");
}
# endif
}
void HkyFirstMat (double **ch_prob, double time, double k, double r, double piA, double piC, double piG, double piT)
{
int i, j;
double t, u, w, x, y, z, beta, bigPi_j[4], pij, bigPij, pis[4];
pis[0] = piA;
pis[1] = piC;
pis[2] = piG;
pis[3] = piT;
beta = 0.5 / ((piA + piG)*(piC + piT) + k*((piA*piG) + (piC*piT)));
bigPi_j[0] = piA + piG;
bigPi_j[1] = piC + piT;
bigPi_j[2] = piA + piG;
bigPi_j[3] = piC + piT;
t = time * r;
for (i=0; i<4; i++)
{
for (j=0; j<4; j++)
{
bigPij = bigPi_j[j];
pij = pis[j];
u = 1.0/bigPij - 1.0;
w = -beta * (1.0 + bigPij * (k - 1.0));
x = exp(-beta * t);
y = exp(w * t);
z = (bigPij - pij) / bigPij;
if (i == j)
ch_prob[i][j] = pij * u * (-beta) * r * x + z * w * r * y;
else if ((i == 0 && j == 2) || (i == 2 && j == 0) || (i == 1 && j == 3) || (i == 3 && j == 1))
ch_prob[i][j] = pij * u * (-beta) * r * x - (pij/bigPij) * w * r * y;
else
ch_prob[i][j] = (beta) * pij * r * x;
}
}
# if defined (SHOWTIPROBS)
printf ("Change probabilities (first dv) (HKY 85, time = %lf):\n", time);
for (i=0; i<4; i++)
{
for (j=0; j<4; j++)
{
printf ("%lf ", ch_prob[i][j]);
}
printf ("\n");
}
# endif
}
void HkySecondMat (double **ch_prob, double time, double k, double r, double piA, double piC, double piG, double piT)
{
int i, j;
double t, u, w, x, y, z, beta, bigPi_j[4], pij, bigPij, pis[4];
pis[0] = piA;
pis[1] = piC;
pis[2] = piG;
pis[3] = piT;
beta = 0.5 / ((piA + piG)*(piC + piT) + k*((piA*piG) + (piC*piT)));
bigPi_j[0] = piA + piG;
bigPi_j[1] = piC + piT;
bigPi_j[2] = piA + piG;
bigPi_j[3] = piC + piT;
t = time * r;
for (i=0; i<4; i++)
{
for (j=0; j<4; j++)
{
bigPij = bigPi_j[j];
pij = pis[j];
u = 1.0/bigPij - 1.0;
w = -beta * (1.0 + bigPij * (k - 1.0));
x = exp(-beta * t);
y = exp(w * t);
z = (bigPij - pij) / bigPij;
if (i == j)
ch_prob[i][j] = pij * u * beta * beta * r * r* x + z * w * w * r * r * y;
else if ((i == 0 && j == 2) || (i == 2 && j == 0) || (i == 1 && j == 3) || (i == 3 && j == 1))
ch_prob[i][j] = pij * u * beta * beta * r * r * x - (pij/bigPij) * w * w * r * r * y;
else
ch_prob[i][j] = - beta * beta * pij * r * r * x;
}
}
# if defined (SHOWTIPROBS)
printf ("Change probabilities (first dv) (HKY 85, time = %lf):\n", time);
for (i=0; i<4; i++)
{
for (j=0; j<4; j++)
{
printf ("%lf ", ch_prob[i][j]);
}
printf ("\n");
}
# endif
}
double IncompleteBetaFunction (double alpha, double beta, double x)
{
double bt, gm1, gm2, gm3, temp;
if (x < 0.0 || x > 1.0)
{
printf ("Error in IncompleteBetaFunction.\n");
exit (-1);
}
if (x == 0.0 || x == 1.0)
{
bt = 0.0;
}
else
{
gm1 = LnGamma (alpha + beta);
gm2 = LnGamma (alpha);
gm3 = LnGamma (beta);
temp = gm1 - gm2 - gm3 + (alpha) * log(x) + (beta) * log(1.0 - x);
bt = exp(temp);
}
if (x < (alpha + 1.0)/(alpha + beta + 2.0))
return (bt * BetaCf(alpha, beta, x) / alpha);
else
return (1.0 - bt * BetaCf(beta, alpha, 1.0-x) / beta);
}
int InitializeConditionalLikes (int numTaxa, int numChars, int numRateCats)
{
int i, b, c, s, s1, s2, s3, k, n, *nuc1, cd1[4], cd2[4], cd3[4],
oneMatSize, nNucs, aaId, rsId, foundCodon, nLocalStates;
double *cl0, *cl1, uncertObs, uncertUnobs;
if ((dataType == DNA || dataType == RNA) && enforceCodonModel == YES)
{
if (!strcmp(codonModelType, "covny98"))
nLocalStates = 3 * nStates;
else
nLocalStates = nStates;
}
else
{
if (useCovarion == YES)
nLocalStates = 2 * nStates;
else
nLocalStates = nStates;
}
printf (" Initializing conditional likelihoods\n");
oneMatSize = numNodes * numChars * numRateCats * nLocalStates * numBetaCats;
nuc1 = (int *)malloc((size_t) (nStates * sizeof(int)));
if (!nuc1)
{
printf ("ERROR: Problem allocating nuc1\n");
return (ERROR);
}
condLike = (double *)malloc((size_t) (numChains * 2 * oneMatSize * sizeof(double)));
if (!condLike)
{
printf ("\n ERROR: Problem allocating conditional likelihoods.\n");
printf (" Try allocating more memory to the program or\n");
printf (" running the program on a computer with more\n");
printf (" memory.\n");
free (nuc1);
FreeMemory ();
return (ERROR);
}
else
allocatedMemory[ALLOC_COND_LIKES] = YES;
# if defined (SUPER_FAST)
isPartAmbig = (int *)malloc((size_t) ((numTaxa + numTaxa * numChars) * sizeof(int)));
if (!isPartAmbig)
{
printf ("ERROR: Problem allocating isPartAmbig and termStates\n");
return (ERROR);
}
else
allocatedMemory[ALLOC_TERM_STATES] = YES;
termState = isPartAmbig + numTaxa;
# endif
for (i=0; i<numChains*2*oneMatSize; i++)
condLike[i] = 0.0;
if ((dataType == DNA || dataType == RNA) && enforceCodonModel == YES)
{
/* 61 X 61 model of DNA substitution */
for (n=0; n<numChains; n++)
{
for (i=0; i<numTaxa; i++)
{
cl0 = &condLike[n*2*oneMatSize + 0*oneMatSize + i*numChars*numRateCats*nLocalStates];
cl1 = &condLike[n*2*oneMatSize + 1*oneMatSize + i*numChars*numRateCats*nLocalStates];
for (c=0; c<numChars; c++, *(cl0+=(numRateCats*nLocalStates)), *(cl1+=(numRateCats*nLocalStates)))
{
GetPossibleNucs (matrix[pos(i,c*3 ,numChars*3)], cd1);
GetPossibleNucs (matrix[pos(i,c*3+1,numChars*3)], cd2);
GetPossibleNucs (matrix[pos(i,c*3+2,numChars*3)], cd3);
s = 0;
foundCodon = NO;
for (s1=0; s1<4; s1++)
{
for (s2=0; s2<4; s2++)
{
for (s3=0; s3<4; s3++)
{
if (cd1[s1] == 1 && cd2[s2] == 1 && cd3[s3] == 1 && codon[16*s1 + 4*s2 + s3] != 21)
{
for (k=0; k<numRateCats; k++)
{
cl0[k*nLocalStates+s] = 1.0;
cl1[k*nLocalStates+s] = 1.0;
if (!strcmp(codonModelType, "covny98"))
{
cl0[k*nLocalStates+(nStates + s)] = 1.0;
cl1[k*nLocalStates+(nStates + s)] = 1.0;
cl0[k*nLocalStates+(2*nStates + s)] = 1.0;
cl1[k*nLocalStates+(2*nStates + s)] = 1.0;
}
}
foundCodon = YES;
}
if (codon[16*s1 + 4*s2 + s3] != 21)
s++;
}
}
}
if (foundCodon == NO)
{
printf ("\n ERROR: Found stop codon at taxon %d and sites %d, %d, and %d\n", i+1, c*3+1, c*3+2, c*3+3);
printf ("%d%d%d%d %d%d%d%d %d%d%d%d\n", cd1[0], cd1[1], cd1[2], cd1[3], cd2[0], cd2[1], cd2[2], cd2[3], cd3[0], cd3[1], cd3[2], cd3[3]);
free (nuc1);
FreeMemory ();
return (ERROR);
}
}
}
}
}
else
{
/* 2 X 2 or 4 X 4 or 20 X 20 model of substitution */
for (n=0; n<numChains; n++)
{
for (i=0; i<numTaxa; i++)
{
cl0 = &condLike[n*2*oneMatSize + 0*oneMatSize + i*numChars*numRateCats*numBetaCats*nLocalStates];
cl1 = &condLike[n*2*oneMatSize + 1*oneMatSize + i*numChars*numRateCats*numBetaCats*nLocalStates];
for (c=0; c<numChars; c++, *(cl0+=(numRateCats*nLocalStates*numBetaCats)), *(cl1+=(numRateCats*nLocalStates*numBetaCats)))
{
if (dataType == DNA || dataType == RNA)
{
GetPossibleNucs (matrix[pos(i,c,numChars)], nuc1);
nNucs = 0;
for (s=0; s<nStates; s++)
if (nuc1[s] == 1)
nNucs++;
uncertObs = 1.0;
uncertUnobs = 0.0;
if (nNucs == 1)
{
uncertObs = 1.0 - seqErrorProb;
uncertUnobs = seqErrorProb / 3.0;
}
else if (nNucs == 2)
{
uncertObs = 1.0 - (2.0 * seqErrorProb / 3.0);
uncertUnobs = 2.0 * seqErrorProb / 3.0;
}
else if (nNucs == 3)
{
uncertObs = 1.0 - (seqErrorProb / 3.0);
uncertUnobs = seqErrorProb;
}
for (s=0; s<nStates; s++)
{
if (nuc1[s] == 1)
{
for (k=0; k<numRateCats; k++)
{
cl0[k*nLocalStates+s] = uncertObs;
cl1[k*nLocalStates+s] = uncertObs;
}
}
else
{
for (k=0; k<numRateCats; k++)
{
cl0[k*nLocalStates+s] = uncertUnobs;
cl1[k*nLocalStates+s] = uncertUnobs;
}
}
}
if (useCovarion == YES)
{
for (s=0; s<nStates; s++)
{
if (nuc1[s] == 1)
{
for (k=0; k<numRateCats; k++)
{
cl0[k*nLocalStates+(nStates+s)] = uncertObs;
cl1[k*nLocalStates+(nStates+s)] = uncertObs;
}
}
else
{
for (k=0; k<numRateCats; k++)
{
cl0[k*nLocalStates+(nStates+s)] = uncertUnobs;
cl1[k*nLocalStates+(nStates+s)] = uncertUnobs;
}
}
}
}
}
else if (dataType == PROTEIN)
{
uncertObs = 1.0 - seqErrorProb;
uncertUnobs = seqErrorProb / 19.0;
aaId = matrix[pos(i,c,numChars)];
for (k=0; k<numRateCats; k++)
{
for (s=0; s<nStates; s++)
{
cl0[k*nLocalStates+s] = uncertUnobs;
cl1[k*nLocalStates+s] = uncertUnobs;
}
}
if (aaId > 0 && aaId <= 20)
{
for (k=0; k<numRateCats; k++)
{
cl0[k*nLocalStates + (aaId-1)] = uncertObs;
cl1[k*nLocalStates + (aaId-1)] = uncertObs;
}
}
else
{
for (k=0; k<numRateCats; k++)
{
for (s=0; s<nStates; s++)
{
cl0[k*nLocalStates+s] = 1.0;
cl1[k*nLocalStates+s] = 1.0;
}
}
}
if (useCovarion == YES)
{
for (k=0; k<numRateCats; k++)
{
for (s=0; s<nStates; s++)
{
cl0[k*nLocalStates+(nStates+s)] = uncertUnobs;
cl1[k*nLocalStates+(nStates+s)] = uncertUnobs;
}
}
if (aaId > 0 && aaId <= 20)
{
for (k=0; k<numRateCats; k++)
{
cl0[k*nLocalStates + nStates+(aaId-1)] = uncertObs;
cl1[k*nLocalStates + nStates+(aaId-1)] = uncertObs;
}
}
else
{
for (k=0; k<numRateCats; k++)
{
for (s=0; s<nStates; s++)
{
cl0[k*nLocalStates+(nStates+s)] = 1.0;
cl1[k*nLocalStates+(nStates+s)] = 1.0;
}
}
}
}
}
else if (dataType == RESTRICTION)
{
rsId = matrix[pos(i,c,numChars)];
uncertObs = 1.0;
uncertUnobs = 0.0;
for (k=0; k<numRateCats; k++)
{
if (rsId == 1)
{
cl0[k*nLocalStates+0] = uncertObs;
cl0[k*nLocalStates+1] = uncertUnobs;
cl1[k*nLocalStates+0] = uncertObs;
cl1[k*nLocalStates+1] = uncertUnobs;
}
else if (rsId == 2)
{
cl0[k*nLocalStates+0] = uncertUnobs;
cl0[k*nLocalStates+1] = uncertObs;
cl1[k*nLocalStates+0] = uncertUnobs;
cl1[k*nLocalStates+1] = uncertObs;
}
else
{
cl0[k*nLocalStates+0] = 1.0;
cl0[k*nLocalStates+1] = 1.0;
cl1[k*nLocalStates+0] = 1.0;
cl1[k*nLocalStates+1] = 1.0;
}
}
}
else if (dataType == STANDARD)
{
rsId = matrix[pos(i,c,numChars)];
uncertObs = 1.0;
uncertUnobs = 0.0;
for (k=0; k<numRateCats; k++)
{
for (b=0; b<numBetaCats; b++)
{
if (rsId == 1)
{
cl0[k*numBetaCats*nLocalStates + b*nLocalStates + 0] = uncertObs;
cl0[k*numBetaCats*nLocalStates + b*nLocalStates + 1] = uncertUnobs;
cl1[k*numBetaCats*nLocalStates + b*nLocalStates + 0] = uncertObs;
cl1[k*numBetaCats*nLocalStates + b*nLocalStates + 1] = uncertUnobs;
}
else if (rsId == 2)
{
cl0[k*numBetaCats*nLocalStates + b*nLocalStates + 0] = uncertUnobs;
cl0[k*numBetaCats*nLocalStates + b*nLocalStates + 1] = uncertObs;
cl1[k*numBetaCats*nLocalStates + b*nLocalStates + 0] = uncertUnobs;
cl1[k*numBetaCats*nLocalStates + b*nLocalStates + 1] = uncertObs;
}
else
{
cl0[k*numBetaCats*nLocalStates + b*nLocalStates + 0] = 1.0;
cl0[k*numBetaCats*nLocalStates + b*nLocalStates + 1] = 1.0;
cl1[k*numBetaCats*nLocalStates + b*nLocalStates + 0] = 1.0;
cl1[k*numBetaCats*nLocalStates + b*nLocalStates + 1] = 1.0;
}
}
}
}
}
}
}
}
# if defined (SUPER_FAST)
/*set termStates and isPartAmbig */
for (i=0; i<numTaxa; i++)
isPartAmbig[i] = NO;
/* find the right pointer values depending on terminal state and model */
if ((dataType == DNA || dataType == RNA) && enforceCodonModel == YES)
/* 61 x 61 codon models and derivatives (switch models) */
{
b = 0;
for (i=0; i<numTaxa; i++)
{
for (c=0; c<numChars; c++)
{
GetPossibleNucs (matrix[pos(i,c*3 ,numChars*3)], cd1);
GetPossibleNucs (matrix[pos(i,c*3+1,numChars*3)], cd2);
GetPossibleNucs (matrix[pos(i,c*3+2,numChars*3)], cd3);
s = 0;
nNucs = 0;
for (s1=0; s1<4; s1++)
{
for (s2=0; s2<4; s2++)
{
for (s3=0; s3<4; s3++)
{
if (cd1[s1] == 1 && cd2[s2] == 1 && cd3[s3] == 1)
{
termState[b] = s * nLocalStates;
nNucs ++;
}
if (codon[16*s1 + 4*s2 + s3] != 21)
s++;
}
}
}
if (nNucs > 1)
{
if (nNucs == 64) //all states are possible
termState[b] = nStates * nLocalStates;
else
isPartAmbig[i] = YES;
}
b++;
}
}
}
else if (dataType == DNA || dataType == RNA)
/* 4 x 4 DNA or RNA model */
{
b = 0;
for (i=0; i<numTaxa; i++)
{
for (c=0; c<numChars; c++)
{
GetPossibleNucs(matrix[b],nuc1);
nNucs = 0;
for (s=0; s<nStates; s++)
if (nuc1[s] == 1)
nNucs++;
if (nNucs == 2 || nNucs == 3)
isPartAmbig[i] = YES;
else if (nNucs == 0 || nNucs == 4)
termState[b] = 16;
else if (nNucs == 1)
{
if (nuc1[A] == 1)
termState[b] = 0;
if (nuc1[C] == 1)
termState[b] = 4;
if (nuc1[G] == 1)
termState[b] = 8;
if (nuc1[T] == 1)
termState[b] = 12;
}
b++;
}
}
}
else if (dataType == PROTEIN)
{
for (i=b=0; i<numTaxa; i++)
{
for (c=0; c<numChars; c++)
{
aaId = matrix[pos(i,c,numChars)];
if (aaId > 0 && aaId <= 20)
termState[b] = (aaId - 1) * 20;
else
termState[b] = 20 * 20;
b++;
}
}
}
if (useCovarion == YES) // nStates is doubled if covarion model is used
{
for (i=b=0; i<numTaxa; i++)
{
for (c=0; c<numChars; c++)
{
termState[b++] *= 2;
}
}
}
# endif
/* allocate space for clScaler */
clScaler = (double *)calloc(numChains * 2 * numIntNodes * numChars, sizeof(double));
if (!clScaler)
{
printf ("\n ERROR: Problem allocating clScaler\n");
free (nuc1);
FreeMemory ();
return (ERROR);
}
else
allocatedMemory[ALLOC_COND_SCALER] = YES;
/* allocate space for lnSiteScaler */
lnSiteScaler = (double *)calloc(numChains * 2 * numChars, sizeof(double));
if (!lnSiteScaler)
{
printf ("\n ERROR: Problem allocating lnSiteScaler\n");
free (nuc1);
FreeMemory ();
return (ERROR);
}
else
allocatedMemory[ALLOC_LN_SITE_SCALER] = YES;
free (nuc1);
# if defined (DEBUG_INITCONDLIKES)
for (c=0; c<numChars; c++)
{
int j;
printf ("%3d: ", c);
for (i=0; i<numTaxa; i++)
{
cl0 = &condLike[0*2*oneMatSize + 0*oneMatSize + i*numChars*numRateCats*nLocalStates];
cl0 += nLocalStates*numRateCats*c;
for (k=0; k<numRateCats; k++)
{
for (j=0; j<nLocalStates; j++)
printf("%1.0lf", cl0[k*nLocalStates + j]);
}
printf ("\n ");
}
}
# endif
return (NO_ERROR);
}
int InitializeTipStates (int numTaxa, int numChars)
{
int i, c, s, n,
oneMatSize, aaId, rsId;
unsigned int st, *cl, x;
printf (" Initializing tip states\n");
oneMatSize = numNodes * numChars;
stateSet = (unsigned int *)malloc((size_t) (numChains * oneMatSize * sizeof(unsigned int)));
if (!stateSet)
{
printf ("\n ERROR: Problem allocating state set.\n");
printf (" Try allocating more memory to the program or\n");
printf (" running the program on a computer with more\n");
printf (" memory.\n");
FreeMemory ();
return (ERROR);
}
else
allocatedMemory[ALLOC_COND_LIKES] = YES;
for (i=0; i<numChains*oneMatSize; i++)
stateSet[i] = 0;
/* 2 X 2 or 4 X 4 or 20 X 20 model of substitution */
for (n=0; n<numChains; n++)
{
for (i=0; i<numTaxa; i++)
{
cl = &stateSet[n*oneMatSize + i*numChars];
for (c=0; c<numChars; c++)
{
if (dataType == DNA || dataType == RNA)
{
cl[c] = matrix[pos(i,c,numChars)];
}
else if (dataType == PROTEIN)
{
aaId = matrix[pos(i,c,numChars)];
st = 0;
if (aaId > 0 && aaId <= 20)
{
x = 1 << (aaId-1);
cl[c] = x;
//printf ("%d -> %d\n", aaId, cl[c]);
}
else
{
cl[c] = 0;
for (s=0; s<20; s++)
{
x = 1 << s;
cl[c] |= x;
}
//printf ("%d -> %d\n", aaId, cl[c]);
}
}
else if (dataType == RESTRICTION)
{
rsId = matrix[pos(i,c,numChars)];
if (rsId == 1)
{
cl[c] = 1;
}
else if (rsId == 2)
{
cl[c] = 2;
}
else
{
cl[c] = 3;
}
}
else if (dataType == STANDARD)
{
rsId = matrix[pos(i,c,numChars)];
if (rsId == 1)
{
cl[c] = 1;
}
else if (rsId == 2)
{
cl[c] = 2;
}
else
{
cl[c] = 3;
}
}
}
}
}
return (NO_ERROR);
}
int InitTiMatrix (double m[3][3], double x, double y, double z, double pPurifying, double pNeutral, double pPositive, int model)
{
if (model == 1)
{
m[0][1] = (1.0 - x) * pNeutral;
m[0][2] = (1.0 - x) * pPositive;
m[1][0] = (1.0 - x) * pPurifying;
m[1][2] = (1.0 - x) * pPositive;
m[2][0] = (1.0 - x) * pPurifying;
m[2][1] = (1.0 - x) * pNeutral;
m[0][0] = 1.0 - (m[0][1] + m[0][2]);
m[1][1] = 1.0 - (m[1][0] + m[1][2]);
m[2][2] = 1.0 - (m[2][0] + m[2][1]);
}
else if (model == 2)
{
m[0][1] = (1.0 - x) * pNeutral;
m[0][2] = (1.0 - y) * pPositive;
m[1][0] = (1.0 - x) * pPurifying;
m[1][2] = (1.0 - z) * pPositive;
m[2][0] = (1.0 - y) * pPurifying;
m[2][1] = (1.0 - z) * pNeutral;
m[0][0] = 1.0 - (m[0][1] + m[0][2]);
m[1][1] = 1.0 - (m[1][0] + m[1][2]);
m[2][2] = 1.0 - (m[2][0] + m[2][1]);
}
else
{
return (ERROR);
}
# if 0
{
int i, j;
printf ("%lf %lf %lf %lf %lf %lf (%d)\n", x, y, z, pPurifying, pNeutral, pPositive, model);
for (i=0; i<3; i++)
{
for (j=0; j<3; j++)
{
printf ("%lf ", m[i][j]);
}
printf ("\n");
}
}
# endif
return (NO_ERROR);
}
int IsKink (TreeNode *p)
{
int numMarked;
if (p->anc == NULL)
return (YES);
if (p->anc->marked == NO) /* added 4/20/00 */
return (YES);
numMarked = 0;
if (p->left != NULL)
if (p->left->marked == YES)
numMarked++;
if (p->right != NULL)
if (p->right->marked == YES)
numMarked++;
if (numMarked == 2)
return (YES);
return (NO);
}
int IsLeaf (TreeNode *p)
{
if (p->left == NULL || p->right == NULL || p->anc == NULL)
return (YES);
return (NO);
}
int LnBDPrior (int whichState, int whichChain, int numTaxa, double *prob)
{
int i, j;
double sR, eR, sF, rootTime, *nt;
TreeNode *p;
sR = spRate[whichChain*2 + whichState];
eR = exRate[whichChain*2 + whichState];
sF = samplingFraction;
rootTime = root[whichChain*2+whichState]->left->nodeTime;
if (enforceCalibrations == NO)
{
/* get node times */
for (i=0; i<numNodes; i++)
{
p = allNodesDownPassSeq[whichChain*2*numNodes + whichState*numNodes + i];
if (p->left == NULL && p->right == NULL)
p->nodeTime = 0.0;
else
p->nodeTime += p->left->nodeTime + p->left->length;
}
for (i=0; i<numNodes; i++)
{
p = allNodesDownPassSeq[whichChain*2*numNodes + whichState*numNodes + i];
if (p->left == NULL && p->right == NULL)
p->nodeTime = 0.0;
else
p->nodeTime /= rootTime;
}
}
/* allocate memory */
nt = (double *)malloc((size_t) (numTaxa-1) * sizeof(double));
if (!nt)
{
printf ("\n ERROR: Problem allocating nt\n");
return (ERROR);
}
/* put node times into vector */
j = 0;
for (i=0; i<numNodes; i++)
{
p = allNodesDownPassSeq[whichChain*2*numNodes + whichState*numNodes + i];
if (p->left != NULL && p->right != NULL && p->anc != NULL)
{
nt[j] = p->nodeTime;
j++;
}
}
# if 0
for (i=0; i<numTaxa-1; i++)
printf ("%d %lf\n", i, nt[i]);
printf ("sr = %lf er = %lf sf = %lf rt = %lf\n", sR, eR, sF, rootTime);
# endif
/* calculate probabilities of tree */
(*prob) = (numTaxa-2)*log(sR);
for (i=0; i<numTaxa-2; i++)
{
(*prob) += lnP1(nt[i], sR, eR, sF) - lnVt(rootTime, sR, eR, sF);
}
free (nt);
return (NO_ERROR);
}
double LnGamma (double alp)
{
double x = alp, f = 0.0, z;
if (x < 7)
{
f = 1.0;
z = x-1.0;
while (++z < 7.0)
f *= z;
x = z;
f = -log(f);
}
z = 1.0/(x*x);
return (f + (x-0.5)*log(x) - x + 0.918938533204673 +
(((-0.000595238095238*z+0.000793650793651)*z-0.002777777777778)*z +
0.083333333333333)/x);
}
int LnLike (int whichState, int whichChain, int numChars, int numRateCats, double *lnL, int refreshScalers)
{
double x;
x = 0.0;
# if defined (SMART_TI_PROBS)
//UpDateAllTIs (whichState, whichChain);
if (CalcTransitionProbs (whichState, whichChain, numRateCats) == ERROR)
return (ERROR);
# endif
if ((dataType == DNA || dataType == RNA) && enforceCodonModel == NO)
{
if (useCovarion == NO)
{
if (LnLikeDNA (whichState, whichChain, numChars, numRateCats, &x, refreshScalers) == ERROR)
return (ERROR);
}
else
{
if (LnLikeCovarion (whichState, whichChain, numChars, numRateCats, &x, refreshScalers) == ERROR)
return (ERROR);
}
}
else if ((dataType == DNA || dataType == RNA) && enforceCodonModel == YES)
{
if (useCovarion == NO)
{
if (LnLikeCodon (whichState, whichChain, numChars, &x, refreshScalers) == ERROR)
return (ERROR);
}
else
{
return (ERROR);
}
}
else if (dataType == PROTEIN)
{
if (useCovarion == NO)
{
if (LnLikeAA (whichState, whichChain, numChars, numRateCats, &x, refreshScalers) == ERROR)
return (ERROR);
}
else
{
if (LnLikeCovarion (whichState, whichChain, numChars, numRateCats, &x, refreshScalers) == ERROR)
return (ERROR);
}
}
else if (dataType == RESTRICTION)
{
if (useCovarion == NO)
{
if (LnLikeRestriction (whichState, whichChain, numChars, numRateCats, &x, refreshScalers) == ERROR)
return (ERROR);
}
else
{
return (ERROR);
}
}
else if (dataType == STANDARD)
{
if (useCovarion == NO)
{
// TODO: split this between LnLikeStandardBinF and LnLikeStandardMkF
if (LnLikeStandardBin (whichState, whichChain, numChars, numRateCats, &x, refreshScalers) == ERROR)
return (ERROR);
}
else
{
return (ERROR);
}
}
else
return (ERROR);
(*lnL) = x;
return (NO_ERROR);
}
# if !defined (SUPER_FAST)
/*-----------------------------------------------------------
LnLikeAA: 'Fast' version, core written 2001-03-12
------------------------------------------------------------*/
int LnLikeAA (int whichState, int whichChain, int numChars, int numRateCats, double *lnL, int refreshScalers)
{
# define N_STATES_SQUARED 400
# define N_STATES 20
register int i, j, k, c, n, m, cn, h;
int lnumRateCats, lnPartitions, oneMatSize, oneNodeSize,
index, nRates, pat, localLag, *usedBin,
intNodeOffset, condLikeOffset, scalerOffset;
double bs[N_STATES], *catFreq, *catRate, *partRate,
*clL, *clR, *clA, *clP, *scP, *pL, *pR, *pA,
*lnScaler, scaler, like, lnC, *biN, max, temp, correlation,
*ratePr, **markovTi, likeL, likeR, likeA;
TreeNode *p;
# if !defined (SMART_TI_PROBS)
int nPij, isComplex, indexL, indexR, indexA;
double theRate, **probs, **q, *eigenValues, *eigvalsImag, **eigvecs, **inverseEigvecs, *c_ijk;
complex **Ceigvecs, **CinverseEigvecs;
# else
int nForOneState;
# endif
/* initialize offset for transition probabilities */
# if defined (SMART_TI_PROBS)
nForOneState = numNodes*nodeTiSize;
# endif
/* initialize intNodeOffset */
intNodeOffset = whichChain*2*numIntNodes + whichState*numIntNodes;
/* load base frequencies */
index = whichChain*2*N_STATES + whichState*N_STATES;
for (i=0; i<N_STATES; i++)
bs[i] = baseFreq[index + i];
/* how many different rates? */
/* lnumRateCats contains a local copy of numRateCats if appropriate, else 1 */
/* lnPartitions contains a local copy of nPartitions if appropriate, else 1 */
/* the code introduced here only makes sure that the number of partitions */
/* or rate categories is set to 1 when appropriate, in case the global variables */
/* are not set to 1 when they are not "in use" */
if (!strcmp(ratesModel, "sitespec") || !strcmp(ratesModel, "ssgamma") || !strcmp(ratesModel, "ssadgamma"))
lnPartitions = nPartitions;
else
lnPartitions = 1;
if (!strcmp(ratesModel, "equal") || !strcmp(ratesModel, "sitespec"))
lnumRateCats = 1;
else
lnumRateCats = numRateCats;
nRates = lnPartitions * lnumRateCats; // number of rates needing P matrices
/* allocate memory for the calculations */
/* pL, pR and pA will contain the transition probs for Left, Right and Anc */
/* One transition probability matrix is needed for each possible rate */
# if !defined (SMART_TI_PROBS)
probs = psdmatrix (N_STATES);
nPij = nRates * N_STATES_SQUARED;
pL = (double *)malloc((size_t)(3 * nPij * sizeof(double)));
if (!pL)
{
printf ("\n ERROR: Problem allocating Pij\n");
goto error_exit;
}
pR = pL + nPij;
pA = pR + nPij;
# endif
/* allocate memory for rate and rate category frequencies */
catFreq = (double *)malloc((size_t) ((2 * lnumRateCats + lnPartitions) * sizeof(double)));
if (!catFreq)
{
printf ("\n ERROR: Problem allocating space for rate multipliers and rate category freqs.\n");
goto error_exit;
}
catRate = catFreq + lnumRateCats;
partRate = catRate + lnumRateCats;
/* allocate memory for autocorrelated gamma models */
if (!strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "ssadgamma"))
{
ratePr = (double *)malloc((size_t) (lnumRateCats * (numChars + nChar) * sizeof(double)));
if (!ratePr)
{
printf ("\n ERROR: Problem allocating ratePr and biN.\n");
goto error_exit;
}
biN = ratePr + lnumRateCats * numChars;
usedBin = (int *)malloc((size_t) (nChar * sizeof(int)));
if (!usedBin)
{
printf ("\n ERROR: Problem allocating usedBin.\n");
goto error_exit;
}
}
// set pointer to the lnSiteScaler for this tree
lnScaler = &lnSiteScaler[whichChain * 2 * numChars + whichState * numChars];
/* fill in rate categories with frequencies and rates by dividing the */
/* gamma distribution into discrete categories, if appropriate */
/* NB! this is inefficient; store values instead */
if (!strcmp(ratesModel,"gamma")|| !strcmp(ratesModel, "ssgamma"))
{
DiscreteGamma (catFreq, catRate, alpha[whichChain*2 + whichState], alpha[whichChain*2 + whichState], lnumRateCats, 0);
}
else if (!strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "ssadgamma"))
{
markovTi = psdmatrix (lnumRateCats);
AutodGamma (markovTi, catFreq, catRate, &correlation, alpha[whichChain*2 + whichState], rateCorrelation[whichChain*2 + whichState], lnumRateCats);
}
else if (!strcmp(ratesModel, "invgamma"))
{
DiscreteGamma (catFreq, catRate, alpha[whichChain*2 + whichState], alpha[whichChain*2 + whichState], lnumRateCats-1, 0);
catRate[lnumRateCats-1] = 0.0;
catFreq[lnumRateCats-1] = invP[whichChain*2 + whichState];
for (i=0; i<lnumRateCats-1; i++)
{
catRate[i] *= 1.0 / (1.0 - invP[whichChain*2 + whichState]);
catFreq[i] *= (1.0 - invP[whichChain*2 + whichState]);
}
}
else if (!strcmp(ratesModel, "invariant"))
{
catRate[0] = 0.0;
catRate[1] = 1.0 / (1.0 - invP[whichChain*2 + whichState]);
catFreq[0] = invP[whichChain*2 + whichState];
catFreq[1] = 1.0 - invP[whichChain*2 + whichState];
}
else { // "sitespec" or "equal"
catRate[0] = 1.0;
catFreq[0] = 1.0;
}
/* initialize partition rates, if appropriate */
if (lnPartitions > 1)
{
for (i=0; i<lnPartitions; i++)
partRate[i] = scaledRates[whichChain*2*lnPartitions + whichState*lnPartitions + i];
}
else
partRate[0] = 1.0;
/* get eigenvalues and eigenvectors for AAQ matrix */
# if !defined (SMART_TI_PROBS)
q = psdmatrix (N_STATES);
eigenValues = (double *)malloc((size_t) (2 * N_STATES * sizeof(double)));
if (!eigenValues)
{
printf ("\n ERROR: Problem allocating eigenValues and eigvalsImag.\n");
goto error_exit;
}
eigvalsImag = eigenValues + N_STATES;
eigvecs = psdmatrix (N_STATES);
inverseEigvecs = psdmatrix (N_STATES);
Ceigvecs = pscmatrix (N_STATES);
CinverseEigvecs = pscmatrix (N_STATES);
if (SetAAQMatrix (q, whichState, whichChain) == ERROR)
goto error_exit;
isComplex = GetEigens (N_STATES, q, eigenValues, eigvalsImag, eigvecs, inverseEigvecs, Ceigvecs, CinverseEigvecs);
if (isComplex == NO)
{
c_ijk = (double *)malloc((size_t) (8000 * sizeof(double)));
if (!c_ijk)
{
printf ("\n ERROR: Problem allocating c_ijk.\n");
goto error_exit;
}
CalcCijk (c_ijk, N_STATES, eigvecs, inverseEigvecs);
}
# endif
/* how large is the information for one tree and one node*/
oneMatSize = numNodes * numChars * lnumRateCats * N_STATES;
oneNodeSize = numChars * lnumRateCats * N_STATES;
/* calculate indices */
condLikeOffset = whichChain*2*oneMatSize + whichState*oneMatSize;
scalerOffset = whichChain*2*numIntNodes*numChars + whichState*numIntNodes*numChars;
/* pass down tree */
for (n=0; n<numIntNodes; n++)
{
p = intNodeDownPassSeq[intNodeOffset + n];
// for debugging purposes
// set all nodes to update
// p->upDateCl = YES;
clUpdateFlag[p->index] = NO;
if (p->anc->anc == NULL && treeModel == UNROOTED)
{
if (p->upDateCl == YES)
{
//printf ("visiting basal node %d\n", p->index);
/* get transition probabilities */
# if defined (SMART_TI_PROBS)
pL = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (p->left->index)*nodeTiSize);
pR = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (p->right->index)*nodeTiSize);
pA = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (p->index)*nodeTiSize);
# else
for (m=indexL=indexR=indexA=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
theRate = partRate[m] * catRate[k];
// calculate transition probabilities for left branch
if (isComplex == NO)
CalcPij (c_ijk, N_STATES, eigenValues, p->left->length, theRate, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, N_STATES, probs, p->left->length, theRate) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<N_STATES; i++)
for (j=0; j<N_STATES; j++)
pL[indexL++] = probs[i][j];
// calculate transition probabilities for right branch
if (isComplex == NO)
CalcPij (c_ijk, N_STATES, eigenValues, p->right->length, theRate, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, N_STATES, probs, p->right->length, theRate) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<N_STATES; i++)
for (j=0; j<N_STATES; j++)
pR[indexR++] = probs[i][j];
// calculate transition probabilities for ancestral branch
if (isComplex == NO)
CalcPij (c_ijk, N_STATES, eigenValues, p->length, theRate, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, N_STATES, probs, p->length, theRate) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<N_STATES; i++)
for (j=0; j<N_STATES; j++)
pA[indexA++] = probs[i][j];
}
}
# endif
/* calculate conditional likelihoods */
/* first set pointers to cond likes of left, right, p and anc */
clL = &condLike[condLikeOffset + (p->left->index)*oneNodeSize];
clR = &condLike[condLikeOffset + (p->right->index)*oneNodeSize];
clA = &condLike[condLikeOffset + (p->anc->index)*oneNodeSize];
clP = &condLike[condLikeOffset + (p->index)*oneNodeSize];
/* then branch to models */
if (!strcmp(ratesModel, "equal"))
{
for (c=0; c<numChars; c++)
{
for (i=m=0; i<N_STATES; i++)
{
likeL = likeR = likeA = 0.0;
for (j=0; j<N_STATES; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m]*clR[j];
likeA += pA[m++]*clA[j];
}
*(clP++) = likeL * likeR * likeA;
}
clL += N_STATES;
clR += N_STATES;
clA += N_STATES;
}
}
else if (!strcmp(ratesModel, "gamma") || !strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "invariant") || !strcmp(ratesModel, "invgamma"))
{
for (c=h=0; c<numChars; c++)
{
for (k=m=0; k<lnumRateCats; k++)
{
for (i=0; i<N_STATES; i++)
{
likeL = likeR = likeA = 0.0;
for (j=0; j<N_STATES; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m]*clR[j];
likeA += pA[m++]*clA[j];
}
clP[h++] = likeL * likeR * likeA;
}
clL += N_STATES;
clR += N_STATES;
clA += N_STATES;
}
}
}
else if (!strcmp(ratesModel, "ssgamma") || !strcmp(ratesModel, "ssadgamma"))
{
for (c=0; c<numChars; c++)
{
m = partitionId[c]*lnumRateCats*N_STATES_SQUARED;
for (k=0; k<lnumRateCats; k++)
{
for (i=0; i<N_STATES; i++)
{
likeL = likeR = likeA = 0.0;
for (j=0; j<N_STATES; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m]*clR[j];
likeA += pA[m++]*clA[j];
}
*(clP++) = likeL * likeR * likeA;
}
clL += N_STATES;
clR += N_STATES;
clA += N_STATES;
}
}
}
else if (!strcmp(ratesModel, "sitespec"))
{
for (c=0; c<numChars; c++)
{
m = partitionId[c]*N_STATES_SQUARED;
for (i=0; i<N_STATES; i++)
{
likeL = likeR = likeA = 0.0;
for (j=0; j<N_STATES; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m]*clR[j];
likeA += pA[m++]*clA[j];
}
*(clP++) = likeL * likeR * likeA;
}
clL += N_STATES;
clR += N_STATES;
clA += N_STATES;
}
}
p->upDateCl = NO;
clUpdateFlag[p->index] = YES;
} // done if p->upDateCl == YES for internal root node
} // done with internal root node
else
{
if (p->upDateCl == YES)
{
//printf ("visiting interior node %d\n", p->index);
/* get transition probabilities */
# if defined (SMART_TI_PROBS)
pL = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (p->left->index)*nodeTiSize);
pR = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (p->right->index)*nodeTiSize);
# else
for (m=indexL=indexR=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
theRate = partRate[m] * catRate[k];
// calculate transition probabilities for left branch
if (isComplex == NO)
CalcPij (c_ijk, N_STATES, eigenValues, p->left->length, theRate, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, N_STATES, probs, p->left->length, theRate) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<N_STATES; i++)
for (j=0; j<N_STATES; j++)
pL[indexL++] = probs[i][j];
// calculate transition probabilities for right branch
if (isComplex == NO)
CalcPij (c_ijk, N_STATES, eigenValues, p->right->length, theRate, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, N_STATES, probs, p->right->length, theRate) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<N_STATES; i++)
for (j=0; j<N_STATES; j++)
pR[indexR++] = probs[i][j];
}
}
# endif
/* calculate conditional likelihoods */
/* first set pointers to cond likes of left, right and p */
clL = &condLike[condLikeOffset + (p->left->index)*oneNodeSize];
clR = &condLike[condLikeOffset + (p->right->index)*oneNodeSize];
clP = &condLike[condLikeOffset + (p->index)*oneNodeSize];
/* then branch to models */
if (!strcmp(ratesModel, "equal"))
{
for (c=0; c<numChars; c++)
{
for (i=m=0; i<N_STATES; i++)
{
likeL = likeR = 0.0;
for (j=0; j<N_STATES; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m++]*clR[j];
}
*(clP++) = likeL * likeR;
}
clL += N_STATES;
clR += N_STATES;
}
}
else if (!strcmp(ratesModel, "gamma") || !strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "invariant") || !strcmp(ratesModel, "invgamma"))
{
for (c=h=0; c<numChars; c++)
{
for (k=m=0; k<lnumRateCats; k++)
{
for (i=0; i<N_STATES; i++)
{
likeL = likeR = 0.0;
for (j=0; j<N_STATES; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m++]*clR[j];
}
clP[h++] = likeL * likeR;
}
clL += N_STATES;
clR += N_STATES;
}
}
for (c=h=0; c<numChars; c++)
{
for (k=m=0; k<lnumRateCats; k++)
{
for (i=0; i<N_STATES; i++)
{
if (clP[h] < 0 || clP[h] >1.0)
printf("");
h++;
}
}
}
}
else if (!strcmp(ratesModel, "ssgamma") || !strcmp(ratesModel, "ssadgamma"))
{
for (c=0; c<numChars; c++)
{
m = partitionId[c]*lnumRateCats*N_STATES_SQUARED;
for (k=0; k<lnumRateCats; k++)
{
for (i=0; i<N_STATES; i++)
{
likeL = likeR = 0.0;
for (j=0; j<N_STATES; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m++]*clR[j];
}
*(clP++) = likeL * likeR;
}
clL += N_STATES;
clR += N_STATES;
}
}
}
else if (!strcmp(ratesModel, "sitespec"))
{
for (c=0; c<numChars; c++)
{
m = partitionId[c]*N_STATES_SQUARED;
for (i=0; i<N_STATES; i++)
{
likeL = likeR = 0.0;
for (j=0; j<N_STATES; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m++]*clR[j];
}
*(clP++) = likeL * likeR;
}
clL += N_STATES;
clR += N_STATES;
}
}
p->upDateCl = NO;
clUpdateFlag[p->index] = YES;
} // done with interior node if p->upDateCl == YES
} // done with interior node
// deal with scaling
// first check if we need to refresh scalers and potentially shift scaler nodes
// we have to remember scalerIndex because the node may move in the tree
if (refreshScalers == YES)
{
if (n % RESCALE_FREQ == 0)
{
p->scalerNode = YES;
p->scalerIndex = n;
}
else
p->scalerNode = NO;
}
if (p->scalerNode == YES && clUpdateFlag[p->index] == YES)
{
scalerUpdateFlag[p->scalerIndex] = YES;
scP = &clScaler[scalerOffset + (p->scalerIndex)*numChars];
clP = &condLike[condLikeOffset + (p->index)*oneNodeSize];
i = j = 0;
for (c=0; c<numChars; c++)
{
scaler = 0.0;
for (k=0; k<lnumRateCats; k++)
{
for (m=0; m<N_STATES; m++)
{
if (clP[i] > scaler)
scaler = clP[i];
i++;
}
}
for (k=0; k<lnumRateCats; k++)
{
for (m=0; m<N_STATES; m++)
clP[j++] /= scaler;
}
lnScaler[c] -= scP[c]; //subtract old value
scP[c] = log(scaler);
lnScaler[c] += scP[c]; //add new value
}
}
} // next node
/* get likelihood at base of tree */
p = root[whichChain*2+whichState]->left;
clP = &condLike[condLikeOffset + (p->index)*oneNodeSize];
(*lnL) = 0.0; // reset lnL
if (!strcmp(ratesModel, "equal") || !strcmp(ratesModel, "sitespec"))
{
for (c=0; c<numChars; c++)
{
like = 0.0;
for (i=0; i<N_STATES; i++)
like += ((*(clP++)) * bs[i]);
//printf ("%d: %1.25lf %lf %d\n", c, like, log(like), numSitesOfPat[c]);
if (like < LIKE_EPSILON) /* likelihood for a site can go to zero when */
{ /* two adjacent terminal branches have zero length. */
printf (" WARNING: In LIKE_EPSILON\n");
goto error_exit;
}
else
{
(*lnL) += (lnScaler[c] + log(like)) * numSitesOfPat[c];
}
}
}
else if (!strcmp(ratesModel, "gamma") || !strcmp(ratesModel, "invariant") || !strcmp(ratesModel, "invgamma") || !strcmp(ratesModel, "ssgamma"))
{
for (c=0; c<numChars; c++)
{
like = 0.0;
for (k=0; k<lnumRateCats; k++)
{
for (i=0; i<N_STATES; i++)
like += ((*(clP++)) * bs[i]) * catFreq[k];
}
if (like < LIKE_EPSILON) /* likelihood for a site can go to zero when */
{ /* two adjacent terminal branches have zero length. */
printf (" WARNING: In LIKE_EPSILON (%d) %1.30lf\n", c, like);
goto error_exit;
}
else
{
(*lnL) += (lnScaler[c] + log(like)) * numSitesOfPat[c];
}
}
}
else if (!strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "ssadgamma"))
{
/* initialize usedBin */
for (i=0; i<nChar; i++)
usedBin[i] = NO;
lnC = 0.0;
m = j = 0;
for (c=0; c<numChars; c++)
{
for (k=0; k<lnumRateCats; k++)
{
like = 0.0;
for (i=0; i<N_STATES; i++)
like += clP[j++] * bs[i];
ratePr[m++] = like;
}
lnC += (lnScaler[c] * numSitesOfPat[c]);
}
localLag = lag[whichChain*2 + whichState];
for (c=nChar-1; c>=0; c--)
{
cn = c*lnumRateCats;
if (patternId[c] >= 0)
{
pat = patternId[c];
if (c + localLag >= nChar)
{
max = 0.0;
for (k=0; k<lnumRateCats; k++)
{
biN[cn + k] = ratePr[pat*lnumRateCats + k];
if (biN[cn + k] > max)
max = biN[cn + k];
}
if (max > 0.0)
{
for (k=0; k<lnumRateCats; k++)
biN[cn + k] /= max;
lnC += log(max);
}
else
{
printf (" ERROR: Scaling factor for adgamma model is less than 0\n");
goto error_exit;
}
}
else
{
for (i=0; i<lnumRateCats; i++)
{
temp = max = 0.0;
for (j=0; j<lnumRateCats; j++)
temp += markovTi[i][j] * biN[(c+localLag)*lnumRateCats + j];
biN[cn + i] = ratePr[pat*lnumRateCats+i] * temp;
if (biN[cn + i] > max)
max = biN[cn + i];
usedBin[c+localLag] = YES;
}
if (max > 0.0)
{
for (k=0; k<lnumRateCats; k++)
biN[cn + k] /= max;
lnC += log(max);
}
else
{
printf (" ERROR: Scaling factor for adgamma model is less than 0\n");
goto error_exit;
}
}
}
else
{
printf (" ERROR: Unidentified pattern\n");
goto error_exit;
}
}
(*lnL) = lnC;
for (c=0; c<nChar; c++)
{
if (usedBin[c] == NO)
{
temp = 0.0;
for (k=0; k<lnumRateCats; k++)
{
temp += (catFreq[k] * biN[c*lnumRateCats + k]);
}
(*lnL) += log(temp);
usedBin[c] = YES;
}
}
}
/* free memory */
# if !defined (SMART_TI_PROBS)
free_psdmatrix (probs);
free (pL);
free_psdmatrix (q);
free (eigenValues);
free_psdmatrix (eigvecs);
free_psdmatrix (inverseEigvecs);
free_pscmatrix (Ceigvecs);
free_pscmatrix (CinverseEigvecs);
if (isComplex != YES)
free (c_ijk);
# endif
free (catFreq);
if (!strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "ssadgamma"))
{
free_psdmatrix(markovTi);
free (ratePr);
free (usedBin);
}
return (NO_ERROR);
error_exit:
# if !defined (SMART_TI_PROBS)
free_psdmatrix (probs);
free (pL);
free_psdmatrix (q);
free (eigenValues);
free_psdmatrix (eigvecs);
free_psdmatrix (inverseEigvecs);
free_pscmatrix (Ceigvecs);
free_pscmatrix (CinverseEigvecs);
if (isComplex != YES)
free (c_ijk);
# endif
free (catFreq);
if (!strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "ssadgamma"))
{
free_psdmatrix(markovTi);
free (ratePr);
free (usedBin);
}
return (ERROR);
# undef N_STATES_SQUARED
# undef N_STATES
}
/*-----------------------------------------------------------
LnLikeCodon: 'Fast' version, core written 2001-03-21
------------------------------------------------------------*/
int LnLikeCodon (int whichState, int whichChain, int numChars, double *lnL, int refreshScalers)
{
register int i, j, k, c, n, m, cn;
int nOmegaCats, oneMatSize, oneNodeSize,
index, pat, isFirst,
intNodeOffset, condLikeOffset, scalerOffset,
lnStates, lnStatesSquared, lnStatesCube;
double *bs, *pL, *pR, *pA, *clL, *clR, *clA, *clP, *scP,
*lnScaler, scaler, like, lnC, *biN, max, temp, *omegaPr, markovTi[3][3],
likeL, likeR, likeA, likePos, likeNeu, likePur;
TreeNode *p;
# if defined (SMART_TI_PROBS)
int nForOneState;
# else
int nPij, isComplex, indexL, indexR, indexA, isComplex2, isComplex3;
double lkappa, theRate, **probs, **q, *eigenValues, *eigvalsImag, **eigvecs, **inverseEigvecs, *c_ijk,
*eigenValues2, *eigvalsImag2, **eigvecs2, **inverseEigvecs2, *c_ijk2,
*eigenValues3, *eigvalsImag3, **eigvecs3, **inverseEigvecs3, *c_ijk3;
complex **Ceigvecs, **CinverseEigvecs, **Ceigvecs2, **CinverseEigvecs2,
**Ceigvecs3, **CinverseEigvecs3;
# endif
/* set number of states */
if (!strcmp(codonModelType, "covny98"))
lnStates = 3 * nStates;
else
lnStates = nStates;
lnStatesSquared = lnStates * lnStates;
lnStatesCube = lnStatesSquared * lnStates;
/* initialize offset for transition probabilities */
# if defined (SMART_TI_PROBS)
nForOneState = numNodes*nodeTiSize;
# endif
/* load codon frequencies */
bs = (double *)malloc((size_t) (lnStates * sizeof(double)));
if (!bs)
{
printf ("\n ERROR: Problem allocating bs.\n");
goto error_exit;
}
index = whichChain*2*nStates + whichState*nStates;
if (!strcmp(codonModelType, "covny98"))
{
k = 0;
for (i=0; i<nStates; i++)
{
bs[k] = baseFreq[index + i] * probPur[whichChain*2 + whichState];
k++;
}
for (i=0; i<nStates; i++)
{
bs[k] = baseFreq[index + i] * probNeu[whichChain*2 + whichState];
k++;
}
for (i=0; i<nStates; i++)
{
bs[k] = baseFreq[index + i] * probPos[whichChain*2 + whichState];
k++;
}
}
else
{
for (i=0; i<nStates; i++)
bs[i] = baseFreq[index + i];
}
/* how many different omega categories */
if (!strcmp(codonModelType, "ny98") || !strcmp(codonModelType, "ac1ny98") || !strcmp(codonModelType, "ac2ny98"))
nOmegaCats = 3;
else
nOmegaCats = 1;
/* allocate memory for autocorrelated codon models */
if (!strcmp(codonModelType, "ac1ny98") || !strcmp(codonModelType, "ac2ny98"))
{
omegaPr = (double *)malloc((size_t) (nOmegaCats * (numChars + nChar) * sizeof(double)));
if (!omegaPr)
{
printf ("\n ERROR: Problem allocating omegaPr and biN.\n");
goto error_exit;
}
biN = omegaPr + nOmegaCats * numChars;
}
/* allocate memory for the calculations */
/* pL, pR and pA will contain the transition probs for Left, Right and Anc */
/* One transition probability matrix is needed for each possible omega value */
# if !defined (SMART_TI_PROBS)
probs = psdmatrix (lnStates);
nPij = nOmegaCats * lnStatesSquared;
pL = (double *)malloc((size_t)(3 * nPij * sizeof(double)));
if (!pL)
{
printf ("\n ERROR: Problem allocating Pij\n");
goto error_exit;
}
pR = pL + nPij;
pA = pR + nPij;
# endif
// set pointer to the lnSiteScaler for this tree
lnScaler = &lnSiteScaler[whichChain * 2 * numChars + whichState * numChars];
/* allocate memory for eigenvalues and eigenvectors */
# if !defined (SMART_TI_PROBS)
q = psdmatrix (lnStates);
eigenValues = (double *)malloc((size_t) (2 * lnStates * sizeof(double)));
if (!eigenValues)
{
printf ("\n ERROR: Problem allocating eigenValues and eigvalsImag.\n");
goto error_exit;
}
eigvalsImag = eigenValues + lnStates;
eigvecs = psdmatrix (lnStates);
inverseEigvecs = psdmatrix (lnStates);
Ceigvecs = pscmatrix (lnStates);
CinverseEigvecs = pscmatrix (lnStates);
/* get eigenvalues and eigenvectors for codon Q matrix */
if (!strcmp(codonModelType, "covny98"))
{
if (SetCodonSwitchQMatrix (q, whichState, whichChain, omega[whichChain*2 + whichState], kappa[whichChain*2 + whichState], switchRate[whichChain*4 + whichState*2 + 0]) == ERROR)
goto error_exit;
}
else
{
if (SetCodonQMatrix (q, whichState, whichChain, omega[whichChain*2 + whichState], kappa[whichChain*2 + whichState]) == ERROR)
goto error_exit;
}
isComplex = GetEigens (lnStates, q, eigenValues, eigvalsImag, eigvecs, inverseEigvecs, Ceigvecs, CinverseEigvecs);
if (isComplex == NO)
{
c_ijk = (double *)malloc((size_t) (lnStatesCube * sizeof(double)));
if (!c_ijk)
{
printf ("\n ERROR: Problem allocating c_ijk.\n");
goto error_exit;
}
CalcCijk (c_ijk, lnStates, eigvecs, inverseEigvecs);
}
if (!strcmp(codonModelType, "ny98") || !strcmp(codonModelType, "ac1ny98") || !strcmp(codonModelType, "ac2ny98"))
{
/* these models use several omega categories, one Q matrix needed for each */
/* first set Q matrix for synonymous changes (negative selection) */
eigenValues2 = (double *)malloc((size_t) (2 * lnStates * sizeof(double)));
if (!eigenValues2)
{
printf ("\n ERROR: Problem allocating eigenValues2 and eigvalsImag2.\n");
goto error_exit;
}
eigvalsImag2 = eigenValues2 + lnStates;
eigvecs2 = psdmatrix (lnStates);
inverseEigvecs2 = psdmatrix (lnStates);
Ceigvecs2 = pscmatrix (lnStates);
CinverseEigvecs2 = pscmatrix (lnStates);
if (SetCodonQMatrix (q, whichState, whichChain, 0.0, kappa[whichChain*2 + whichState]) == ERROR)
goto error_exit;
isComplex2 = GetEigens (lnStates, q, eigenValues2, eigvalsImag2, eigvecs2, inverseEigvecs2, Ceigvecs2, CinverseEigvecs2);
if (isComplex2 == NO)
{
c_ijk2 = (double *)malloc((size_t) (lnStatesCube * sizeof(double)));
if (!c_ijk2)
{
printf ("\n ERROR: Problem allocating c_ijk2.\n");
goto error_exit;
}
CalcCijk (c_ijk2, lnStates, eigvecs2, inverseEigvecs2);
}
/* then set Q matrix for nonsynonymous changes (positive selection) */
eigenValues3 = (double *)malloc((size_t) (2 * lnStates * sizeof(double)));
if (!eigenValues2)
{
printf ("\n ERROR: Problem allocating eigenValues2 and eigvalsImag2.\n");
goto error_exit;
}
eigvalsImag3 = eigenValues2 + lnStates;
eigvecs3 = psdmatrix (lnStates);
inverseEigvecs3 = psdmatrix (lnStates);
Ceigvecs3 = pscmatrix (lnStates);
CinverseEigvecs3 = pscmatrix (lnStates);
if (SetCodonQMatrix (q, whichState, whichChain, 1.0, kappa[whichChain*2 + whichState]) == ERROR)
goto error_exit;
isComplex3 = GetEigens (lnStates, q, eigenValues3, eigvalsImag3, eigvecs3, inverseEigvecs3, Ceigvecs3, CinverseEigvecs3);
if (isComplex3 == NO)
{
c_ijk3 = (double *)malloc((size_t) (lnStatesCube * sizeof(double)));
if (!c_ijk3)
{
printf ("\n ERROR: Problem allocating c_ijk3.\n");
goto error_exit;
}
CalcCijk (c_ijk3, lnStates, eigvecs3, inverseEigvecs3);
}
}
# endif
/* how large is the information for one tree and one node */
oneMatSize = numNodes * numChars * nOmegaCats * lnStates;
oneNodeSize = numChars * nOmegaCats * lnStates;
/* calculate index offsets */
intNodeOffset = whichChain*2*numIntNodes + whichState*numIntNodes;
condLikeOffset = whichChain*2*oneMatSize + whichState*oneMatSize;
scalerOffset = whichChain*2*numIntNodes*numChars + whichState*numIntNodes*numChars;
/* pass down tree */
for (n=0; n<numIntNodes; n++)
{
p = intNodeDownPassSeq[intNodeOffset + n];
// for debugging purposes
// set all nodes to update
// p->upDateCl = YES;
clUpdateFlag[p->index] = NO;
if (p->anc->anc == NULL && treeModel == UNROOTED)
{
if (p->upDateCl == YES)
{
//printf ("visiting basal node %d\n", p->index);
/* get transition probabilities */
# if defined (SMART_TI_PROBS)
pL = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (p->left->index)*nodeTiSize);
pR = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (p->right->index)*nodeTiSize);
pA = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (p->index)*nodeTiSize);
# else
indexL = indexR = indexA = 0;
// calculate transition probabilities for left branch
if (isComplex == NO)
CalcPij (c_ijk, lnStates, eigenValues, p->left->length, 1.0, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, lnStates, probs, p->left->length, 1.0) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<lnStates; i++)
for (j=0; j<lnStates; j++)
pL[indexL++] = probs[i][j];
// calculate transition probabilities for right branch
if (isComplex == NO)
CalcPij (c_ijk, lnStates, eigenValues, p->right->length, 1.0, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, lnStates, probs, p->right->length, 1.0) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<lnStates; i++)
for (j=0; j<lnStates; j++)
pR[indexR++] = probs[i][j];
// calculate transition probabilities for ancestral branch
if (isComplex == NO)
CalcPij (c_ijk, lnStates, eigenValues, p->length, 1.0, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, lnStates, probs, p->length, 1.0) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<lnStates; i++)
for (j=0; j<lnStates; j++)
pA[indexA++] = probs[i][j];
if (!strcmp(codonModelType, "ny98") || !strcmp(codonModelType, "ac1ny98") || !strcmp(codonModelType, "ac2ny98"))
{
/* set transition probabilities for synonymous changes */
// left branch
if (isComplex2 == NO)
CalcPij (c_ijk2, lnStates, eigenValues2, p->left->length, 1.0, probs);
else
if (ComplexChangeMatrix (eigenValues2, eigvalsImag2, Ceigvecs2, CinverseEigvecs2, lnStates, probs, p->left->length, 1.0) == ERROR)
printf ("Problem calculating transition probabilities for complex eigen values.\n");
for (i=0; i<lnStates; i++)
for (j=0; j<lnStates; j++)
pL[indexL++] = probs[i][j];
// right branch
if (isComplex2 == NO)
CalcPij (c_ijk2, lnStates, eigenValues2, p->right->length, 1.0, probs);
else
if (ComplexChangeMatrix (eigenValues2, eigvalsImag2, Ceigvecs2, CinverseEigvecs2, lnStates, probs, p->right->length, 1.0) == ERROR)
printf ("Problem calculating transition probabilities for complex eigen values.\n");
for (i=0; i<lnStates; i++)
for (j=0; j<lnStates; j++)
pR[indexR++] = probs[i][j];
// ancestral branch
if (isComplex2 == NO)
CalcPij (c_ijk2, lnStates, eigenValues2, p->length, 1.0, probs);
else
if (ComplexChangeMatrix (eigenValues2, eigvalsImag2, Ceigvecs2, CinverseEigvecs2, lnStates, probs, p->length, 1.0) == ERROR)
printf ("Problem calculating transition probabilities for complex eigen values.\n");
for (i=0; i<lnStates; i++)
for (j=0; j<lnStates; j++)
pA[indexA++] = probs[i][j];
/* set transition probabilities for nonsynonymous changes */
// left branch
if (isComplex3 == NO)
CalcPij (c_ijk3, lnStates, eigenValues3, p->left->length, 1.0, probs);
else
if (ComplexChangeMatrix (eigenValues3, eigvalsImag3, Ceigvecs3, CinverseEigvecs3, lnStates, probs, p->left->length, 1.0) == ERROR)
printf ("Problem calculating transition probabilities for complex eigen values.\n");
for (i=0; i<lnStates; i++)
for (j=0; j<lnStates; j++)
pL[indexL++] = probs[i][j];
// right branch
if (isComplex3 == NO)
CalcPij (c_ijk3, lnStates, eigenValues3, p->right->length, 1.0, probs);
else
if (ComplexChangeMatrix (eigenValues3, eigvalsImag3, Ceigvecs3, CinverseEigvecs3, lnStates, probs, p->right->length, 1.0) == ERROR)
printf ("Problem calculating transition probabilities for complex eigen values.\n");
for (i=0; i<lnStates; i++)
for (j=0; j<lnStates; j++)
pR[indexR++] = probs[i][j];
// ancestral branch
if (isComplex3 == NO)
CalcPij (c_ijk3, lnStates, eigenValues3, p->length, 1.0, probs);
else
if (ComplexChangeMatrix (eigenValues3, eigvalsImag3, Ceigvecs3, CinverseEigvecs3, lnStates, probs, p->length, 1.0) == ERROR)
printf ("Problem calculating transition probabilities for complex eigen values.\n");
for (i=0; i<lnStates; i++)
for (j=0; j<lnStates; j++)
pA[indexA++] = probs[i][j];
}
# endif
/* calculate conditional likelihoods */
/* first set pointers to cond likes of left, right, p and anc */
clL = &condLike[condLikeOffset + (p->left->index)*oneNodeSize];
clR = &condLike[condLikeOffset + (p->right->index)*oneNodeSize];
clA = &condLike[condLikeOffset + (p->anc->index)*oneNodeSize];
clP = &condLike[condLikeOffset + (p->index)*oneNodeSize];
/* then branch to models */
if (!strcmp(codonModelType, "ny98") || !strcmp(codonModelType, "ac1ny98") || !strcmp(codonModelType, "ac2ny98"))
{
for (c=0; c<numChars; c++)
{
for (k=m=0; k<nOmegaCats; k++)
{
for (i=0; i<lnStates; i++)
{
likeL = likeR = likeA = 0.0;
for (j=0; j<lnStates; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m]*clR[j];
likeA += pA[m++]*clA[j];
}
*(clP++) = likeL * likeR * likeA;
}
clL += lnStates;
clR += lnStates;
clA += lnStates;
}
}
}
else /* no omega variation or omega switch model */
{
for (c=0; c<numChars; c++)
{
for (i=m=0; i<lnStates; i++)
{
likeL = likeR = likeA = 0.0;
for (j=0; j<lnStates; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m]*clR[j];
likeA += pA[m++]*clA[j];
}
*(clP++) = likeL * likeR * likeA;
}
clL += lnStates;
clR += lnStates;
clA += lnStates;
}
}
p->upDateCl = NO;
clUpdateFlag[p->index] = YES;
} // done if p->upDateCl == YES for internal root node
} // done with internal root node
else
{
if (p->upDateCl == YES)
{
//printf ("visiting interior node %d\n", p->index);
/* get transition probabilities */
# if defined (SMART_TI_PROBS)
pL = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (p->left->index)*nodeTiSize);
pR = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (p->right->index)*nodeTiSize);
# else
indexL = indexR = 0;
// calculate transition probabilities for left branch
if (isComplex == NO)
CalcPij (c_ijk, lnStates, eigenValues, p->left->length, 1.0, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, lnStates, probs, p->left->length, 1.0) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<lnStates; i++)
for (j=0; j<lnStates; j++)
pL[indexL++] = probs[i][j];
// calculate transition probabilities for right branch
if (isComplex == NO)
CalcPij (c_ijk, lnStates, eigenValues, p->right->length, 1.0, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, lnStates, probs, p->right->length, 1.0) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<lnStates; i++)
for (j=0; j<lnStates; j++)
pR[indexR++] = probs[i][j];
if (!strcmp(codonModelType, "ny98") || !strcmp(codonModelType, "ac1ny98") || !strcmp(codonModelType, "ac2ny98"))
{
/* set transition probabilities for synonymous changes */
// left branch
if (isComplex2 == NO)
CalcPij (c_ijk2, lnStates, eigenValues2, p->left->length, 1.0, probs);
else
if (ComplexChangeMatrix (eigenValues2, eigvalsImag2, Ceigvecs2, CinverseEigvecs2, lnStates, probs, p->left->length, 1.0) == ERROR)
printf ("Problem calculating transition probabilities for complex eigen values.\n");
for (i=0; i<lnStates; i++)
for (j=0; j<lnStates; j++)
pL[indexL++] = probs[i][j];
// right branch
if (isComplex2 == NO)
CalcPij (c_ijk2, lnStates, eigenValues2, p->right->length, 1.0, probs);
else
if (ComplexChangeMatrix (eigenValues2, eigvalsImag2, Ceigvecs2, CinverseEigvecs2, lnStates, probs, p->right->length, 1.0) == ERROR)
printf ("Problem calculating transition probabilities for complex eigen values.\n");
for (i=0; i<lnStates; i++)
for (j=0; j<lnStates; j++)
pR[indexR++] = probs[i][j];
/* set transition probabilities for nonsynonymous changes */
// left branch
if (isComplex3 == NO)
CalcPij (c_ijk3, lnStates, eigenValues3, p->left->length, 1.0, probs);
else
if (ComplexChangeMatrix (eigenValues3, eigvalsImag3, Ceigvecs3, CinverseEigvecs3, lnStates, probs, p->left->length, 1.0) == ERROR)
printf ("Problem calculating transition probabilities for complex eigen values.\n");
for (i=0; i<lnStates; i++)
for (j=0; j<lnStates; j++)
pL[indexL++] = probs[i][j];
// right branch
if (isComplex3 == NO)
CalcPij (c_ijk3, lnStates, eigenValues3, p->right->length, 1.0, probs);
else
if (ComplexChangeMatrix (eigenValues3, eigvalsImag3, Ceigvecs3, CinverseEigvecs3, lnStates, probs, p->right->length, 1.0) == ERROR)
printf ("Problem calculating transition probabilities for complex eigen values.\n");
for (i=0; i<lnStates; i++)
for (j=0; j<lnStates; j++)
pR[indexR++] = probs[i][j];
}
# endif
/* calculate conditional likelihoods */
/* first set pointers to cond likes of left, right and p */
clL = &condLike[condLikeOffset + (p->left->index)*oneNodeSize];
clR = &condLike[condLikeOffset + (p->right->index)*oneNodeSize];
clP = &condLike[condLikeOffset + (p->index)*oneNodeSize];
/* then branch to models */
if (!strcmp(codonModelType, "ny98") || !strcmp(codonModelType, "ac1ny98") || !strcmp(codonModelType, "ac2ny98"))
{
for (c=0; c<numChars; c++)
{
for (k=m=0; k<nOmegaCats; k++)
{
for (i=0; i<lnStates; i++)
{
likeL = likeR = 0.0;
for (j=0; j<lnStates; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m++]*clR[j];
}
*(clP++) = likeL * likeR;
}
clL += lnStates;
clR += lnStates;
}
}
}
else /* no omega variation or omega switch model */
{
for (c=0; c<numChars; c++)
{
for (i=m=0; i<lnStates; i++)
{
likeL = likeR = 0.0;
for (j=0; j<lnStates; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m++]*clR[j];
}
*(clP++) = likeL * likeR;
}
clL += lnStates;
clR += lnStates;
}
}
p->upDateCl = NO;
clUpdateFlag[p->index] = YES;
} // done with interior node if p->upDateCl == YES
} // done with interior node
// deal with scaling
// first check if we need to refresh scalers and potentially shift scaler nodes
// we have to remember scalerIndex because the node may move in the tree
if (refreshScalers == YES)
{
if (n % RESCALE_FREQ == 0)
{
p->scalerNode = YES;
p->scalerIndex = n;
}
else
p->scalerNode = NO;
}
if (p->scalerNode == YES && clUpdateFlag[p->index] == YES)
{
scalerUpdateFlag[p->scalerIndex] = YES;
scP = &clScaler[scalerOffset + (p->scalerIndex)*numChars];
clP = &condLike[condLikeOffset + (p->index)*oneNodeSize];
i = j = 0;
for (c=0; c<numChars; c++)
{
scaler = 0.0;
for (k=0; k<nOmegaCats; k++)
{
for (m=0; m<lnStates; m++)
{
if (clP[i] > scaler)
scaler = clP[i];
i++;
}
}
for (k=0; k<nOmegaCats; k++)
{
for (m=0; m<lnStates; m++)
clP[j++] /= scaler;
}
lnScaler[c] -= scP[c]; //subtract old value
scP[c] = log(scaler);
lnScaler[c] += scP[c]; //add new value
}
}
} // next node
/* get likelihood at base of tree */
p = root[whichChain*2+whichState]->left;
clP = &condLike[condLikeOffset + (p->index)*oneNodeSize];
(*lnL) = 0.0; // reset lnL
if (!strcmp(codonModelType, "ny98"))
{
for (c=0; c<numChars; c++)
{
likePur = likeNeu = likePos = 0.0;
for (i=0; i<lnStates; i++)
likePos += (*(clP++)) * bs[i];
for (i=0; i<lnStates; i++)
likePur += (*(clP++)) * bs[i];
for (i=0; i<lnStates; i++)
likeNeu += (*(clP++)) * bs[i];
//printf ("%4d -- %lf %lf %lf (%lf)\n", c, likePur, likeNeu, likePos, like);
like = likePos * probPos[whichChain*2 + whichState] + likePur * probPur[whichChain*2 + whichState] + likeNeu * probNeu[whichChain*2 + whichState];
if (like < LIKE_EPSILON) /* likelihood for a site can go to zero when */
{ /* two adjacent terminal branches have zero length. */
printf (" WARNING: In LIKE_EPSILON (%d) %1.30lf\n", c, like);
goto error_exit;
}
else
{
(*lnL) += (lnScaler[c] + log(like)) * numSitesOfPat[c];
}
}
}
else if (!strcmp(codonModelType, "ac1ny98") || !strcmp(codonModelType, "ac2ny98"))
{
if (!strcmp(codonModelType, "ac1ny98"))
InitTiMatrix (markovTi, rateCorrelation[whichChain*2 + whichState], 0.0, 0.0, probPur[whichChain*2 + whichState], probNeu[whichChain*2 + whichState], probPos[whichChain*2 + whichState], 1);
else
InitTiMatrix (markovTi, rateCorrelation[whichChain*2 + whichState], rateCorrelation2[whichChain*4 + whichState*2 + 0], rateCorrelation2[whichChain*4 + whichState*2 + 1], probPur[whichChain*2 + whichState], probNeu[whichChain*2 + whichState], probPos[whichChain*2 + whichState], 2);
lnC = 0.0;
m = j = 0;
for (c=0; c<numChars; c++)
{
likePur = likeNeu = likePos = 0.0;
for (i=0; i<lnStates; i++)
likePos += clP[j++] * bs[i];
for (i=0; i<lnStates; i++)
likePur += clP[j++] * bs[i];
for (i=0; i<lnStates; i++)
likeNeu += clP[j++] * bs[i];
omegaPr[m++] = likePur;
omegaPr[m++] = likeNeu;
omegaPr[m++] = likePos;
lnC += (lnScaler[c] * numSitesOfPat[c]);
}
isFirst = YES;
for (c=(nChar/3)-1; c>=0; c--)
{
cn = c*3;
if (patternId[c] >= 0)
{
pat = patternId[c];
if (isFirst == YES)
{
max = 0.0;
for (k=0; k<3; k++)
{
biN[cn + k] = omegaPr[pat*3 + k];
if (biN[cn + k] > max)
max = biN[cn + k];
}
if (max > 0.0)
{
for (k=0; k<3; k++)
biN[cn + k] /= max;
lnC += log(max);
}
else
{
printf (" ERROR: Scaling factor for ac1ny98 or ac2ny98 model is less than 0\n");
goto error_exit;
}
isFirst = NO;
}
else // isFirst == NO
{
for (i=0; i<3; i++)
{
temp = max = 0.0;
for (j=0; j<3; j++)
temp += markovTi[i][j] * biN[(c+1)*3 + j];
biN[cn + i] = omegaPr[pat*3+i] * temp;
if (biN[cn + i] > max)
max = biN[cn + i];
}
if (max > 0.0)
{
for (k=0; k<3; k++)
biN[cn + k] /= max;
lnC += log(max);
}
else
{
printf (" ERROR: Scaling factor for adgamma model is less than 0\n");
goto error_exit;
}
}
}
else
{
printf (" ERROR: Unidentified pattern\n");
goto error_exit;
}
}
temp = biN[0] * probPur[whichChain*2 + whichState];
temp += biN[1] * probNeu[whichChain*2 + whichState];
temp += biN[2] * probPos[whichChain*2 + whichState];
(*lnL) = lnC + log(temp);
}
else /* no omega variation or covarion-like model */
{
for (c=0; c<numChars; c++)
{
like = 0.0;
for (i=0; i<lnStates; i++)
like += ((*(clP++)) * bs[i]);
//printf ("%d: %1.25lf %lf %d\n", c, like, log(like), numSitesOfPat[c]);
if (like < LIKE_EPSILON) /* likelihood for a site can go to zero when */
{ /* two adjacent terminal branches have zero length. */
printf (" WARNING: In LIKE_EPSILON\n");
printf ("c %d like %f \n", c, like);
goto error_exit;
}
else
{
(*lnL) += (lnScaler[c] + log(like)) * numSitesOfPat[c];
}
}
}
/* free memory */
# if !defined (SMART_TI_PROBS)
free_psdmatrix (probs);
free_psdmatrix (q);
free (pL);
free (eigenValues);
free_psdmatrix (eigvecs);
free_psdmatrix (inverseEigvecs);
free_pscmatrix (Ceigvecs);
free_pscmatrix (CinverseEigvecs);
if (isComplex != YES)
free (c_ijk);
if (!strcmp(codonModelType, "ny98") || !strcmp(codonModelType, "ac1ny98") || !strcmp(codonModelType, "ac2ny98"))
{
free (eigenValues2);
free_psdmatrix (eigvecs2);
free_psdmatrix (inverseEigvecs2);
free_pscmatrix (Ceigvecs2);
free_pscmatrix (CinverseEigvecs2);
if (isComplex2 != YES)
free (c_ijk2);
free (eigenValues3);
free_psdmatrix (eigvecs3);
free_psdmatrix (inverseEigvecs3);
free_pscmatrix (Ceigvecs3);
free_pscmatrix (CinverseEigvecs3);
if (isComplex3 != YES)
free (c_ijk3);
}
# endif
free (bs);
if (!strcmp(codonModelType, "ac1ny98") || !strcmp(codonModelType, "ac2ny98"))
free (omegaPr);
return (NO_ERROR);
error_exit:
# if !defined (SMART_TI_PROBS)
free_psdmatrix (probs);
free_psdmatrix (q);
free (pL);
free (eigenValues);
free_psdmatrix (eigvecs);
free_psdmatrix (inverseEigvecs);
free_pscmatrix (Ceigvecs);
free_pscmatrix (CinverseEigvecs);
if (isComplex != YES)
free (c_ijk);
if (!strcmp(codonModelType, "ny98") || !strcmp(codonModelType, "ac1ny98") || !strcmp(codonModelType, "ac2ny98"))
{
free (eigenValues2);
free_psdmatrix (eigvecs2);
free_psdmatrix (inverseEigvecs2);
free_pscmatrix (Ceigvecs2);
free_pscmatrix (CinverseEigvecs2);
if (isComplex2 != YES)
free (c_ijk2);
free (eigenValues3);
free_psdmatrix (eigvecs3);
free_psdmatrix (inverseEigvecs3);
free_pscmatrix (Ceigvecs3);
free_pscmatrix (CinverseEigvecs3);
if (isComplex3 != YES)
free (c_ijk3);
}
# endif
free (bs);
if (!strcmp(codonModelType, "ac1ny98") || !strcmp(codonModelType, "ac2ny98"))
free (omegaPr);
return (ERROR);
}
/*---------------------------------------------------------------------
LnLikeCovarion: 'Fast' version, core written 2001-03-20
-----------------------------------------------------------------------*/
int LnLikeCovarion (int whichState, int whichChain, int numChars, int numRateCats, double *lnL, int refreshScalers)
{
register int i, j, k, c, n, m, cn;
int lnumRateCats, lnPartitions, oneMatSize, oneNodeSize,
index, index1, index2, nRates, pat, localLag, *usedBin,
intNodeOffset, condLikeOffset, scalerOffset,
lnStates, lnStatesSquared, lnStatesCube;
double *bs, *pL, *pR, *pA, *catFreq, *catRate, *partRate,
*clL, *clR, *clA, *clP, *scP, s01, s10, prob0, prob1,
*lnScaler, scaler, like, lnC, *biN, max, temp, correlation,
*ratePr, **markovTi, likeL, likeR, likeA;
TreeNode *p;
# if defined (SMART_TI_PROBS)
int nForOneState;
# else
register int a, b;
int nPij, *isComplex, indexL, indexR, indexA;
double **probs, **q, *eigenValues, *eigvalsImag, **eigvecs, **inverseEigvecs, *c_ijk,
*eigenValuesP, *eigvalsImagP, *eigvecsP, *inverseEigvecsP, *c_ijkP;
complex **Ceigvecs, **CinverseEigvecs, *CeigvecsP, *CinverseEigvecsP;
# endif
/* calculate local number of states */
/* twice nStates because matrix is doubled */
lnStates = 2 * nStates;
lnStatesSquared = lnStates * lnStates;
lnStatesCube = lnStates * lnStatesSquared;
/* initialize offset for transition probabilities */
# if defined (SMART_TI_PROBS)
nForOneState = numNodes*nodeTiSize;
# endif
/* load base frequencies */
index = whichChain*2*lnStates + whichState*lnStates;
index1 = whichChain*4 + whichState*2;
index2 = whichChain*2 + whichState;
bs = (double *)malloc((size_t) (lnStates * sizeof(double)));
if (!bs)
{
printf ("\n ERROR: Problem allocating bs.\n");
goto error_exit;
}
if (!strcmp(covarionModelType, "ts98"))
{
k = 0;
for (j=0; j<2; j++)
{
for (i=0; i<nStates; i++)
{
bs[k] = baseFreq[whichChain*2*nStates + whichState*nStates + i] * switchPi[whichChain*4 + whichState*2 + j];
k++;
}
}
}
else if (!strcmp(covarionModelType, "gcswitch"))
{
s01 = switchRate[index1 + 0];
s10 = switchRate[index1 + 1];
prob0 = s10 / (s01+s10);
prob1 = s01 / (s01+s10);
bs[0] = (1.0 - gc1[index2]) * (fracA[index2]) * prob0;
bs[1] = (gc1[index2]) * (1.0 - fracG[index2]) * prob0;
bs[2] = (gc1[index2]) * (fracG[index2]) * prob0;
bs[3] = (1.0 - gc1[index2]) * (1.0 - fracA[index2]) * prob0;
bs[4] = (1.0 - gc2[index2]) * (fracA[index2]) * prob1;
bs[5] = (gc2[index2]) * (1.0 - fracG[index2]) * prob1;
bs[6] = (gc2[index2]) * (fracG[index2]) * prob1;
bs[7] = (1.0 - gc2[index2]) * (1.0 - fracA[index2]) * prob1;
}
/* how many different rates? */
/* lnumRateCats contains a local copy of numRateCats if appropriate, else 1 */
/* lnPartitions contains a local copy of nPartitions if appropriate, else 1 */
/* the code introduced here only makes sure that the number of partitions */
/* or rate categories is set to 1 when appropriate, in case the global variables */
/* are not set to 1 when they are not "in use" */
if (!strcmp(ratesModel, "sitespec") || !strcmp(ratesModel, "ssgamma") || !strcmp(ratesModel, "ssadgamma"))
lnPartitions = nPartitions;
else
lnPartitions = 1;
if (!strcmp(ratesModel, "equal") || !strcmp(ratesModel, "sitespec"))
lnumRateCats = 1;
else
lnumRateCats = numRateCats;
nRates = lnPartitions * lnumRateCats; // number of rates needing P matrices
/* allocate memory for the calculations */
/* pL, pR and pA will contain the transition probs for Left, Right and Anc */
/* One transition probability matrix is needed for each possible rate */
# if !defined (SMART_TI_PROBS)
probs = psdmatrix (lnStates);
nPij = nRates * lnStatesSquared;
pL = (double *)malloc((size_t)(3 * nPij * sizeof(double)));
if (!pL)
{
printf ("\n ERROR: Problem allocating Pij\n");
goto error_exit;
}
pR = pL + nPij;
pA = pR + nPij;
# endif
/* allocate memory for rate and rate category frequencies */
catFreq = (double *)malloc((size_t) ((2 * lnumRateCats + lnPartitions) * sizeof(double)));
if (!catFreq)
{
printf ("\n ERROR: Problem allocating space for rate multipliers and rate category freqs.\n");
goto error_exit;
}
catRate = catFreq + lnumRateCats;
partRate = catRate + lnumRateCats;
/* allocate memory for autocorrelated gamma models */
if (!strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "ssadgamma"))
{
ratePr = (double *)malloc((size_t) (lnumRateCats * (numChars + nChar) * sizeof(double)));
if (!ratePr)
{
printf ("\n ERROR: Problem allocating ratePr and biN.\n");
goto error_exit;
}
biN = ratePr + lnumRateCats * numChars;
usedBin = (int *)malloc((size_t) (nChar * sizeof(int)));
if (!usedBin)
{
printf ("\n ERROR: Problem allocating usedBin.\n");
goto error_exit;
}
}
// set pointer to the lnSiteScaler for this tree
lnScaler = &lnSiteScaler[whichChain * 2 * numChars + whichState * numChars];
/* fill in rate categories with frequencies and rates by dividing the */
/* gamma distribution into discrete categories, if appropriate */
/* NB! this is inefficient; store values instead */
if (!strcmp(ratesModel,"gamma")|| !strcmp(ratesModel, "ssgamma"))
{
DiscreteGamma (catFreq, catRate, alpha[whichChain*2 + whichState], alpha[whichChain*2 + whichState], lnumRateCats, 0);
}
else if (!strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "ssadgamma"))
{
markovTi = psdmatrix (lnumRateCats);
AutodGamma (markovTi, catFreq, catRate, &correlation, alpha[whichChain*2 + whichState], rateCorrelation[whichChain*2 + whichState], lnumRateCats);
}
else if (!strcmp(ratesModel, "invgamma"))
{
DiscreteGamma (catFreq, catRate, alpha[whichChain*2 + whichState], alpha[whichChain*2 + whichState], lnumRateCats-1, 0);
catRate[lnumRateCats-1] = 0.0;
catFreq[lnumRateCats-1] = invP[whichChain*2 + whichState];
for (i=0; i<lnumRateCats-1; i++)
{
catRate[i] *= 1.0 / (1.0 - invP[whichChain*2 + whichState]);
catFreq[i] *= (1.0 - invP[whichChain*2 + whichState]);
}
}
else if (!strcmp(ratesModel, "invariant"))
{
catRate[0] = 0.0;
catRate[1] = 1.0 / (1.0 - invP[whichChain*2 + whichState]);
catFreq[0] = invP[whichChain*2 + whichState];
catFreq[1] = 1.0 - invP[whichChain*2 + whichState];
}
else { // "sitespec" or "equal"
catRate[0] = 1.0;
catFreq[0] = 1.0;
}
/* initialize partition rates, if appropriate */
if (lnPartitions > 1)
{
for (i=0; i<lnPartitions; i++)
partRate[i] = scaledRates[whichChain*2*lnPartitions + whichState*lnPartitions + i];
}
else
partRate[0] = 1.0;
/* allocate memory for eigenvalues and eigenvectors */
/* first for base matrix */
# if !defined (SMART_TI_PROBS)
q = psdmatrix (lnStates);
eigenValues = (double *)malloc((size_t) (2 * lnStates * sizeof(double)));
if (!eigenValues)
{
printf ("\n ERROR: Problem allocating eigenValues and eigvalsImag.\n");
goto error_exit;
}
eigvalsImag = eigenValues + lnStates;
c_ijk = (double *)malloc((size_t) (lnStatesCube * sizeof(double)));
if (!c_ijk)
{
printf ("\n ERROR: Problem allocating c_ijk.\n");
goto error_exit;
}
eigvecs = psdmatrix (lnStates);
inverseEigvecs = psdmatrix (lnStates);
Ceigvecs = pscmatrix (lnStates);
CinverseEigvecs = pscmatrix (lnStates);
/* then for partitions */
isComplex = (int *)malloc((size_t) (nRates * sizeof(int)));
if (!isComplex)
{
printf ("\n ERROR: Problem allocating isComplex.\n");
goto error_exit;
}
eigenValuesP = (double *)malloc((size_t) (2 * nRates * lnStates * sizeof(double)));
if (!eigenValuesP)
{
printf ("\n ERROR: Problem allocating eigenValuesP and eigvalsImagP.\n");
goto error_exit;
}
eigvalsImagP = eigenValuesP + nRates * lnStates;
eigvecsP = (double *)malloc((size_t) (2 * nRates * lnStatesSquared * sizeof(double)));
if (!eigvecsP)
{
printf ("\n ERROR: Problem allocating eigvecsP and inverseEigvecsP.\n");
goto error_exit;
}
inverseEigvecsP = eigvecsP + nRates * lnStatesSquared;
CeigvecsP = (complex *)malloc((size_t) (2 * nRates * lnStatesSquared * sizeof(complex)));
if (!CeigvecsP)
{
printf ("\n ERROR: Problem allocating CeigvecsP and CinverseEigvecsP.\n");
goto error_exit;
}
CinverseEigvecsP = CeigvecsP + nRates * lnStatesSquared;
c_ijkP = (double *)malloc((size_t) (nRates * lnStatesCube * sizeof(double)));
if (!c_ijkP)
{
printf ("\n ERROR: Problem allocating c_ijkP.\n");
goto error_exit;
}
/* get eigenvalues and eigenvectors for covarion matrices */
/* one matrix needed for each rate because catrates and partrates
affect only part of the matrix */
// a is index to rate eigenvectors, b is index to rates
for (m=a=b=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
if (dataType == DNA || dataType == RNA)
{
if (!strcmp(covarionModelType, "ts98"))
{
if (SetDNACovQMatrix (q, whichState, whichChain, catRate[k]*partRate[m]) == ERROR)
goto error_exit;
}
else if (!strcmp(covarionModelType, "gcswitch"))
{
if (SetGCSwitchQMatrix (q, whichState, whichChain, catRate[k]*partRate[m]) == ERROR)
goto error_exit;
}
else
{
goto error_exit;
}
}
else
{
if (SetAACovQMatrix (q, whichState, whichChain, catRate[k]*partRate[m]) == ERROR)
goto error_exit;
}
isComplex[b] = GetEigens (lnStates, q, eigenValues, eigvalsImag, eigvecs, inverseEigvecs, Ceigvecs, CinverseEigvecs);
if (isComplex[b] == NO)
{
CalcCijk (c_ijk, lnStates, eigvecs, inverseEigvecs);
}
for (i=0; i<lnStates; i++)
{
eigenValuesP[b*lnStates + i] = eigenValues[i];
eigvalsImagP[b*lnStates + i] = eigvalsImag[i];
}
for (i=0; i<lnStates; i++)
{
for (j=0; j<lnStates; j++)
{
eigvecsP[a] = eigvecs[i][j];
inverseEigvecsP[a] = inverseEigvecs[i][j];
CeigvecsP[a].re = Ceigvecs[i][j].re;
CinverseEigvecsP[a].re = CinverseEigvecs[i][j].re;
CeigvecsP[a].im = Ceigvecs[i][j].im;
CinverseEigvecsP[a].im = CinverseEigvecs[i][j].im;
a++;
}
}
for (i=0; i<lnStatesCube; i++)
c_ijkP[b*lnStatesCube + i] = c_ijk[i];
b++;
}
}
# endif
/* how large is the information for one tree and one node*/
oneMatSize = numNodes * numChars * lnumRateCats * lnStates;
oneNodeSize = numChars * lnumRateCats * lnStates;
/* calculate index offsets */
condLikeOffset = whichChain*2*oneMatSize + whichState*oneMatSize;
scalerOffset = whichChain*2*numIntNodes*numChars + whichState*numIntNodes*numChars;
intNodeOffset = whichChain*2*numIntNodes + whichState*numIntNodes;
/* pass down tree */
for (n=0; n<numIntNodes; n++)
{
p = intNodeDownPassSeq[intNodeOffset + n];
// for debugging purposes
// set all nodes to update
// p->upDateCl = YES;
clUpdateFlag[p->index] = NO;
if (p->anc->anc == NULL && treeModel == UNROOTED)
{
if (p->upDateCl == YES)
{
//printf ("visiting basal node %d\n", p->index);
/* get transition probabilities */
# if defined (SMART_TI_PROBS)
pL = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (p->left->index)*nodeTiSize);
pR = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (p->right->index)*nodeTiSize);
pA = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (p->index)*nodeTiSize);
# else
for (m=indexL=indexR=indexA=b=a=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
// fetch eigenvalues and eigenvectors for this rate
// the rate itself is not needed because it has
// been taken care of in the diagonalized matrices
for (i=0; i<lnStates; i++)
{
eigenValues[i] = eigenValuesP[b*lnStates + i];
eigvalsImag[i] = eigvalsImagP[b*lnStates + i];
}
for (i=0; i<lnStates; i++)
{
for (j=0; j<lnStates; j++)
{
eigvecs[i][j] = eigvecsP[a];
inverseEigvecs[i][j] = inverseEigvecsP[a];
Ceigvecs[i][j].re = CeigvecsP[a].re;
CinverseEigvecs[i][j].re = CinverseEigvecsP[a].re;
Ceigvecs[i][j].im = CeigvecsP[a].im;
CinverseEigvecs[i][j].im = CinverseEigvecsP[a].im;
a++;
}
}
// fetch c_ijk for this rate
for (i=0; i<lnStatesCube; i++)
c_ijk[i] = c_ijkP[b*lnStatesCube + i];
// calculate transition probabilities for left branch
if (isComplex[b] == NO)
CalcPij (c_ijk, lnStates, eigenValues, p->left->length, 1.0, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, lnStates, probs, p->left->length, 1.0) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<lnStates; i++)
for (j=0; j<lnStates; j++)
pL[indexL++] = probs[i][j];
// calculate transition probabilities for right branch
if (isComplex[b] == NO)
CalcPij (c_ijk, lnStates, eigenValues, p->right->length, 1.0, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, lnStates, probs, p->right->length, 1.0) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<lnStates; i++)
for (j=0; j<lnStates; j++)
pR[indexR++] = probs[i][j];
// calculate transition probabilities for ancestral branch
if (isComplex[b] == NO)
CalcPij (c_ijk, lnStates, eigenValues, p->length, 1.0, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, lnStates, probs, p->length, 1.0) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<lnStates; i++)
for (j=0; j<lnStates; j++)
pA[indexA++] = probs[i][j];
b++;
}
}
# endif
/* calculate conditional likelihoods */
/* first set pointers to cond likes of left, right, p and anc */
clL = &condLike[condLikeOffset + (p->left->index)*oneNodeSize];
clR = &condLike[condLikeOffset + (p->right->index)*oneNodeSize];
clA = &condLike[condLikeOffset + (p->anc->index)*oneNodeSize];
clP = &condLike[condLikeOffset + (p->index)*oneNodeSize];
/* then branch to models */
if (!strcmp(ratesModel, "equal"))
{
for (c=0; c<numChars; c++)
{
for (i=m=0; i<lnStates; i++)
{
likeL = likeR = likeA = 0.0;
for (j=0; j<lnStates; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m]*clR[j];
likeA += pA[m++]*clA[j];
}
*(clP++) = likeL * likeR * likeA;
}
clL += lnStates;
clR += lnStates;
clA += lnStates;
}
}
else if (!strcmp(ratesModel, "gamma") || !strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "invariant") || !strcmp(ratesModel, "invgamma"))
{
for (c=0; c<numChars; c++)
{
for (k=m=0; k<lnumRateCats; k++)
{
for (i=0; i<lnStates; i++)
{
likeL = likeR = likeA = 0.0;
for (j=0; j<lnStates; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m]*clR[j];
likeA += pA[m++]*clA[j];
}
*(clP++) = likeL * likeR * likeA;
}
clL += lnStates;
clR += lnStates;
clA += lnStates;
}
}
}
else if (!strcmp(ratesModel, "ssgamma") || !strcmp(ratesModel, "ssadgamma"))
{
for (c=0; c<numChars; c++)
{
m = partitionId[c]*lnumRateCats*lnStatesSquared;
for (k=0; k<lnumRateCats; k++)
{
for (i=0; i<lnStates; i++)
{
likeL = likeR = likeA = 0.0;
for (j=0; j<lnStates; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m]*clR[j];
likeA += pA[m++]*clA[j];
}
*(clP++) = likeL * likeR * likeA;
}
clL += lnStates;
clR += lnStates;
clA += lnStates;
}
}
}
else if (!strcmp(ratesModel, "sitespec"))
{
for (c=0; c<numChars; c++)
{
m = partitionId[c]*lnStatesSquared;
for (i=0; i<lnStates; i++)
{
likeL = likeR = likeA = 0.0;
for (j=0; j<lnStates; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m]*clR[j];
likeA += pA[m++]*clA[j];
}
*(clP++) = likeL * likeR * likeA;
}
clL += lnStates;
clR += lnStates;
clA += lnStates;
}
}
p->upDateCl = NO;
clUpdateFlag[p->index] = YES;
} // done if p->upDateCl == YES for internal root node
} // done with internal root node
else
{
if (p->upDateCl == YES)
{
//printf ("visiting interior node %d\n", p->index);
/* get transition probabilities */
# if defined (SMART_TI_PROBS)
pL = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (p->left->index)*nodeTiSize);
pR = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (p->right->index)*nodeTiSize);
# else
for (m=indexL=indexR=b=a=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
// fetch eigenvalues and eigenvectors for this rate
// the rate itself is not needed because it has
// been taken care of in the diagonalized matrices
for (i=0; i<lnStates; i++)
{
eigenValues[i] = eigenValuesP[b*lnStates + i];
eigvalsImag[i] = eigvalsImagP[b*lnStates + i];
}
for (i=0; i<lnStates; i++)
{
for (j=0; j<lnStates; j++)
{
eigvecs[i][j] = eigvecsP[a];
inverseEigvecs[i][j] = inverseEigvecsP[a];
Ceigvecs[i][j].re = CeigvecsP[a].re;
CinverseEigvecs[i][j].re = CinverseEigvecsP[a].re;
Ceigvecs[i][j].im = CeigvecsP[a].im;
CinverseEigvecs[i][j].im = CinverseEigvecsP[a].im;
a++;
}
}
// fetch c_ijk for this rate
for (i=0; i<lnStatesCube; i++)
c_ijk[i] = c_ijkP[b*lnStatesCube + i];
// calculate transition probabilities for left branch
if (isComplex[b] == NO)
CalcPij (c_ijk, lnStates, eigenValues, p->left->length, 1.0, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, lnStates, probs, p->left->length, 1.0) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<lnStates; i++)
for (j=0; j<lnStates; j++)
pL[indexL++] = probs[i][j];
// calculate transition probabilities for right branch
if (isComplex[b] == NO)
CalcPij (c_ijk, lnStates, eigenValues, p->right->length, 1.0, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, lnStates, probs, p->right->length, 1.0) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<lnStates; i++)
for (j=0; j<lnStates; j++)
pR[indexR++] = probs[i][j];
b++;
}
}
# endif
/* calculate conditional likelihoods */
/* first set pointers to cond likes of left, right and p */
clL = &condLike[condLikeOffset + (p->left->index)*oneNodeSize];
clR = &condLike[condLikeOffset + (p->right->index)*oneNodeSize];
clP = &condLike[condLikeOffset + (p->index)*oneNodeSize];
/* then branch to models */
if (!strcmp(ratesModel, "equal"))
{
for (c=0; c<numChars; c++)
{
for (i=m=0; i<lnStates; i++)
{
likeL = likeR = 0.0;
for (j=0; j<lnStates; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m++]*clR[j];
}
*(clP++) = likeL * likeR;
}
clL += lnStates;
clR += lnStates;
}
}
else if (!strcmp(ratesModel, "gamma") || !strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "invariant") || !strcmp(ratesModel, "invgamma"))
{
for (c=0; c<numChars; c++)
{
for (k=m=0; k<lnumRateCats; k++)
{
for (i=0; i<lnStates; i++)
{
likeL = likeR = 0.0;
for (j=0; j<lnStates; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m++]*clR[j];
}
*(clP++) = likeL * likeR;
}
clL += lnStates;
clR += lnStates;
}
}
}
else if (!strcmp(ratesModel, "ssgamma") || !strcmp(ratesModel, "ssadgamma"))
{
for (c=0; c<numChars; c++)
{
m = partitionId[c]*lnumRateCats*lnStatesSquared;
for (k=0; k<lnumRateCats; k++)
{
for (i=0; i<lnStates; i++)
{
likeL = likeR = 0.0;
for (j=0; j<lnStates; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m++]*clR[j];
}
*(clP++) = likeL * likeR;
}
clL += lnStates;
clR += lnStates;
}
}
}
else if (!strcmp(ratesModel, "sitespec"))
{
for (c=0; c<numChars; c++)
{
m = partitionId[c]*lnStatesSquared;
for (i=0; i<lnStates; i++)
{
likeL = likeR = 0.0;
for (j=0; j<lnStates; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m++]*clR[j];
}
*(clP++) = likeL * likeR;
}
clL += lnStates;
clR += lnStates;
}
}
p->upDateCl = NO;
clUpdateFlag[p->index] = YES;
} // done with interior node if p->upDateCl == YES
} // done with interior node
// deal with scaling
// first check if we need to refresh scalers and potentially shift scaler nodes
// we have to remember scalerIndex because the node may move in the tree
if (refreshScalers == YES)
{
if (n % RESCALE_FREQ == 0)
{
p->scalerNode = YES;
p->scalerIndex = n;
}
else
p->scalerNode = NO;
}
if (p->scalerNode == YES && clUpdateFlag[p->index] == YES)
{
scalerUpdateFlag[p->scalerIndex] = YES;
scP = &clScaler[scalerOffset + (p->scalerIndex)*numChars];
clP = &condLike[condLikeOffset + (p->index)*oneNodeSize];
i = j = 0;
for (c=0; c<numChars; c++)
{
scaler = 0.0;
for (k=0; k<lnumRateCats; k++)
{
for (m=0; m<lnStates; m++)
{
if (clP[i] > scaler)
scaler = clP[i];
i++;
}
}
for (k=0; k<lnumRateCats; k++)
{
for (m=0; m<lnStates; m++)
clP[j++] /= scaler;
}
lnScaler[c] -= scP[c]; //subtract old value
scP[c] = log(scaler);
lnScaler[c] += scP[c]; //add new value
}
}
} // next node
/* get likelihood at base of tree */
p = root[whichChain*2+whichState]->left;
clP = &condLike[condLikeOffset + (p->index)*oneNodeSize];
(*lnL) = 0.0; // reset lnL
if (!strcmp(ratesModel, "equal") || !strcmp(ratesModel, "sitespec"))
{
for (c=0; c<numChars; c++)
{
like = 0.0;
for (i=0; i<lnStates; i++)
like += ((*(clP++)) * bs[i]);
//printf ("%d: %1.25lf %lf %d\n", c, like, log(like), numSitesOfPat[c]);
if (like < LIKE_EPSILON) /* likelihood for a site can go to zero when */
{ /* two adjacent terminal branches have zero length. */
printf (" WARNING: In LIKE_EPSILON\n");
goto error_exit;
}
else
{
(*lnL) += (lnScaler[c] + log(like)) * numSitesOfPat[c];
}
}
}
else if (!strcmp(ratesModel, "gamma") || !strcmp(ratesModel, "invariant") || !strcmp(ratesModel, "invgamma") || !strcmp(ratesModel, "ssgamma"))
{
for (c=0; c<numChars; c++)
{
like = 0.0;
for (k=0; k<lnumRateCats; k++)
{
for (i=0; i<lnStates; i++)
like += ((*(clP++)) * bs[i]) * catFreq[k];
}
if (like < LIKE_EPSILON) /* likelihood for a site can go to zero when */
{ /* two adjacent terminal branches have zero length. */
printf (" WARNING: In LIKE_EPSILON (%d) %1.30lf\n", c, like);
goto error_exit;
}
else
{
(*lnL) += (lnScaler[c] + log(like)) * numSitesOfPat[c];
}
}
}
else if (!strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "ssadgamma"))
{
/* initialize usedBin */
for (i=0; i<nChar; i++)
usedBin[i] = NO;
lnC = 0.0;
m = j = 0;
for (c=0; c<numChars; c++)
{
for (k=0; k<lnumRateCats; k++)
{
like = 0.0;
for (i=0; i<lnStates; i++)
like += clP[j++] * bs[i];
ratePr[m++] = like;
}
lnC += (lnScaler[c] * numSitesOfPat[c]);
}
localLag = lag[whichChain*2 + whichState];
for (c=nChar-1; c>=0; c--)
{
cn = c*lnumRateCats;
if (patternId[c] >= 0)
{
pat = patternId[c];
if (c + localLag >= nChar)
{
max = 0.0;
for (k=0; k<lnumRateCats; k++)
{
biN[cn + k] = ratePr[pat*lnumRateCats + k];
if (biN[cn + k] > max)
max = biN[cn + k];
}
if (max > 0.0)
{
for (k=0; k<lnumRateCats; k++)
biN[cn + k] /= max;
lnC += log(max);
}
else
{
printf (" ERROR: Scaling factor for adgamma model is less than 0\n");
goto error_exit;
}
}
else
{
for (i=0; i<lnumRateCats; i++)
{
temp = max = 0.0;
for (j=0; j<lnumRateCats; j++)
temp += markovTi[i][j] * biN[(c+localLag)*lnumRateCats + j];
biN[cn + i] = ratePr[pat*lnumRateCats+i] * temp;
if (biN[cn + i] > max)
max = biN[cn + i];
usedBin[c+localLag] = YES;
}
if (max > 0.0)
{
for (k=0; k<lnumRateCats; k++)
biN[cn + k] /= max;
lnC += log(max);
}
else
{
printf (" ERROR: Scaling factor for adgamma model is less than 0\n");
goto error_exit;
}
}
}
else
{
printf (" ERROR: Unidentified pattern\n");
goto error_exit;
}
}
(*lnL) = lnC;
for (c=0; c<nChar; c++)
{
if (usedBin[c] == NO)
{
temp = 0.0;
for (k=0; k<lnumRateCats; k++)
{
temp += (catFreq[k] * biN[c*lnumRateCats + k]);
}
(*lnL) += log(temp);
usedBin[c] = YES;
}
}
}
/* free memory */
# if !defined (SMART_TI_PROBS)
free_psdmatrix (probs);
free (pL);
free_psdmatrix (q);
free (eigenValues);
free_psdmatrix (eigvecs);
free_psdmatrix (inverseEigvecs);
free_pscmatrix (Ceigvecs);
free_pscmatrix (CinverseEigvecs);
free (c_ijk);
free (isComplex);
free (eigenValuesP);
free (eigvecsP);
free (CeigvecsP);
free (c_ijkP);
# endif
free (catFreq);
if (!strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "ssadgamma"))
{
free_psdmatrix(markovTi);
free (ratePr);
free (usedBin);
}
return (NO_ERROR);
error_exit:
# if !defined (SMART_TI_PROBS)
free_psdmatrix (probs);
free (pL);
free_psdmatrix (q);
free (eigenValues);
free_psdmatrix (eigvecs);
free_psdmatrix (inverseEigvecs);
free_pscmatrix (Ceigvecs);
free_pscmatrix (CinverseEigvecs);
free (c_ijk);
free (isComplex);
free (eigenValuesP);
free (eigvecsP);
free (CeigvecsP);
free (c_ijkP);
# endif
free (catFreq);
if (!strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "ssadgamma"))
{
free_psdmatrix(markovTi);
free (ratePr);
free (usedBin);
}
return (ERROR);
}
/*-----------------------------------------------------------
LnLikeDNA: 'Fast' version, core written 2001-03-10--11
------------------------------------------------------------*/
int LnLikeDNA (int whichState, int whichChain, int numChars, int numRateCats, double *lnL, int refreshScalers)
{
# define N_STATES 4
# define N_STATES_SQUARED 16
# define N_STATES_CUBE 64
register int i, j, k, c, n, cn;
int lnumRateCats, lnPartitions, oneMatSize, oneNodeSize,
index, pat, localLag, *usedBin, nRates,
intNodeOffset, condLikeOffset, scalerOffset;
double bs[N_STATES], *pL, *pR, *pA, *catFreq, *catRate, *partRate,
*clL, *clR, *clA, *clP, *tiPL, *tiPR, *tiPA, *scP,
*lnScaler, scaler, like, lnC, *biN, max, temp, correlation,
*ratePr, **markovTi;
TreeNode *p;
# if defined (SMART_TI_PROBS)
int nForOneState;
# else
register int m;
int nPij, *isComplex, indexL, indexR, indexA;
double lkappa, **probs, **q, *eigenValues, *eigvalsImag, **eigvecs, **inverseEigvecs, *c_ijk, theRate;
complex **Ceigvecs, **CinverseEigvecs;
# endif
/* initialize offset for transition probabilities */
# if defined (SMART_TI_PROBS)
nForOneState = numNodes*nodeTiSize;
# endif
/* initialize intNodeOffset */
intNodeOffset = whichChain*2*numIntNodes + whichState*numIntNodes;
/* load base frequencies */
index = whichChain*2*nStates + whichState*nStates;
bs[A] = baseFreq[index + A];
bs[C] = baseFreq[index + C];
bs[G] = baseFreq[index + G];
bs[T] = baseFreq[index + T];
/* how many different rates? */
/* lnumRateCats contains a local copy of numRateCats if appropriate, else 1 */
/* lnPartitions contains a local copy of nPartitions if appropriate, else 1 */
/* the code introduced here only makes sure that the number of partitions */
/* or rate categories is set to 1 when appropriate, in case the global variables */
/* are not set to 1 when they are not "in use" */
if (!strcmp(ratesModel, "sitespec") || !strcmp(ratesModel, "ssgamma") || !strcmp(ratesModel, "ssadgamma"))
lnPartitions = nPartitions;
else
lnPartitions = 1;
if (!strcmp(ratesModel, "equal") || !strcmp(ratesModel, "sitespec"))
lnumRateCats = 1;
else
lnumRateCats = numRateCats;
nRates = lnPartitions * lnumRateCats; // number of rates needing P matrices
/* allocate memory for the calculations */
/* pL, pR and pA will contain the transition probs for Left, Right and Anc */
/* One transition probability matrix is needed for each possible rate */
# if !defined (SMART_TI_PROBS)
probs = psdmatrix (nStates);
nPij = nRates * N_STATES_SQUARED;
pL = (double *)malloc((size_t)(3 * nPij * sizeof(double)));
if (!pL)
{
printf ("\n ERROR: Problem allocating Pij\n");
goto error_exit;
}
pR = pL + nPij;
pA = pR + nPij;
# endif
/* allocate memory for rate and rate category frequencies */
catFreq = (double *)malloc((size_t) ((2 * lnumRateCats + lnPartitions) * sizeof(double)));
if (!catFreq)
{
printf ("\n ERROR: Problem allocating space for rate multipliers and rate category freqs.\n");
goto error_exit;
}
catRate = catFreq + lnumRateCats;
partRate = catRate + lnumRateCats;
/* allocate memory for autocorrelated gamma models */
if (!strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "ssadgamma"))
{
ratePr = (double *)malloc((size_t) (lnumRateCats * (numChars + nChar) * sizeof(double)));
if (!ratePr)
{
printf ("\n ERROR: Problem allocating ratePr and biN.\n");
goto error_exit;
}
biN = ratePr + lnumRateCats * numChars;
usedBin = (int *)malloc((size_t) (nChar * sizeof(int)));
if (!usedBin)
{
printf ("\n ERROR: Problem allocating usedBin.\n");
goto error_exit;
}
}
// set pointer to the lnSiteScaler for this tree
lnScaler = &lnSiteScaler[whichChain * 2 * numChars + whichState * numChars];
/* fill in rate categories with frequencies and rates by dividing the */
/* gamma distribution into discrete categories, if appropriate */
/* NB! this is inefficient; store values instead */
if (!strcmp(ratesModel,"gamma")|| !strcmp(ratesModel, "ssgamma"))
{
DiscreteGamma (catFreq, catRate, alpha[whichChain*2 + whichState], alpha[whichChain*2 + whichState], lnumRateCats, 0);
}
else if (!strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "ssadgamma"))
{
markovTi = psdmatrix (lnumRateCats);
AutodGamma (markovTi, catFreq, catRate, &correlation, alpha[whichChain*2 + whichState], rateCorrelation[whichChain*2 + whichState], lnumRateCats);
}
else if (!strcmp(ratesModel, "invgamma"))
{
DiscreteGamma (catFreq, catRate, alpha[whichChain*2 + whichState], alpha[whichChain*2 + whichState], lnumRateCats-1, 0);
catRate[lnumRateCats-1] = 0.0;
catFreq[lnumRateCats-1] = invP[whichChain*2 + whichState];
for (i=0; i<lnumRateCats-1; i++)
{
catRate[i] *= 1.0 / (1.0 - invP[whichChain*2 + whichState]);
catFreq[i] *= (1.0 - invP[whichChain*2 + whichState]);
}
}
else if (!strcmp(ratesModel, "invariant"))
{
catRate[0] = 0.0;
catRate[1] = 1.0 / (1.0 - invP[whichChain*2 + whichState]);
catFreq[0] = invP[whichChain*2 + whichState];
catFreq[1] = 1.0 - invP[whichChain*2 + whichState];
}
else { // "sitespec" or "equal"
catRate[0] = 1.0;
catFreq[0] = 1.0;
}
/* initialize partition rates, if appropriate */
if (lnPartitions > 1)
{
for (i=0; i<lnPartitions; i++)
partRate[i] = scaledRates[whichChain*2*lnPartitions + whichState*lnPartitions + i];
}
else
partRate[0] = 1.0;
# if !defined (SMART_TI_PROBS)
/* find kappa if nst == 1 or nst == 2 */
if (nst == 1)
lkappa = 1.0;
else if (nst == 2)
lkappa = kappa[whichChain*2 + whichState];
/* get eigenvalues and eigenvectors if nst=6 or nst=12 */
if (nst == 6 || nst == 12)
{
q = psdmatrix (4);
eigenValues = (double *)malloc((size_t) (2 * N_STATES * sizeof(double)));
if (!eigenValues)
{
printf ("\n ERROR: Problem allocating eigenValues and eigvalsImag.\n");
goto error_exit;
}
eigvalsImag = eigenValues + N_STATES;
eigvecs = psdmatrix (N_STATES);
inverseEigvecs = psdmatrix (N_STATES);
Ceigvecs = pscmatrix (N_STATES);
CinverseEigvecs = pscmatrix (N_STATES);
if (SetQMatrix (q, whichState, whichChain) == ERROR)
goto error_exit;
isComplex = GetEigens (N_STATES, q, eigenValues, eigvalsImag, eigvecs, inverseEigvecs, Ceigvecs, CinverseEigvecs);
if (isComplex == NO)
{
c_ijk = (double *)malloc((size_t) (N_STATES_CUBE * sizeof(double)));
if (!c_ijk)
{
printf ("\n ERROR: Problem allocating c_ijk.\n");
goto error_exit;
}
CalcCijk (c_ijk, N_STATES, eigvecs, inverseEigvecs);
}
}
# endif
/* how large is the information for one tree and one node*/
oneMatSize = numNodes * numChars * lnumRateCats * nStates;
oneNodeSize = numChars * lnumRateCats * nStates;
/* calculate indices */
condLikeOffset = whichChain*2*oneMatSize + whichState*oneMatSize;
scalerOffset = whichChain*2*numIntNodes*numChars + whichState*numIntNodes*numChars;
/* pass down tree */
for (n=0; n<numIntNodes; n++)
{
p = intNodeDownPassSeq[intNodeOffset + n];
// for debugging purposes
// set all nodes to update
// p->upDateCl = YES;
clUpdateFlag[p->index] = NO;
if (p->anc->anc == NULL && treeModel == UNROOTED)
{
if (p->upDateCl == YES)
{
//printf ("visiting basal node %d\n", p->index);
/* get transition probabilities */
# if defined (SMART_TI_PROBS)
pL = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (p->left->index)*nodeTiSize);
pR = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (p->right->index)*nodeTiSize);
pA = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (p->index)*nodeTiSize);
# else
if (nst == 1 || nst == 2)
{
for (m=indexL=indexR=indexA=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
theRate = partRate[m] * catRate[k];
/* calculate transition probabilities for left branch */
HkyChangeMat (probs, p->left->length, lkappa, theRate, bs[A], bs[C], bs[G], bs[T]);
for (i=0; i<4; i++)
for (j=0; j<4; j++)
pL[indexL++] = probs[i][j];
/* calculate transition probabilities for right branch */
HkyChangeMat (probs, p->right->length, lkappa, theRate, bs[A], bs[C], bs[G], bs[T]);
for (i=0; i<4; i++)
for (j=0; j<4; j++)
pR[indexR++] = probs[i][j];
/* calculate transition probabilities for ancestral branch */
HkyChangeMat (probs, p->length, lkappa, theRate, bs[A], bs[C], bs[G], bs[T]);
for (i=0; i<4; i++)
for (j=0; j<4; j++)
pA[indexA++] = probs[i][j];
}
}
}
else // nst == 6 or nst == 12
{
for (m=indexL=indexR=indexA=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
theRate = partRate[m] * catRate[k];
// calculate transition probabilities for left branch
if (isComplex == NO)
CalcPij (c_ijk, 4, eigenValues, p->left->length, theRate, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, 4, probs, p->left->length, theRate) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<4; i++)
for (j=0; j<4; j++)
pL[indexL++] = probs[i][j];
// calculate transition probabilities for right branch
if (isComplex == NO)
CalcPij (c_ijk, 4, eigenValues, p->right->length, theRate, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, 4, probs, p->right->length, theRate) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<4; i++)
for (j=0; j<4; j++)
pR[indexR++] = probs[i][j];
// calculate transition probabilities for ancestral branch
if (isComplex == NO)
CalcPij (c_ijk, 4, eigenValues, p->length, theRate, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, 4, probs, p->length, theRate) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<4; i++)
for (j=0; j<4; j++)
pA[indexA++] = probs[i][j];
}
}
}
# endif
/* calculate conditional likelihoods */
/* first set pointers to cond likes of left, right, p and anc */
clL = &condLike[condLikeOffset + (p->left->index)*oneNodeSize];
clR = &condLike[condLikeOffset + (p->right->index)*oneNodeSize];
clA = &condLike[condLikeOffset + (p->anc->index)*oneNodeSize];
clP = &condLike[condLikeOffset + (p->index)*oneNodeSize];
if (!strcmp(ratesModel, "equal"))
{
tiPL = pL;
tiPR = pR;
tiPA = pA;
for (c=0; c<numChars; c++)
{
clP[A] = (tiPL[AA]*clL[A] + tiPL[AC]*clL[C] + tiPL[AG]*clL[G] + tiPL[AT]*clL[T])
*(tiPR[AA]*clR[A] + tiPR[AC]*clR[C] + tiPR[AG]*clR[G] + tiPR[AT]*clR[T])
*(tiPA[AA]*clA[A] + tiPA[AC]*clA[C] + tiPA[AG]*clA[G] + tiPA[AT]*clA[T]);
clP[C] = (tiPL[CA]*clL[A] + tiPL[CC]*clL[C] + tiPL[CG]*clL[G] + tiPL[CT]*clL[T])
*(tiPR[CA]*clR[A] + tiPR[CC]*clR[C] + tiPR[CG]*clR[G] + tiPR[CT]*clR[T])
*(tiPA[CA]*clA[A] + tiPA[CC]*clA[C] + tiPA[CG]*clA[G] + tiPA[CT]*clA[T]);
clP[G] = (tiPL[GA]*clL[A] + tiPL[GC]*clL[C] + tiPL[GG]*clL[G] + tiPL[GT]*clL[T])
*(tiPR[GA]*clR[A] + tiPR[GC]*clR[C] + tiPR[GG]*clR[G] + tiPR[GT]*clR[T])
*(tiPA[GA]*clA[A] + tiPA[GC]*clA[C] + tiPA[GG]*clA[G] + tiPA[GT]*clA[T]);
clP[T] = (tiPL[TA]*clL[A] + tiPL[TC]*clL[C] + tiPL[TG]*clL[G] + tiPL[TT]*clL[T])
*(tiPR[TA]*clR[A] + tiPR[TC]*clR[C] + tiPR[TG]*clR[G] + tiPR[TT]*clR[T])
*(tiPA[TA]*clA[A] + tiPA[TC]*clA[C] + tiPA[TG]*clA[G] + tiPA[TT]*clA[T]);
clP += 4;
clL += 4;
clR += 4;
clA += 4;
}
}
else if (!strcmp(ratesModel, "gamma") || !strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "invariant") || !strcmp(ratesModel, "invgamma"))
{
for (c=0; c<numChars; c++)
{
tiPL = pL;
tiPR = pR;
tiPA = pA;
for (k=0; k<lnumRateCats; k++)
{
clP[A] = (tiPL[AA]*clL[A] + tiPL[AC]*clL[C] + tiPL[AG]*clL[G] + tiPL[AT]*clL[T])
*(tiPR[AA]*clR[A] + tiPR[AC]*clR[C] + tiPR[AG]*clR[G] + tiPR[AT]*clR[T])
*(tiPA[AA]*clA[A] + tiPA[AC]*clA[C] + tiPA[AG]*clA[G] + tiPA[AT]*clA[T]);
clP[C] = (tiPL[CA]*clL[A] + tiPL[CC]*clL[C] + tiPL[CG]*clL[G] + tiPL[CT]*clL[T])
*(tiPR[CA]*clR[A] + tiPR[CC]*clR[C] + tiPR[CG]*clR[G] + tiPR[CT]*clR[T])
*(tiPA[CA]*clA[A] + tiPA[CC]*clA[C] + tiPA[CG]*clA[G] + tiPA[CT]*clA[T]);
clP[G] = (tiPL[GA]*clL[A] + tiPL[GC]*clL[C] + tiPL[GG]*clL[G] + tiPL[GT]*clL[T])
*(tiPR[GA]*clR[A] + tiPR[GC]*clR[C] + tiPR[GG]*clR[G] + tiPR[GT]*clR[T])
*(tiPA[GA]*clA[A] + tiPA[GC]*clA[C] + tiPA[GG]*clA[G] + tiPA[GT]*clA[T]);
clP[T] = (tiPL[TA]*clL[A] + tiPL[TC]*clL[C] + tiPL[TG]*clL[G] + tiPL[TT]*clL[T])
*(tiPR[TA]*clR[A] + tiPR[TC]*clR[C] + tiPR[TG]*clR[G] + tiPR[TT]*clR[T])
*(tiPA[TA]*clA[A] + tiPA[TC]*clA[C] + tiPA[TG]*clA[G] + tiPA[TT]*clA[T]);
clP += 4;
clL += 4;
clR += 4;
clA += 4;
tiPL += 16;
tiPR += 16;
tiPA += 16;
}
}
}
else if (!strcmp(ratesModel, "ssgamma") || !strcmp(ratesModel, "ssadgamma"))
{
for (c=0; c<numChars; c++)
{
index = partitionId[c]*lnumRateCats*N_STATES_SQUARED;
tiPL = &pL[index];
tiPR = &pR[index];
tiPA = &pA[index];
for (k=0; k<lnumRateCats; k++)
{
clP[A] = (tiPL[AA]*clL[A] + tiPL[AC]*clL[C] + tiPL[AG]*clL[G] + tiPL[AT]*clL[T])
*(tiPR[AA]*clR[A] + tiPR[AC]*clR[C] + tiPR[AG]*clR[G] + tiPR[AT]*clR[T])
*(tiPA[AA]*clA[A] + tiPA[AC]*clA[C] + tiPA[AG]*clA[G] + tiPA[AT]*clA[T]);
clP[C] = (tiPL[CA]*clL[A] + tiPL[CC]*clL[C] + tiPL[CG]*clL[G] + tiPL[CT]*clL[T])
*(tiPR[CA]*clR[A] + tiPR[CC]*clR[C] + tiPR[CG]*clR[G] + tiPR[CT]*clR[T])
*(tiPA[CA]*clA[A] + tiPA[CC]*clA[C] + tiPA[CG]*clA[G] + tiPA[CT]*clA[T]);
clP[G] = (tiPL[GA]*clL[A] + tiPL[GC]*clL[C] + tiPL[GG]*clL[G] + tiPL[GT]*clL[T])
*(tiPR[GA]*clR[A] + tiPR[GC]*clR[C] + tiPR[GG]*clR[G] + tiPR[GT]*clR[T])
*(tiPA[GA]*clA[A] + tiPA[GC]*clA[C] + tiPA[GG]*clA[G] + tiPA[GT]*clA[T]);
clP[T] = (tiPL[TA]*clL[A] + tiPL[TC]*clL[C] + tiPL[TG]*clL[G] + tiPL[TT]*clL[T])
*(tiPR[TA]*clR[A] + tiPR[TC]*clR[C] + tiPR[TG]*clR[G] + tiPR[TT]*clR[T])
*(tiPA[TA]*clA[A] + tiPA[TC]*clA[C] + tiPA[TG]*clA[G] + tiPA[TT]*clA[T]);
clP += 4;
clL += 4;
clR += 4;
clA += 4;
tiPL += 16;
tiPR += 16;
tiPA += 16;
}
}
}
else if (!strcmp(ratesModel, "sitespec"))
{
for (c=0; c<numChars; c++)
{
index = partitionId[c]*N_STATES_SQUARED;
tiPL = &pL[index];
tiPR = &pR[index];
tiPA = &pA[index];
clP[A] = (tiPL[AA]*clL[A] + tiPL[AC]*clL[C] + tiPL[AG]*clL[G] + tiPL[AT]*clL[T])
*(tiPR[AA]*clR[A] + tiPR[AC]*clR[C] + tiPR[AG]*clR[G] + tiPR[AT]*clR[T])
*(tiPA[AA]*clA[A] + tiPA[AC]*clA[C] + tiPA[AG]*clA[G] + tiPA[AT]*clA[T]);
clP[C] = (tiPL[CA]*clL[A] + tiPL[CC]*clL[C] + tiPL[CG]*clL[G] + tiPL[CT]*clL[T])
*(tiPR[CA]*clR[A] + tiPR[CC]*clR[C] + tiPR[CG]*clR[G] + tiPR[CT]*clR[T])
*(tiPA[CA]*clA[A] + tiPA[CC]*clA[C] + tiPA[CG]*clA[G] + tiPA[CT]*clA[T]);
clP[G] = (tiPL[GA]*clL[A] + tiPL[GC]*clL[C] + tiPL[GG]*clL[G] + tiPL[GT]*clL[T])
*(tiPR[GA]*clR[A] + tiPR[GC]*clR[C] + tiPR[GG]*clR[G] + tiPR[GT]*clR[T])
*(tiPA[GA]*clA[A] + tiPA[GC]*clA[C] + tiPA[GG]*clA[G] + tiPA[GT]*clA[T]);
clP[T] = (tiPL[TA]*clL[A] + tiPL[TC]*clL[C] + tiPL[TG]*clL[G] + tiPL[TT]*clL[T])
*(tiPR[TA]*clR[A] + tiPR[TC]*clR[C] + tiPR[TG]*clR[G] + tiPR[TT]*clR[T])
*(tiPA[TA]*clA[A] + tiPA[TC]*clA[C] + tiPA[TG]*clA[G] + tiPA[TT]*clA[T]);
clP += 4;
clL += 4;
clR += 4;
clA += 4;
}
}
p->upDateCl = NO;
clUpdateFlag[p->index] = YES;
} // done if p->upDateCl == YES for internal root node
} // done with internal root node
else
{
if (p->upDateCl == YES)
{
//printf ("visiting interior node %d\n", p->index);
/* get transition probabilities */
# if defined (SMART_TI_PROBS)
pL = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (p->left->index)*nodeTiSize);
pR = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (p->right->index)*nodeTiSize);
# else
if (nst == 1 || nst == 2)
{
for (m=indexL=indexR=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
theRate = partRate[m] * catRate[k];
/* calculate transition probabilities for left branch */
HkyChangeMat (probs, p->left->length, lkappa, theRate, bs[A], bs[C], bs[G], bs[T]);
for (i=0; i<4; i++)
for (j=0; j<4; j++)
pL[indexL++] = probs[i][j];
/* calculate transition probabilities for right branch */
HkyChangeMat (probs, p->right->length, lkappa, theRate, bs[A], bs[C], bs[G], bs[T]);
for (i=0; i<4; i++)
for (j=0; j<4; j++)
pR[indexR++] = probs[i][j];
}
}
}
else // nst == 6 or nst == 12
{
for (m=indexL=indexR=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
theRate = partRate[m] * catRate[k];
// calculate transition probabilities for left branch
if (isComplex == NO)
CalcPij (c_ijk, 4, eigenValues, p->left->length, theRate, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, 4, probs, p->left->length, theRate) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<4; i++)
for (j=0; j<4; j++)
pL[indexL++] = probs[i][j];
// calculate transition probabilities for right branch
if (isComplex == NO)
CalcPij (c_ijk, 4, eigenValues, p->right->length, theRate, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, 4, probs, p->right->length, theRate) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<4; i++)
for (j=0; j<4; j++)
pR[indexR++] = probs[i][j];
}
}
}
# endif
/* calculate conditional likelihoods */
/* first set pointers to cond likes of left, right and p */
clL = &condLike[condLikeOffset + (p->left->index)*oneNodeSize];
clR = &condLike[condLikeOffset + (p->right->index)*oneNodeSize];
clP = &condLike[condLikeOffset + (p->index)*oneNodeSize];
if (!strcmp(ratesModel, "equal"))
{
tiPL = pL;
tiPR = pR;
for (c=0; c<numChars; c++)
{
clP[A] = (tiPL[AA]*clL[A] + tiPL[AC]*clL[C] + tiPL[AG]*clL[G] + tiPL[AT]*clL[T])
*(tiPR[AA]*clR[A] + tiPR[AC]*clR[C] + tiPR[AG]*clR[G] + tiPR[AT]*clR[T]);
clP[C] = (tiPL[CA]*clL[A] + tiPL[CC]*clL[C] + tiPL[CG]*clL[G] + tiPL[CT]*clL[T])
*(tiPR[CA]*clR[A] + tiPR[CC]*clR[C] + tiPR[CG]*clR[G] + tiPR[CT]*clR[T]);
clP[G] = (tiPL[GA]*clL[A] + tiPL[GC]*clL[C] + tiPL[GG]*clL[G] + tiPL[GT]*clL[T])
*(tiPR[GA]*clR[A] + tiPR[GC]*clR[C] + tiPR[GG]*clR[G] + tiPR[GT]*clR[T]);
clP[T] = (tiPL[TA]*clL[A] + tiPL[TC]*clL[C] + tiPL[TG]*clL[G] + tiPL[TT]*clL[T])
*(tiPR[TA]*clR[A] + tiPR[TC]*clR[C] + tiPR[TG]*clR[G] + tiPR[TT]*clR[T]);
clP += 4;
clL += 4;
clR += 4;
}
}
else if (!strcmp(ratesModel, "gamma") || !strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "invariant") || !strcmp(ratesModel, "invgamma"))
{
for (c=0; c<numChars; c++)
{
tiPL = pL;
tiPR = pR;
for (k=0; k<lnumRateCats; k++)
{
clP[A] = (tiPL[AA]*clL[A] + tiPL[AC]*clL[C] + tiPL[AG]*clL[G] + tiPL[AT]*clL[T])
*(tiPR[AA]*clR[A] + tiPR[AC]*clR[C] + tiPR[AG]*clR[G] + tiPR[AT]*clR[T]);
clP[C] = (tiPL[CA]*clL[A] + tiPL[CC]*clL[C] + tiPL[CG]*clL[G] + tiPL[CT]*clL[T])
*(tiPR[CA]*clR[A] + tiPR[CC]*clR[C] + tiPR[CG]*clR[G] + tiPR[CT]*clR[T]);
clP[G] = (tiPL[GA]*clL[A] + tiPL[GC]*clL[C] + tiPL[GG]*clL[G] + tiPL[GT]*clL[T])
*(tiPR[GA]*clR[A] + tiPR[GC]*clR[C] + tiPR[GG]*clR[G] + tiPR[GT]*clR[T]);
clP[T] = (tiPL[TA]*clL[A] + tiPL[TC]*clL[C] + tiPL[TG]*clL[G] + tiPL[TT]*clL[T])
*(tiPR[TA]*clR[A] + tiPR[TC]*clR[C] + tiPR[TG]*clR[G] + tiPR[TT]*clR[T]);
clP += 4;
clL += 4;
clR += 4;
tiPL += 16;
tiPR += 16;
}
}
}
else if (!strcmp(ratesModel, "ssgamma") || !strcmp(ratesModel, "ssadgamma"))
{
for (c=0; c<numChars; c++)
{
index = partitionId[c]*lnumRateCats*N_STATES_SQUARED;
tiPL = &pL[index];
tiPR = &pR[index];
for (k=0; k<lnumRateCats; k++)
{
clP[A] = (tiPL[AA]*clL[A] + tiPL[AC]*clL[C] + tiPL[AG]*clL[G] + tiPL[AT]*clL[T])
*(tiPR[AA]*clR[A] + tiPR[AC]*clR[C] + tiPR[AG]*clR[G] + tiPR[AT]*clR[T]);
clP[C] = (tiPL[CA]*clL[A] + tiPL[CC]*clL[C] + tiPL[CG]*clL[G] + tiPL[CT]*clL[T])
*(tiPR[CA]*clR[A] + tiPR[CC]*clR[C] + tiPR[CG]*clR[G] + tiPR[CT]*clR[T]);
clP[G] = (tiPL[GA]*clL[A] + tiPL[GC]*clL[C] + tiPL[GG]*clL[G] + tiPL[GT]*clL[T])
*(tiPR[GA]*clR[A] + tiPR[GC]*clR[C] + tiPR[GG]*clR[G] + tiPR[GT]*clR[T]);
clP[T] = (tiPL[TA]*clL[A] + tiPL[TC]*clL[C] + tiPL[TG]*clL[G] + tiPL[TT]*clL[T])
*(tiPR[TA]*clR[A] + tiPR[TC]*clR[C] + tiPR[TG]*clR[G] + tiPR[TT]*clR[T]);
clP += 4;
clL += 4;
clR += 4;
tiPL += 16;
tiPR += 16;
}
}
}
else if (!strcmp(ratesModel, "sitespec"))
{
for (c=0; c<numChars; c++)
{
index = partitionId[c]*N_STATES_SQUARED;
tiPL = &pL[index];
tiPR = &pR[index];
clP[A] = (tiPL[AA]*clL[A] + tiPL[AC]*clL[C] + tiPL[AG]*clL[G] + tiPL[AT]*clL[T])
*(tiPR[AA]*clR[A] + tiPR[AC]*clR[C] + tiPR[AG]*clR[G] + tiPR[AT]*clR[T]);
clP[C] = (tiPL[CA]*clL[A] + tiPL[CC]*clL[C] + tiPL[CG]*clL[G] + tiPL[CT]*clL[T])
*(tiPR[CA]*clR[A] + tiPR[CC]*clR[C] + tiPR[CG]*clR[G] + tiPR[CT]*clR[T]);
clP[G] = (tiPL[GA]*clL[A] + tiPL[GC]*clL[C] + tiPL[GG]*clL[G] + tiPL[GT]*clL[T])
*(tiPR[GA]*clR[A] + tiPR[GC]*clR[C] + tiPR[GG]*clR[G] + tiPR[GT]*clR[T]);
clP[T] = (tiPL[TA]*clL[A] + tiPL[TC]*clL[C] + tiPL[TG]*clL[G] + tiPL[TT]*clL[T])
*(tiPR[TA]*clR[A] + tiPR[TC]*clR[C] + tiPR[TG]*clR[G] + tiPR[TT]*clR[T]);
clP += 4;
clL += 4;
clR += 4;
}
}
p->upDateCl = NO;
clUpdateFlag[p->index] = YES;
} // done with interior node if p->upDateCl == YES
} // done with interior node
// deal with scaling
// first check if we need to refresh scalers and potentially shift scaler nodes
// we have to remember scalerIndex because the node may move in the tree
if (refreshScalers == YES)
{
if (n % RESCALE_FREQ == 0)
{
p->scalerNode = YES;
p->scalerIndex = n;
}
else
p->scalerNode = NO;
}
if (p->scalerNode == YES && clUpdateFlag[p->index] == YES)
{
scalerUpdateFlag[p->scalerIndex] = YES;
scP = &clScaler[scalerOffset + (p->scalerIndex)*numChars];
clP = &condLike[condLikeOffset + (p->index)*oneNodeSize];
i = j = 0;
if (lnumRateCats > 1)
{
for (c=0; c<numChars; c++)
{
scaler = 0.0;
for (k=0; k<lnumRateCats; k++)
{
if (clP[i] > scaler)
scaler = clP[i];
i++;
if (clP[i] > scaler)
scaler = clP[i];
i++;
if (clP[i] > scaler)
scaler = clP[i];
i++;
if (clP[i] > scaler)
scaler = clP[i];
i++;
}
for (k=0; k<lnumRateCats; k++)
{
clP[j++] /= scaler;
clP[j++] /= scaler;
clP[j++] /= scaler;
clP[j++] /= scaler;
}
lnScaler[c] -= scP[c]; //subtract old value
scP[c] = log(scaler);
lnScaler[c] += scP[c]; //add new value
}
}
else // lnumRateCats == 1
{
for (c=0; c<numChars; c++)
{
scaler = clP[i++];
if (clP[i] > scaler)
scaler = clP[i];
i++;
if (clP[i] > scaler)
scaler = clP[i];
i++;
if (clP[i] > scaler)
scaler = clP[i];
i++;
clP[j++] /= scaler;
clP[j++] /= scaler;
clP[j++] /= scaler;
clP[j++] /= scaler;
lnScaler[c] -= scP[c]; //subtract old value
scP[c] = log(scaler);
lnScaler[c] += scP[c]; //add new value
}
}
}
} // next node
/* get likelihood at base of tree */
p = root[whichChain*2+whichState]->left;
clP = &condLike[condLikeOffset + (p->index)*oneNodeSize];
(*lnL) = 0.0; // reset lnL
if (!strcmp(ratesModel, "equal") || !strcmp(ratesModel, "sitespec"))
{
for (c=0; c<numChars; c++)
{
like = clP[A] * bs[A] + clP[C] * bs[C] + clP[G] * bs[G] + clP[T] * bs[T];
clP += 4;
//printf ("%d: %1.25lf %lf %d\n", c, like, log(like), numSitesOfPat[c]);
if (like < LIKE_EPSILON) /* likelihood for a site can go to zero when */
{ /* two adjacent terminal branches have zero length. */
printf (" WARNING: In LIKE_EPSILON\n");
goto error_exit;
}
else
{
(*lnL) += (lnScaler[c] + log(like)) * numSitesOfPat[c];
}
}
}
else if (!strcmp(ratesModel, "gamma") || !strcmp(ratesModel, "invariant") || !strcmp(ratesModel, "invgamma") || !strcmp(ratesModel, "ssgamma"))
{
for (c=0; c<numChars; c++)
{
like = 0.0;
for (k=0; k<lnumRateCats; k++)
{
like += (clP[A] * bs[A] + clP[C] * bs[C] + clP[G] * bs[G] + clP[T] * bs[T]) * catFreq[k];
clP += 4;
}
if (like < LIKE_EPSILON) /* likelihood for a site can go to zero when */
{ /* two adjacent terminal branches have zero length. */
printf (" WARNING: In LIKE_EPSILON (%d) %1.30lf\n", c, like);
goto error_exit;
}
else
{
(*lnL) += (lnScaler[c] + log(like)) * numSitesOfPat[c];
}
}
}
else if (!strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "ssadgamma"))
{
/* initialize usedBin */
for (i=0; i<nChar; i++)
usedBin[i] = NO;
lnC = 0.0;
i = 0;
for (c=0; c<numChars; c++)
{
for (k=0; k<lnumRateCats; k++)
{
ratePr[i++] = (clP[A] * bs[A] + clP[C] * bs[C] + clP[G] * bs[G] + clP[T] * bs[T]);
clP += 4;
}
lnC += (lnScaler[c] * numSitesOfPat[c]);
}
localLag = lag[whichChain*2 + whichState];
for (c=nChar-1; c>=0; c--)
{
cn = c*lnumRateCats;
if (patternId[c] >= 0)
{
pat = patternId[c];
if (c + localLag >= nChar)
{
max = 0.0;
for (k=0; k<lnumRateCats; k++)
{
biN[cn + k] = ratePr[pat*lnumRateCats + k];
if (biN[cn + k] > max)
max = biN[cn + k];
}
if (max > 0.0)
{
for (k=0; k<lnumRateCats; k++)
biN[cn + k] /= max;
lnC += log(max);
}
else
{
printf (" ERROR: Scaling factor for adgamma model is less than 0\n");
goto error_exit;
}
}
else
{
for (i=0; i<lnumRateCats; i++)
{
temp = max = 0.0;
for (j=0; j<lnumRateCats; j++)
temp += markovTi[i][j] * biN[(c+localLag)*lnumRateCats + j];
biN[cn + i] = ratePr[pat*lnumRateCats+i] * temp;
if (biN[cn + i] > max)
max = biN[cn + i];
usedBin[c+localLag] = YES;
}
if (max > 0.0)
{
for (k=0; k<lnumRateCats; k++)
biN[cn + k] /= max;
lnC += log(max);
}
else
{
printf (" ERROR: Scaling factor for adgamma model is less than 0\n");
goto error_exit;
}
}
}
else
{
printf (" ERROR: Unidentified pattern\n");
goto error_exit;
}
}
(*lnL) = lnC;
for (c=0; c<nChar; c++)
{
if (usedBin[c] == NO)
{
temp = 0.0;
for (k=0; k<lnumRateCats; k++)
{
temp += (catFreq[k] * biN[c*lnumRateCats + k]);
}
(*lnL) += log(temp);
usedBin[c] = YES;
}
}
}
/* free memory */
# if !defined (SMART_TI_PROBS)
free_psdmatrix (probs);
free (pL);
if (nst == 6 || nst == 12)
{
free_psdmatrix (q);
free (eigenValues);
free_psdmatrix (eigvecs);
free_psdmatrix (inverseEigvecs);
free_pscmatrix (Ceigvecs);
free_pscmatrix (CinverseEigvecs);
if (isComplex != YES)
free (c_ijk);
}
# endif
free (catFreq);
if (!strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "ssadgamma"))
{
free_psdmatrix(markovTi);
free (ratePr);
free (usedBin);
}
return (NO_ERROR);
error_exit:
# if !defined (SMART_TI_PROBS)
free_psdmatrix (probs);
free (pL);
if (nst == 6 || nst == 12)
{
free_psdmatrix (q);
free (eigenValues);
free_psdmatrix (eigvecs);
free_psdmatrix (inverseEigvecs);
free_pscmatrix (Ceigvecs);
free_pscmatrix (CinverseEigvecs);
if (isComplex != YES)
free (c_ijk);
}
# endif
free (catFreq);
if (!strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "ssadgamma"))
{
free_psdmatrix(markovTi);
free (ratePr);
free (usedBin);
}
return (ERROR);
# undef N_STATES
# undef N_STATES_SQUARED
# undef N_STATES_CUBE
}
#else
// SUPER_FAST versions of the above functions
/*-----------------------------------------------------------
LnLikeDNA: 'Superfast' version - improves the speed of expensive
moves by using local compression on terminal branches
------------------------------------------------------------*/
int LnLikeDNA (int whichState, int whichChain, int numChars, int numRateCats, double *lnL, int refreshScalers)
{
#define N_STATES 4
#define N_STATES_SQUARED 16
#define N_STATES_CUBE 64
register int h, i, j, k, c, n, m, cn;
int lnumRateCats, lnPartitions, oneMatSize, oneNodeSize,
index, nRates, pat, localLag, *usedBin,
intNodeOffset, condLikeOffset, scalerOffset;
double bs[N_STATES], *pL, *pR, *pA, *catFreq, *catRate, *partRate,
*clL, *clR, *clA, *clP, *tiPL, *tiPR, *tiPA, *scP,
*lnScaler, scaler, like, lnC, *biN, max, temp, correlation,
*ratePr, **markovTi, *likeL, *likeR, *likeA;
int shortCut, indexMultiplier1, indexMultiplier2,
*lState, *rState, *aState;
TreeNode *p;
# if defined (SMART_TI_PROBS)
int nForOneState;
# else
int nPij, isComplex, indexL, indexR, indexA;
double lkappa, theRate, **probs, **q, *eigenValues, *eigvalsImag, **eigvecs, **inverseEigvecs, *c_ijk;
complex **Ceigvecs, **CinverseEigvecs;
# endif
/* initialize offset for transition probabilities */
# if defined (SMART_TI_PROBS)
nForOneState = numNodes*nodeTiSize;
# endif
/* initialize intNodeOffset */
intNodeOffset = whichChain*2*numIntNodes + whichState*numIntNodes;
/* load base frequencies */
index = whichChain*2*nStates + whichState*nStates;
bs[A] = baseFreq[index + A];
bs[C] = baseFreq[index + C];
bs[G] = baseFreq[index + G];
bs[T] = baseFreq[index + T];
/* how many different rates? */
/* lnumRateCats contains a local copy of numRateCats if appropriate, else 1 */
/* lnPartitions contains a local copy of nPartitions if appropriate, else 1 */
/* the code introduced here only makes sure that the number of partitions */
/* or rate categories is set to 1 when appropriate, in case the global variables */
/* are not set to 1 when they are not "in use" */
if (!strcmp(ratesModel, "sitespec") || !strcmp(ratesModel, "ssgamma") || !strcmp(ratesModel, "ssadgamma"))
lnPartitions = nPartitions;
else
lnPartitions = 1;
if (!strcmp(ratesModel, "equal") || !strcmp(ratesModel, "sitespec"))
lnumRateCats = 1;
else
lnumRateCats = numRateCats;
nRates = lnPartitions * lnumRateCats; // number of rates needing P matrices
/* allocate memory for the calculations */
/* pL, pR and pA will contain the transition probs for Left, Right and Anc */
/* One transition probability matrix is needed for each possible rate */
# if !defined (SMART_TI_PROBS)
probs = psdmatrix (nStates);
nPij = nRates * N_STATES_SQUARED;
pL = (double *)malloc((size_t)(3 * nPij * sizeof(double)));
if (!pL)
{
printf ("\n ERROR: Problem allocating pL, pR and pA\n");
goto error_exit;
}
pR = pL + nPij;
pA = pR + nPij;
# endif
/* likeL, likeR and likeA will contain the cond likelihoods for Left, Right and Anc */
/* if any of them is a terminal with states A C G T or ambiguous/gap */
likeL = (double *)malloc((size_t)(3 * nRates * 20 * sizeof(double)));
if (!likeL)
{
printf ("\n ERROR: Problem allocating likeL, likeR and likeA\n");
goto error_exit;
}
likeR = likeL + nRates * 20;
likeA = likeR + nRates * 20;
/* allocate memory for rate and rate category frequencies */
catFreq = (double *)malloc((size_t) ((2 * lnumRateCats + lnPartitions) * sizeof(double)));
if (!catFreq)
{
printf ("\n ERROR: Problem allocating space for rate multipliers and rate category freqs.\n");
goto error_exit;
}
catRate = catFreq + lnumRateCats;
partRate = catRate + lnumRateCats;
/* allocate memory for autocorrelated gamma models */
if (!strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "ssadgamma"))
{
ratePr = (double *)malloc((size_t) (lnumRateCats * (numChars + nChar) * sizeof(double)));
if (!ratePr)
{
printf ("\n ERROR: Problem allocating ratePr and biN.\n");
goto error_exit;
}
biN = ratePr + lnumRateCats * numChars;
usedBin = (int *)malloc((size_t) (nChar * sizeof(int)));
if (!usedBin)
{
printf ("\n ERROR: Problem allocating usedBin.\n");
goto error_exit;
}
}
// set pointer to the lnSiteScaler for this tree
lnScaler = &lnSiteScaler[whichChain * 2 * numChars + whichState * numChars];
/* fill in rate categories with frequencies and rates by dividing the */
/* gamma distribution into discrete categories, if appropriate */
/* NB! this is inefficient; store values instead */
if (!strcmp(ratesModel,"gamma")|| !strcmp(ratesModel, "ssgamma"))
{
DiscreteGamma (catFreq, catRate, alpha[whichChain*2 + whichState], alpha[whichChain*2 + whichState], lnumRateCats, 0);
}
else if (!strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "ssadgamma"))
{
markovTi = psdmatrix (lnumRateCats);
AutodGamma (markovTi, catFreq, catRate, &correlation, alpha[whichChain*2 + whichState], rateCorrelation[whichChain*2 + whichState], lnumRateCats);
}
else if (!strcmp(ratesModel, "invgamma"))
{
DiscreteGamma (catFreq, catRate, alpha[whichChain*2 + whichState], alpha[whichChain*2 + whichState], lnumRateCats-1, 0);
catRate[lnumRateCats-1] = 0.0;
catFreq[lnumRateCats-1] = invP[whichChain*2 + whichState];
for (i=0; i<lnumRateCats-1; i++)
{
catRate[i] *= 1.0 / (1.0 - invP[whichChain*2 + whichState]);
catFreq[i] *= (1.0 - invP[whichChain*2 + whichState]);
}
}
else if (!strcmp(ratesModel, "invariant"))
{
catRate[0] = 0.0;
catRate[1] = 1.0 / (1.0 - invP[whichChain*2 + whichState]);
catFreq[0] = invP[whichChain*2 + whichState];
catFreq[1] = 1.0 - invP[whichChain*2 + whichState];
}
else { // "sitespec" or "equal"
catRate[0] = 1.0;
catFreq[0] = 1.0;
}
/* initialize partition rates, if appropriate */
if (lnPartitions > 1)
{
for (i=0; i<lnPartitions; i++)
partRate[i] = scaledRates[whichChain*2*lnPartitions + whichState*lnPartitions + i];
}
else
partRate[0] = 1.0;
/* find kappa if nst == 1 or nst == 2 */
# if !defined (SMART_TI_PROBS)
if (nst == 1)
lkappa = 1.0;
else if (nst == 2)
lkappa = kappa[whichChain*2 + whichState];
/* get eigenvalues and eigenvectors if nst=6 or nst=12 */
if (nst == 6 || nst == 12)
{
q = psdmatrix (N_STATES);
eigenValues = (double *)malloc((size_t) (2 * N_STATES * sizeof(double)));
if (!eigenValues)
{
printf ("\n ERROR: Problem allocating eigenValues and eigvalsImag.\n");
goto error_exit;
}
eigvalsImag = eigenValues + N_STATES;
eigvecs = psdmatrix (N_STATES);
inverseEigvecs = psdmatrix (N_STATES);
Ceigvecs = pscmatrix (N_STATES);
CinverseEigvecs = pscmatrix (N_STATES);
if (SetQMatrix (q, whichState, whichChain) == ERROR)
goto error_exit;
isComplex = GetEigens (N_STATES, q, eigenValues, eigvalsImag, eigvecs, inverseEigvecs, Ceigvecs, CinverseEigvecs);
if (isComplex == NO)
{
c_ijk = (double *)malloc((size_t) (N_STATES_CUBE * sizeof(double)));
if (!c_ijk)
{
printf ("\n ERROR: Problem allocating c_ijk.\n");
goto error_exit;
}
CalcCijk (c_ijk, N_STATES, eigvecs, inverseEigvecs);
}
}
# endif
/* how large is the information for one tree and one node*/
oneMatSize = numNodes * numChars * lnumRateCats * nStates;
oneNodeSize = numChars * lnumRateCats * nStates;
/* calculate indices */
condLikeOffset = whichChain*2*oneMatSize + whichState*oneMatSize;
scalerOffset = whichChain*2*numIntNodes*numChars + whichState*numIntNodes*numChars;
/* pass down tree */
for (n=0; n<numIntNodes; n++)
{
p = intNodeDownPassSeq[intNodeOffset + n];
// for debugging purposes
// set all nodes to update
// p->upDateCl = YES;
clUpdateFlag[p->index] = NO;
if (p->anc->anc == NULL && treeModel == UNROOTED)
{
if (p->upDateCl == YES)
{
//printf ("visiting basal node %d\n", p->index);
/* get transition probabilities */
# if defined (SMART_TI_PROBS)
pL = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (p->left->index)*nodeTiSize);
pR = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (p->right->index)*nodeTiSize);
pA = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (p->index)*nodeTiSize);
# else
if (nst == 1 || nst == 2)
{
for (m=indexL=indexR=indexA=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
theRate = partRate[m] * catRate[k];
/* calculate transition probabilities for left branch */
HkyChangeMat (probs, p->left->length, lkappa, theRate, bs[A], bs[C], bs[G], bs[T]);
for (i=0; i<4; i++)
for (j=0; j<4; j++)
pL[indexL++] = probs[i][j];
/* calculate transition probabilities for right branch */
HkyChangeMat (probs, p->right->length, lkappa, theRate, bs[A], bs[C], bs[G], bs[T]);
for (i=0; i<4; i++)
for (j=0; j<4; j++)
pR[indexR++] = probs[i][j];
/* calculate transition probabilities for ancestral branch */
HkyChangeMat (probs, p->length, lkappa, theRate, bs[A], bs[C], bs[G], bs[T]);
for (i=0; i<4; i++)
for (j=0; j<4; j++)
pA[indexA++] = probs[i][j];
}
}
}
else // nst == 6 or nst == 12
{
for (m=indexL=indexR=indexA=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
theRate = partRate[m] * catRate[k];
// calculate transition probabilities for left branch
if (isComplex == NO)
CalcPij (c_ijk, N_STATES, eigenValues, p->left->length, theRate, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, N_STATES, probs, p->left->length, theRate) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<4; i++)
for (j=0; j<4; j++)
pL[indexL++] = probs[i][j];
// calculate transition probabilities for right branch
if (isComplex == NO)
CalcPij (c_ijk, N_STATES, eigenValues, p->right->length, theRate, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, 4, probs, p->right->length, theRate) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<4; i++)
for (j=0; j<4; j++)
pR[indexR++] = probs[i][j];
// calculate transition probabilities for ancestral branch
if (isComplex == NO)
CalcPij (c_ijk, 4, eigenValues, p->length, theRate, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, 4, probs, p->length, theRate) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<4; i++)
for (j=0; j<4; j++)
pA[indexA++] = probs[i][j];
}
}
}
# endif
if (!strcmp(ratesModel, "invariant") || !strcmp(ratesModel, "invgamma"))
{
for (i=0; i<nodeTiSize; i++)
{
if (pL[i] < 0.0)
pL[i] = 0.0;
if (pR[i] < 0.0)
pR[i] = 0.0;
if (pA[i] < 0.0)
pA[i] = 0.0;
}
}
shortCut = 0;
/* calculate likelihoods of site patterns for left branch if terminal */
if (p->left->left == NULL && isPartAmbig[p->left->index] == NO)
{
shortCut |= 1;
lState = termState + p->left->index * numChars;
tiPL = pL;
for (m=j=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
for (i=0; i<4; i++)
{
likeL[j++] = tiPL[0] + ((seqErrorProb - 4.0*seqErrorProb*tiPL[0])/3.0);
likeL[j++] = tiPL[4] + ((seqErrorProb - 4.0*seqErrorProb*tiPL[4])/3.0);
likeL[j++] = tiPL[8] + ((seqErrorProb - 4.0*seqErrorProb*tiPL[8])/3.0);
likeL[j++] = tiPL[12] + ((seqErrorProb - 4.0*seqErrorProb*tiPL[12])/3.0);
tiPL++;
}
/* for ambiguous */
for (i=0; i<4; i++)
likeL[j++] = 1.0;
tiPL += 12;
}
}
}
/* calculate likelihoods of site patterns for right branch if terminal */
if (p->right->left == NULL && isPartAmbig[p->right->index] == NO)
{
shortCut |= 2;
rState = termState + p->right->index * numChars;
tiPR = pR;
for (m=j=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
for (i=0; i<4; i++)
{
likeR[j++] = tiPR[0] + ((seqErrorProb - 4.0*seqErrorProb*tiPR[0])/3.0);
likeR[j++] = tiPR[4] + ((seqErrorProb - 4.0*seqErrorProb*tiPR[4])/3.0);
likeR[j++] = tiPR[8] + ((seqErrorProb - 4.0*seqErrorProb*tiPR[8])/3.0);
likeR[j++] = tiPR[12] + ((seqErrorProb - 4.0*seqErrorProb*tiPR[12])/3.0);
tiPR++;
}
/* for ambiguous */
for (i=0; i<4; i++)
likeR[j++] = 1.0;
tiPR += 12;
}
}
}
/* calculate likelihoods of site patterns for anc branch, always terminal */
if (isPartAmbig[p->anc->index] == YES)
{
shortCut = 4;
}
else
{
aState = termState + p->anc->index * numChars;
tiPA = pA;
for (m=j=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
for (i=0; i<4; i++)
{
likeA[j++] = tiPA[0] + ((seqErrorProb - 4.0*seqErrorProb*tiPA[0])/3.0);
likeA[j++] = tiPA[4] + ((seqErrorProb - 4.0*seqErrorProb*tiPA[4])/3.0);
likeA[j++] = tiPA[8] + ((seqErrorProb - 4.0*seqErrorProb*tiPA[8])/3.0);
likeA[j++] = tiPA[12] + ((seqErrorProb - 4.0*seqErrorProb*tiPA[12])/3.0);
tiPA++;
}
/* for ambiguous */
for (i=0; i<4; i++)
likeA[j++] = 1.0;
tiPA += 12;
}
}
}
/* calculate conditional likelihoods */
/* first set pointers to cond likes of left, right, p and anc */
clL = &condLike[condLikeOffset + (p->left->index)*oneNodeSize];
clR = &condLike[condLikeOffset + (p->right->index)*oneNodeSize];
clA = &condLike[condLikeOffset + (p->anc->index)*oneNodeSize];
clP = &condLike[condLikeOffset + (p->index)*oneNodeSize];
/* then branch to model */
if (!strcmp(ratesModel, "equal"))
{
tiPL = pL;
tiPR = pR;
tiPA = pA;
switch (shortCut)
{
case 4: // anc is partially ambiguous
for (c=h=0; c<numChars; c++)
{
clP[h++] = (tiPL[AA]*clL[A] + tiPL[AC]*clL[C] + tiPL[AG]*clL[G] + tiPL[AT]*clL[T])
*(tiPR[AA]*clR[A] + tiPR[AC]*clR[C] + tiPR[AG]*clR[G] + tiPR[AT]*clR[T])
*(tiPA[AA]*clA[A] + tiPA[AC]*clA[C] + tiPA[AG]*clA[G] + tiPA[AT]*clA[T]);
clP[h++] = (tiPL[CA]*clL[A] + tiPL[CC]*clL[C] + tiPL[CG]*clL[G] + tiPL[CT]*clL[T])
*(tiPR[CA]*clR[A] + tiPR[CC]*clR[C] + tiPR[CG]*clR[G] + tiPR[CT]*clR[T])
*(tiPA[CA]*clA[A] + tiPA[CC]*clA[C] + tiPA[CG]*clA[G] + tiPA[CT]*clA[T]);
clP[h++] = (tiPL[GA]*clL[A] + tiPL[GC]*clL[C] + tiPL[GG]*clL[G] + tiPL[GT]*clL[T])
*(tiPR[GA]*clR[A] + tiPR[GC]*clR[C] + tiPR[GG]*clR[G] + tiPR[GT]*clR[T])
*(tiPA[GA]*clA[A] + tiPA[GC]*clA[C] + tiPA[GG]*clA[G] + tiPA[GT]*clA[T]);
clP[h++] = (tiPL[TA]*clL[A] + tiPL[TC]*clL[C] + tiPL[TG]*clL[G] + tiPL[TT]*clL[T])
*(tiPR[TA]*clR[A] + tiPR[TC]*clR[C] + tiPR[TG]*clR[G] + tiPR[TT]*clR[T])
*(tiPA[TA]*clA[A] + tiPA[TC]*clA[C] + tiPA[TG]*clA[G] + tiPA[TT]*clA[T]);
clL += 4;
clR += 4;
clA += 4;
}
break;
case 0:
case 3: // if both left and right are terminal, this is a 4-taxon tree and no shortcut is necessary
for (c=h=0; c<numChars; c++)
{
i = aState[c];
clP[h++] = (tiPL[AA]*clL[A] + tiPL[AC]*clL[C] + tiPL[AG]*clL[G] + tiPL[AT]*clL[T])
*(tiPR[AA]*clR[A] + tiPR[AC]*clR[C] + tiPR[AG]*clR[G] + tiPR[AT]*clR[T])
*likeA[i++];
clP[h++] = (tiPL[CA]*clL[A] + tiPL[CC]*clL[C] + tiPL[CG]*clL[G] + tiPL[CT]*clL[T])
*(tiPR[CA]*clR[A] + tiPR[CC]*clR[C] + tiPR[CG]*clR[G] + tiPR[CT]*clR[T])
*likeA[i++];
clP[h++] = (tiPL[GA]*clL[A] + tiPL[GC]*clL[C] + tiPL[GG]*clL[G] + tiPL[GT]*clL[T])
*(tiPR[GA]*clR[A] + tiPR[GC]*clR[C] + tiPR[GG]*clR[G] + tiPR[GT]*clR[T])
*likeA[i++];
clP[h++] = (tiPL[TA]*clL[A] + tiPL[TC]*clL[C] + tiPL[TG]*clL[G] + tiPL[TT]*clL[T])
*(tiPR[TA]*clR[A] + tiPR[TC]*clR[C] + tiPR[TG]*clR[G] + tiPR[TT]*clR[T])
*likeA[i];
clL += 4;
clR += 4;
}
break;
case 1:
for (c=h=0; c<numChars; c++)
{
i = lState[c];
j = aState[c];
clP[h++] = likeL[i++]*likeA[j++]
*(tiPR[AA]*clR[A] + tiPR[AC]*clR[C] + tiPR[AG]*clR[G] + tiPR[AT]*clR[T]);
clP[h++] = likeL[i++]*likeA[j++]
*(tiPR[CA]*clR[A] + tiPR[CC]*clR[C] + tiPR[CG]*clR[G] + tiPR[CT]*clR[T]);
clP[h++] = likeL[i++]*likeA[j++]
*(tiPR[GA]*clR[A] + tiPR[GC]*clR[C] + tiPR[GG]*clR[G] + tiPR[GT]*clR[T]);
clP[h++] = likeL[i]*likeA[j]
*(tiPR[TA]*clR[A] + tiPR[TC]*clR[C] + tiPR[TG]*clR[G] + tiPR[TT]*clR[T]);
clR += 4;
}
break;
case 2:
for (c=h=0; c<numChars; c++)
{
i = rState[c];
j = aState[c];
clP[h++] = (tiPL[AA]*clL[A] + tiPL[AC]*clL[C] + tiPL[AG]*clL[G] + tiPL[AT]*clL[T])
*likeR[i++]*likeA[j++];
clP[h++] = (tiPL[CA]*clL[A] + tiPL[CC]*clL[C] + tiPL[CG]*clL[G] + tiPL[CT]*clL[T])
*likeR[i++]*likeA[j++];
clP[h++] = (tiPL[GA]*clL[A] + tiPL[GC]*clL[C] + tiPL[GG]*clL[G] + tiPL[GT]*clL[T])
*likeR[i++]*likeA[j++];
clP[h++] = (tiPL[TA]*clL[A] + tiPL[TC]*clL[C] + tiPL[TG]*clL[G] + tiPL[TT]*clL[T])
*likeR[i]*likeA[j];
clL += 4;
}
break;
}
}
else if (!strcmp(ratesModel, "gamma") || !strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "invariant") || !strcmp(ratesModel, "invgamma"))
{
switch (shortCut)
{
case 4:
for (c=h=0; c<numChars; c++)
{
tiPL = pL;
tiPR = pR;
tiPA = pA;
for (k=0; k<lnumRateCats; k++)
{
clP[h++] = (tiPL[AA]*clL[A] + tiPL[AC]*clL[C] + tiPL[AG]*clL[G] + tiPL[AT]*clL[T])
*(tiPR[AA]*clR[A] + tiPR[AC]*clR[C] + tiPR[AG]*clR[G] + tiPR[AT]*clR[T])
*(tiPA[AA]*clA[A] + tiPA[AC]*clA[C] + tiPA[AG]*clA[G] + tiPA[AT]*clA[T]);
clP[h++] = (tiPL[CA]*clL[A] + tiPL[CC]*clL[C] + tiPL[CG]*clL[G] + tiPL[CT]*clL[T])
*(tiPR[CA]*clR[A] + tiPR[CC]*clR[C] + tiPR[CG]*clR[G] + tiPR[CT]*clR[T])
*(tiPA[CA]*clA[A] + tiPA[CC]*clA[C] + tiPA[CG]*clA[G] + tiPA[CT]*clA[T]);
clP[h++] = (tiPL[GA]*clL[A] + tiPL[GC]*clL[C] + tiPL[GG]*clL[G] + tiPL[GT]*clL[T])
*(tiPR[GA]*clR[A] + tiPR[GC]*clR[C] + tiPR[GG]*clR[G] + tiPR[GT]*clR[T])
*(tiPA[GA]*clA[A] + tiPA[GC]*clA[C] + tiPA[GG]*clA[G] + tiPA[GT]*clA[T]);
clP[h++] = (tiPL[TA]*clL[A] + tiPL[TC]*clL[C] + tiPL[TG]*clL[G] + tiPL[TT]*clL[T])
*(tiPR[TA]*clR[A] + tiPR[TC]*clR[C] + tiPR[TG]*clR[G] + tiPR[TT]*clR[T])
*(tiPA[TA]*clA[A] + tiPA[TC]*clA[C] + tiPA[TG]*clA[G] + tiPA[TT]*clA[T]);
clL += 4;
clR += 4;
clA += 4;
tiPL += 16;
tiPR += 16;
tiPA += 16;
}
}
break;
case 0:
case 3:
for (c=h=0; c<numChars; c++)
{
tiPL = pL;
tiPR = pR;
i = aState[c];
for (k=0; k<lnumRateCats; k++)
{
clP[h++] = (tiPL[AA]*clL[A] + tiPL[AC]*clL[C] + tiPL[AG]*clL[G] + tiPL[AT]*clL[T])
*(tiPR[AA]*clR[A] + tiPR[AC]*clR[C] + tiPR[AG]*clR[G] + tiPR[AT]*clR[T])
*likeA[i++];
clP[h++] = (tiPL[CA]*clL[A] + tiPL[CC]*clL[C] + tiPL[CG]*clL[G] + tiPL[CT]*clL[T])
*(tiPR[CA]*clR[A] + tiPR[CC]*clR[C] + tiPR[CG]*clR[G] + tiPR[CT]*clR[T])
*likeA[i++];
clP[h++] = (tiPL[GA]*clL[A] + tiPL[GC]*clL[C] + tiPL[GG]*clL[G] + tiPL[GT]*clL[T])
*(tiPR[GA]*clR[A] + tiPR[GC]*clR[C] + tiPR[GG]*clR[G] + tiPR[GT]*clR[T])
*likeA[i++];
clP[h++] = (tiPL[TA]*clL[A] + tiPL[TC]*clL[C] + tiPL[TG]*clL[G] + tiPL[TT]*clL[T])
*(tiPR[TA]*clR[A] + tiPR[TC]*clR[C] + tiPR[TG]*clR[G] + tiPR[TT]*clR[T])
*likeA[i++];
clL += 4;
clR += 4;
tiPL += 16;
tiPR += 16;
i += 16;
}
}
break;
case 1:
for (c=h=0; c<numChars; c++)
{
tiPR = pR;
i = lState[c];
j = aState[c];
for (k=0; k<lnumRateCats; k++)
{
clP[h++] = (tiPR[AA]*clR[A] + tiPR[AC]*clR[C] + tiPR[AG]*clR[G] + tiPR[AT]*clR[T])
*likeL[i++]*likeA[j++];
clP[h++] = (tiPR[CA]*clR[A] + tiPR[CC]*clR[C] + tiPR[CG]*clR[G] + tiPR[CT]*clR[T])
*likeL[i++]*likeA[j++];
clP[h++] = (tiPR[GA]*clR[A] + tiPR[GC]*clR[C] + tiPR[GG]*clR[G] + tiPR[GT]*clR[T])
*likeL[i++]*likeA[j++];
clP[h++] = (tiPR[TA]*clR[A] + tiPR[TC]*clR[C] + tiPR[TG]*clR[G] + tiPR[TT]*clR[T])
*likeL[i++]*likeA[j++];
clR += 4;
tiPR += 16;
i += 16;
j += 16;
}
}
break;
case 2:
for (c=h=0; c<numChars; c++)
{
tiPL = pL;
i = rState[c];
j = aState[c];
for (k=0; k<lnumRateCats; k++)
{
clP[h++] = (tiPL[AA]*clL[A] + tiPL[AC]*clL[C] + tiPL[AG]*clL[G] + tiPL[AT]*clL[T])
*likeR[i++]*likeA[j++];
clP[h++] = (tiPL[CA]*clL[A] + tiPL[CC]*clL[C] + tiPL[CG]*clL[G] + tiPL[CT]*clL[T])
*likeR[i++]*likeA[j++];
clP[h++] = (tiPL[GA]*clL[A] + tiPL[GC]*clL[C] + tiPL[GG]*clL[G] + tiPL[GT]*clL[T])
*likeR[i++]*likeA[j++];
clP[h++] = (tiPL[TA]*clL[A] + tiPL[TC]*clL[C] + tiPL[TG]*clL[G] + tiPL[TT]*clL[T])
*likeR[i++]*likeA[j++];
clL += 4;
tiPL += 16;
i += 16;
j += 16;
}
}
break;
}
}
else if (!strcmp(ratesModel, "ssgamma") || !strcmp(ratesModel, "ssadgamma"))
{
indexMultiplier1 = lnumRateCats * N_STATES_SQUARED;
indexMultiplier2 = lnumRateCats * 20;
switch (shortCut)
{
case 4:
for (c=h=0; c<numChars; c++)
{
index = partitionId[c] * indexMultiplier1;
tiPL = &pL[index];
tiPR = &pR[index];
tiPA = &pA[index];
for (k=0; k<lnumRateCats; k++)
{
clP[h++] = (tiPL[AA]*clL[A] + tiPL[AC]*clL[C] + tiPL[AG]*clL[G] + tiPL[AT]*clL[T])
*(tiPR[AA]*clR[A] + tiPR[AC]*clR[C] + tiPR[AG]*clR[G] + tiPR[AT]*clR[T])
*(tiPA[AA]*clA[A] + tiPA[AC]*clA[C] + tiPA[AG]*clA[G] + tiPA[AT]*clA[T]);
clP[h++] = (tiPL[CA]*clL[A] + tiPL[CC]*clL[C] + tiPL[CG]*clL[G] + tiPL[CT]*clL[T])
*(tiPR[CA]*clR[A] + tiPR[CC]*clR[C] + tiPR[CG]*clR[G] + tiPR[CT]*clR[T])
*(tiPA[CA]*clA[A] + tiPA[CC]*clA[C] + tiPA[CG]*clA[G] + tiPA[CT]*clA[T]);
clP[h++] = (tiPL[GA]*clL[A] + tiPL[GC]*clL[C] + tiPL[GG]*clL[G] + tiPL[GT]*clL[T])
*(tiPR[GA]*clR[A] + tiPR[GC]*clR[C] + tiPR[GG]*clR[G] + tiPR[GT]*clR[T])
*(tiPA[GA]*clA[A] + tiPA[GC]*clA[C] + tiPA[GG]*clA[G] + tiPA[GT]*clA[T]);
clP[h++] = (tiPL[TA]*clL[A] + tiPL[TC]*clL[C] + tiPL[TG]*clL[G] + tiPL[TT]*clL[T])
*(tiPR[TA]*clR[A] + tiPR[TC]*clR[C] + tiPR[TG]*clR[G] + tiPR[TT]*clR[T])
*(tiPA[TA]*clA[A] + tiPA[TC]*clA[C] + tiPA[TG]*clA[G] + tiPA[TT]*clA[T]);
clL += 4;
clR += 4;
clA += 4;
tiPL += 16;
tiPR += 16;
tiPA += 16;
}
}
break;
case 0:
case 3:
for (c=h=0; c<numChars; c++)
{
index = partitionId[c] * indexMultiplier1;
tiPL = &pL[index];
tiPR = &pR[index];
i = aState[c] + (partitionId[c] * indexMultiplier2);
for (k=0; k<lnumRateCats; k++)
{
clP[h++] = (tiPL[AA]*clL[A] + tiPL[AC]*clL[C] + tiPL[AG]*clL[G] + tiPL[AT]*clL[T])
*(tiPR[AA]*clR[A] + tiPR[AC]*clR[C] + tiPR[AG]*clR[G] + tiPR[AT]*clR[T])
*likeA[i++];
clP[h++] = (tiPL[CA]*clL[A] + tiPL[CC]*clL[C] + tiPL[CG]*clL[G] + tiPL[CT]*clL[T])
*(tiPR[CA]*clR[A] + tiPR[CC]*clR[C] + tiPR[CG]*clR[G] + tiPR[CT]*clR[T])
*likeA[i++];
clP[h++] = (tiPL[GA]*clL[A] + tiPL[GC]*clL[C] + tiPL[GG]*clL[G] + tiPL[GT]*clL[T])
*(tiPR[GA]*clR[A] + tiPR[GC]*clR[C] + tiPR[GG]*clR[G] + tiPR[GT]*clR[T])
*likeA[i++];
clP[h++] = (tiPL[TA]*clL[A] + tiPL[TC]*clL[C] + tiPL[TG]*clL[G] + tiPL[TT]*clL[T])
*(tiPR[TA]*clR[A] + tiPR[TC]*clR[C] + tiPR[TG]*clR[G] + tiPR[TT]*clR[T])
*likeA[i++];
clL += 4;
clR += 4;
tiPL += 16;
tiPR += 16;
i += 16;
}
}
break;
case 1:
for (c=h=0; c<numChars; c++)
{
tiPR = &pR[partitionId[c] * indexMultiplier1];
index = partitionId[c] * indexMultiplier2;
i = index + lState[c];
j = index + aState[c];
for (k=0; k<lnumRateCats; k++)
{
clP[h++] = (tiPR[AA]*clR[A] + tiPR[AC]*clR[C] + tiPR[AG]*clR[G] + tiPR[AT]*clR[T])
*likeL[i++]*likeA[j++];
clP[h++] = (tiPR[CA]*clR[A] + tiPR[CC]*clR[C] + tiPR[CG]*clR[G] + tiPR[CT]*clR[T])
*likeL[i++]*likeA[j++];
clP[h++] = (tiPR[GA]*clR[A] + tiPR[GC]*clR[C] + tiPR[GG]*clR[G] + tiPR[GT]*clR[T])
*likeL[i++]*likeA[j++];
clP[h++] = (tiPR[TA]*clR[A] + tiPR[TC]*clR[C] + tiPR[TG]*clR[G] + tiPR[TT]*clR[T])
*likeL[i++]*likeA[j++];
clR += 4;
tiPR += 16;
i += 16;
j += 16;
}
}
break;
case 2:
for (c=h=0; c<numChars; c++)
{
tiPL = &pL[partitionId[c] * indexMultiplier1];
index = partitionId[c] * indexMultiplier2;
i = index + rState[c];
j = index + aState[c];
for (k=0; k<lnumRateCats; k++)
{
clP[h++] = (tiPL[AA]*clL[A] + tiPL[AC]*clL[C] + tiPL[AG]*clL[G] + tiPL[AT]*clL[T])
*likeR[i++]*likeA[j++];
clP[h++] = (tiPL[CA]*clL[A] + tiPL[CC]*clL[C] + tiPL[CG]*clL[G] + tiPL[CT]*clL[T])
*likeR[i++]*likeA[j++];
clP[h++] = (tiPL[GA]*clL[A] + tiPL[GC]*clL[C] + tiPL[GG]*clL[G] + tiPL[GT]*clL[T])
*likeR[i++]*likeA[j++];
clP[h++] = (tiPL[TA]*clL[A] + tiPL[TC]*clL[C] + tiPL[TG]*clL[G] + tiPL[TT]*clL[T])
*likeR[i++]*likeA[j++];
clL += 4;
tiPL += 16;
i += 16;
j += 16;
}
}
break;
}
}
else if (!strcmp(ratesModel, "sitespec"))
{
indexMultiplier1 = lnumRateCats * N_STATES_SQUARED;
indexMultiplier2 = lnumRateCats * 20;
switch (shortCut)
{
case 4:
for (c=h=0; c<numChars; c++)
{
index = partitionId[c] * indexMultiplier1;
tiPL = &pL[index];
tiPR = &pR[index];
tiPA = &pA[index];
clP[h++] = (tiPL[AA]*clL[A] + tiPL[AC]*clL[C] + tiPL[AG]*clL[G] + tiPL[AT]*clL[T])
*(tiPR[AA]*clR[A] + tiPR[AC]*clR[C] + tiPR[AG]*clR[G] + tiPR[AT]*clR[T])
*(tiPA[AA]*clA[A] + tiPA[AC]*clA[C] + tiPA[AG]*clA[G] + tiPA[AT]*clA[T]);
clP[h++] = (tiPL[CA]*clL[A] + tiPL[CC]*clL[C] + tiPL[CG]*clL[G] + tiPL[CT]*clL[T])
*(tiPR[CA]*clR[A] + tiPR[CC]*clR[C] + tiPR[CG]*clR[G] + tiPR[CT]*clR[T])
*(tiPA[CA]*clA[A] + tiPA[CC]*clA[C] + tiPA[CG]*clA[G] + tiPA[CT]*clA[T]);
clP[h++] = (tiPL[GA]*clL[A] + tiPL[GC]*clL[C] + tiPL[GG]*clL[G] + tiPL[GT]*clL[T])
*(tiPR[GA]*clR[A] + tiPR[GC]*clR[C] + tiPR[GG]*clR[G] + tiPR[GT]*clR[T])
*(tiPA[GA]*clA[A] + tiPA[GC]*clA[C] + tiPA[GG]*clA[G] + tiPA[GT]*clA[T]);
clP[h++] = (tiPL[TA]*clL[A] + tiPL[TC]*clL[C] + tiPL[TG]*clL[G] + tiPL[TT]*clL[T])
*(tiPR[TA]*clR[A] + tiPR[TC]*clR[C] + tiPR[TG]*clR[G] + tiPR[TT]*clR[T])
*(tiPA[TA]*clA[A] + tiPA[TC]*clA[C] + tiPA[TG]*clA[G] + tiPA[TT]*clA[T]);
clL += 4;
clR += 4;
clA += 4;
}
break;
case 0:
case 3:
for (c=h=0; c<numChars; c++)
{
index = partitionId[c] * indexMultiplier1;
tiPL = &pL[index];
tiPR = &pR[index];
i = (partitionId[c] * indexMultiplier2) + aState[c];
clP[h++] = (tiPL[AA]*clL[A] + tiPL[AC]*clL[C] + tiPL[AG]*clL[G] + tiPL[AT]*clL[T])
*(tiPR[AA]*clR[A] + tiPR[AC]*clR[C] + tiPR[AG]*clR[G] + tiPR[AT]*clR[T])
*likeA[i++];
clP[h++] = (tiPL[CA]*clL[A] + tiPL[CC]*clL[C] + tiPL[CG]*clL[G] + tiPL[CT]*clL[T])
*(tiPR[CA]*clR[A] + tiPR[CC]*clR[C] + tiPR[CG]*clR[G] + tiPR[CT]*clR[T])
*likeA[i++];
clP[h++] = (tiPL[GA]*clL[A] + tiPL[GC]*clL[C] + tiPL[GG]*clL[G] + tiPL[GT]*clL[T])
*(tiPR[GA]*clR[A] + tiPR[GC]*clR[C] + tiPR[GG]*clR[G] + tiPR[GT]*clR[T])
*likeA[i++];
clP[h++] = (tiPL[TA]*clL[A] + tiPL[TC]*clL[C] + tiPL[TG]*clL[G] + tiPL[TT]*clL[T])
*(tiPR[TA]*clR[A] + tiPR[TC]*clR[C] + tiPR[TG]*clR[G] + tiPR[TT]*clR[T])
*likeA[i];
clL += 4;
clR += 4;
}
break;
case 1:
for (c=h=0; c<numChars; c++)
{
tiPR = &pR[partitionId[c] * indexMultiplier1];
index = partitionId[c] * indexMultiplier2;
i = index + lState[c];
j = index + aState[c];
clP[h++] = (tiPR[AA]*clR[A] + tiPR[AC]*clR[C] + tiPR[AG]*clR[G] + tiPR[AT]*clR[T])
*likeL[i++]*likeA[j++];
clP[h++] = (tiPR[CA]*clR[A] + tiPR[CC]*clR[C] + tiPR[CG]*clR[G] + tiPR[CT]*clR[T])
*likeL[i++]*likeA[j++];
clP[h++] = (tiPR[GA]*clR[A] + tiPR[GC]*clR[C] + tiPR[GG]*clR[G] + tiPR[GT]*clR[T])
*likeL[i++]*likeA[j++];
clP[h++] = (tiPR[TA]*clR[A] + tiPR[TC]*clR[C] + tiPR[TG]*clR[G] + tiPR[TT]*clR[T])
*likeL[i]*likeA[j];
clR += 4;
}
break;
case 2:
for (c=h=0; c<numChars; c++)
{
tiPL = &pL[partitionId[c] * indexMultiplier1];
index = partitionId[c] * indexMultiplier2;
i = index + rState[c];
j = index + aState[c];
clP[h++] = (tiPL[AA]*clL[A] + tiPL[AC]*clL[C] + tiPL[AG]*clL[G] + tiPL[AT]*clL[T])
*likeR[i++]*likeA[j++];
clP[h++] = (tiPL[CA]*clL[A] + tiPL[CC]*clL[C] + tiPL[CG]*clL[G] + tiPL[CT]*clL[T])
*likeR[i++]*likeA[j++];
clP[h++] = (tiPL[GA]*clL[A] + tiPL[GC]*clL[C] + tiPL[GG]*clL[G] + tiPL[GT]*clL[T])
*likeR[i++]*likeA[j++];
clP[h++] = (tiPL[TA]*clL[A] + tiPL[TC]*clL[C] + tiPL[TG]*clL[G] + tiPL[TT]*clL[T])
*likeR[i]*likeA[j];
clL += 4;
}
break;
}
}
p->upDateCl = NO;
clUpdateFlag[p->index] = YES;
} // done if p->upDateCl == YES for internal root node
} // done with internal root node
else
{
if (p->upDateCl == YES)
{
//printf ("visiting interior node %d\n", p->index);
/* get transition probabilities */
# if defined (SMART_TI_PROBS)
pL = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (p->left->index)*nodeTiSize);
pR = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (p->right->index)*nodeTiSize);
# else
if (nst == 1 || nst == 2)
{
for (m=indexL=indexR=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
theRate = partRate[m] * catRate[k];
/* calculate transition probabilities for left branch */
HkyChangeMat (probs, p->left->length, lkappa, theRate, bs[A], bs[C], bs[G], bs[T]);
for (i=0; i<4; i++)
for (j=0; j<4; j++)
pL[indexL++] = probs[i][j];
/* calculate transition probabilities for right branch */
HkyChangeMat (probs, p->right->length, lkappa, theRate, bs[A], bs[C], bs[G], bs[T]);
for (i=0; i<4; i++)
for (j=0; j<4; j++)
pR[indexR++] = probs[i][j];
}
}
}
else // nst == 6 or nst == 12
{
for (m=indexL=indexR=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
theRate = partRate[m] * catRate[k];
// calculate transition probabilities for left branch
if (isComplex == NO)
CalcPij (c_ijk, 4, eigenValues, p->left->length, theRate, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, 4, probs, p->left->length, theRate) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<4; i++)
for (j=0; j<4; j++)
pL[indexL++] = probs[i][j];
// calculate transition probabilities for right branch
if (isComplex == NO)
CalcPij (c_ijk, 4, eigenValues, p->right->length, theRate, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, 4, probs, p->right->length, theRate) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<4; i++)
for (j=0; j<4; j++)
pR[indexR++] = probs[i][j];
}
}
}
# endif
if (!strcmp(ratesModel, "invariant") || !strcmp(ratesModel, "invgamma"))
{
for (i=0; i<nodeTiSize; i++)
{
if (pL[i] < 0.0)
pL[i] = 0.0;
if (pR[i] < 0.0)
pR[i] = 0.0;
}
}
/*
for (i=0; i<nodeTiSize; i++)
if (pL[i] < 0.0 || pR[i] < 0.0) {
printf (" WARNING! Ti prob negative\n");
getchar();
}
*/
shortCut = 0;
/* calculate likelihoods of site patterns for right branch if terminal */
if (p->left->left == NULL && isPartAmbig[p->left->index] == NO)
{
shortCut |= 1;
lState = termState + p->left->index * numChars;
tiPL = pL;
for (m=j=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
for (i=0; i<4; i++)
{
likeL[j++] = tiPL[0] + ((seqErrorProb - 4.0*seqErrorProb*tiPL[0])/3.0);
likeL[j++] = tiPL[4] + ((seqErrorProb - 4.0*seqErrorProb*tiPL[4])/3.0);
likeL[j++] = tiPL[8] + ((seqErrorProb - 4.0*seqErrorProb*tiPL[8])/3.0);
likeL[j++] = tiPL[12] + ((seqErrorProb - 4.0*seqErrorProb*tiPL[12])/3.0);
tiPL++;
}
/* for ambiguous */
for (i=0; i<4; i++)
likeL[j++] = 1.0;
tiPL += 12;
}
}
}
/* calculate likelihoods of site patterns for right branch if terminal */
if (p->right->left == NULL && isPartAmbig[p->right->index] == NO)
{
shortCut |= 2;
rState = termState + p->right->index * numChars;
tiPR = pR;
for (m=j=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
for (i=0; i<4; i++)
{
likeR[j++] = tiPR[0] + ((seqErrorProb - 4.0*seqErrorProb*tiPR[0])/3.0);
likeR[j++] = tiPR[4] + ((seqErrorProb - 4.0*seqErrorProb*tiPR[4])/3.0);
likeR[j++] = tiPR[8] + ((seqErrorProb - 4.0*seqErrorProb*tiPR[8])/3.0);
likeR[j++] = tiPR[12] + ((seqErrorProb - 4.0*seqErrorProb*tiPR[12])/3.0);
tiPR++;
}
/* for ambiguous */
for (i=0; i<4; i++)
likeR[j++] = 1.0;
tiPR += 12;
}
}
}
/* calculate conditional likelihoods */
/* first set pointers to cond likes of left, right, p and anc */
clL = &condLike[condLikeOffset + (p->left->index)*oneNodeSize];
clR = &condLike[condLikeOffset + (p->right->index)*oneNodeSize];
clP = &condLike[condLikeOffset + (p->index)*oneNodeSize];
/* then branch to model */
if (!strcmp(ratesModel, "equal"))
{
tiPL = pL;
tiPR = pR;
switch (shortCut)
{
case 0:
for (c=h=0; c<numChars; c++)
{
clP[h++] = (tiPL[AA]*clL[A] + tiPL[AC]*clL[C] + tiPL[AG]*clL[G] + tiPL[AT]*clL[T])
*(tiPR[AA]*clR[A] + tiPR[AC]*clR[C] + tiPR[AG]*clR[G] + tiPR[AT]*clR[T]);
clP[h++] = (tiPL[CA]*clL[A] + tiPL[CC]*clL[C] + tiPL[CG]*clL[G] + tiPL[CT]*clL[T])
*(tiPR[CA]*clR[A] + tiPR[CC]*clR[C] + tiPR[CG]*clR[G] + tiPR[CT]*clR[T]);
clP[h++] = (tiPL[GA]*clL[A] + tiPL[GC]*clL[C] + tiPL[GG]*clL[G] + tiPL[GT]*clL[T])
*(tiPR[GA]*clR[A] + tiPR[GC]*clR[C] + tiPR[GG]*clR[G] + tiPR[GT]*clR[T]);
clP[h++] = (tiPL[TA]*clL[A] + tiPL[TC]*clL[C] + tiPL[TG]*clL[G] + tiPL[TT]*clL[T])
*(tiPR[TA]*clR[A] + tiPR[TC]*clR[C] + tiPR[TG]*clR[G] + tiPR[TT]*clR[T]);
clL += 4;
clR += 4;
}
break;
case 1:
for (c=h=0; c<numChars; c++)
{
i = lState[c];
clP[h++] = likeL[i++]
*(tiPR[AA]*clR[A] + tiPR[AC]*clR[C] + tiPR[AG]*clR[G] + tiPR[AT]*clR[T]);
clP[h++] = likeL[i++]
*(tiPR[CA]*clR[A] + tiPR[CC]*clR[C] + tiPR[CG]*clR[G] + tiPR[CT]*clR[T]);
clP[h++] = likeL[i++]
*(tiPR[GA]*clR[A] + tiPR[GC]*clR[C] + tiPR[GG]*clR[G] + tiPR[GT]*clR[T]);
clP[h++] = likeL[i]
*(tiPR[TA]*clR[A] + tiPR[TC]*clR[C] + tiPR[TG]*clR[G] + tiPR[TT]*clR[T]);
clR += 4;
}
break;
case 2:
for (c=h=0; c<numChars; c++)
{
i = rState[c];
clP[h++] = (tiPL[AA]*clL[A] + tiPL[AC]*clL[C] + tiPL[AG]*clL[G] + tiPL[AT]*clL[T])
*likeR[i++];
clP[h++] = (tiPL[CA]*clL[A] + tiPL[CC]*clL[C] + tiPL[CG]*clL[G] + tiPL[CT]*clL[T])
*likeR[i++];
clP[h++] = (tiPL[GA]*clL[A] + tiPL[GC]*clL[C] + tiPL[GG]*clL[G] + tiPL[GT]*clL[T])
*likeR[i++];
clP[h++] = (tiPL[TA]*clL[A] + tiPL[TC]*clL[C] + tiPL[TG]*clL[G] + tiPL[TT]*clL[T])
*likeR[i];
clL += 4;
}
break;
case 3:
for (c=h=0; c<numChars; c++)
{
i = lState[c];
j = rState[c];
clP[h++] = likeL[i++]*likeR[j++];
clP[h++] = likeL[i++]*likeR[j++];
clP[h++] = likeL[i++]*likeR[j++];
clP[h++] = likeL[i]*likeR[j];
}
}
}
else if (!strcmp(ratesModel, "gamma") || !strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "invariant") || !strcmp(ratesModel, "invgamma"))
{
switch (shortCut)
{
case 0:
for (c=h=0; c<numChars; c++)
{
tiPL = pL;
tiPR = pR;
for (k=0; k<lnumRateCats; k++)
{
clP[h++] = (tiPL[AA]*clL[A] + tiPL[AC]*clL[C] + tiPL[AG]*clL[G] + tiPL[AT]*clL[T])
*(tiPR[AA]*clR[A] + tiPR[AC]*clR[C] + tiPR[AG]*clR[G] + tiPR[AT]*clR[T]);
clP[h++] = (tiPL[CA]*clL[A] + tiPL[CC]*clL[C] + tiPL[CG]*clL[G] + tiPL[CT]*clL[T])
*(tiPR[CA]*clR[A] + tiPR[CC]*clR[C] + tiPR[CG]*clR[G] + tiPR[CT]*clR[T]);
clP[h++] = (tiPL[GA]*clL[A] + tiPL[GC]*clL[C] + tiPL[GG]*clL[G] + tiPL[GT]*clL[T])
*(tiPR[GA]*clR[A] + tiPR[GC]*clR[C] + tiPR[GG]*clR[G] + tiPR[GT]*clR[T]);
clP[h++] = (tiPL[TA]*clL[A] + tiPL[TC]*clL[C] + tiPL[TG]*clL[G] + tiPL[TT]*clL[T])
*(tiPR[TA]*clR[A] + tiPR[TC]*clR[C] + tiPR[TG]*clR[G] + tiPR[TT]*clR[T]);
clL += 4;
clR += 4;
tiPL += 16;
tiPR += 16;
}
}
break;
case 1:
for (c=h=0; c<numChars; c++)
{
tiPR = pR;
i = lState[c];
for (k=0; k<lnumRateCats; k++)
{
clP[h++] = (tiPR[AA]*clR[A] + tiPR[AC]*clR[C] + tiPR[AG]*clR[G] + tiPR[AT]*clR[T])
*likeL[i++];
clP[h++] = (tiPR[CA]*clR[A] + tiPR[CC]*clR[C] + tiPR[CG]*clR[G] + tiPR[CT]*clR[T])
*likeL[i++];
clP[h++] = (tiPR[GA]*clR[A] + tiPR[GC]*clR[C] + tiPR[GG]*clR[G] + tiPR[GT]*clR[T])
*likeL[i++];
clP[h++] = (tiPR[TA]*clR[A] + tiPR[TC]*clR[C] + tiPR[TG]*clR[G] + tiPR[TT]*clR[T])
*likeL[i++];
clR += 4;
tiPR += 16;
i += 16;
}
}
break;
case 2:
for (c=h=0; c<numChars; c++)
{
tiPL = pL;
i = rState[c];
for (k=0; k<lnumRateCats; k++)
{
clP[h++] = (tiPL[AA]*clL[A] + tiPL[AC]*clL[C] + tiPL[AG]*clL[G] + tiPL[AT]*clL[T])
*likeR[i++];
clP[h++] = (tiPL[CA]*clL[A] + tiPL[CC]*clL[C] + tiPL[CG]*clL[G] + tiPL[CT]*clL[T])
*likeR[i++];
clP[h++] = (tiPL[GA]*clL[A] + tiPL[GC]*clL[C] + tiPL[GG]*clL[G] + tiPL[GT]*clL[T])
*likeR[i++];
clP[h++] = (tiPL[TA]*clL[A] + tiPL[TC]*clL[C] + tiPL[TG]*clL[G] + tiPL[TT]*clL[T])
*likeR[i++];
clL += 4;
tiPL += 16;
i += 16;
}
}
break;
case 3:
for (c=h=0; c<numChars; c++)
{
i = lState[c];
j = rState[c];
for (k=0; k<lnumRateCats; k++)
{
clP[h++] = likeL[i++]*likeR[j++];
clP[h++] = likeL[i++]*likeR[j++];
clP[h++] = likeL[i++]*likeR[j++];
clP[h++] = likeL[i++]*likeR[j++];
i += 16;
j += 16;
}
}
break;
}
}
else if (!strcmp(ratesModel, "ssgamma") || !strcmp(ratesModel, "ssadgamma"))
{
indexMultiplier1 = lnumRateCats * N_STATES_SQUARED;
indexMultiplier2 = lnumRateCats * 20;
switch (shortCut)
{
case 0:
for (c=h=0; c<numChars; c++)
{
index = partitionId[c] * indexMultiplier1;
tiPL = &pL[index];
tiPR = &pR[index];
for (k=0; k<lnumRateCats; k++)
{
clP[h++] = (tiPL[AA]*clL[A] + tiPL[AC]*clL[C] + tiPL[AG]*clL[G] + tiPL[AT]*clL[T])
*(tiPR[AA]*clR[A] + tiPR[AC]*clR[C] + tiPR[AG]*clR[G] + tiPR[AT]*clR[T]);
clP[h++] = (tiPL[CA]*clL[A] + tiPL[CC]*clL[C] + tiPL[CG]*clL[G] + tiPL[CT]*clL[T])
*(tiPR[CA]*clR[A] + tiPR[CC]*clR[C] + tiPR[CG]*clR[G] + tiPR[CT]*clR[T]);
clP[h++] = (tiPL[GA]*clL[A] + tiPL[GC]*clL[C] + tiPL[GG]*clL[G] + tiPL[GT]*clL[T])
*(tiPR[GA]*clR[A] + tiPR[GC]*clR[C] + tiPR[GG]*clR[G] + tiPR[GT]*clR[T]);
clP[h++] = (tiPL[TA]*clL[A] + tiPL[TC]*clL[C] + tiPL[TG]*clL[G] + tiPL[TT]*clL[T])
*(tiPR[TA]*clR[A] + tiPR[TC]*clR[C] + tiPR[TG]*clR[G] + tiPR[TT]*clR[T]);
clL += 4;
clR += 4;
tiPL += 16;
tiPR += 16;
}
}
break;
case 1:
for (c=h=0; c<numChars; c++)
{
tiPR = &pR[partitionId[c] * indexMultiplier1];
i = (partitionId[c] * indexMultiplier2) + lState[c];
for (k=0; k<lnumRateCats; k++)
{
clP[h++] = (tiPR[AA]*clR[A] + tiPR[AC]*clR[C] + tiPR[AG]*clR[G] + tiPR[AT]*clR[T])
*likeL[i++];
clP[h++] = (tiPR[CA]*clR[A] + tiPR[CC]*clR[C] + tiPR[CG]*clR[G] + tiPR[CT]*clR[T])
*likeL[i++];
clP[h++] = (tiPR[GA]*clR[A] + tiPR[GC]*clR[C] + tiPR[GG]*clR[G] + tiPR[GT]*clR[T])
*likeL[i++];
clP[h++] = (tiPR[TA]*clR[A] + tiPR[TC]*clR[C] + tiPR[TG]*clR[G] + tiPR[TT]*clR[T])
*likeL[i++];
clR += 4;
tiPR += 16;
i += 16;
}
}
break;
case 2:
for (c=h=0; c<numChars; c++)
{
tiPL = &pL[partitionId[c] * indexMultiplier1];
i = (partitionId[c] * indexMultiplier2) + rState[c];
for (k=0; k<lnumRateCats; k++)
{
clP[h++] = (tiPL[AA]*clL[A] + tiPL[AC]*clL[C] + tiPL[AG]*clL[G] + tiPL[AT]*clL[T])
*likeR[i++];
clP[h++] = (tiPL[CA]*clL[A] + tiPL[CC]*clL[C] + tiPL[CG]*clL[G] + tiPL[CT]*clL[T])
*likeR[i++];
clP[h++] = (tiPL[GA]*clL[A] + tiPL[GC]*clL[C] + tiPL[GG]*clL[G] + tiPL[GT]*clL[T])
*likeR[i++];
clP[h++] = (tiPL[TA]*clL[A] + tiPL[TC]*clL[C] + tiPL[TG]*clL[G] + tiPL[TT]*clL[T])
*likeR[i++];
clL += 4;
tiPL += 16;
i += 16;
}
}
break;
case 3:
for (c=h=0; c<numChars; c++)
{
index = partitionId[c] * indexMultiplier2;
i = index + lState[c];
j = index + rState[c];
for (k=0; k<lnumRateCats; k++)
{
clP[h++] = likeL[i++]*likeR[j++];
clP[h++] = likeL[i++]*likeR[j++];
clP[h++] = likeL[i++]*likeR[j++];
clP[h++] = likeL[i++]*likeR[j++];
i += 16;
j += 16;
}
}
break;
}
}
else if (!strcmp(ratesModel, "sitespec"))
{
indexMultiplier1 = lnumRateCats * N_STATES_SQUARED;
indexMultiplier2 = lnumRateCats * 20;
switch (shortCut)
{
case 0:
for (c=h=0; c<numChars; c++)
{
index = partitionId[c] * indexMultiplier1;
tiPL = &pL[index];
tiPR = &pR[index];
clP[h++] = (tiPL[AA]*clL[A] + tiPL[AC]*clL[C] + tiPL[AG]*clL[G] + tiPL[AT]*clL[T])
*(tiPR[AA]*clR[A] + tiPR[AC]*clR[C] + tiPR[AG]*clR[G] + tiPR[AT]*clR[T]);
clP[h++] = (tiPL[CA]*clL[A] + tiPL[CC]*clL[C] + tiPL[CG]*clL[G] + tiPL[CT]*clL[T])
*(tiPR[CA]*clR[A] + tiPR[CC]*clR[C] + tiPR[CG]*clR[G] + tiPR[CT]*clR[T]);
clP[h++] = (tiPL[GA]*clL[A] + tiPL[GC]*clL[C] + tiPL[GG]*clL[G] + tiPL[GT]*clL[T])
*(tiPR[GA]*clR[A] + tiPR[GC]*clR[C] + tiPR[GG]*clR[G] + tiPR[GT]*clR[T]);
clP[h++] = (tiPL[TA]*clL[A] + tiPL[TC]*clL[C] + tiPL[TG]*clL[G] + tiPL[TT]*clL[T])
*(tiPR[TA]*clR[A] + tiPR[TC]*clR[C] + tiPR[TG]*clR[G] + tiPR[TT]*clR[T]);
clL += 4;
clR += 4;
}
break;
case 1:
for (c=h=0; c<numChars; c++)
{
tiPR = &pR[partitionId[c] * indexMultiplier1];
i = (partitionId[c] * indexMultiplier2) + lState[c];
clP[h++] = (tiPR[AA]*clR[A] + tiPR[AC]*clR[C] + tiPR[AG]*clR[G] + tiPR[AT]*clR[T])
*likeL[i++];
clP[h++] = (tiPR[CA]*clR[A] + tiPR[CC]*clR[C] + tiPR[CG]*clR[G] + tiPR[CT]*clR[T])
*likeL[i++];
clP[h++] = (tiPR[GA]*clR[A] + tiPR[GC]*clR[C] + tiPR[GG]*clR[G] + tiPR[GT]*clR[T])
*likeL[i++];
clP[h++] = (tiPR[TA]*clR[A] + tiPR[TC]*clR[C] + tiPR[TG]*clR[G] + tiPR[TT]*clR[T])
*likeL[i++];
clR += 4;
}
break;
case 2:
for (c=h=0; c<numChars; c++)
{
tiPL = &pL[partitionId[c] * indexMultiplier1];
i = (partitionId[c] * indexMultiplier2) + rState[c];
clP[h++] = (tiPL[AA]*clL[A] + tiPL[AC]*clL[C] + tiPL[AG]*clL[G] + tiPL[AT]*clL[T])
*likeR[i++];
clP[h++] = (tiPL[CA]*clL[A] + tiPL[CC]*clL[C] + tiPL[CG]*clL[G] + tiPL[CT]*clL[T])
*likeR[i++];
clP[h++] = (tiPL[GA]*clL[A] + tiPL[GC]*clL[C] + tiPL[GG]*clL[G] + tiPL[GT]*clL[T])
*likeR[i++];
clP[h++] = (tiPL[TA]*clL[A] + tiPL[TC]*clL[C] + tiPL[TG]*clL[G] + tiPL[TT]*clL[T])
*likeR[i++];
clL += 4;
}
break;
case 3:
for (c=h=0; c<numChars; c++)
{
index = partitionId[c] * indexMultiplier2;
i = index + lState[c];
j = index + rState[c];
clP[h++] = likeL[i++]*likeR[j++];
clP[h++] = likeL[i++]*likeR[j++];
clP[h++] = likeL[i++]*likeR[j++];
clP[h++] = likeL[i++]*likeR[j++];
}
break;
}
}
p->upDateCl = NO;
clUpdateFlag[p->index] = YES;
} // done with interior node if p->upDateCl == YES
} // done with interior node
// deal with scaling
// first check if we need to refresh scalers and potentially shift scaler nodes
// we have to remember scalerIndex because the node may move in the tree
if (refreshScalers == YES)
{
if (n % RESCALE_FREQ == 0)
{
p->scalerNode = YES;
p->scalerIndex = n;
}
else
p->scalerNode = NO;
}
if (p->scalerNode == YES && clUpdateFlag[p->index] == YES)
{
scalerUpdateFlag[p->scalerIndex] = YES;
scP = &clScaler[scalerOffset + (p->scalerIndex)*numChars];
clP = &condLike[condLikeOffset + (p->index)*oneNodeSize];
i = j = 0;
if (lnumRateCats > 1)
{
for (c=0; c<numChars; c++)
{
scaler = 0.0;
for (k=0; k<lnumRateCats; k++)
{
if (clP[i] > scaler)
scaler = clP[i];
i++;
if (clP[i] > scaler)
scaler = clP[i];
i++;
if (clP[i] > scaler)
scaler = clP[i];
i++;
if (clP[i] > scaler)
scaler = clP[i];
i++;
}
for (k=0; k<lnumRateCats; k++)
{
clP[j++] /= scaler;
clP[j++] /= scaler;
clP[j++] /= scaler;
clP[j++] /= scaler;
}
lnScaler[c] -= scP[c]; //subtract old value
scP[c] = log(scaler);
lnScaler[c] += scP[c]; //add new value
}
}
else // lnumRateCats == 1
{
for (c=0; c<numChars; c++)
{
scaler = clP[i++];
if (clP[i] > scaler)
scaler = clP[i];
i++;
if (clP[i] > scaler)
scaler = clP[i];
i++;
if (clP[i] > scaler)
scaler = clP[i];
i++;
clP[j++] /= scaler;
clP[j++] /= scaler;
clP[j++] /= scaler;
clP[j++] /= scaler;
lnScaler[c] -= scP[c]; //subtract old value
scP[c] = log(scaler);
lnScaler[c] += scP[c]; //add new value
}
}
}
} // next node
/* get likelihood at base of tree */
p = root[whichChain*2+whichState]->left;
clP = &condLike[condLikeOffset + (p->index)*oneNodeSize];
(*lnL) = 0.0; // reset lnL
if (!strcmp(ratesModel, "equal") || !strcmp(ratesModel, "sitespec"))
{
for (c=0; c<numChars; c++)
{
like = clP[A] * bs[A] + clP[C] * bs[C] + clP[G] * bs[G] + clP[T] * bs[T];
clP += 4;
//printf ("%d: %1.25lf %lf %d\n", c, like, log(like), numSitesOfPat[c]);
if (like < LIKE_EPSILON) /* likelihood for a site can go to zero when */
{ /* two adjacent terminal branches have zero length. */
printf (" WARNING: In LIKE_EPSILON\n");
goto error_exit;
}
else
{
(*lnL) += (lnScaler[c] + log(like)) * numSitesOfPat[c];
}
}
}
else if (!strcmp(ratesModel, "gamma") || !strcmp(ratesModel, "invariant") || !strcmp(ratesModel, "invgamma") || !strcmp(ratesModel, "ssgamma"))
{
for (c=0; c<numChars; c++)
{
like = 0.0;
for (k=0; k<lnumRateCats; k++)
{
like += (clP[A] * bs[A] + clP[C] * bs[C] + clP[G] * bs[G] + clP[T] * bs[T]) * catFreq[k];
clP += 4;
}
if (like < LIKE_EPSILON) /* likelihood for a site can go to zero when */
{ /* two adjacent terminal branches have zero length. */
printf (" WARNING: In LIKE_EPSILON (%d) %1.30lf\n", c, like);
goto error_exit;
}
else
{
(*lnL) += (lnScaler[c] + log(like)) * numSitesOfPat[c];
}
}
}
else if (!strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "ssadgamma"))
{
/* initialize usedBin */
for (i=0; i<nChar; i++)
usedBin[i] = NO;
lnC = 0.0;
i = 0;
for (c=0; c<numChars; c++)
{
for (k=0; k<lnumRateCats; k++)
{
ratePr[i++] = (clP[A] * bs[A] + clP[C] * bs[C] + clP[G] * bs[G] + clP[T] * bs[T]);
clP += 4;
}
lnC += (lnScaler[c] * numSitesOfPat[c]);
}
localLag = lag[whichChain*2 + whichState];
for (c=nChar-1; c>=0; c--)
{
cn = c*lnumRateCats;
if (patternId[c] >= 0)
{
pat = patternId[c];
if (c + localLag >= nChar)
{
max = 0.0;
for (k=0; k<lnumRateCats; k++)
{
biN[cn + k] = ratePr[pat*lnumRateCats + k];
if (biN[cn + k] > max)
max = biN[cn + k];
}
if (max > 0.0)
{
for (k=0; k<lnumRateCats; k++)
biN[cn + k] /= max;
lnC += log(max);
}
else
{
printf (" ERROR: Scaling factor for adgamma model is less than 0\n");
goto error_exit;
}
}
else
{
for (i=0; i<lnumRateCats; i++)
{
temp = max = 0.0;
for (j=0; j<lnumRateCats; j++)
temp += markovTi[i][j] * biN[(c+localLag)*lnumRateCats + j];
biN[cn + i] = ratePr[pat*lnumRateCats+i] * temp;
if (biN[cn + i] > max)
max = biN[cn + i];
usedBin[c+localLag] = YES;
}
if (max > 0.0)
{
for (k=0; k<lnumRateCats; k++)
biN[cn + k] /= max;
lnC += log(max);
}
else
{
printf (" ERROR: Scaling factor for adgamma model is less than 0\n");
goto error_exit;
}
}
}
else
{
printf (" ERROR: Unidentified pattern\n");
goto error_exit;
}
}
(*lnL) = lnC;
for (c=0; c<nChar; c++)
{
if (usedBin[c] == NO)
{
temp = 0.0;
for (k=0; k<lnumRateCats; k++)
{
temp += (catFreq[k] * biN[c*lnumRateCats + k]);
}
(*lnL) += log(temp);
usedBin[c] = YES;
}
}
}
/* free memory */
# if !defined (SMART_TI_PROBS)
free_psdmatrix (probs);
free (pL);
if (nst == 6 || nst == 12)
{
free_psdmatrix (q);
free (eigenValues);
free_psdmatrix (eigvecs);
free_psdmatrix (inverseEigvecs);
free_pscmatrix (Ceigvecs);
free_pscmatrix (CinverseEigvecs);
if (isComplex != YES)
free (c_ijk);
}
# endif
free (catFreq);
free (likeL);
if (!strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "ssadgamma"))
{
free_psdmatrix(markovTi);
free (ratePr);
free (usedBin);
}
return (NO_ERROR);
error_exit:
# if !defined (SMART_TI_PROBS)
free_psdmatrix (probs);
free (pL);
if (nst == 6 || nst == 12)
{
free_psdmatrix (q);
free (eigenValues);
free_psdmatrix (eigvecs);
free_psdmatrix (inverseEigvecs);
free_pscmatrix (Ceigvecs);
free_pscmatrix (CinverseEigvecs);
if (isComplex != YES)
free (c_ijk);
}
# endif
free (catFreq);
free (likeL);
if (!strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "ssadgamma"))
{
free_psdmatrix(markovTi);
free (ratePr);
free (usedBin);
}
return (ERROR);
#undef N_STATES
#undef N_STATES_SQUARED
#undef N_STATES_CUBE
}
/*-----------------------------------------------------------
LnLikeAA: Superfast version. Core written 2001-04-22
------------------------------------------------------------*/
#define N_STATES_SQUARED 400
#define N_STATES 20
int LnLikeAA (int whichState, int whichChain, int numChars, int numRateCats, double *lnL, int refreshScalers)
{
register int a, b, i, j, k, c, n, m, cn;
int lnumRateCats, lnPartitions, oneMatSize, oneNodeSize,
index, nRates, pat, localLag, *usedBin,
intNodeOffset, condLikeOffset, scalerOffset,
indexMultiplier1, indexMultiplier2, *aState, *lState, *rState, shortCut;
double bs[N_STATES], *pL, *pR, *pA, *catFreq, *catRate, *partRate,
*clL, *clR, *clA, *clP, *scP, *preLikeL, *preLikeR, *preLikeA,
*lnScaler, scaler, like, lnC, *biN, max, temp, correlation,
*ratePr, **markovTi, likeL, likeR, likeA;
TreeNode *p;
# if !defined (SMART_TI_PROBS)
int nPij, isComplex, indexL, indexR, indexA;
double theRate, **probs, **q, *eigenValues, *eigvalsImag, **eigvecs, **inverseEigvecs, *c_ijk;
complex **Ceigvecs, **CinverseEigvecs;
# else
int nForOneState;
# endif
/* initialize offset for transition probabilities */
# if defined (SMART_TI_PROBS)
nForOneState = numNodes*nodeTiSize;
# endif
/* initialize intNodeOffset */
intNodeOffset = whichChain*2*numIntNodes + whichState*numIntNodes;
/* load base frequencies */
index = whichChain*2*nStates + whichState*nStates;
for (i=0; i<N_STATES; i++)
bs[i] = baseFreq[index + i];
/* how many different rates? */
/* lnumRateCats contains a local copy of numRateCats if appropriate, else 1 */
/* lnPartitions contains a local copy of nPartitions if appropriate, else 1 */
/* the code introduced here only makes sure that the number of partitions */
/* or rate categories is set to 1 when appropriate, in case the global variables */
/* are not set to 1 when they are not "in use" */
if (!strcmp(ratesModel, "sitespec") || !strcmp(ratesModel, "ssgamma") || !strcmp(ratesModel, "ssadgamma"))
lnPartitions = nPartitions;
else
lnPartitions = 1;
if (!strcmp(ratesModel, "equal") || !strcmp(ratesModel, "sitespec"))
lnumRateCats = 1;
else
lnumRateCats = numRateCats;
nRates = lnPartitions * lnumRateCats; // number of rates needing P matrices
/* preLikeL, preLikeR and preLikeA will contain the cond likelihoods for */
/* Left, Right and Anc if any of them is a terminal */
preLikeL = (double *)malloc((size_t)(3 * nRates * (N_STATES_SQUARED + N_STATES) * sizeof(double)));
if (!preLikeL)
{
printf ("\n ERROR: Problem allocating preLikeL, preLikeR and preLikeA\n");
goto error_exit;
}
preLikeR = preLikeL + nRates * (N_STATES_SQUARED + N_STATES);
preLikeA = preLikeR + nRates * (N_STATES_SQUARED + N_STATES);
/* allocate memory for the calculations */
/* pL, pR and pA will contain the transition probs for Left, Right and Anc */
/* One transition probability matrix is needed for each possible rate */
# if !defined (SMART_TI_PROBS)
probs = psdmatrix (nStates);
nPij = nRates * N_STATES_SQUARED;
pL = (double *)malloc((size_t)(3 * nPij * sizeof(double)));
if (!pL)
{
printf ("\n ERROR: Problem allocating Pij\n");
goto error_exit;
}
pR = pL + nPij;
pA = pR + nPij;
# endif
/* allocate memory for rate and rate category frequencies */
catFreq = (double *)malloc((size_t) ((2 * lnumRateCats + lnPartitions) * sizeof(double)));
if (!catFreq)
{
printf ("\n ERROR: Problem allocating space for rate multipliers and rate category freqs.\n");
goto error_exit;
}
catRate = catFreq + lnumRateCats;
partRate = catRate + lnumRateCats;
/* allocate memory for autocorrelated gamma models */
if (!strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "ssadgamma"))
{
ratePr = (double *)malloc((size_t) (lnumRateCats * (numChars + nChar) * sizeof(double)));
if (!ratePr)
{
printf ("\n ERROR: Problem allocating ratePr and biN.\n");
goto error_exit;
}
biN = ratePr + lnumRateCats * numChars;
usedBin = (int *)malloc((size_t) (nChar * sizeof(int)));
if (!usedBin)
{
printf ("\n ERROR: Problem allocating usedBin.\n");
goto error_exit;
}
}
// set pointer to the lnSiteScaler for this tree
lnScaler = &lnSiteScaler[whichChain * 2 * numChars + whichState * numChars];
/* fill in rate categories with frequencies and rates by dividing the */
/* gamma distribution into discrete categories, if appropriate */
/* NB! this is inefficient; store values instead */
if (!strcmp(ratesModel,"gamma")|| !strcmp(ratesModel, "ssgamma"))
{
DiscreteGamma (catFreq, catRate, alpha[whichChain*2 + whichState], alpha[whichChain*2 + whichState], lnumRateCats, 0);
}
else if (!strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "ssadgamma"))
{
markovTi = psdmatrix (lnumRateCats);
AutodGamma (markovTi, catFreq, catRate, &correlation, alpha[whichChain*2 + whichState], rateCorrelation[whichChain*2 + whichState], lnumRateCats);
}
else if (!strcmp(ratesModel, "invgamma"))
{
DiscreteGamma (catFreq, catRate, alpha[whichChain*2 + whichState], alpha[whichChain*2 + whichState], lnumRateCats-1, 0);
catRate[lnumRateCats-1] = 0.0;
catFreq[lnumRateCats-1] = invP[whichChain*2 + whichState];
for (i=0; i<lnumRateCats-1; i++)
{
catRate[i] *= 1.0 / (1.0 - invP[whichChain*2 + whichState]);
catFreq[i] *= (1.0 - invP[whichChain*2 + whichState]);
}
}
else if (!strcmp(ratesModel, "invariant"))
{
catRate[0] = 0.0;
catRate[1] = 1.0 / (1.0 - invP[whichChain*2 + whichState]);
catFreq[0] = invP[whichChain*2 + whichState];
catFreq[1] = 1.0 - invP[whichChain*2 + whichState];
}
else { // "sitespec" or "equal"
catRate[0] = 1.0;
catFreq[0] = 1.0;
}
/* initialize partition rates, if appropriate */
if (lnPartitions > 1)
{
for (i=0; i<lnPartitions; i++)
partRate[i] = scaledRates[whichChain*2*lnPartitions + whichState*lnPartitions + i];
}
else
partRate[0] = 1.0;
/* get eigenvalues and eigenvectors for AAQ matrix */
# if !defined (SMART_TI_PROBS)
q = psdmatrix (N_STATES);
eigenValues = (double *)malloc((size_t) (2 * N_STATES * sizeof(double)));
if (!eigenValues)
{
printf ("\n ERROR: Problem allocating eigenValues and eigvalsImag.\n");
goto error_exit;
}
eigvalsImag = eigenValues + N_STATES;
eigvecs = psdmatrix (N_STATES);
inverseEigvecs = psdmatrix (N_STATES);
Ceigvecs = pscmatrix (N_STATES);
CinverseEigvecs = pscmatrix (N_STATES);
if (SetAAQMatrix (q, whichState, whichChain) == ERROR)
goto error_exit;
isComplex = GetEigens (N_STATES, q, eigenValues, eigvalsImag, eigvecs, inverseEigvecs, Ceigvecs, CinverseEigvecs);
if (isComplex == NO)
{
c_ijk = (double *)malloc((size_t) (8000 * sizeof(double)));
if (!c_ijk)
{
printf ("\n ERROR: Problem allocating c_ijk.\n");
goto error_exit;
}
CalcCijk (c_ijk, N_STATES, eigvecs, inverseEigvecs);
}
# endif
/* how large is the information for one tree and one node ?*/
oneMatSize = numNodes * numChars * lnumRateCats * N_STATES;
oneNodeSize = numChars * lnumRateCats * N_STATES;
/* calculate indices */
condLikeOffset = whichChain*2*oneMatSize + whichState*oneMatSize;
scalerOffset = whichChain*2*numIntNodes*numChars + whichState*numIntNodes*numChars;
/* pass down tree */
for (n=0; n<numIntNodes; n++)
{
p = intNodeDownPassSeq[intNodeOffset + n];
// for debugging purposes
// set all nodes to update
// p->upDateCl = YES;
clUpdateFlag[p->index] = NO;
if (p->anc->anc == NULL && treeModel == UNROOTED)
{
if (p->upDateCl == YES)
{
//printf ("visiting basal node %d\n", p->index);
/* get transition probabilities */
# if defined (SMART_TI_PROBS)
pL = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (p->left->index)*nodeTiSize);
pR = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (p->right->index)*nodeTiSize);
pA = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (p->index)*nodeTiSize);
# else
for (m=indexL=indexR=indexA=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
theRate = partRate[m] * catRate[k];
// calculate transition probabilities for left branch
if (isComplex == NO)
CalcPij (c_ijk, N_STATES, eigenValues, p->left->length, theRate, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, N_STATES, probs, p->left->length, theRate) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<N_STATES; i++)
for (j=0; j<N_STATES; j++)
pL[indexL++] = probs[i][j];
// calculate transition probabilities for right branch
if (isComplex == NO)
CalcPij (c_ijk, N_STATES, eigenValues, p->right->length, theRate, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, N_STATES, probs, p->right->length, theRate) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<N_STATES; i++)
for (j=0; j<N_STATES; j++)
pR[indexR++] = probs[i][j];
// calculate transition probabilities for ancestral branch
if (isComplex == NO)
CalcPij (c_ijk, N_STATES, eigenValues, p->length, theRate, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, N_STATES, probs, p->length, theRate) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<N_STATES; i++)
for (j=0; j<N_STATES; j++)
pA[indexA++] = probs[i][j];
}
}
# endif
if (!strcmp(ratesModel, "invariant") || !strcmp(ratesModel, "invgamma"))
{
for (i=0; i<nodeTiSize; i++)
{
if (pL[i] < 0.0)
pL[i] = 0.0;
if (pR[i] < 0.0)
pR[i] = 0.0;
if (pA[i] < 0.0)
pA[i] = 0.0;
}
}
shortCut = 0;
/* calculate likelihoods of site patterns for left branch if terminal */
if (p->left->left == NULL && isPartAmbig[p->left->index] == NO)
{
shortCut |= 1;
lState = termState + p->left->index * numChars;
for (m=a=b=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
for (i=0; i<N_STATES; i++)
for (j=i+b; j<N_STATES_SQUARED+b; j+=N_STATES)
preLikeL[a++] = pL[j] + ((seqErrorProb - N_STATES*seqErrorProb*pL[j])/19.0);
/* for ambiguous */
for (i=0; i<N_STATES; i++)
preLikeL[a++] = 1.0;
b += N_STATES_SQUARED;
}
}
}
/* calculate likelihoods of site patterns for right branch if terminal */
if (p->right->left == NULL && isPartAmbig[p->right->index] == NO)
{
shortCut |= 2;
rState = termState + p->right->index * numChars;
for (m=a=b=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
for (i=0; i<N_STATES; i++)
for (j=i+b; j<N_STATES_SQUARED+b; j+=N_STATES)
preLikeR[a++] = pR[j] + ((seqErrorProb - N_STATES*seqErrorProb*pR[j])/19.0);
/* for ambiguous */
for (i=0; i<N_STATES; i++)
preLikeR[a++] = 1.0;
b += N_STATES_SQUARED;
}
}
}
/* calculate likelihoods of site patterns for anc branch, always terminal */
if (isPartAmbig[p->anc->index] == YES)
{
shortCut = 4;
}
else
{
aState = termState + p->anc->index * numChars;
for (m=a=b=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
for (i=0; i<N_STATES; i++)
for (j=i+b; j<N_STATES_SQUARED+b; j+=N_STATES)
preLikeA[a++] = pA[j] + ((seqErrorProb - N_STATES*seqErrorProb*pA[j])/19.0);
/* for ambiguous */
for (i=0; i<N_STATES; i++)
preLikeA[a++] = 1.0;
b += N_STATES_SQUARED;
}
}
}
/* calculate conditional likelihoods */
/* first set pointers to cond likes of left, right, p and anc */
clL = &condLike[condLikeOffset + (p->left->index)*oneNodeSize];
clR = &condLike[condLikeOffset + (p->right->index)*oneNodeSize];
clA = &condLike[condLikeOffset + (p->anc->index)*oneNodeSize];
clP = &condLike[condLikeOffset + (p->index)*oneNodeSize];
/* then branch to models */
if (!strcmp(ratesModel, "equal"))
{
switch (shortCut)
{
case 4: // anc is partially ambiguous, do not use any shortcut
for (c=0; c<numChars; c++)
{
for (i=m=0; i<N_STATES; i++)
{
likeL = likeR = likeA = 0.0;
for (j=0; j<N_STATES; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m]*clR[j];
likeA += pA[m++]*clA[j];
}
*(clP++) = likeL * likeR * likeA;
}
clL += N_STATES;
clR += N_STATES;
clA += N_STATES;
}
break;
case 0: // only anc is terminal
for (c=0; c<numChars; c++)
{
a = aState[c];
for (i=m=0; i<N_STATES; i++)
{
likeL = likeR = 0.0;
for (j=0; j<N_STATES; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m++]*clR[j];
}
*(clP++) = likeL * likeR * preLikeA[a++];
}
clL += N_STATES;
clR += N_STATES;
}
break;
case 1: // left is terminal
case 3: // both left and right are terminal; this is a 3-taxon tree
for (c=0; c<numChars; c++)
{
a = aState[c];
b = lState[c];
for (i=m=0; i<N_STATES; i++)
{
likeR = 0.0;
for (j=0; j<N_STATES; j++)
{
likeR += pR[m++]*clR[j];
}
*(clP++) = preLikeL[b++] * likeR * preLikeA[a++];
}
clR += N_STATES;
}
break;
case 2: // right is terminal
for (c=0; c<numChars; c++)
{
a = aState[c];
b = rState[c];
for (i=m=0; i<N_STATES; i++)
{
likeL = 0.0;
for (j=0; j<N_STATES; j++)
{
likeL += pL[m++]*clL[j];
}
*(clP++) = likeL * preLikeR[b++] * preLikeA[a++];
}
clL += N_STATES;
}
break;
}
}
else if (!strcmp(ratesModel, "gamma") || !strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "invariant") || !strcmp(ratesModel, "invgamma"))
{
switch (shortCut)
{
case 4: // anc is partially ambiguous, do not use any shortcut
for (c=0; c<numChars; c++)
{
for (k=m=0; k<lnumRateCats; k++)
{
for (i=0; i<N_STATES; i++)
{
likeL = likeR = likeA = 0.0;
for (j=0; j<N_STATES; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m]*clR[j];
likeA += pA[m++]*clA[j];
}
*(clP++) = likeL * likeR * likeA;
}
clL += N_STATES;
clR += N_STATES;
clA += N_STATES;
}
}
break;
case 0: // only anc is terminal
for (c=0; c<numChars; c++)
{
a = aState[c];
for (k=m=0; k<lnumRateCats; k++)
{
for (i=0; i<N_STATES; i++)
{
likeL = likeR = 0.0;
for (j=0; j<N_STATES; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m++]*clR[j];
}
*(clP++) = likeL * likeR * preLikeA[a++];
}
clL += N_STATES;
clR += N_STATES;
a += N_STATES_SQUARED;
}
}
break;
case 1: // left is terminal
case 3: // both left and right are terminal
for (c=0; c<numChars; c++)
{
a = aState[c];
b = lState[c];
for (k=m=0; k<lnumRateCats; k++)
{
for (i=0; i<N_STATES; i++)
{
likeR = 0.0;
for (j=0; j<N_STATES; j++)
{
likeR += pR[m++]*clR[j];
}
*(clP++) = preLikeL[b++] * likeR * preLikeA[a++];
}
clR += N_STATES;
a += N_STATES_SQUARED;
b += N_STATES_SQUARED;
}
}
break;
case 2: // right is terminal
for (c=0; c<numChars; c++)
{
a = aState[c];
b = rState[c];
for (k=m=0; k<lnumRateCats; k++)
{
for (i=0; i<N_STATES; i++)
{
likeL = 0.0;
for (j=0; j<N_STATES; j++)
{
likeL += pL[m++]*clL[j];
}
*(clP++) = likeL * preLikeR[b++] * preLikeA[a++];
}
clL += N_STATES;
a += N_STATES_SQUARED;
b += N_STATES_SQUARED;
}
}
break;
}
}
else if (!strcmp(ratesModel, "ssgamma") || !strcmp(ratesModel, "ssadgamma"))
{
indexMultiplier1 = lnumRateCats * N_STATES_SQUARED;
indexMultiplier2 = lnumRateCats * (N_STATES_SQUARED + N_STATES);
switch (shortCut)
{
case 4: // anc is partially ambiguous, do not use any shortcut
for (c=0; c<numChars; c++)
{
m = partitionId[c]*indexMultiplier1;
for (k=0; k<lnumRateCats; k++)
{
for (i=0; i<N_STATES; i++)
{
likeL = likeR = likeA = 0.0;
for (j=0; j<N_STATES; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m]*clR[j];
likeA += pA[m++]*clA[j];
}
*(clP++) = likeL * likeR * likeA;
}
clL += N_STATES;
clR += N_STATES;
clA += N_STATES;
}
}
break;
case 0: // only anc is terminal
for (c=0; c<numChars; c++)
{
m = partitionId[c]*indexMultiplier1;
a = aState[c] + (partitionId[c]*indexMultiplier2);
for (k=0; k<lnumRateCats; k++)
{
for (i=0; i<N_STATES; i++)
{
likeL = likeR = 0.0;
for (j=0; j<N_STATES; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m++]*clR[j];
}
*(clP++) = likeL * likeR * preLikeA[a++];
}
clL += N_STATES;
clR += N_STATES;
a += N_STATES_SQUARED;
}
}
break;
case 1: // left is terminal
case 3: // both left and right are terminal
for (c=0; c<numChars; c++)
{
m = partitionId[c]*indexMultiplier1;
index = partitionId[c] * indexMultiplier2;
a = aState[c] + index;
b = lState[c] + index;
for (k=0; k<lnumRateCats; k++)
{
for (i=0; i<N_STATES; i++)
{
likeR = 0.0;
for (j=0; j<N_STATES; j++)
{
likeR += pR[m++]*clR[j];
}
*(clP++) = preLikeL[b++] * likeR * preLikeA[a++];
}
clR += N_STATES;
a += N_STATES_SQUARED;
b += N_STATES_SQUARED;
}
}
break;
case 2: // right is terminal
for (c=0; c<numChars; c++)
{
m = partitionId[c]*indexMultiplier1;
index = partitionId[c] * indexMultiplier2;
a = aState[c] + index;
b = rState[c] + index;
for (k=0; k<lnumRateCats; k++)
{
for (i=0; i<N_STATES; i++)
{
likeL = 0.0;
for (j=0; j<N_STATES; j++)
{
likeL += pL[m++]*clL[j];
}
*(clP++) = likeL * preLikeR[b++] * preLikeA[a++];
}
clL += N_STATES;
a += N_STATES_SQUARED;
b += N_STATES_SQUARED;
}
}
break;
}
}
else if (!strcmp(ratesModel, "sitespec"))
{
indexMultiplier1 = N_STATES_SQUARED;
indexMultiplier2 = (N_STATES_SQUARED + N_STATES);
switch (shortCut)
{
case 4: // anc is partially ambiguous, do not use any shortcut
for (c=0; c<numChars; c++)
{
m = partitionId[c]*indexMultiplier1;
for (i=0; i<N_STATES; i++)
{
likeL = likeR = likeA = 0.0;
for (j=0; j<N_STATES; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m]*clR[j];
likeA += pA[m++]*clA[j];
}
*(clP++) = likeL * likeR * likeA;
}
clL += N_STATES;
clR += N_STATES;
clA += N_STATES;
}
break;
case 0: // only anc is terminal
for (c=0; c<numChars; c++)
{
m = partitionId[c]*indexMultiplier1;
a = aState[c] + (partitionId[c]*indexMultiplier2);
for (i=0; i<N_STATES; i++)
{
likeL = likeR = 0.0;
for (j=0; j<N_STATES; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m++]*clR[j];
}
*(clP++) = likeL * likeR * preLikeA[a++];
}
clL += N_STATES;
clR += N_STATES;
a += N_STATES_SQUARED;
}
break;
case 1: // left is terminal
case 3: // both left and right are terminal
for (c=0; c<numChars; c++)
{
m = partitionId[c]*indexMultiplier1;
index = partitionId[c]*indexMultiplier2;
a = aState[c] + index;
b = lState[c] + index;
for (i=0; i<N_STATES; i++)
{
likeR = 0.0;
for (j=0; j<N_STATES; j++)
{
likeR += pR[m++]*clR[j];
}
*(clP++) = preLikeL[b++] * likeR * preLikeA[a++];
}
clR += N_STATES;
a += N_STATES_SQUARED;
b += N_STATES_SQUARED;
}
break;
case 2: // right is terminal
for (c=0; c<numChars; c++)
{
m = partitionId[c]*indexMultiplier1;
index = partitionId[c]*indexMultiplier2;
a = aState[c] + index;
b = rState[c] + index;
for (i=0; i<N_STATES; i++)
{
likeL = 0.0;
for (j=0; j<N_STATES; j++)
{
likeL += pL[m++]*clL[j];
}
*(clP++) = likeL * preLikeR[b++] * preLikeA[a++];
}
clL += N_STATES;
a += N_STATES_SQUARED;
b += N_STATES_SQUARED;
}
break;
}
}
p->upDateCl = NO;
clUpdateFlag[p->index] = YES;
} // done if p->upDateCl == YES for internal root node
} // done with internal root node
else
{
if (p->upDateCl == YES)
{
//printf ("visiting interior node %d\n", p->index);
/* get transition probabilities */
# if defined (SMART_TI_PROBS)
pL = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (p->left->index)*nodeTiSize);
pR = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (p->right->index)*nodeTiSize);
# else
for (m=indexL=indexR=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
theRate = partRate[m] * catRate[k];
// calculate transition probabilities for left branch
if (isComplex == NO)
CalcPij (c_ijk, N_STATES, eigenValues, p->left->length, theRate, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, N_STATES, probs, p->left->length, theRate) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<N_STATES; i++)
for (j=0; j<N_STATES; j++)
pL[indexL++] = probs[i][j];
// calculate transition probabilities for right branch
if (isComplex == NO)
CalcPij (c_ijk, N_STATES, eigenValues, p->right->length, theRate, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, N_STATES, probs, p->right->length, theRate) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<N_STATES; i++)
for (j=0; j<N_STATES; j++)
pR[indexR++] = probs[i][j];
}
}
# endif
if (!strcmp(ratesModel, "invariant") || !strcmp(ratesModel, "invgamma"))
{
for (i=0; i<nodeTiSize; i++)
{
if (pL[i] < 0.0)
pL[i] = 0.0;
if (pR[i] < 0.0)
pR[i] = 0.0;
}
}
shortCut = 0;
/* calculate likelihoods of site patterns for left branch if terminal */
if (p->left->left == NULL && isPartAmbig[p->left->index] == NO)
{
shortCut |= 1;
lState = termState + p->left->index * numChars;
for (m=a=b=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
for (i=0; i<N_STATES; i++)
for (j=i+b; j<N_STATES_SQUARED+b; j+=N_STATES)
preLikeL[a++] = pL[j] + ((seqErrorProb - N_STATES*seqErrorProb*pL[j])/19.0);
/* for ambiguous */
for (i=0; i<N_STATES; i++)
preLikeL[a++] = 1.0;
b += N_STATES_SQUARED;
}
}
}
/* calculate likelihoods of site patterns for right branch if terminal */
if (p->right->left == NULL && isPartAmbig[p->right->index] == NO)
{
shortCut |= 2;
rState = termState + p->right->index * numChars;
for (m=a=b=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
for (i=0; i<N_STATES; i++)
for (j=i+b; j<N_STATES_SQUARED+b; j+=N_STATES)
preLikeR[a++] = pR[j] + ((seqErrorProb - N_STATES*seqErrorProb*pR[j])/19.0);
/* for ambiguous */
for (i=0; i<N_STATES; i++)
preLikeR[a++] = 1.0;
b += N_STATES_SQUARED;
}
}
}
/* calculate conditional likelihoods */
/* first set pointers to cond likes of left, right and p */
clL = &condLike[condLikeOffset + (p->left->index)*oneNodeSize];
clR = &condLike[condLikeOffset + (p->right->index)*oneNodeSize];
clP = &condLike[condLikeOffset + (p->index)*oneNodeSize];
/* then branch to models */
if (!strcmp(ratesModel, "equal"))
{
switch (shortCut)
{
case 0: // none is terminal
for (c=0; c<numChars; c++)
{
for (i=m=0; i<N_STATES; i++)
{
likeL = likeR = 0.0;
for (j=0; j<N_STATES; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m++]*clR[j];
}
*(clP++) = likeL * likeR;
}
clL += N_STATES;
clR += N_STATES;
}
break;
case 1: // left is terminal
for (c=0; c<numChars; c++)
{
a = lState[c];
for (i=m=0; i<N_STATES; i++)
{
likeR = 0.0;
for (j=0; j<N_STATES; j++)
{
likeR += pR[m++]*clR[j];
}
*(clP++) = preLikeL[a++] * likeR;
}
clR += N_STATES;
}
break;
case 2: // right is terminal
for (c=0; c<numChars; c++)
{
a = rState[c];
for (i=m=0; i<N_STATES; i++)
{
likeL = 0.0;
for (j=0; j<N_STATES; j++)
{
likeL += pL[m++]*clL[j];
}
*(clP++) = likeL * preLikeR[a++];
}
clL += N_STATES;
}
break;
case 3: // both left and right are terminal
for (c=0; c<numChars; c++)
{
a = lState[c];
b = rState[c];
for (i=m=0; i<N_STATES; i++)
{
*(clP++) = preLikeL[a++] * preLikeR[b++];
}
}
break;
}
}
else if (!strcmp(ratesModel, "gamma") || !strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "invariant") || !strcmp(ratesModel, "invgamma"))
{
switch (shortCut)
{
case 0: // none is terminal
for (c=0; c<numChars; c++)
{
for (k=m=0; k<lnumRateCats; k++)
{
for (i=0; i<N_STATES; i++)
{
likeL = likeR = 0.0;
for (j=0; j<N_STATES; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m++]*clR[j];
}
*(clP++) = likeL * likeR;
}
clL += N_STATES;
clR += N_STATES;
}
}
break;
case 1: // left is terminal
for (c=0; c<numChars; c++)
{
a = lState[c];
for (k=m=0; k<lnumRateCats; k++)
{
for (i=0; i<N_STATES; i++)
{
likeR = 0.0;
for (j=0; j<N_STATES; j++)
{
likeR += pR[m++]*clR[j];
}
*(clP++) = preLikeL[a++] * likeR;
}
clR += N_STATES;
a += N_STATES_SQUARED;
}
}
break;
case 2: // right is terminal
for (c=0; c<numChars; c++)
{
a = rState[c];
for (k=m=0; k<lnumRateCats; k++)
{
for (i=0; i<N_STATES; i++)
{
likeL = 0.0;
for (j=0; j<N_STATES; j++)
{
likeL += pL[m++]*clL[j];
}
*(clP++) = likeL * preLikeR[a++];
}
clL += N_STATES;
a += N_STATES_SQUARED;
}
}
break;
case 3: // both left and right are terminal
for (c=0; c<numChars; c++)
{
a = lState[c];
b = rState[c];
for (k=0; k<lnumRateCats; k++)
{
for (i=0; i<N_STATES; i++)
{
*(clP++) = preLikeL[a++] * preLikeR[b++];
}
a += N_STATES_SQUARED;
b += N_STATES_SQUARED;
}
}
break;
}
}
else if (!strcmp(ratesModel, "ssgamma") || !strcmp(ratesModel, "ssadgamma"))
{
indexMultiplier1 = lnumRateCats * N_STATES_SQUARED;
indexMultiplier2 = lnumRateCats * (N_STATES_SQUARED + N_STATES);
switch (shortCut)
{
case 0: // none is terminal
for (c=0; c<numChars; c++)
{
m = partitionId[c]*indexMultiplier1;
for (k=0; k<lnumRateCats; k++)
{
for (i=0; i<N_STATES; i++)
{
likeL = likeR = 0.0;
for (j=0; j<N_STATES; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m++]*clR[j];
}
*(clP++) = likeL * likeR;
}
clL += N_STATES;
clR += N_STATES;
}
}
break;
case 1: // left is terminal
for (c=0; c<numChars; c++)
{
m = partitionId[c]*indexMultiplier1;
a = lState[c] + (partitionId[c]*indexMultiplier2);
for (k=0; k<lnumRateCats; k++)
{
for (i=0; i<N_STATES; i++)
{
likeR = 0.0;
for (j=0; j<N_STATES; j++)
{
likeR += pR[m++]*clR[j];
}
*(clP++) = preLikeL[a++] * likeR;
}
clR += N_STATES;
a += N_STATES_SQUARED;
}
}
break;
case 2: // right is terminal
for (c=0; c<numChars; c++)
{
m = partitionId[c]*indexMultiplier1;
a = rState[c] + partitionId[c] * indexMultiplier2;
for (k=0; k<lnumRateCats; k++)
{
for (i=0; i<N_STATES; i++)
{
likeL = 0.0;
for (j=0; j<N_STATES; j++)
{
likeL += pL[m++]*clL[j];
}
*(clP++) = likeL * preLikeR[a++];
}
clL += N_STATES;
a += N_STATES_SQUARED;
}
}
break;
case 3: // both left and right are terminal
for (c=0; c<numChars; c++)
{
m = partitionId[c]*indexMultiplier1;
index = partitionId[c] * indexMultiplier2;
a = lState[c] + index;
b = rState[c] + index;
for (k=0; k<lnumRateCats; k++)
{
for (i=0; i<N_STATES; i++)
{
*(clP++) = preLikeL[a++] * preLikeR[b++];
}
a += N_STATES_SQUARED;
b += N_STATES_SQUARED;
}
}
break;
}
}
else if (!strcmp(ratesModel, "sitespec"))
{
indexMultiplier1 = N_STATES_SQUARED;
indexMultiplier2 = (N_STATES_SQUARED + N_STATES);
switch (shortCut)
{
case 0: // none is terminal
for (c=0; c<numChars; c++)
{
m = partitionId[c]*indexMultiplier1;
for (i=0; i<N_STATES; i++)
{
likeL = likeR = 0.0;
for (j=0; j<N_STATES; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m++]*clR[j];
}
*(clP++) = likeL * likeR;
}
clL += N_STATES;
clR += N_STATES;
}
break;
case 1: // left is terminal
for (c=0; c<numChars; c++)
{
m = partitionId[c]*indexMultiplier1;
a = lState[c] + (partitionId[c]*indexMultiplier2);
for (i=0; i<N_STATES; i++)
{
likeR = 0.0;
for (j=0; j<N_STATES; j++)
{
likeR += pR[m++]*clR[j];
}
*(clP++) = preLikeL[a++] * likeR;
}
clR += N_STATES;
a += N_STATES_SQUARED;
}
break;
case 2: // right is terminal
for (c=0; c<numChars; c++)
{
m = partitionId[c]*indexMultiplier1;
a = rState[c] + (partitionId[c] * indexMultiplier2);
for (i=0; i<N_STATES; i++)
{
likeL = 0.0;
for (j=0; j<N_STATES; j++)
{
likeL += pL[m++]*clL[j];
}
*(clP++) = likeL * preLikeR[a++];
}
clL += N_STATES;
a += N_STATES_SQUARED;
}
break;
case 3: // both left and right are terminal
for (c=0; c<numChars; c++)
{
m = partitionId[c]*indexMultiplier1;
index = partitionId[c] * indexMultiplier2;
a = lState[c] + index;
b = rState[c] + index;
for (i=0; i<N_STATES; i++)
{
*(clP++) = preLikeL[a++] * preLikeR[b++];
}
a += N_STATES_SQUARED;
b += N_STATES_SQUARED;
}
break;
}
}
p->upDateCl = NO;
clUpdateFlag[p->index] = YES;
} // done with interior node if p->upDateCl == YES
} // done with interior node
// deal with scaling
// first check if we need to refresh scalers and potentially shift scaler nodes
// we have to remember scalerIndex because the node may move in the tree
if (refreshScalers == YES)
{
if (n % RESCALE_FREQ == 0)
{
p->scalerNode = YES;
p->scalerIndex = n;
}
else
p->scalerNode = NO;
}
if (p->scalerNode == YES && clUpdateFlag[p->index] == YES)
{
scalerUpdateFlag[p->scalerIndex] = YES;
scP = &clScaler[scalerOffset + (p->scalerIndex)*numChars];
clP = &condLike[condLikeOffset + (p->index)*oneNodeSize];
i = j = 0;
for (c=0; c<numChars; c++)
{
scaler = 0.0;
for (k=0; k<lnumRateCats; k++)
{
for (m=0; m<N_STATES; m++)
{
if (clP[i] > scaler)
scaler = clP[i];
i++;
}
}
for (k=0; k<lnumRateCats; k++)
{
for (m=0; m<N_STATES; m++)
clP[j++] /= scaler;
}
lnScaler[c] -= scP[c]; //subtract old value
scP[c] = log(scaler);
lnScaler[c] += scP[c]; //add new value
}
}
} // next node
/* get likelihood at base of tree */
p = root[whichChain*2+whichState]->left;
clP = &condLike[condLikeOffset + (p->index)*oneNodeSize];
(*lnL) = 0.0; // reset lnL
if (!strcmp(ratesModel, "equal") || !strcmp(ratesModel, "sitespec"))
{
for (c=0; c<numChars; c++)
{
like = 0.0;
for (i=0; i<N_STATES; i++)
like += ((*(clP++)) * bs[i]);
//printf ("%d: %1.25lf %lf %d\n", c, like, log(like), numSitesOfPat[c]);
if (like < LIKE_EPSILON) /* likelihood for a site can go to zero when */
{ /* two adjacent terminal branches have zero length. */
printf (" WARNING: In LIKE_EPSILON\n");
goto error_exit;
}
else
{
(*lnL) += (lnScaler[c] + log(like)) * numSitesOfPat[c];
}
}
}
else if (!strcmp(ratesModel, "gamma") || !strcmp(ratesModel, "invariant") || !strcmp(ratesModel, "invgamma") || !strcmp(ratesModel, "ssgamma"))
{
for (c=0; c<numChars; c++)
{
like = 0.0;
for (k=0; k<lnumRateCats; k++)
{
for (i=0; i<N_STATES; i++)
like += ((*(clP++)) * bs[i]) * catFreq[k];
}
if (like < LIKE_EPSILON) /* likelihood for a site can go to zero when */
{ /* two adjacent terminal branches have zero length. */
printf (" WARNING: In LIKE_EPSILON (%d) %1.30lf\n", c, like);
goto error_exit;
}
else
{
(*lnL) += (lnScaler[c] + log(like)) * numSitesOfPat[c];
}
}
}
else if (!strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "ssadgamma"))
{
/* initialize usedBin */
for (i=0; i<nChar; i++)
usedBin[i] = NO;
lnC = 0.0;
m = j = 0;
for (c=0; c<numChars; c++)
{
for (k=0; k<lnumRateCats; k++)
{
like = 0.0;
for (i=0; i<N_STATES; i++)
like += clP[j++] * bs[i];
ratePr[m++] = like;
}
lnC += (lnScaler[c] * numSitesOfPat[c]);
}
localLag = lag[whichChain*2 + whichState];
for (c=nChar-1; c>=0; c--)
{
cn = c*lnumRateCats;
if (patternId[c] >= 0)
{
pat = patternId[c];
if (c + localLag >= nChar)
{
max = 0.0;
for (k=0; k<lnumRateCats; k++)
{
biN[cn + k] = ratePr[pat*lnumRateCats + k];
if (biN[cn + k] > max)
max = biN[cn + k];
}
if (max > 0.0)
{
for (k=0; k<lnumRateCats; k++)
biN[cn + k] /= max;
lnC += log(max);
}
else
{
printf (" ERROR: Scaling factor for adgamma model is less than 0\n");
goto error_exit;
}
}
else
{
for (i=0; i<lnumRateCats; i++)
{
temp = max = 0.0;
for (j=0; j<lnumRateCats; j++)
temp += markovTi[i][j] * biN[(c+localLag)*lnumRateCats + j];
biN[cn + i] = ratePr[pat*lnumRateCats+i] * temp;
if (biN[cn + i] > max)
max = biN[cn + i];
usedBin[c+localLag] = YES;
}
if (max > 0.0)
{
for (k=0; k<lnumRateCats; k++)
biN[cn + k] /= max;
lnC += log(max);
}
else
{
printf (" ERROR: Scaling factor for adgamma model is less than 0\n");
goto error_exit;
}
}
}
else
{
printf (" ERROR: Unidentified pattern\n");
goto error_exit;
}
}
(*lnL) = lnC;
for (c=0; c<nChar; c++)
{
if (usedBin[c] == NO)
{
temp = 0.0;
for (k=0; k<lnumRateCats; k++)
{
temp += (catFreq[k] * biN[c*lnumRateCats + k]);
}
(*lnL) += log(temp);
usedBin[c] = YES;
}
}
}
/* free memory */
# if !defined (SMART_TI_PROBS)
free_psdmatrix (probs);
free (pL);
free_psdmatrix (q);
free (eigenValues);
free_psdmatrix (eigvecs);
free_psdmatrix (inverseEigvecs);
free_pscmatrix (Ceigvecs);
free_pscmatrix (CinverseEigvecs);
if (isComplex != YES)
free (c_ijk);
# endif
free (catFreq);
free (preLikeL);
if (!strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "ssadgamma"))
{
free_psdmatrix(markovTi);
free (ratePr);
free (usedBin);
}
return (NO_ERROR);
error_exit:
# if !defined (SMART_TI_PROBS)
free_psdmatrix (probs);
free (pL);
free_psdmatrix (q);
free (eigenValues);
free_psdmatrix (eigvecs);
free_psdmatrix (inverseEigvecs);
free_pscmatrix (Ceigvecs);
free_pscmatrix (CinverseEigvecs);
if (isComplex != YES)
free (c_ijk);
# endif
free (catFreq);
free (preLikeL);
if (!strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "ssadgamma"))
{
free_psdmatrix(markovTi);
free (ratePr);
free (usedBin);
}
return (ERROR);
#undef N_STATES_SQUARED
#undef N_STATES
}
/*-----------------------------------------------------------
LnLikeCodon: Superfast version of the codon likelihood function
Written 2001-04-04
------------------------------------------------------------*/
int LnLikeCodon (int whichState, int whichChain, int numChars, double *lnL, int refreshScalers)
{
register int i, j, k, c, n, m, cn, a, b;
int nOmegaCats, oneMatSize, oneNodeSize,
index, pat, isFirst,
intNodeOffset, condLikeOffset, scalerOffset,
lnStates, lnStatesSquared, lnStatesCube, shortCut, *lState, *rState, *aState;
double *bs, *pL, *pR, *pA, *clL, *clR, *clA, *clP, *scP,
*lnScaler, scaler, like, lnC, *biN, max, temp, *omegaPr, markovTi[3][3],
likeL, likeR, likeA, likePos, likeNeu, likePur, *preLikeL, *preLikeR, *preLikeA;
TreeNode *p;
# if defined (SMART_TI_PROBS)
int nForOneState;
# else
int nPij, isComplex, indexL, indexR, indexA, isComplex2, isComplex3;
double lkappa, theRate, **probs, **q, *eigenValues, *eigvalsImag, **eigvecs, **inverseEigvecs, *c_ijk,
*eigenValues2, *eigvalsImag2, **eigvecs2, **inverseEigvecs2, *c_ijk2,
*eigenValues3, *eigvalsImag3, **eigvecs3, **inverseEigvecs3, *c_ijk3;
complex **Ceigvecs, **CinverseEigvecs, **Ceigvecs2, **CinverseEigvecs2,
**Ceigvecs3, **CinverseEigvecs3;
# endif
/* set number of states */
if (!strcmp(codonModelType, "covny98"))
lnStates = 3 * nStates;
else
lnStates = nStates;
lnStatesSquared = lnStates * lnStates;
lnStatesCube = lnStatesSquared * lnStates;
/* initialize offset for transition probabilities */
# if defined (SMART_TI_PROBS)
nForOneState = numNodes*nodeTiSize;
# endif
/* load codon frequencies */
bs = (double *)malloc((size_t) (lnStates * sizeof(double)));
if (!bs)
{
printf ("\n ERROR: Problem allocating bs.\n");
goto error_exit;
}
index = whichChain*2*nStates + whichState*nStates;
if (!strcmp(codonModelType, "covny98"))
{
k = 0;
for (i=0; i<nStates; i++)
{
bs[k] = baseFreq[index + i] * probPur[whichChain*2 + whichState];
k++;
}
for (i=0; i<nStates; i++)
{
bs[k] = baseFreq[index + i] * probNeu[whichChain*2 + whichState];
k++;
}
for (i=0; i<nStates; i++)
{
bs[k] = baseFreq[index + i] * probPos[whichChain*2 + whichState];
k++;
}
}
else
{
for (i=0; i<nStates; i++)
bs[i] = baseFreq[index + i];
}
/* how many different omega categories */
if (!strcmp(codonModelType, "ny98") || !strcmp(codonModelType, "ac1ny98") || !strcmp(codonModelType, "ac2ny98"))
nOmegaCats = 3;
else
nOmegaCats = 1;
/* allocate memory for autocorrelated codon models */
if (!strcmp(codonModelType, "ac1ny98") || !strcmp(codonModelType, "ac2ny98"))
{
omegaPr = (double *)malloc((size_t) (nOmegaCats * (numChars + nChar) * sizeof(double)));
if (!omegaPr)
{
printf ("\n ERROR: Problem allocating omegaPr and biN.\n");
goto error_exit;
}
biN = omegaPr + nOmegaCats * numChars;
}
/* allocate memory for the calculations */
/* pL, pR and pA will contain the transition probs for Left, Right and Anc */
/* One transition probability matrix is needed for each possible omega value */
# if !defined (SMART_TI_PROBS)
probs = psdmatrix (lnStates);
nPij = nOmegaCats * lnStatesSquared;
pL = (double *)malloc((size_t)(3 * nPij * sizeof(double)));
if (!pL)
{
printf ("\n ERROR: Problem allocating Pij\n");
goto error_exit;
}
pR = pL + nPij;
pA = pR + nPij;
# endif
/* preLikeL, preLikeR and preLikeA will contain the cond likelihoods for Left, Right and Anc */
/* if any of them is a terminal with unambiguous codon states or completely ambiguous/gap */
preLikeL = (double *)malloc((size_t)(3 * nOmegaCats * (nStates + 1) * lnStates * sizeof(double)));
if (!preLikeL)
{
printf ("\n ERROR: Problem allocating preLikeL, preLikeR and preLikeA\n");
goto error_exit;
}
preLikeR = preLikeL + nOmegaCats * (nStates + 1) * lnStates;
preLikeA = preLikeR + nOmegaCats * (nStates + 1) * lnStates;
// set pointer to the lnSiteScaler for this tree
lnScaler = &lnSiteScaler[whichChain * 2 * numChars + whichState * numChars];
/* allocate memory for eigenvalues and eigenvectors */
# if !defined (SMART_TI_PROBS)
q = psdmatrix (lnStates);
eigenValues = (double *)malloc((size_t) (2 * lnStates * sizeof(double)));
if (!eigenValues)
{
printf ("\n ERROR: Problem allocating eigenValues and eigvalsImag.\n");
goto error_exit;
}
eigvalsImag = eigenValues + lnStates;
eigvecs = psdmatrix (lnStates);
inverseEigvecs = psdmatrix (lnStates);
Ceigvecs = pscmatrix (lnStates);
CinverseEigvecs = pscmatrix (lnStates);
/* get eigenvalues and eigenvectors for codon Q matrix */
if (!strcmp(codonModelType, "covny98"))
{
if (SetCodonSwitchQMatrix (q, whichState, whichChain, omega[whichChain*2 + whichState], kappa[whichChain*2 + whichState], switchRate[whichChain*4 + whichState*2 + 0]) == ERROR)
goto error_exit;
}
else
{
if (SetCodonQMatrix (q, whichState, whichChain, omega[whichChain*2 + whichState], kappa[whichChain*2 + whichState]) == ERROR)
goto error_exit;
}
isComplex = GetEigens (lnStates, q, eigenValues, eigvalsImag, eigvecs, inverseEigvecs, Ceigvecs, CinverseEigvecs);
if (isComplex == NO)
{
c_ijk = (double *)malloc((size_t) (lnStatesCube * sizeof(double)));
if (!c_ijk)
{
printf ("\n ERROR: Problem allocating c_ijk.\n");
goto error_exit;
}
CalcCijk (c_ijk, lnStates, eigvecs, inverseEigvecs);
}
if (!strcmp(codonModelType, "ny98") || !strcmp(codonModelType, "ac1ny98") || !strcmp(codonModelType, "ac2ny98"))
{
/* these models use several omega categories, one Q matrix needed for each */
/* first set Q matrix for synonymous changes (negative selection) */
eigenValues2 = (double *)malloc((size_t) (2 * lnStates * sizeof(double)));
if (!eigenValues2)
{
printf ("\n ERROR: Problem allocating eigenValues2 and eigvalsImag2.\n");
goto error_exit;
}
eigvalsImag2 = eigenValues2 + lnStates;
eigvecs2 = psdmatrix (lnStates);
inverseEigvecs2 = psdmatrix (lnStates);
Ceigvecs2 = pscmatrix (lnStates);
CinverseEigvecs2 = pscmatrix (lnStates);
if (SetCodonQMatrix (q, whichState, whichChain, 0.0, kappa[whichChain*2 + whichState]) == ERROR)
goto error_exit;
isComplex2 = GetEigens (lnStates, q, eigenValues2, eigvalsImag2, eigvecs2, inverseEigvecs2, Ceigvecs2, CinverseEigvecs2);
if (isComplex2 == NO)
{
c_ijk2 = (double *)malloc((size_t) (lnStatesCube * sizeof(double)));
if (!c_ijk2)
{
printf ("\n ERROR: Problem allocating c_ijk2.\n");
goto error_exit;
}
CalcCijk (c_ijk2, lnStates, eigvecs2, inverseEigvecs2);
}
/* then set Q matrix for nonsynonymous changes (positive selection) */
eigenValues3 = (double *)malloc((size_t) (2 * lnStates * sizeof(double)));
if (!eigenValues2)
{
printf ("\n ERROR: Problem allocating eigenValues2 and eigvalsImag2.\n");
goto error_exit;
}
eigvalsImag3 = eigenValues2 + lnStates;
eigvecs3 = psdmatrix (lnStates);
inverseEigvecs3 = psdmatrix (lnStates);
Ceigvecs3 = pscmatrix (lnStates);
CinverseEigvecs3 = pscmatrix (lnStates);
if (SetCodonQMatrix (q, whichState, whichChain, 1.0, kappa[whichChain*2 + whichState]) == ERROR)
goto error_exit;
isComplex3 = GetEigens (lnStates, q, eigenValues3, eigvalsImag3, eigvecs3, inverseEigvecs3, Ceigvecs3, CinverseEigvecs3);
if (isComplex3 == NO)
{
c_ijk3 = (double *)malloc((size_t) (lnStatesCube * sizeof(double)));
if (!c_ijk3)
{
printf ("\n ERROR: Problem allocating c_ijk3.\n");
goto error_exit;
}
CalcCijk (c_ijk3, lnStates, eigvecs3, inverseEigvecs3);
}
}
# endif
/* how large is the information for one tree and one node */
oneMatSize = numNodes * numChars * nOmegaCats * lnStates;
oneNodeSize = numChars * nOmegaCats * lnStates;
/* calculate index offsets */
intNodeOffset = whichChain*2*numIntNodes + whichState*numIntNodes;
condLikeOffset = whichChain*2*oneMatSize + whichState*oneMatSize;
scalerOffset = whichChain*2*numIntNodes*numChars + whichState*numIntNodes*numChars;
/* pass down tree */
for (n=0; n<numIntNodes; n++)
{
p = intNodeDownPassSeq[intNodeOffset + n];
// for debugging purposes
// set all nodes to update
// p->upDateCl = YES;
clUpdateFlag[p->index] = NO;
if (p->anc->anc == NULL && treeModel == UNROOTED)
{
if (p->upDateCl == YES)
{
# if defined (SMART_TI_PROBS)
pL = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (p->left->index)*nodeTiSize);
pR = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (p->right->index)*nodeTiSize);
pA = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (p->index)*nodeTiSize);
# else
//printf ("visiting basal node %d\n", p->index);
/* get transition probabilities */
indexL = indexR = indexA = 0;
// calculate transition probabilities for left branch
if (isComplex == NO)
CalcPij (c_ijk, lnStates, eigenValues, p->left->length, 1.0, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, lnStates, probs, p->left->length, 1.0) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<lnStates; i++)
for (j=0; j<lnStates; j++)
pL[indexL++] = probs[i][j];
// calculate transition probabilities for right branch
if (isComplex == NO)
CalcPij (c_ijk, lnStates, eigenValues, p->right->length, 1.0, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, lnStates, probs, p->right->length, 1.0) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<lnStates; i++)
for (j=0; j<lnStates; j++)
pR[indexR++] = probs[i][j];
// calculate transition probabilities for ancestral branch
if (isComplex == NO)
CalcPij (c_ijk, lnStates, eigenValues, p->length, 1.0, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, lnStates, probs, p->length, 1.0) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<lnStates; i++)
for (j=0; j<lnStates; j++)
pA[indexA++] = probs[i][j];
if (!strcmp(codonModelType, "ny98") || !strcmp(codonModelType, "ac1ny98") || !strcmp(codonModelType, "ac2ny98"))
{
/* set transition probabilities for synonymous changes */
// left branch
if (isComplex2 == NO)
CalcPij (c_ijk2, lnStates, eigenValues2, p->left->length, 1.0, probs);
else
if (ComplexChangeMatrix (eigenValues2, eigvalsImag2, Ceigvecs2, CinverseEigvecs2, lnStates, probs, p->left->length, 1.0) == ERROR)
printf ("Problem calculating transition probabilities for complex eigen values.\n");
for (i=0; i<lnStates; i++)
for (j=0; j<lnStates; j++)
pL[indexL++] = probs[i][j];
// right branch
if (isComplex2 == NO)
CalcPij (c_ijk2, lnStates, eigenValues2, p->right->length, 1.0, probs);
else
if (ComplexChangeMatrix (eigenValues2, eigvalsImag2, Ceigvecs2, CinverseEigvecs2, lnStates, probs, p->right->length, 1.0) == ERROR)
printf ("Problem calculating transition probabilities for complex eigen values.\n");
for (i=0; i<lnStates; i++)
for (j=0; j<lnStates; j++)
pR[indexR++] = probs[i][j];
// ancestral branch
if (isComplex2 == NO)
CalcPij (c_ijk2, lnStates, eigenValues2, p->length, 1.0, probs);
else
if (ComplexChangeMatrix (eigenValues2, eigvalsImag2, Ceigvecs2, CinverseEigvecs2, lnStates, probs, p->length, 1.0) == ERROR)
printf ("Problem calculating transition probabilities for complex eigen values.\n");
for (i=0; i<lnStates; i++)
for (j=0; j<lnStates; j++)
pA[indexA++] = probs[i][j];
/* set transition probabilities for nonsynonymous changes */
// left branch
if (isComplex3 == NO)
CalcPij (c_ijk3, lnStates, eigenValues3, p->left->length, 1.0, probs);
else
if (ComplexChangeMatrix (eigenValues3, eigvalsImag3, Ceigvecs3, CinverseEigvecs3, lnStates, probs, p->left->length, 1.0) == ERROR)
printf ("Problem calculating transition probabilities for complex eigen values.\n");
for (i=0; i<lnStates; i++)
for (j=0; j<lnStates; j++)
pL[indexL++] = probs[i][j];
// right branch
if (isComplex3 == NO)
CalcPij (c_ijk3, lnStates, eigenValues3, p->right->length, 1.0, probs);
else
if (ComplexChangeMatrix (eigenValues3, eigvalsImag3, Ceigvecs3, CinverseEigvecs3, lnStates, probs, p->right->length, 1.0) == ERROR)
printf ("Problem calculating transition probabilities for complex eigen values.\n");
for (i=0; i<lnStates; i++)
for (j=0; j<lnStates; j++)
pR[indexR++] = probs[i][j];
// ancestral branch
if (isComplex3 == NO)
CalcPij (c_ijk3, lnStates, eigenValues3, p->length, 1.0, probs);
else
if (ComplexChangeMatrix (eigenValues3, eigvalsImag3, Ceigvecs3, CinverseEigvecs3, lnStates, probs, p->length, 1.0) == ERROR)
printf ("Problem calculating transition probabilities for complex eigen values.\n");
for (i=0; i<lnStates; i++)
for (j=0; j<lnStates; j++)
pA[indexA++] = probs[i][j];
}
# endif
shortCut = 0;
/* calculate likelihoods of site patterns for left branch if terminal */
if (p->left->left == NULL && isPartAmbig[p->left->index] == NO)
{
shortCut |= 1;
lState = termState + p->left->index * numChars;
for (k=m=0; k<nOmegaCats; k++)
{
if (!strcmp(codonModelType, "covny98"))
{
// 183 x 183 model, only first third of matrix needed
for (i=0; i<nStates; i++)
for (j=i; j<lnStatesSquared; j+=lnStates)
preLikeL[m++] = pL[j] + pL[j+nStates] + pL[j+(2*nStates)];
}
else // 61 x 61 model
{
a = k*lnStatesSquared;
for (i=0; i<lnStates; i++)
for (j=i; j<lnStatesSquared; j+=lnStates)
preLikeL[m++] = pL[j+a];
}
/* for completely ambiguous */
for (i=0; i<lnStates; i++)
{
preLikeL[m++] = 1.0;
}
}
}
/* calculate likelihoods of site patterns for right branch if terminal */
if (p->right->left == NULL && isPartAmbig[p->right->index] == NO)
{
shortCut |= 2;
rState = termState + p->right->index * numChars;
for (k=m=0; k<nOmegaCats; k++)
{
if (!strcmp(codonModelType, "covny98"))
{
// 183 x 183 model
for (i=0; i<nStates; i++)
for (j=i; j<lnStatesSquared; j+=lnStates)
preLikeR[m++] = pR[j] + pR[j+nStates] + pR[j+(2*nStates)];
}
else // 61 x 61 model
{
a = k*lnStatesSquared;
for (i=0; i<lnStates; i++)
for (j=i; j<lnStatesSquared; j+=lnStates)
preLikeR[m++] = pR[j+a];
}
/* for completely ambiguous */
for (i=0; i<lnStates; i++)
{
preLikeR[m++] = 1.0;
}
}
}
/* calculate likelihoods of site patterns for ancestral branch, always terminal */
if (isPartAmbig[p->anc->index] == YES)
{
shortCut = 4;
}
else
{
aState = termState + p->anc->index * numChars;
for (k=m=0; k<nOmegaCats; k++)
{
if (!strcmp(codonModelType, "covny98"))
{
// 183 x 183 model
for (i=0; i<nStates; i++)
for (j=i; j<lnStatesSquared; j+=lnStates)
preLikeA[m++] = pA[j] + pA[j+nStates] + pA[j+(2*nStates)];
}
else // 61 x 61 model
{
a = k*lnStatesSquared;
for (i=0; i<lnStates; i++)
for (j=i; j<lnStatesSquared; j+=lnStates)
preLikeA[m++] = pA[j+a];
}
/* for completely ambiguous */
for (i=0; i<lnStates; i++)
{
preLikeA[m++] = 1.0;
}
}
}
/* calculate conditional likelihoods */
/* first set pointers to cond likes of left, right, p and anc */
clL = &condLike[condLikeOffset + (p->left->index)*oneNodeSize];
clR = &condLike[condLikeOffset + (p->right->index)*oneNodeSize];
clA = &condLike[condLikeOffset + (p->anc->index)*oneNodeSize];
clP = &condLike[condLikeOffset + (p->index)*oneNodeSize];
/* then branch to models */
if (!strcmp(codonModelType, "ny98") || !strcmp(codonModelType, "ac1ny98") || !strcmp(codonModelType, "ac2ny98"))
{
switch (shortCut)
{
case 4: // anc is partially ambiguous
for (c=0; c<numChars; c++)
{
for (k=m=0; k<nOmegaCats; k++)
{
for (i=0; i<lnStates; i++)
{
likeL = likeR = likeA = 0.0;
for (j=0; j<lnStates; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m]*clR[j];
likeA += pA[m++]*clA[j];
}
*(clP++) = likeL * likeR * likeA;
}
clL += lnStates;
clR += lnStates;
clA += lnStates;
}
}
break;
case 0:
case 3: // if both left and right are terminal, this is a 3-taxon tree and no shortcut is necessary
for (c=0; c<numChars; c++)
{
a = aState[c];
for (k=m=0; k<nOmegaCats; k++)
{
for (i=0; i<lnStates; i++)
{
likeL = likeR = 0.0;
for (j=0; j<lnStates; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m++]*clR[j];
}
*(clP++) = likeL * likeR * preLikeA[a++];
}
clL += lnStates;
clR += lnStates;
a += lnStatesSquared;
}
}
break;
case 1:
for (c=0; c<numChars; c++)
{
a = aState[c];
b = lState[c];
for (k=m=0; k<nOmegaCats; k++)
{
for (i=0; i<lnStates; i++)
{
likeR = 0.0;
for (j=0; j<lnStates; j++)
{
likeR += pR[m++]*clR[j];
}
*(clP++) = preLikeL[b++] * likeR * preLikeA[a++];
}
clR += lnStates;
a += lnStatesSquared;
b += lnStatesSquared;
}
}
break;
case 2:
for (c=0; c<numChars; c++)
{
a = aState[c];
b = rState[c];
for (k=m=0; k<nOmegaCats; k++)
{
for (i=0; i<lnStates; i++)
{
likeL = 0.0;
for (j=0; j<lnStates; j++)
{
likeL += pL[m++]*clL[j];
}
*(clP++) = likeL * preLikeR[b++] * preLikeA[a++];
}
clL += lnStates;
a += lnStatesSquared;
b += lnStatesSquared;
}
}
break;
}
}
else /* no omega variation or omega switch model */
{
switch (shortCut)
{
case 4: // anc is partially ambiguous
for (c=0; c<numChars; c++)
{
for (i=m=0; i<lnStates; i++)
{
likeL = likeR = likeA = 0.0;
for (j=0; j<lnStates; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m]*clR[j];
likeA += pA[m++]*clA[j];
}
*(clP++) = likeL * likeR * likeA;
}
clL += lnStates;
clR += lnStates;
clA += lnStates;
}
break;
case 0: // only anc is terminal
for (c=0; c<numChars; c++)
{
a = aState[c];
for (i=m=0; i<lnStates; i++)
{
likeL = likeR = 0.0;
for (j=0; j<lnStates; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m++]*clR[j];
}
*(clP++) = likeL * likeR * preLikeA[a++];
}
clL += lnStates;
clR += lnStates;
}
break;
case 1: // left terminal
case 3: // both right and left terminal - this is a three-taxon tree
for (c=0; c<numChars; c++)
{
a = aState[c];
b = lState[c];
for (i=m=0; i<lnStates; i++)
{
likeR = 0.0;
for (j=0; j<lnStates; j++)
{
likeR += pR[m++]*clR[j];
}
*(clP++) = preLikeL[b++] * likeR * preLikeA[a++];
}
clR += lnStates;
}
break;
case 2: // right terminal
for (c=0; c<numChars; c++)
{
a = aState[c];
b = rState[c];
for (i=m=0; i<lnStates; i++)
{
likeL = 0.0;
for (j=0; j<lnStates; j++)
{
likeL += pL[m++]*clL[j];
}
*(clP++) = likeL * preLikeR[b++] * preLikeA[a++];
}
clL += lnStates;
}
break;
}
}
p->upDateCl = NO;
clUpdateFlag[p->index] = YES;
} // done if p->upDateCl == YES for internal root node
} // done with internal root node
else
{
if (p->upDateCl == YES)
{
//printf ("visiting interior node %d\n", p->index);
/* get transition probabilities */
# if defined (SMART_TI_PROBS)
pL = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (p->left->index)*nodeTiSize);
pR = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (p->right->index)*nodeTiSize);
# else
indexL = indexR = 0;
// calculate transition probabilities for left branch
if (isComplex == NO)
CalcPij (c_ijk, lnStates, eigenValues, p->left->length, 1.0, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, lnStates, probs, p->left->length, 1.0) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<lnStates; i++)
for (j=0; j<lnStates; j++)
pL[indexL++] = probs[i][j];
// calculate transition probabilities for right branch
if (isComplex == NO)
CalcPij (c_ijk, lnStates, eigenValues, p->right->length, 1.0, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, lnStates, probs, p->right->length, 1.0) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<lnStates; i++)
for (j=0; j<lnStates; j++)
pR[indexR++] = probs[i][j];
if (!strcmp(codonModelType, "ny98") || !strcmp(codonModelType, "ac1ny98") || !strcmp(codonModelType, "ac2ny98"))
{
/* set transition probabilities for synonymous changes */
// left branch
if (isComplex2 == NO)
CalcPij (c_ijk2, lnStates, eigenValues2, p->left->length, 1.0, probs);
else
if (ComplexChangeMatrix (eigenValues2, eigvalsImag2, Ceigvecs2, CinverseEigvecs2, lnStates, probs, p->left->length, 1.0) == ERROR)
printf ("Problem calculating transition probabilities for complex eigen values.\n");
for (i=0; i<lnStates; i++)
for (j=0; j<lnStates; j++)
pL[indexL++] = probs[i][j];
// right branch
if (isComplex2 == NO)
CalcPij (c_ijk2, lnStates, eigenValues2, p->right->length, 1.0, probs);
else
if (ComplexChangeMatrix (eigenValues2, eigvalsImag2, Ceigvecs2, CinverseEigvecs2, lnStates, probs, p->right->length, 1.0) == ERROR)
printf ("Problem calculating transition probabilities for complex eigen values.\n");
for (i=0; i<lnStates; i++)
for (j=0; j<lnStates; j++)
pR[indexR++] = probs[i][j];
/* set transition probabilities for nonsynonymous changes */
// left branch
if (isComplex3 == NO)
CalcPij (c_ijk3, lnStates, eigenValues3, p->left->length, 1.0, probs);
else
if (ComplexChangeMatrix (eigenValues3, eigvalsImag3, Ceigvecs3, CinverseEigvecs3, lnStates, probs, p->left->length, 1.0) == ERROR)
printf ("Problem calculating transition probabilities for complex eigen values.\n");
for (i=0; i<lnStates; i++)
for (j=0; j<lnStates; j++)
pL[indexL++] = probs[i][j];
// right branch
if (isComplex3 == NO)
CalcPij (c_ijk3, lnStates, eigenValues3, p->right->length, 1.0, probs);
else
if (ComplexChangeMatrix (eigenValues3, eigvalsImag3, Ceigvecs3, CinverseEigvecs3, lnStates, probs, p->right->length, 1.0) == ERROR)
printf ("Problem calculating transition probabilities for complex eigen values.\n");
for (i=0; i<lnStates; i++)
for (j=0; j<lnStates; j++)
pR[indexR++] = probs[i][j];
}
# endif
shortCut = 0;
/* calculate likelihoods of site patterns for left branch if terminal */
if (p->left->left == NULL && isPartAmbig[p->left->index] == NO)
{
shortCut |= 1;
lState = termState + p->left->index * numChars;
for (k=m=0; k<nOmegaCats; k++)
{
if (!strcmp(codonModelType, "covny98"))
{
// 183 x 183 model, only first third of matrix needed
for (i=0; i<nStates; i++)
for (j=i; j<lnStatesSquared; j+=lnStates)
preLikeL[m++] = pL[j] + pL[j+nStates] + pL[j+(2*nStates)];
}
else // 61 x 61 model
{
a = k*lnStatesSquared;
for (i=0; i<lnStates; i++)
for (j=i; j<lnStatesSquared; j+=lnStates)
preLikeL[m++] = pL[j+a];
}
/* for completely ambiguous */
for (i=0; i<lnStates; i++)
{
preLikeL[m++] = 1.0;
}
}
}
/* calculate likelihoods of site patterns for right branch if terminal */
if (p->right->left == NULL && isPartAmbig[p->right->index] == NO)
{
shortCut |= 2;
rState = termState + p->right->index * numChars;
for (k=m=0; k<nOmegaCats; k++)
{
if (!strcmp(codonModelType, "covny98"))
{
// 183 x 183 model
for (i=0; i<nStates; i++)
for (j=i; j<lnStatesSquared; j+=lnStates)
preLikeR[m++] = pR[j] + pR[j+nStates] + pR[j+(2*nStates)];
}
else // 61 x 61 model
{
a = k*lnStatesSquared;
for (i=0; i<lnStates; i++)
for (j=i; j<lnStatesSquared; j+=lnStates)
preLikeR[m++] = pR[j+a];
}
/* for completely ambiguous */
for (i=0; i<lnStates; i++)
{
preLikeR[m++] = 1.0;
}
}
}
/* calculate conditional likelihoods */
/* first set pointers to cond likes of left, right and p */
clL = &condLike[condLikeOffset + (p->left->index)*oneNodeSize];
clR = &condLike[condLikeOffset + (p->right->index)*oneNodeSize];
clP = &condLike[condLikeOffset + (p->index)*oneNodeSize];
/* then branch to models */
if (!strcmp(codonModelType, "ny98") || !strcmp(codonModelType, "ac1ny98") || !strcmp(codonModelType, "ac2ny98"))
{
switch (shortCut)
{
case 0: // none is terminal
for (c=0; c<numChars; c++)
{
for (k=m=0; k<nOmegaCats; k++)
{
for (i=0; i<lnStates; i++)
{
likeL = likeR = 0.0;
for (j=0; j<lnStates; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m++]*clR[j];
}
*(clP++) = likeL * likeR;
}
clL += lnStates;
clR += lnStates;
}
}
break;
case 1: // left is terminal
for (c=0; c<numChars; c++)
{
a = lState[c];
for (k=m=0; k<nOmegaCats; k++)
{
for (i=0; i<lnStates; i++)
{
likeR = 0.0;
for (j=0; j<lnStates; j++)
{
likeR += pR[m++]*clR[j];
}
*(clP++) = preLikeL[a++] * likeR;
}
clR += lnStates;
a += lnStatesSquared;
}
}
break;
case 2: // right is terminal
for (c=0; c<numChars; c++)
{
a = rState[c];
for (k=m=0; k<nOmegaCats; k++)
{
for (i=0; i<lnStates; i++)
{
likeL = 0.0;
for (j=0; j<lnStates; j++)
{
likeL += pL[m++]*clL[j];
}
*(clP++) = likeL * preLikeR[a++];
}
clL += lnStates;
a += lnStatesSquared;
}
}
break;
case 3: // both right and left are terminal
for (c=0; c<numChars; c++)
{
a = lState[c];
b = rState[c];
for (k=m=0; k<nOmegaCats; k++)
{
for (i=0; i<lnStates; i++)
{
*(clP++) = preLikeL[a++] * preLikeR[b++];
}
a += lnStatesSquared;
b += lnStatesSquared;
}
}
break;
}
}
else /* no omega variation or omega switch model */
{
switch (shortCut)
{
case 0:
for (c=0; c<numChars; c++)
{
for (i=m=0; i<lnStates; i++)
{
likeL = likeR = 0.0;
for (j=0; j<lnStates; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m++]*clR[j];
}
*(clP++) = likeL * likeR;
}
clL += lnStates;
clR += lnStates;
}
break;
case 1:
for (c=0; c<numChars; c++)
{
a = lState[c];
for (i=m=0; i<lnStates; i++)
{
likeR = 0.0;
for (j=0; j<lnStates; j++)
{
likeR += pR[m++]*clR[j];
}
*(clP++) = preLikeL[a++] * likeR;
}
clR += lnStates;
}
break;
case 2:
for (c=0; c<numChars; c++)
{
a = rState[c];
for (i=m=0; i<lnStates; i++)
{
likeL = 0.0;
for (j=0; j<lnStates; j++)
{
likeL += pL[m++]*clL[j];
}
*(clP++) = likeL * preLikeR[a++];
}
clL += lnStates;
}
break;
case 3:
for (c=0; c<numChars; c++)
{
a = lState[c];
b = rState[c];
for (i=0; i<lnStates; i++)
{
*(clP++) = preLikeL[a++] * preLikeR[b++];
}
}
break;
}
}
p->upDateCl = NO;
clUpdateFlag[p->index] = YES;
} // done with interior node if p->upDateCl == YES
} // done with interior node
// deal with scaling
// first check if we need to refresh scalers and potentially shift scaler nodes
// we have to remember scalerIndex because the node may move in the tree
if (refreshScalers == YES)
{
if (n % RESCALE_FREQ == 0)
{
p->scalerNode = YES;
p->scalerIndex = n;
}
else
p->scalerNode = NO;
}
if (p->scalerNode == YES && clUpdateFlag[p->index] == YES)
{
scalerUpdateFlag[p->scalerIndex] = YES;
scP = &clScaler[scalerOffset + (p->scalerIndex)*numChars];
clP = &condLike[condLikeOffset + (p->index)*oneNodeSize];
i = j = 0;
for (c=0; c<numChars; c++)
{
scaler = 0.0;
for (k=0; k<nOmegaCats; k++)
{
for (m=0; m<lnStates; m++)
{
if (clP[i] > scaler)
scaler = clP[i];
i++;
}
}
for (k=0; k<nOmegaCats; k++)
{
for (m=0; m<lnStates; m++)
clP[j++] /= scaler;
}
lnScaler[c] -= scP[c]; //subtract old value
scP[c] = log(scaler);
lnScaler[c] += scP[c]; //add new value
}
}
} // next node
/* get likelihood at base of tree */
p = root[whichChain*2+whichState]->left;
clP = &condLike[condLikeOffset + (p->index)*oneNodeSize];
(*lnL) = 0.0; // reset lnL
if (!strcmp(codonModelType, "ny98"))
{
for (c=0; c<numChars; c++)
{
likePur = likeNeu = likePos = 0.0;
for (i=0; i<lnStates; i++)
likePos += (*(clP++)) * bs[i];
for (i=0; i<lnStates; i++)
likePur += (*(clP++)) * bs[i];
for (i=0; i<lnStates; i++)
likeNeu += (*(clP++)) * bs[i];
//printf ("%4d -- %lf %lf %lf (%lf)\n", c, likePur, likeNeu, likePos, like);
like = likePos * probPos[whichChain*2 + whichState] + likePur * probPur[whichChain*2 + whichState] + likeNeu * probNeu[whichChain*2 + whichState];
if (like < LIKE_EPSILON) /* likelihood for a site can go to zero when */
{ /* two adjacent terminal branches have zero length. */
printf (" WARNING: In LIKE_EPSILON (%d) %1.30lf\n", c, like);
goto error_exit;
}
else
{
(*lnL) += (lnScaler[c] + log(like)) * numSitesOfPat[c];
}
}
}
else if (!strcmp(codonModelType, "ac1ny98") || !strcmp(codonModelType, "ac2ny98"))
{
if (!strcmp(codonModelType, "ac1ny98"))
InitTiMatrix (markovTi, rateCorrelation[whichChain*2 + whichState], 0.0, 0.0, probPur[whichChain*2 + whichState], probNeu[whichChain*2 + whichState], probPos[whichChain*2 + whichState], 1);
else
InitTiMatrix (markovTi, rateCorrelation[whichChain*2 + whichState], rateCorrelation2[whichChain*4 + whichState*2 + 0], rateCorrelation2[whichChain*4 + whichState*2 + 1], probPur[whichChain*2 + whichState], probNeu[whichChain*2 + whichState], probPos[whichChain*2 + whichState], 2);
lnC = 0.0;
m = j = 0;
for (c=0; c<numChars; c++)
{
likePur = likeNeu = likePos = 0.0;
for (i=0; i<lnStates; i++)
likePos += clP[j++] * bs[i];
for (i=0; i<lnStates; i++)
likePur += clP[j++] * bs[i];
for (i=0; i<lnStates; i++)
likeNeu += clP[j++] * bs[i];
omegaPr[m++] = likePur;
omegaPr[m++] = likeNeu;
omegaPr[m++] = likePos;
lnC += (lnScaler[c] * numSitesOfPat[c]);
}
isFirst = YES;
for (c=(nChar/3)-1; c>=0; c--)
{
cn = c*3;
if (patternId[c] >= 0)
{
pat = patternId[c];
if (isFirst == YES)
{
max = 0.0;
for (k=0; k<3; k++)
{
biN[cn + k] = omegaPr[pat*3 + k];
if (biN[cn + k] > max)
max = biN[cn + k];
}
if (max > 0.0)
{
for (k=0; k<3; k++)
biN[cn + k] /= max;
lnC += log(max);
}
else
{
printf (" ERROR: Scaling factor for ac1ny98 or ac2ny98 model is less than 0\n");
goto error_exit;
}
isFirst = NO;
}
else // isFirst == NO
{
for (i=0; i<3; i++)
{
temp = max = 0.0;
for (j=0; j<3; j++)
temp += markovTi[i][j] * biN[(c+1)*3 + j];
biN[cn + i] = omegaPr[pat*3+i] * temp;
if (biN[cn + i] > max)
max = biN[cn + i];
}
if (max > 0.0)
{
for (k=0; k<3; k++)
biN[cn + k] /= max;
lnC += log(max);
}
else
{
printf (" ERROR: Scaling factor for adgamma model is less than 0\n");
goto error_exit;
}
}
}
else
{
printf (" ERROR: Unidentified pattern\n");
goto error_exit;
}
}
temp = biN[0] * probPur[whichChain*2 + whichState];
temp += biN[1] * probNeu[whichChain*2 + whichState];
temp += biN[2] * probPos[whichChain*2 + whichState];
(*lnL) = lnC + log(temp);
}
else /* no omega variation or covarion-like model */
{
for (c=0; c<numChars; c++)
{
like = 0.0;
for (i=0; i<lnStates; i++)
like += ((*(clP++)) * bs[i]);
//printf ("%d: %1.25lf %lf %d\n", c, like, log(like), numSitesOfPat[c]);
if (like < LIKE_EPSILON) /* likelihood for a site can go to zero when */
{ /* two adjacent terminal branches have zero length. */
printf (" WARNING: In LIKE_EPSILON\n");
printf ("c %d like %f \n", c, like);
goto error_exit;
}
else
{
(*lnL) += (lnScaler[c] + log(like)) * numSitesOfPat[c];
}
}
}
/* free memory */
# if !defined (SMART_TI_PROBS)
free_psdmatrix (probs);
free (pL);
free_psdmatrix (q);
free (eigenValues);
free_psdmatrix (eigvecs);
free_psdmatrix (inverseEigvecs);
free_pscmatrix (Ceigvecs);
free_pscmatrix (CinverseEigvecs);
if (isComplex != YES)
free (c_ijk);
if (!strcmp(codonModelType, "ny98") || !strcmp(codonModelType, "ac1ny98") || !strcmp(codonModelType, "ac2ny98"))
{
free (eigenValues2);
free_psdmatrix (eigvecs2);
free_psdmatrix (inverseEigvecs2);
free_pscmatrix (Ceigvecs2);
free_pscmatrix (CinverseEigvecs2);
if (isComplex2 != YES)
free (c_ijk2);
free (eigenValues3);
free_psdmatrix (eigvecs3);
free_psdmatrix (inverseEigvecs3);
free_pscmatrix (Ceigvecs3);
free_pscmatrix (CinverseEigvecs3);
if (isComplex3 != YES)
free (c_ijk3);
}
# endif
free (bs);
free (preLikeL);
if (!strcmp(codonModelType, "ac1ny98") || !strcmp(codonModelType, "ac2ny98"))
free (omegaPr);
return (NO_ERROR);
error_exit:
# if !defined (SMART_TI_PROBS)
free_psdmatrix (probs);
free (pL);
free_psdmatrix (q);
free (eigenValues);
free_psdmatrix (eigvecs);
free_psdmatrix (inverseEigvecs);
free_pscmatrix (Ceigvecs);
free_pscmatrix (CinverseEigvecs);
if (isComplex != YES)
free (c_ijk);
if (!strcmp(codonModelType, "ny98") || !strcmp(codonModelType, "ac1ny98") || !strcmp(codonModelType, "ac2ny98"))
{
free (eigenValues2);
free_psdmatrix (eigvecs2);
free_psdmatrix (inverseEigvecs2);
free_pscmatrix (Ceigvecs2);
free_pscmatrix (CinverseEigvecs2);
if (isComplex2 != YES)
free (c_ijk2);
free (eigenValues3);
free_psdmatrix (eigvecs3);
free_psdmatrix (inverseEigvecs3);
free_pscmatrix (Ceigvecs3);
free_pscmatrix (CinverseEigvecs3);
if (isComplex3 != YES)
free (c_ijk3);
}
# endif
free (bs);
free (preLikeL);
if (!strcmp(codonModelType, "ac1ny98") || !strcmp(codonModelType, "ac2ny98"))
free (omegaPr);
return (ERROR);
}
/*---------------------------------------------------------------------
LnLikeCovarion: 'Superfast' version of likelihood function for covariotide
or covarion models. Core written 2001-04-20
-----------------------------------------------------------------------*/
int LnLikeCovarion (int whichState, int whichChain, int numChars, int numRateCats, double *lnL, int refreshScalers)
{
register int a, b, i, j, k, c, n, m, cn;
int lnumRateCats, lnPartitions, oneMatSize, oneNodeSize,
index, index1, index2, nRates, pat, localLag, *usedBin,
intNodeOffset, condLikeOffset, scalerOffset, preLikeIncrement,
lnStates, lnStatesSquared, lnStatesCube, shortCut,
*aState, *lState, *rState, indexMultiplier1, indexMultiplier2;
double *bs, *pL, *pR, *pA, *catFreq, *catRate, *partRate,
*clL, *clR, *clA, *clP, *scP, s01, s10, prob0, prob1,
*lnScaler, scaler, like, lnC, *biN, max, temp, correlation,
*ratePr, **markovTi, likeL, likeR, likeA, *preLikeL, *preLikeR, *preLikeA;
TreeNode *p;
# if defined (SMART_TI_PROBS)
int nForOneState;
# else
int nPij, *isComplex, indexL, indexR, indexA;
double **probs, **q, *eigenValues, *eigvalsImag, **eigvecs, **inverseEigvecs, *c_ijk,
*eigenValuesP, *eigvalsImagP, *eigvecsP, *inverseEigvecsP, *c_ijkP;
complex **Ceigvecs, **CinverseEigvecs, *CeigvecsP, *CinverseEigvecsP;
# endif
/* initialize offset for transition probabilities */
# if defined (SMART_TI_PROBS)
nForOneState = numNodes*nodeTiSize;
# endif
/* calculate local number of states */
/* twice nStates because matrix is doubled */
/* calculate increment for precalculated likelihoods */
lnStates = 2 * nStates;
lnStatesSquared = lnStates * lnStates;
lnStatesCube = lnStates * lnStatesSquared;
preLikeIncrement = nStates * lnStates;
/* load base frequencies */
index = whichChain*2*lnStates + whichState*lnStates;
index1 = whichChain*4 + whichState*2;
index2 = whichChain*2 + whichState;
bs = (double *)malloc((size_t) (lnStates * sizeof(double)));
if (!bs)
{
printf ("\n ERROR: Problem allocating bs.\n");
goto error_exit;
}
if (!strcmp(covarionModelType, "ts98"))
{
k = 0;
for (j=0; j<2; j++)
{
for (i=0; i<nStates; i++)
{
bs[k] = baseFreq[whichChain*2*nStates + whichState*nStates + i] * switchPi[whichChain*4 + whichState*2 + j];
//bs[k] = baseFreq[index + i] * switchPi[index1 + j];
k++;
}
}
}
else if (!strcmp(covarionModelType, "gcswitch"))
{
s01 = switchRate[index1 + 0];
s10 = switchRate[index1 + 1];
prob0 = s10 / (s01+s10);
prob1 = s01 / (s01+s10);
bs[0] = (1.0 - gc1[index2]) * (fracA[index2]) * prob0;
bs[1] = (gc1[index2]) * (1.0 - fracG[index2]) * prob0;
bs[2] = (gc1[index2]) * (fracG[index2]) * prob0;
bs[3] = (1.0 - gc1[index2]) * (1.0 - fracA[index2]) * prob0;
bs[4] = (1.0 - gc2[index2]) * (fracA[index2]) * prob1;
bs[5] = (gc2[index2]) * (1.0 - fracG[index2]) * prob1;
bs[6] = (gc2[index2]) * (fracG[index2]) * prob1;
bs[7] = (1.0 - gc2[index2]) * (1.0 - fracA[index2]) * prob1;
}
/*for (i=0; i<lnStates; i++)
printf ("%lf ", bs[i]);
printf ("\n");*/
/* how many different rates? */
/* lnumRateCats contains a local copy of numRateCats if appropriate, else 1
/* lnPartitions contains a local copy of nPartitions if appropriate, else 1
/* the code introduced here only makes sure that the number of partitions
/* or rate categories is set to 1 when appropriate, in case the global variables
/* are not set to 1 when they are not "in use" */
if (!strcmp(ratesModel, "sitespec") || !strcmp(ratesModel, "ssgamma") || !strcmp(ratesModel, "ssadgamma"))
lnPartitions = nPartitions;
else
lnPartitions = 1;
if (!strcmp(ratesModel, "equal") || !strcmp(ratesModel, "sitespec"))
lnumRateCats = 1;
else
lnumRateCats = numRateCats;
nRates = lnPartitions * lnumRateCats; // number of rates needing P matrices
/* preLikeL, preLikeR and preLikeA will contain the cond likelihoods for */
/* Left, Right and Anc if any of them is a terminal */
preLikeL = (double *)malloc((size_t)(3 * nRates * (nStates + 1) * lnStates * sizeof(double)));
if (!preLikeL)
{
printf ("\n ERROR: Problem allocating preLikeL, preLikeR and preLikeA\n");
goto error_exit;
}
preLikeR = preLikeL + nRates * (nStates + 1) * lnStates;
preLikeA = preLikeR + nRates * (nStates + 1) * lnStates;
/* allocate memory for the calculations */
/* pL, pR and pA will contain the transition probs for Left, Right and Anc */
/* One transition probability matrix is needed for each possible rate */
# if !defined (SMART_TI_PROBS)
probs = psdmatrix (lnStates);
nPij = nRates * lnStatesSquared;
pL = (double *)malloc((size_t)(3 * nPij * sizeof(double)));
if (!pL)
{
printf ("\n ERROR: Problem allocating Pij\n");
goto error_exit;
}
pR = pL + nPij;
pA = pR + nPij;
# endif
/* allocate memory for rate and rate category frequencies */
catFreq = (double *)malloc((size_t) ((2 * lnumRateCats + lnPartitions) * sizeof(double)));
if (!catFreq)
{
printf ("\n ERROR: Problem allocating space for rate multipliers and rate category freqs.\n");
goto error_exit;
}
catRate = catFreq + lnumRateCats;
partRate = catRate + lnumRateCats;
/* allocate memory for autocorrelated gamma models */
if (!strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "ssadgamma"))
{
ratePr = (double *)malloc((size_t) (lnumRateCats * (numChars + nChar) * sizeof(double)));
if (!ratePr)
{
printf ("\n ERROR: Problem allocating ratePr and biN.\n");
goto error_exit;
}
biN = ratePr + lnumRateCats * numChars;
usedBin = (int *)malloc((size_t) (nChar * sizeof(int)));
if (!usedBin)
{
printf ("\n ERROR: Problem allocating usedBin.\n");
goto error_exit;
}
}
// set pointer to the lnSiteScaler for this tree
lnScaler = &lnSiteScaler[whichChain * 2 * numChars + whichState * numChars];
/* fill in rate categories with frequencies and rates by dividing the */
/* gamma distribution into discrete categories, if appropriate */
/* NB! this is inefficient; store values instead */
if (!strcmp(ratesModel,"gamma")|| !strcmp(ratesModel, "ssgamma"))
{
DiscreteGamma (catFreq, catRate, alpha[whichChain*2 + whichState], alpha[whichChain*2 + whichState], lnumRateCats, 0);
}
else if (!strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "ssadgamma"))
{
markovTi = psdmatrix (lnumRateCats);
AutodGamma (markovTi, catFreq, catRate, &correlation, alpha[whichChain*2 + whichState], rateCorrelation[whichChain*2 + whichState], lnumRateCats);
}
else if (!strcmp(ratesModel, "invgamma"))
{
DiscreteGamma (catFreq, catRate, alpha[whichChain*2 + whichState], alpha[whichChain*2 + whichState], lnumRateCats-1, 0);
catRate[lnumRateCats-1] = 0.0;
catFreq[lnumRateCats-1] = invP[whichChain*2 + whichState];
for (i=0; i<lnumRateCats-1; i++)
{
catRate[i] *= 1.0 / (1.0 - invP[whichChain*2 + whichState]);
catFreq[i] *= (1.0 - invP[whichChain*2 + whichState]);
}
}
else if (!strcmp(ratesModel, "invariant"))
{
catRate[0] = 0.0;
catRate[1] = 1.0 / (1.0 - invP[whichChain*2 + whichState]);
catFreq[0] = invP[whichChain*2 + whichState];
catFreq[1] = 1.0 - invP[whichChain*2 + whichState];
}
else { // "sitespec" or "equal"
catRate[0] = 1.0;
catFreq[0] = 1.0;
}
/* initialize partition rates, if appropriate */
if (lnPartitions > 1)
{
for (i=0; i<lnPartitions; i++)
partRate[i] = scaledRates[whichChain*2*lnPartitions + whichState*lnPartitions + i];
}
else
partRate[0] = 1.0;
/* allocate memory for eigenvalues and eigenvectors */
/* first for base matrix */
# if !defined (SMART_TI_PROBS)
q = psdmatrix (lnStates);
eigenValues = (double *)malloc((size_t) (2 * lnStates * sizeof(double)));
if (!eigenValues)
{
printf ("\n ERROR: Problem allocating eigenValues and eigvalsImag.\n");
goto error_exit;
}
eigvalsImag = eigenValues + lnStates;
c_ijk = (double *)malloc((size_t) (lnStatesCube * sizeof(double)));
if (!c_ijk)
{
printf ("\n ERROR: Problem allocating c_ijk.\n");
goto error_exit;
}
eigvecs = psdmatrix (lnStates);
inverseEigvecs = psdmatrix (lnStates);
Ceigvecs = pscmatrix (lnStates);
CinverseEigvecs = pscmatrix (lnStates);
/* then for partitions */
isComplex = (int *)malloc((size_t) (nRates * sizeof(int)));
if (!isComplex)
{
printf ("\n ERROR: Problem allocating isComplex.\n");
goto error_exit;
}
eigenValuesP = (double *)malloc((size_t) (2 * nRates * lnStates * sizeof(double)));
if (!eigenValuesP)
{
printf ("\n ERROR: Problem allocating eigenValuesP and eigvalsImagP.\n");
goto error_exit;
}
eigvalsImagP = eigenValuesP + nRates * lnStates;
eigvecsP = (double *)malloc((size_t) (2 * nRates * lnStatesSquared * sizeof(double)));
if (!eigvecsP)
{
printf ("\n ERROR: Problem allocating eigvecsP and inverseEigvecsP.\n");
goto error_exit;
}
inverseEigvecsP = eigvecsP + nRates * lnStatesSquared;
CeigvecsP = (complex *)malloc((size_t) (2 * nRates * lnStatesSquared * sizeof(complex)));
if (!CeigvecsP)
{
printf ("\n ERROR: Problem allocating CeigvecsP and CinverseEigvecsP.\n");
goto error_exit;
}
CinverseEigvecsP = CeigvecsP + nRates * lnStatesSquared;
c_ijkP = (double *)malloc((size_t) (nRates * lnStatesCube * sizeof(double)));
if (!c_ijkP)
{
printf ("\n ERROR: Problem allocating c_ijkP.\n");
goto error_exit;
}
/* get eigenvalues and eigenvectors for covarion matrices */
/* one matrix needed for each rate because catrates and partrates
affect only part of the matrix */
// a is index to rate eigenvectors, b is index to rates
for (m=a=b=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
if (dataType == DNA || dataType == RNA)
{
if (!strcmp(covarionModelType, "ts98"))
{
if (SetDNACovQMatrix (q, whichState, whichChain, catRate[k]*partRate[m]) == ERROR)
goto error_exit;
}
else if (!strcmp(covarionModelType, "gcswitch"))
{
if (SetGCSwitchQMatrix (q, whichState, whichChain, catRate[k]*partRate[m]) == ERROR)
goto error_exit;
}
else
{
goto error_exit;
}
}
else
{
if (SetAACovQMatrix (q, whichState, whichChain, catRate[k]*partRate[m]) == ERROR)
goto error_exit;
}
isComplex[b] = GetEigens (lnStates, q, eigenValues, eigvalsImag, eigvecs, inverseEigvecs, Ceigvecs, CinverseEigvecs);
if (isComplex[b] == NO)
{
CalcCijk (c_ijk, lnStates, eigvecs, inverseEigvecs);
}
for (i=0; i<lnStates; i++)
{
eigenValuesP[b*lnStates + i] = eigenValues[i];
eigvalsImagP[b*lnStates + i] = eigvalsImag[i];
}
for (i=0; i<lnStates; i++)
{
for (j=0; j<lnStates; j++)
{
eigvecsP[a] = eigvecs[i][j];
inverseEigvecsP[a] = inverseEigvecs[i][j];
CeigvecsP[a].re = Ceigvecs[i][j].re;
CinverseEigvecsP[a].re = CinverseEigvecs[i][j].re;
CeigvecsP[a].im = Ceigvecs[i][j].im;
CinverseEigvecsP[a].im = CinverseEigvecs[i][j].im;
a++;
}
}
for (i=0; i<lnStatesCube; i++)
c_ijkP[b*lnStatesCube + i] = c_ijk[i];
b++;
}
}
# endif
/* how large is the information for one tree and one node ?*/
oneMatSize = numNodes * numChars * lnumRateCats * lnStates;
oneNodeSize = numChars * lnumRateCats * lnStates;
/* calculate index offsets */
condLikeOffset = whichChain*2*oneMatSize + whichState*oneMatSize;
scalerOffset = whichChain*2*numIntNodes*numChars + whichState*numIntNodes*numChars;
intNodeOffset = whichChain*2*numIntNodes + whichState*numIntNodes;
/* pass down tree */
for (n=0; n<numIntNodes; n++)
{
p = intNodeDownPassSeq[intNodeOffset + n];
// for debugging purposes
// set all nodes to update
// p->upDateCl = YES;
clUpdateFlag[p->index] = NO;
if (p->anc->anc == NULL && treeModel == UNROOTED)
{
if (p->upDateCl == YES)
{
//printf ("visiting basal node %d\n", p->index);
/* get transition probabilities */
# if defined (SMART_TI_PROBS)
pL = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (p->left->index)*nodeTiSize);
pR = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (p->right->index)*nodeTiSize);
pA = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (p->index)*nodeTiSize);
# else
for (m=indexL=indexR=indexA=b=a=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
// fetch eigenvalues and eigenvectors for this rate
// the rate itself is not needed because it has
// been taken care of in the diagonalized matrices
for (i=0; i<lnStates; i++)
{
eigenValues[i] = eigenValuesP[b*lnStates + i];
eigvalsImag[i] = eigvalsImagP[b*lnStates + i];
}
for (i=0; i<lnStates; i++)
{
for (j=0; j<lnStates; j++)
{
eigvecs[i][j] = eigvecsP[a];
inverseEigvecs[i][j] = inverseEigvecsP[a];
Ceigvecs[i][j].re = CeigvecsP[a].re;
CinverseEigvecs[i][j].re = CinverseEigvecsP[a].re;
Ceigvecs[i][j].im = CeigvecsP[a].im;
CinverseEigvecs[i][j].im = CinverseEigvecsP[a].im;
a++;
}
}
// fetch c_ijk for this rate
for (i=0; i<lnStatesCube; i++)
c_ijk[i] = c_ijkP[b*lnStatesCube + i];
// calculate transition probabilities for left branch
if (isComplex[b] == NO)
CalcPij (c_ijk, lnStates, eigenValues, p->left->length, 1.0, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, lnStates, probs, p->left->length, 1.0) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<lnStates; i++)
for (j=0; j<lnStates; j++)
pL[indexL++] = probs[i][j];
// calculate transition probabilities for right branch
if (isComplex[b] == NO)
CalcPij (c_ijk, lnStates, eigenValues, p->right->length, 1.0, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, lnStates, probs, p->right->length, 1.0) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<lnStates; i++)
for (j=0; j<lnStates; j++)
pR[indexR++] = probs[i][j];
// calculate transition probabilities for ancestral branch
if (isComplex[b] == NO)
CalcPij (c_ijk, lnStates, eigenValues, p->length, 1.0, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, lnStates, probs, p->length, 1.0) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<lnStates; i++)
for (j=0; j<lnStates; j++)
pA[indexA++] = probs[i][j];
b++;
}
}
# endif
if (!strcmp(ratesModel, "invariant") || !strcmp(ratesModel, "invgamma"))
{
for (i=0; i<nodeTiSize; i++)
{
if (pL[i] < 0.0)
pL[i] = 0.0;
if (pR[i] < 0.0)
pR[i] = 0.0;
if (pA[i] < 0.0)
pA[i] = 0.0;
}
}
shortCut = 0;
/* calculate likelihoods of site patterns for left branch if terminal */
if (p->left->left == NULL && isPartAmbig[p->left->index] == NO)
{
shortCut |= 1;
lState = termState + p->left->index * numChars;
for (m=a=b=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
for (i=0; i<nStates; i++)
for (j=i+b; j<lnStatesSquared+b; j+=lnStates)
{
temp = pL[j] + pL[j+nStates];
preLikeL[a++] = temp + ((seqErrorProb - nStates*seqErrorProb*temp)/(nStates-1.0));
}
/* for ambiguous */
for (i=0; i<lnStates; i++)
preLikeL[a++] = 1.0;
b += lnStatesSquared;
}
}
}
/* calculate likelihoods of site patterns for right branch if terminal */
if (p->right->left == NULL && isPartAmbig[p->right->index] == NO)
{
shortCut |= 2;
rState = termState + p->right->index * numChars;
for (m=a=b=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
for (i=0; i<nStates; i++)
for (j=i+b; j<lnStatesSquared+b; j+=lnStates)
{
temp = pR[j] + pR[j+nStates];
preLikeR[a++] = temp + ((seqErrorProb - nStates*seqErrorProb*temp)/(nStates-1.0));
}
/* for ambiguous */
for (i=0; i<lnStates; i++)
preLikeR[a++] = 1.0;
b += lnStatesSquared;
}
}
}
/* calculate likelihoods of site patterns for anc branch, always terminal */
if (isPartAmbig[p->anc->index] == YES)
{
shortCut = 4;
}
else
{
aState = termState + p->anc->index * numChars;
for (m=a=b=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
for (i=0; i<nStates; i++)
for (j=i+b; j<lnStatesSquared+b; j+=lnStates)
{
temp = pA[j] + pA[j+nStates];
preLikeA[a++] = temp + ((seqErrorProb - nStates*seqErrorProb*temp)/(nStates-1.0));
}
/* for ambiguous */
for (i=0; i<lnStates; i++)
preLikeA[a++] = 1.0;
b += lnStatesSquared;
}
}
}
/* calculate conditional likelihoods */
/* first set pointers to cond likes of left, right, p and anc */
clL = &condLike[condLikeOffset + (p->left->index)*oneNodeSize];
clR = &condLike[condLikeOffset + (p->right->index)*oneNodeSize];
clA = &condLike[condLikeOffset + (p->anc->index)*oneNodeSize];
clP = &condLike[condLikeOffset + (p->index)*oneNodeSize];
/* then branch to models */
if (!strcmp(ratesModel, "equal"))
{
switch (shortCut)
{
case 4: // anc is partially ambiguous, do not use any shortcut
for (c=0; c<numChars; c++)
{
for (i=m=0; i<lnStates; i++)
{
likeL = likeR = likeA = 0.0;
for (j=0; j<lnStates; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m]*clR[j];
likeA += pA[m++]*clA[j];
}
*(clP++) = likeL * likeR * likeA;
}
clL += lnStates;
clR += lnStates;
clA += lnStates;
}
break;
case 0:
for (c=0; c<numChars; c++)
{
a = aState[c];
for (i=m=0; i<lnStates; i++)
{
likeL = likeR = 0.0;
for (j=0; j<lnStates; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m++]*clR[j];
}
*(clP++) = likeL * likeR * preLikeA[a++];
}
clL += lnStates;
clR += lnStates;
}
break;
case 1: // left is terminal
case 3: // both left and right are terminal; this is a 3-taxon tree
for (c=0; c<numChars; c++)
{
a = aState[c];
b = lState[c];
for (i=m=0; i<lnStates; i++)
{
likeR = 0.0;
for (j=0; j<lnStates; j++)
{
likeR += pR[m++]*clR[j];
}
*(clP++) = preLikeL[b++] * likeR * preLikeA[a++];
}
clR += lnStates;
}
break;
case 2: // right is terminal
for (c=0; c<numChars; c++)
{
a = aState[c];
b = rState[c];
for (i=m=0; i<lnStates; i++)
{
likeL = 0.0;
for (j=0; j<lnStates; j++)
{
likeL += pL[m++]*clL[j];
}
*(clP++) = likeL * preLikeR[b++] * preLikeA[a++];
}
clL += lnStates;
}
break;
}
}
else if (!strcmp(ratesModel, "gamma") || !strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "invariant") || !strcmp(ratesModel, "invgamma"))
{
switch (shortCut)
{
case 4: // anc is partially ambiguous, do not use any shortcut
for (c=0; c<numChars; c++)
{
for (k=m=0; k<lnumRateCats; k++)
{
for (i=0; i<lnStates; i++)
{
likeL = likeR = likeA = 0.0;
for (j=0; j<lnStates; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m]*clR[j];
likeA += pA[m++]*clA[j];
}
*(clP++) = likeL * likeR * likeA;
}
clL += lnStates;
clR += lnStates;
clA += lnStates;
}
}
break;
case 0: // only anc is terminal
for (c=0; c<numChars; c++)
{
a = aState[c];
for (k=m=0; k<lnumRateCats; k++)
{
for (i=0; i<lnStates; i++)
{
likeL = likeR = 0.0;
for (j=0; j<lnStates; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m++]*clR[j];
}
*(clP++) = likeL * likeR * preLikeA[a++];
}
clL += lnStates;
clR += lnStates;
a += preLikeIncrement;
}
}
break;
case 1: // left is terminal
case 3: // both left and right are terminal
for (c=0; c<numChars; c++)
{
a = aState[c];
b = lState[c];
for (k=m=0; k<lnumRateCats; k++)
{
for (i=0; i<lnStates; i++)
{
likeR = 0.0;
for (j=0; j<lnStates; j++)
{
likeR += pR[m++]*clR[j];
}
*(clP++) = preLikeL[b++] * likeR * preLikeA[a++];
}
clR += lnStates;
a += preLikeIncrement;
b += preLikeIncrement;
}
}
break;
case 2: // right is terminal
for (c=0; c<numChars; c++)
{
a = aState[c];
b = rState[c];
for (k=m=0; k<lnumRateCats; k++)
{
for (i=0; i<lnStates; i++)
{
likeL = 0.0;
for (j=0; j<lnStates; j++)
{
likeL += pL[m++]*clL[j];
}
*(clP++) = likeL * preLikeR[b++] * preLikeA[a++];
}
clL += lnStates;
a += preLikeIncrement;
b += preLikeIncrement;
}
}
break;
}
}
else if (!strcmp(ratesModel, "ssgamma") || !strcmp(ratesModel, "ssadgamma"))
{
indexMultiplier1 = lnumRateCats * lnStatesSquared;
indexMultiplier2 = lnumRateCats * (nStates + 1) * lnStates;
switch (shortCut)
{
case 4: // anc is partially ambiguous, do not use any shortcut
for (c=0; c<numChars; c++)
{
m = partitionId[c]*indexMultiplier1;
for (k=0; k<lnumRateCats; k++)
{
for (i=0; i<lnStates; i++)
{
likeL = likeR = likeA = 0.0;
for (j=0; j<lnStates; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m]*clR[j];
likeA += pA[m++]*clA[j];
}
*(clP++) = likeL * likeR * likeA;
}
clL += lnStates;
clR += lnStates;
clA += lnStates;
}
}
break;
case 0: // only anc is terminal
for (c=0; c<numChars; c++)
{
m = partitionId[c]*indexMultiplier1;
a = aState[c] + (partitionId[c]*indexMultiplier2);
for (k=0; k<lnumRateCats; k++)
{
for (i=0; i<lnStates; i++)
{
likeL = likeR = 0.0;
for (j=0; j<lnStates; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m++]*clR[j];
}
*(clP++) = likeL * likeR * preLikeA[a++];
}
clL += lnStates;
clR += lnStates;
a += preLikeIncrement;
}
}
break;
case 1: // left is terminal
case 3: // both left and right are terminal
for (c=0; c<numChars; c++)
{
m = partitionId[c]*indexMultiplier1;
index = partitionId[c] * indexMultiplier2;
a = aState[c] + index;
b = lState[c] + index;
for (k=0; k<lnumRateCats; k++)
{
for (i=0; i<lnStates; i++)
{
likeR = 0.0;
for (j=0; j<lnStates; j++)
{
likeR += pR[m++]*clR[j];
}
*(clP++) = preLikeL[b++] * likeR * preLikeA[a++];
}
clR += lnStates;
a += preLikeIncrement;
b += preLikeIncrement;
}
}
break;
case 2: // right is terminal
for (c=0; c<numChars; c++)
{
m = partitionId[c]*indexMultiplier1;
index = partitionId[c] * indexMultiplier2;
a = aState[c] + index;
b = rState[c] + index;
for (k=0; k<lnumRateCats; k++)
{
for (i=0; i<lnStates; i++)
{
likeL = 0.0;
for (j=0; j<lnStates; j++)
{
likeL += pL[m++]*clL[j];
}
*(clP++) = likeL * preLikeR[b++] * preLikeA[a++];
}
clL += lnStates;
a += preLikeIncrement;
b += preLikeIncrement;
}
}
break;
}
}
else if (!strcmp(ratesModel, "sitespec"))
{
indexMultiplier1 = lnStatesSquared;
indexMultiplier2 = (nStates + 1) * lnStates;
switch (shortCut)
{
case 4: // anc is partially ambiguous, do not use any shortcut
for (c=0; c<numChars; c++)
{
m = partitionId[c]*indexMultiplier1;
for (i=0; i<lnStates; i++)
{
likeL = likeR = likeA = 0.0;
for (j=0; j<lnStates; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m]*clR[j];
likeA += pA[m++]*clA[j];
}
*(clP++) = likeL * likeR * likeA;
}
clL += lnStates;
clR += lnStates;
clA += lnStates;
}
break;
case 0: // only anc is terminal
for (c=0; c<numChars; c++)
{
m = partitionId[c]*indexMultiplier1;
a = aState[c] + (partitionId[c]*indexMultiplier2);
for (i=0; i<lnStates; i++)
{
likeL = likeR = 0.0;
for (j=0; j<lnStates; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m++]*clR[j];
}
*(clP++) = likeL * likeR * preLikeA[a++];
}
clL += lnStates;
clR += lnStates;
}
break;
case 1: // left is terminal
case 3: // both left and right are terminal
for (c=0; c<numChars; c++)
{
m = partitionId[c]*indexMultiplier1;
index = partitionId[c] * indexMultiplier2;
a = aState[c] + index;
b = lState[c] + index;
for (i=0; i<lnStates; i++)
{
likeR = 0.0;
for (j=0; j<lnStates; j++)
{
likeR += pR[m++]*clR[j];
}
*(clP++) = preLikeL[b++] * likeR * preLikeA[a++];
}
clR += lnStates;
}
break;
case 2: // right is terminal
for (c=0; c<numChars; c++)
{
m = partitionId[c]*indexMultiplier1;
index = partitionId[c] * indexMultiplier2;
a = aState[c] + index;
b = rState[c] + index;
for (i=0; i<lnStates; i++)
{
likeL = 0.0;
for (j=0; j<lnStates; j++)
{
likeL += pL[m++]*clL[j];
}
*(clP++) = likeL * preLikeR[b++] * preLikeA[a++];
}
clL += lnStates;
}
break;
}
}
p->upDateCl = NO;
clUpdateFlag[p->index] = YES;
} // done if p->upDateCl == YES for internal root node
} // done with internal root node
else
{
if (p->upDateCl == YES)
{
//printf ("visiting interior node %d\n", p->index);
/* get transition probabilities */
# if defined (SMART_TI_PROBS)
pL = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (p->left->index)*nodeTiSize);
pR = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (p->right->index)*nodeTiSize);
# else
for (m=indexL=indexR=b=a=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
// fetch eigenvalues and eigenvectors for this rate
// the rate itself is not needed because it has
// been taken care of in the diagonalized matrices
for (i=0; i<lnStates; i++)
{
eigenValues[i] = eigenValuesP[b*lnStates + i];
eigvalsImag[i] = eigvalsImagP[b*lnStates + i];
}
for (i=0; i<lnStates; i++)
{
for (j=0; j<lnStates; j++)
{
eigvecs[i][j] = eigvecsP[a];
inverseEigvecs[i][j] = inverseEigvecsP[a];
Ceigvecs[i][j].re = CeigvecsP[a].re;
CinverseEigvecs[i][j].re = CinverseEigvecsP[a].re;
Ceigvecs[i][j].im = CeigvecsP[a].im;
CinverseEigvecs[i][j].im = CinverseEigvecsP[a].im;
a++;
}
}
// fetch c_ijk for this rate
for (i=0; i<lnStatesCube; i++)
c_ijk[i] = c_ijkP[b*lnStatesCube + i];
// calculate transition probabilities for left branch
if (isComplex[b] == NO)
CalcPij (c_ijk, lnStates, eigenValues, p->left->length, 1.0, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, lnStates, probs, p->left->length, 1.0) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<lnStates; i++)
for (j=0; j<lnStates; j++)
pL[indexL++] = probs[i][j];
// calculate transition probabilities for right branch
if (isComplex[b] == NO)
CalcPij (c_ijk, lnStates, eigenValues, p->right->length, 1.0, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, lnStates, probs, p->right->length, 1.0) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<lnStates; i++)
for (j=0; j<lnStates; j++)
pR[indexR++] = probs[i][j];
b++;
}
}
# endif
if (!strcmp(ratesModel, "invariant") || !strcmp(ratesModel, "invgamma"))
{
for (i=0; i<nodeTiSize; i++)
{
if (pL[i] < 0.0)
pL[i] = 0.0;
if (pR[i] < 0.0)
pR[i] = 0.0;
}
}
shortCut = 0;
/* calculate likelihoods of site patterns for left branch if terminal */
if (p->left->left == NULL && isPartAmbig[p->left->index] == NO)
{
shortCut |= 1;
lState = termState + p->left->index * numChars;
for (m=a=b=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
for (i=0; i<nStates; i++)
for (j=i+b; j<lnStatesSquared+b; j+=lnStates)
{
temp = pL[j] + pL[j+nStates];
preLikeL[a++] = temp + ((seqErrorProb - nStates*seqErrorProb*temp)/(nStates-1.0));
}
/* for ambiguous */
for (i=0; i<lnStates; i++)
preLikeL[a++] = 1.0;
b += lnStatesSquared;
}
}
}
/* calculate likelihoods of site patterns for right branch if terminal */
if (p->right->left == NULL && isPartAmbig[p->right->index] == NO)
{
shortCut |= 2;
rState = termState + p->right->index * numChars;
for (m=a=b=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
for (i=0; i<nStates; i++)
for (j=i+b; j<lnStatesSquared+b; j+=lnStates)
{
temp = pR[j] + pR[j+nStates];
preLikeR[a++] = temp + ((seqErrorProb - nStates*seqErrorProb*temp)/(nStates-1.0));
}
/* for ambiguous */
for (i=0; i<lnStates; i++)
preLikeR[a++] = 1.0;
b += lnStatesSquared;
}
}
}
/* calculate conditional likelihoods */
/* first set pointers to cond likes of left, right and p */
clL = &condLike[condLikeOffset + (p->left->index)*oneNodeSize];
clR = &condLike[condLikeOffset + (p->right->index)*oneNodeSize];
clP = &condLike[condLikeOffset + (p->index)*oneNodeSize];
/* then branch to models */
if (!strcmp(ratesModel, "equal"))
{
switch (shortCut)
{
case 0: // none is terminal
for (c=0; c<numChars; c++)
{
for (i=m=0; i<lnStates; i++)
{
likeL = likeR = 0.0;
for (j=0; j<lnStates; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m++]*clR[j];
}
*(clP++) = likeL * likeR;
}
clL += lnStates;
clR += lnStates;
}
break;
case 1: // left is terminal
for (c=0; c<numChars; c++)
{
a = lState[c];
for (i=m=0; i<lnStates; i++)
{
likeR = 0.0;
for (j=0; j<lnStates; j++)
{
likeR += pR[m++]*clR[j];
}
*(clP++) = preLikeL[a++] * likeR;
}
clR += lnStates;
}
break;
case 2: // right is terminal
for (c=0; c<numChars; c++)
{
a = rState[c];
for (i=m=0; i<lnStates; i++)
{
likeL = 0.0;
for (j=0; j<lnStates; j++)
{
likeL += pL[m++]*clL[j];
}
*(clP++) = likeL * preLikeR[a++];
}
clL += lnStates;
}
break;
case 3: // both left and right are terminal
for (c=0; c<numChars; c++)
{
a = lState[c];
b = rState[c];
for (i=m=0; i<lnStates; i++)
{
*(clP++) = preLikeL[a++] * preLikeR[b++];
}
}
break;
}
}
else if (!strcmp(ratesModel, "gamma") || !strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "invariant") || !strcmp(ratesModel, "invgamma"))
{
switch (shortCut)
{
case 0: // none is terminal
for (c=0; c<numChars; c++)
{
for (k=m=0; k<lnumRateCats; k++)
{
for (i=0; i<lnStates; i++)
{
likeL = likeR = 0.0;
for (j=0; j<lnStates; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m++]*clR[j];
}
*(clP++) = likeL * likeR;
}
clL += lnStates;
clR += lnStates;
}
}
break;
case 1: // left is terminal
for (c=0; c<numChars; c++)
{
a = lState[c];
for (k=m=0; k<lnumRateCats; k++)
{
for (i=0; i<lnStates; i++)
{
likeR = 0.0;
for (j=0; j<lnStates; j++)
{
likeR += pR[m++]*clR[j];
}
*(clP++) = preLikeL[a++] * likeR;
}
clR += lnStates;
a += preLikeIncrement;
}
}
break;
case 2: // right is terminal
for (c=0; c<numChars; c++)
{
a = rState[c];
for (k=m=0; k<lnumRateCats; k++)
{
for (i=0; i<lnStates; i++)
{
likeL = 0.0;
for (j=0; j<lnStates; j++)
{
likeL += pL[m++]*clL[j];
}
*(clP++) = likeL * preLikeR[a++];
}
clL += lnStates;
a += preLikeIncrement;
}
}
break;
case 3: // both left and right are terminal
for (c=0; c<numChars; c++)
{
a = lState[c];
b = rState[c];
for (k=m=0; k<lnumRateCats; k++)
{
for (i=0; i<lnStates; i++)
{
*(clP++) = preLikeL[a++] * preLikeR[b++];
}
a += preLikeIncrement;
b += preLikeIncrement;
}
}
break;
}
}
else if (!strcmp(ratesModel, "ssgamma") || !strcmp(ratesModel, "ssadgamma"))
{
indexMultiplier1 = lnumRateCats * lnStatesSquared;
indexMultiplier2 = lnumRateCats * (nStates + 1) * lnStates;
switch (shortCut)
{
case 0: // none is terminal
for (c=0; c<numChars; c++)
{
m = partitionId[c]*indexMultiplier1;
for (k=0; k<lnumRateCats; k++)
{
for (i=0; i<lnStates; i++)
{
likeL = likeR = 0.0;
for (j=0; j<lnStates; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m++]*clR[j];
}
*(clP++) = likeL * likeR;
}
clL += lnStates;
clR += lnStates;
}
}
break;
case 1: // left is terminal
for (c=0; c<numChars; c++)
{
m = partitionId[c]*indexMultiplier1;
a = lState[c] + (partitionId[c]*indexMultiplier2);
for (k=0; k<lnumRateCats; k++)
{
for (i=0; i<lnStates; i++)
{
likeR = 0.0;
for (j=0; j<lnStates; j++)
{
likeR += pR[m++]*clR[j];
}
*(clP++) = preLikeL[a++] * likeR;
}
clR += lnStates;
a += preLikeIncrement;
}
}
break;
case 2: // right is terminal
for (c=0; c<numChars; c++)
{
m = partitionId[c]*indexMultiplier1;
a = rState[c] + (partitionId[c] * indexMultiplier2);
for (k=0; k<lnumRateCats; k++)
{
for (i=0; i<lnStates; i++)
{
likeL = 0.0;
for (j=0; j<lnStates; j++)
{
likeL += pL[m++]*clL[j];
}
*(clP++) = likeL * preLikeR[a++];
}
clL += lnStates;
a += preLikeIncrement;
}
}
break;
case 3: // both left and right are terminal
for (c=0; c<numChars; c++)
{
m = partitionId[c]*indexMultiplier1;
index = partitionId[c] * indexMultiplier2;
a = lState[c] + index;
b = rState[c] + index;
for (k=0; k<lnumRateCats; k++)
{
for (i=0; i<lnStates; i++)
{
*(clP++) = preLikeL[a++] * preLikeR[b++];
}
a += preLikeIncrement;
b += preLikeIncrement;
}
}
break;
}
}
else if (!strcmp(ratesModel, "sitespec"))
{
indexMultiplier1 = lnStatesSquared;
indexMultiplier2 = (nStates + 1) * lnStates;
switch (shortCut)
{
case 0: // none is terminal
for (c=0; c<numChars; c++)
{
m = partitionId[c]*indexMultiplier1;
for (i=0; i<lnStates; i++)
{
likeL = likeR = 0.0;
for (j=0; j<lnStates; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m++]*clR[j];
}
*(clP++) = likeL * likeR;
}
clL += lnStates;
clR += lnStates;
}
break;
case 1: // left is terminal
for (c=0; c<numChars; c++)
{
m = partitionId[c]*indexMultiplier1;
a = lState[c] + (partitionId[c]*indexMultiplier2);
for (i=0; i<lnStates; i++)
{
likeR = 0.0;
for (j=0; j<lnStates; j++)
{
likeR += pR[m++]*clR[j];
}
*(clP++) = preLikeL[a++] * likeR;
}
clR += lnStates;
}
break;
case 2: // right is terminal
for (c=0; c<numChars; c++)
{
m = partitionId[c]*indexMultiplier1;
a = rState[c] + (partitionId[c] * indexMultiplier2);
for (i=0; i<lnStates; i++)
{
likeL = 0.0;
for (j=0; j<lnStates; j++)
{
likeL += pL[m++]*clL[j];
}
*(clP++) = likeL * preLikeR[a++];
}
clL += lnStates;
}
break;
case 3: // both left and right are terminal
for (c=0; c<numChars; c++)
{
m = partitionId[c]*indexMultiplier1;
index = partitionId[c] * indexMultiplier2;
a = lState[c] + index;
b = rState[c] + index;
for (i=0; i<lnStates; i++)
{
*(clP++) = preLikeL[a++] * preLikeR[b++];
}
}
break;
}
}
p->upDateCl = NO;
clUpdateFlag[p->index] = YES;
} // done with interior node if p->upDateCl == YES
} // done with interior node
// deal with scaling
// first check if we need to refresh scalers and potentially shift scaler nodes
// we have to remember scalerIndex because the node may move in the tree
if (refreshScalers == YES)
{
if (n % RESCALE_FREQ == 0)
{
p->scalerNode = YES;
p->scalerIndex = n;
}
else
p->scalerNode = NO;
}
if (p->scalerNode == YES && clUpdateFlag[p->index] == YES)
{
scalerUpdateFlag[p->scalerIndex] = YES;
scP = &clScaler[scalerOffset + (p->scalerIndex)*numChars];
clP = &condLike[condLikeOffset + (p->index)*oneNodeSize];
i = j = 0;
for (c=0; c<numChars; c++)
{
scaler = 0.0;
for (k=0; k<lnumRateCats; k++)
{
for (m=0; m<lnStates; m++)
{
if (clP[i] > scaler)
scaler = clP[i];
i++;
}
}
for (k=0; k<lnumRateCats; k++)
{
for (m=0; m<lnStates; m++)
clP[j++] /= scaler;
}
lnScaler[c] -= scP[c]; //subtract old value
scP[c] = log(scaler);
lnScaler[c] += scP[c]; //add new value
}
}
} // next node
/* get likelihood at base of tree */
p = root[whichChain*2+whichState]->left;
clP = &condLike[condLikeOffset + (p->index)*oneNodeSize];
(*lnL) = 0.0; // reset lnL
if (!strcmp(ratesModel, "equal") || !strcmp(ratesModel, "sitespec"))
{
for (c=0; c<numChars; c++)
{
like = 0.0;
for (i=0; i<lnStates; i++)
like += ((*(clP++)) * bs[i]);
//printf ("%d: %1.25lf %lf %d\n", c, like, log(like), numSitesOfPat[c]);
if (like < LIKE_EPSILON) /* likelihood for a site can go to zero when */
{ /* two adjacent terminal branches have zero length. */
printf (" WARNING: In LIKE_EPSILON\n");
goto error_exit;
}
else
{
(*lnL) += (lnScaler[c] + log(like)) * numSitesOfPat[c];
}
}
}
else if (!strcmp(ratesModel, "gamma") || !strcmp(ratesModel, "invariant") || !strcmp(ratesModel, "invgamma") || !strcmp(ratesModel, "ssgamma"))
{
for (c=0; c<numChars; c++)
{
like = 0.0;
for (k=0; k<lnumRateCats; k++)
{
for (i=0; i<lnStates; i++)
like += ((*(clP++)) * bs[i]) * catFreq[k];
}
if (like < LIKE_EPSILON) /* likelihood for a site can go to zero when */
{ /* two adjacent terminal branches have zero length. */
printf (" WARNING: In LIKE_EPSILON (%d) %1.30lf\n", c, like);
goto error_exit;
}
else
{
(*lnL) += (lnScaler[c] + log(like)) * numSitesOfPat[c];
}
}
}
else if (!strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "ssadgamma"))
{
/* initialize usedBin */
for (i=0; i<nChar; i++)
usedBin[i] = NO;
lnC = 0.0;
m = j = 0;
for (c=0; c<numChars; c++)
{
for (k=0; k<lnumRateCats; k++)
{
like = 0.0;
for (i=0; i<lnStates; i++)
like += clP[j++] * bs[i];
ratePr[m++] = like;
}
lnC += (lnScaler[c] * numSitesOfPat[c]);
}
localLag = lag[whichChain*2 + whichState];
for (c=nChar-1; c>=0; c--)
{
cn = c*lnumRateCats;
if (patternId[c] >= 0)
{
pat = patternId[c];
if (c + localLag >= nChar)
{
max = 0.0;
for (k=0; k<lnumRateCats; k++)
{
biN[cn + k] = ratePr[pat*lnumRateCats + k];
if (biN[cn + k] > max)
max = biN[cn + k];
}
if (max > 0.0)
{
for (k=0; k<lnumRateCats; k++)
biN[cn + k] /= max;
lnC += log(max);
}
else
{
printf (" ERROR: Scaling factor for adgamma model is less than 0\n");
goto error_exit;
}
}
else
{
for (i=0; i<lnumRateCats; i++)
{
temp = max = 0.0;
for (j=0; j<lnumRateCats; j++)
temp += markovTi[i][j] * biN[(c+localLag)*lnumRateCats + j];
biN[cn + i] = ratePr[pat*lnumRateCats+i] * temp;
if (biN[cn + i] > max)
max = biN[cn + i];
usedBin[c+localLag] = YES;
}
if (max > 0.0)
{
for (k=0; k<lnumRateCats; k++)
biN[cn + k] /= max;
lnC += log(max);
}
else
{
printf (" ERROR: Scaling factor for adgamma model is less than 0\n");
goto error_exit;
}
}
}
else
{
printf (" ERROR: Unidentified pattern\n");
goto error_exit;
}
}
(*lnL) = lnC;
for (c=0; c<nChar; c++)
{
if (usedBin[c] == NO)
{
temp = 0.0;
for (k=0; k<lnumRateCats; k++)
{
temp += (catFreq[k] * biN[c*lnumRateCats + k]);
}
(*lnL) += log(temp);
usedBin[c] = YES;
}
}
}
/* free memory */
# if !defined (SMART_TI_PROBS)
free_psdmatrix (probs);
free (pL);
free_psdmatrix (q);
free (eigenValues);
free_psdmatrix (eigvecs);
free_psdmatrix (inverseEigvecs);
free_pscmatrix (Ceigvecs);
free_pscmatrix (CinverseEigvecs);
free (c_ijk);
free (isComplex);
free (eigenValuesP);
free (eigvecsP);
free (CeigvecsP);
free (c_ijkP);
# endif
free (catFreq);
free (bs);
free (preLikeL);
if (!strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "ssadgamma"))
{
free_psdmatrix(markovTi);
free (ratePr);
free (usedBin);
}
return (NO_ERROR);
error_exit:
# if !defined (SMART_TI_PROBS)
free_psdmatrix (probs);
free (pL);
free_psdmatrix (q);
free (eigenValues);
free_psdmatrix (eigvecs);
free_psdmatrix (inverseEigvecs);
free_pscmatrix (Ceigvecs);
free_pscmatrix (CinverseEigvecs);
free (c_ijk);
free (isComplex);
free (eigenValuesP);
free (eigvecsP);
free (CeigvecsP);
free (c_ijkP);
# endif
free (catFreq);
free (bs);
free (preLikeL);
if (!strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "ssadgamma"))
{
free_psdmatrix(markovTi);
free (ratePr);
free (usedBin);
}
return (ERROR);
}
#endif
/*-----------------------------------------------------------
LnLikeRestriction: 'Fast' version, core written 2001-03-12
------------------------------------------------------------*/
int LnLikeRestriction (int whichState, int whichChain, int numChars, int numRateCats, double *lnL, int refreshScalers)
{
register int i, j, k, b, c, n, m;
int nPij, lnumRateCats, lnPartitions, oneMatSize, oneNodeSize,
condLikeOffset, scalerOffset, indexL, indexR, indexA,
index, intNodeOffset, nRates;
double bs[2], *pL, *pR, *pA, *catFreq, *catRate, alp, bet, x, v, eV,
*clL, *clR, *clA, *clP, *tiPL, *tiPR, *tiPA, like, theRate,
*lnScaler, *scP, *partRate, scaler;
TreeNode *p;
# define N_STATES_SQUARED 4
# define N_STATES 2
/* initialize intNodeOffset */
intNodeOffset = whichChain*2*numIntNodes + whichState*numIntNodes;
/* how many different rate categories?
/* deal with relevant models
/* lnumRateCats contains a local copy of numRateCats if appropriate, else 1
/* lnPartitions contains a local copy of nPartitions if appropriate, else 1
/* this is to make sure that these variables are set locally to 1 if not
/* relevant for the model specified for the data */
if (!strcmp(ratesModel, "sitespec") || !strcmp(ratesModel, "ssgamma"))
lnPartitions = nPartitions;
else
lnPartitions = 1;
if (!strcmp(ratesModel, "equal") || !strcmp(ratesModel, "sitespec"))
lnumRateCats = 1;
else if (!strcmp(ratesModel, "gamma") || !strcmp(ratesModel, "ssgamma"))
lnumRateCats = numRateCats;
nRates = lnPartitions * lnumRateCats; // number of rates needing P matrices
/* allocate memory for the calculations */
/* pL, pR and pA will contain the transition probs for Left, Right and Anc */
/* one trans prob matrix needed for each possible rate */
nPij = nRates * numBetaCats * N_STATES_SQUARED;
pL = (double *)malloc((size_t)(3 * nPij * sizeof(double)));
if (!pL)
{
printf ("\n ERROR: Problem allocating Pij\n");
goto error_exit;
}
pR = pL + nPij;
pA = pR + nPij;
/* allocate memory for rates and rate category frequencies */
catFreq = (double *)malloc((size_t) ((2 * lnumRateCats + lnPartitions) * sizeof(double)));
if (!catFreq)
{
printf ("\n ERROR: Problem allocating space for rate multipliers and rate category freqs.\n");
goto error_exit;
}
catRate = catFreq + lnumRateCats;
partRate = catRate + lnumRateCats;
// set pointer to the lnSiteScaler for this tree
lnScaler = &lnSiteScaler[whichChain * 2 * numChars + whichState * numChars];
/* fill in rate categories with frequencies and rates by dividing the */
/* gamma distribution into discrete categories, if appropriate */
/* NB! this is inefficient; store values instead */
if (lnumRateCats > 1)
{
DiscreteGamma (catFreq, catRate, alpha[whichChain*2 + whichState], alpha[whichChain*2 + whichState], lnumRateCats, 0);
}
else {
catRate[0] = 1.0;
catFreq[0] = 1.0;
}
/* initialize partition rates, if appropriate */
if (lnPartitions > 1)
{
for (i=0; i<lnPartitions; i++)
partRate[i] = scaledRates[whichChain*2*lnPartitions + whichState*lnPartitions + i];
}
else
partRate[0] = 1.0;
/* set forward/backward ratio */
x = kappa[whichChain*2 + whichState];
alp = (x*x + x) / (2*x);
bet = (x + 1.0) / (2*x);
/* fill in stationary frequencies */
bs[0] = bet / (alp + bet);
bs[1] = alp / (alp + bet);
/* how large is the information for one tree and one node*/
oneMatSize = numNodes * numChars * lnumRateCats * numBetaCats * N_STATES;
oneNodeSize = numChars * lnumRateCats * numBetaCats * N_STATES;
/* calculate indices */
condLikeOffset = whichChain*2*oneMatSize + whichState*oneMatSize;
scalerOffset = whichChain*2*numIntNodes*numChars + whichState*numIntNodes*numChars;
/* pass down tree */
for (n=0; n<numIntNodes; n++)
{
p = intNodeDownPassSeq[intNodeOffset + n];
// for debugging purposes
// set all nodes to update
// p->upDateCl = YES;
clUpdateFlag[p->index] = NO;
if (p->anc->anc == NULL && treeModel == UNROOTED)
{
if (p->upDateCl == YES)
{
//printf ("visiting basal node %d\n", p->index);
/* get transition probabilities */
for (m=indexL=indexR=indexA=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
theRate = partRate[m] * catRate[k];
v = p->left->length * theRate;
eV = exp(-(alp+bet)*v);
pL[indexL++] = bs[0] + bs[1] * eV;
pL[indexL++] = bs[1] - bs[1] * eV;
pL[indexL++] = bs[0] - bs[0] * eV;
pL[indexL++] = bs[1] + bs[0] * eV;
v = p->right->length * theRate;
eV = exp(-(alp+bet)*v);
pR[indexR++] = bs[0] + bs[1] * eV;
pR[indexR++] = bs[1] - bs[1] * eV;
pR[indexR++] = bs[0] - bs[0] * eV;
pR[indexR++] = bs[1] + bs[0] * eV;
v = p->length * theRate;
eV = exp(-(alp+bet)*v);
pA[indexA++] = bs[0] + bs[1] * eV;
pA[indexA++] = bs[1] - bs[1] * eV;
pA[indexA++] = bs[0] - bs[0] * eV;
pA[indexA++] = bs[1] + bs[0] * eV;
}
}
/* calculate conditional likelihoods */
/* first set pointers to cond likes of left, right, p and anc */
clL = &condLike[condLikeOffset + (p->left->index)*oneNodeSize];
clR = &condLike[condLikeOffset + (p->right->index)*oneNodeSize];
clA = &condLike[condLikeOffset + (p->anc->index)*oneNodeSize];
clP = &condLike[condLikeOffset + (p->index)*oneNodeSize];
if (!strcmp(ratesModel, "equal"))
{
tiPL = pL;
tiPR = pR;
tiPA = pA;
for (c=0; c<numChars; c++)
{
*(clP++) = (tiPL[0]*clL[0] + tiPL[1]*clL[1])
*(tiPR[0]*clR[0] + tiPR[1]*clR[1])
*(tiPA[0]*clA[0] + tiPA[1]*clA[1]);
*(clP++) = (tiPL[2]*clL[0] + tiPL[3]*clL[1])
*(tiPR[2]*clR[0] + tiPR[3]*clR[1])
*(tiPA[2]*clA[0] + tiPA[3]*clA[1]);
clL += 2;
clR += 2;
clA += 2;
}
}
else if (!strcmp(ratesModel, "gamma"))
{
for (c=0; c<numChars; c++)
{
tiPL = pL;
tiPR = pR;
tiPA = pA;
for (k=0; k<lnumRateCats; k++)
{
*(clP++) = (tiPL[0]*clL[0] + tiPL[1]*clL[1])
*(tiPR[0]*clR[0] + tiPR[1]*clR[1])
*(tiPA[0]*clA[0] + tiPA[1]*clA[1]);
*(clP++) = (tiPL[2]*clL[0] + tiPL[3]*clL[1])
*(tiPR[2]*clR[0] + tiPR[3]*clR[1])
*(tiPA[2]*clA[0] + tiPA[3]*clA[1]);
tiPL += 4;
tiPR += 4;
tiPA += 4;
clL += 2;
clR += 2;
clA += 2;
}
}
}
else if (!strcmp(ratesModel, "ssgamma"))
{
for (c=0; c<numChars; c++)
{
index = partitionId[c]* lnumRateCats * numBetaCats * N_STATES_SQUARED;
tiPL = &pL[index];
tiPR = &pR[index];
tiPA = &pA[index];
for (k=0; k<lnumRateCats; k++)
{
*(clP++) = (tiPL[0]*clL[0] + tiPL[1]*clL[1])
*(tiPR[0]*clR[0] + tiPR[1]*clR[1])
*(tiPA[0]*clA[0] + tiPA[1]*clA[1]);
*(clP++) = (tiPL[2]*clL[0] + tiPL[3]*clL[1])
*(tiPR[2]*clR[0] + tiPR[3]*clR[1])
*(tiPA[2]*clA[0] + tiPA[3]*clA[1]);
tiPL += 4;
tiPR += 4;
tiPA += 4;
clL += 2;
clR += 2;
clA += 2;
}
}
}
else if (!strcmp(ratesModel, "sitespec"))
{
for (c=0; c<numChars; c++)
{
index = partitionId[c] * numBetaCats * N_STATES_SQUARED;
tiPL = &pL[index];
tiPR = &pR[index];
tiPA = &pA[index];
*(clP++) = (tiPL[0]*clL[0] + tiPL[1]*clL[1])
*(tiPR[0]*clR[0] + tiPR[1]*clR[1])
*(tiPA[0]*clA[0] + tiPA[1]*clA[1]);
*(clP++) = (tiPL[2]*clL[0] + tiPL[3]*clL[1])
*(tiPR[2]*clR[0] + tiPR[3]*clR[1])
*(tiPA[2]*clA[0] + tiPA[3]*clA[1]);
clL += 2;
clR += 2;
clA += 2;
}
}
p->upDateCl = NO;
clUpdateFlag[p->index] = YES;
} // done if p->upDateCl == YES for root node
} // done with root node
else
{
if (p->upDateCl == YES)
{
//printf ("visiting internal node %d\n", p->index);
/* get transition probabilities */
for (m=indexL=indexR=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
theRate = partRate[m] * catRate[k];
v = p->left->length * theRate;
eV = exp(-(alp+bet)*v);
pL[indexL++] = bs[0] + bs[1] * eV;
pL[indexL++] = bs[1] - bs[1] * eV;
pL[indexL++] = bs[0] - bs[0] * eV;
pL[indexL++] = bs[1] + bs[0] * eV;
v = p->right->length * theRate;
eV = exp(-(alp+bet)*v);
pR[indexR++] = bs[0] + bs[1] * eV;
pR[indexR++] = bs[1] - bs[1] * eV;
pR[indexR++] = bs[0] - bs[0] * eV;
pR[indexR++] = bs[1] + bs[0] * eV;
}
}
/* calculate conditional likelihoods */
/* first assign pointers to right, left and p */
clL = &condLike[condLikeOffset + (p->left->index)*oneNodeSize];
clR = &condLike[condLikeOffset + (p->right->index)*oneNodeSize];
clP = &condLike[condLikeOffset + (p->index)*oneNodeSize];
if (!strcmp(ratesModel, "equal"))
{
tiPL = pL;
tiPR = pR;
for (c=0; c<numChars; c++)
{
*(clP++) = (tiPL[0]*clL[0] + tiPL[1]*clL[1])
*(tiPR[0]*clR[0] + tiPR[1]*clR[1]);
*(clP++) = (tiPL[2]*clL[0] + tiPL[3]*clL[1])
*(tiPR[2]*clR[0] + tiPR[3]*clR[1]);
clL += 2;
clR += 2;
}
}
else if (!strcmp(ratesModel, "gamma"))
{
for (c=0; c<numChars; c++)
{
tiPL = pL;
tiPR = pR;
for (k=0; k<lnumRateCats; k++)
{
*(clP++) = (tiPL[0]*clL[0] + tiPL[1]*clL[1])
*(tiPR[0]*clR[0] + tiPR[1]*clR[1]);
*(clP++) = (tiPL[2]*clL[0] + tiPL[3]*clL[1])
*(tiPR[2]*clR[0] + tiPR[3]*clR[1]);
tiPL += 4;
tiPR += 4;
clL += 2;
clR += 2;
}
}
}
else if (!strcmp(ratesModel, "ssgamma"))
{
for (c=0; c<numChars; c++)
{
index = partitionId[c] * lnumRateCats * numBetaCats * N_STATES_SQUARED;
tiPL = &pL[index];
tiPR = &pR[index];
for (k=0; k<lnumRateCats; k++)
{
*(clP++) = (tiPL[0]*clL[0] + tiPL[1]*clL[1])
*(tiPR[0]*clR[0] + tiPR[1]*clR[1]);
*(clP++) = (tiPL[2]*clL[0] + tiPL[3]*clL[1])
*(tiPR[2]*clR[0] + tiPR[3]*clR[1]);
tiPL += 4;
tiPR += 4;
clL += 2;
clR += 2;
}
}
}
else if (!strcmp(ratesModel, "sitespec"))
{
for (c=0; c<numChars; c++)
{
index = partitionId[c] * numBetaCats * N_STATES_SQUARED ;
tiPL = &pL[index];
tiPR = &pR[index];
*(clP++) = (tiPL[0]*clL[0] + tiPL[1]*clL[1])
*(tiPR[0]*clR[0] + tiPR[1]*clR[1]);
*(clP++) = (tiPL[2]*clL[0] + tiPL[3]*clL[1])
*(tiPR[2]*clR[0] + tiPR[3]*clR[1]);
clL += 2;
clR += 2;
}
}
p->upDateCl = NO;
clUpdateFlag[p->index] = YES;
} // done with interior node if p->upDateCl == YES
} // done with interior node
// deal with scaling
// first check if we need to refresh scalers
// and potentially shift scaler nodes
// we have to remember scalerIndex
// because the node may move in the tree
if (refreshScalers == YES)
{
if (n % RESCALE_FREQ == 0)
{
p->scalerNode = YES;
p->scalerIndex = n;
}
else
p->scalerNode = NO;
}
if (p->scalerNode == YES && clUpdateFlag[p->index] == YES)
{
scalerUpdateFlag[p->scalerIndex] = YES;
scP = &clScaler[scalerOffset + (p->scalerIndex)*numChars];
clP = &condLike[condLikeOffset + (p->index)*oneNodeSize];
i = j = 0;
for (c=0; c<numChars; c++)
{
scaler = 0.0;
for (k=0; k<lnumRateCats; k++)
{
for (b=0; b<numBetaCats; b++)
{
if (clP[i] > scaler)
scaler = clP[i];
i++;
if (clP[i] > scaler)
scaler = clP[i];
i++;
}
}
for (k=0; k<lnumRateCats; k++)
{
for (b=0; b<numBetaCats; b++)
{
clP[j++] /= scaler;
clP[j++] /= scaler;
}
}
lnScaler[c] -= scP[c]; //subtract old value
scP[c] = log(scaler);
lnScaler[c] += scP[c]; //add new value
}
}
} // next node
/* get likelihood at base of tree */
/* deal with conditioning by dividing like with pObserved */
p = root[whichChain*2+whichState]->left;
(*lnL) = 0.0;
for (k=0; k<lnumRateCats; k++)
pObserved = 0.0;
clP = &condLike[condLikeOffset + (p->index)*oneNodeSize];
if (!strcmp(ratesModel, "equal") || !strcmp(ratesModel, "sitespec"))
{
for (c=j=0; c<numDummyChars; c++)
{
like = (clP[j++] * bs[0]);
like += (clP[j++] * bs[1]);
if (like < LIKE_EPSILON) /* likelihood for a site can go to zero when */
{ /* two adjacent terminal branches have zero length. */
printf (" WARNING: In LIKE_EPSILON\n");
goto error_exit;
}
else
pObserved += exp(lnScaler[c]) * like;
}
pObserved = 1.0 - pObserved;
for (c=numDummyChars; c<numChars; c++)
{
like = (clP[j++] * bs[0]);
like += (clP[j++] * bs[1]);
like /= pObserved;
if (like < LIKE_EPSILON) /* likelihood for a site can go to zero when */
{ /* two adjacent terminal branches have zero length. */
printf (" WARNING: In LIKE_EPSILON\n");
goto error_exit;
}
else
(*lnL) += (lnScaler[c] + log(like)) * numSitesOfPat[c];
}
}
else if (!strcmp(ratesModel, "gamma") || !strcmp(ratesModel, "ssgamma"))
{
for (c=j=0; c<numDummyChars; c++)
{
like=0.0;
for (k=0; k<lnumRateCats; k++)
{
like += clP[j++] * bs[0] * catFreq[k];
like += clP[j++] * bs[1] * catFreq[k];
}
pObserved += like * exp(lnScaler[c]);
}
pObserved = 1.0 - pObserved;
if (pObserved < LIKE_EPSILON)
pObserved = LIKE_EPSILON;
for (c=numDummyChars; c<numChars; c++)
{
like = 0.0;
for (k=0; k<lnumRateCats; k++)
{
like += (clP[j++] * bs[0] * catFreq[k]);
like += (clP[j++] * bs[1] * catFreq[k]);
}
like /= pObserved;
if (like < LIKE_EPSILON) /* likelihood for a site can go to zero when */
{ /* two adjacent terminal branches have zero length. */
printf (" WARNING: In LIKE_EPSILON\n");
goto error_exit;
}
else
(*lnL) += (lnScaler[c] + log(like)) * numSitesOfPat[c];
}
}
/* free memory */
free (pL);
free (catFreq);
return (NO_ERROR);
error_exit:
free (pL);
free (catFreq);
return (ERROR);
# undef N_STATES_SQUARED
# undef N_STATES
}
/*----------------------------------------------------------------------
LnLikeStandardBin: Likelihood function for standard binary data
This function deals with conditioning on coding type and different independent
stationary frequencies determined by a discrete beta function
Rate var dealt with according to equal, sitespec, gamma or ssgamma models
Core written 2001-03-11
------------------------------------------------------------------------*/
int LnLikeStandardBin (int whichState, int whichChain, int numChars, int numRateCats, double *lnL, int refreshScalers)
{
register int i, j, k, b, c, n, m;
int nPij, lnumRateCats, lnPartitions, oneMatSize, oneNodeSize,
condLikeOffset, scalerOffset, indexL, indexR, indexA,
index, intNodeOffset, nRates;
double *bs, *pL, *pR, *pA, *catFreq, *catRate, alp, bet, x, v, eV,
*clL, *clR, *clA, *clP, *tiPL, *tiPR, *tiPA, like, theRate,
*lnScaler, *scP, *partRate, scaler, *betaFreq, *betaValues,
bs0, bs1;
TreeNode *p;
# define N_STATES_SQUARED 4
# define N_STATES 2
/* initialize intNodeOffset */
intNodeOffset = whichChain*2*numIntNodes + whichState*numIntNodes;
/* how many different rate categories?
/* deal with relevant models
/* lnumRateCats contains a local copy of numRateCats if appropriate, else 1
/* lnPartitions contains a local copy of nPartitions if appropriate, else 1
/* this is to make sure that these variables are set locally to 1 if not
/* relevant for the model specified for the data */
if (!strcmp(ratesModel, "sitespec") || !strcmp(ratesModel, "ssgamma"))
lnPartitions = nPartitions;
else
lnPartitions = 1;
if (!strcmp(ratesModel, "equal") || !strcmp(ratesModel, "sitespec"))
lnumRateCats = 1;
else if (!strcmp(ratesModel, "gamma") || !strcmp(ratesModel, "ssgamma"))
lnumRateCats = numRateCats;
nRates = lnPartitions * lnumRateCats; // number of rates needing P matrices
/* allocate memory for the calculations */
/* pL, pR and pA will contain the transition probs for Left, Right and Anc */
/* one trans prob matrix needed for each possible rate */
nPij = nRates * numBetaCats * N_STATES_SQUARED;
pL = (double *)malloc((size_t)(3 * nPij * sizeof(double)));
if (!pL)
{
printf ("\n ERROR: Problem allocating Pij\n");
goto error_exit;
}
pR = pL + nPij;
pA = pR + nPij;
/* allocate memory for rates and rate category frequencies */
catFreq = (double *)malloc((size_t) ((2 * lnumRateCats + lnPartitions) * sizeof(double)));
if (!catFreq)
{
printf ("\n ERROR: Problem allocating space for rate multipliers and rate category freqs.\n");
goto error_exit;
}
catRate = catFreq + lnumRateCats;
partRate = catRate + lnumRateCats;
/* allocate memory for the discrete beta values */
betaFreq = (double *)malloc((size_t) (4 * numBetaCats * sizeof(double)));
if (!betaFreq)
{
printf ("\n ERROR: Problem allocating betaValues, betaFreq and bs.\n");
goto error_exit;
}
betaValues = betaFreq + numBetaCats;
bs = betaValues + numBetaCats;
// set pointer to the lnSiteScaler for this tree
lnScaler = &lnSiteScaler[whichChain * 2 * numChars + whichState * numChars];
/* fill in rate categories with frequencies and rates by dividing the */
/* gamma distribution into discrete categories, if appropriate */
/* NB! this is inefficient; store values instead */
if (lnumRateCats > 1)
{
DiscreteGamma (catFreq, catRate, alpha[whichChain*2 + whichState], alpha[whichChain*2 + whichState], lnumRateCats, 0);
}
else {
catRate[0] = 1.0;
catFreq[0] = 1.0;
}
/* initialize partition rates, if appropriate */
if (lnPartitions > 1)
{
for (i=0; i<lnPartitions; i++)
partRate[i] = scaledRates[whichChain*2*lnPartitions + whichState*lnPartitions + i];
}
else
partRate[0] = 1.0;
/* fill in beta categories */
if (!strcmp(stateFreqPrModel, "fixed"))
{
betaValues[0] = 0.5;
betaFreq[0] = 1.0;
}
else if (!strcmp(stateFreqPrModel, "dirichlet"))
{
BetaBreaks (statefreqP[whichChain*2 + whichState], statefreqP[whichChain*2 + whichState], betaValues, betaFreq, numBetaCats);
# if defined (DEBUG_LNLIKEBIN)
for (i=0; i<numBetaCats; i++)
printf ("%4d -- %lf %lf\n", i+1, betaValues[i], betaFreq[i]);
# endif
}
/* fill in stationary frequencies */
for (b=j=0; b<numBetaCats; b++)
{
x = (1.0 / betaValues[b]) - 1.0;
alp = (x*x + x) / (2*x);
bet = (x + 1.0) / (2*x);
bs[j++] = bet / (alp + bet);
bs[j++] = alp / (alp + bet);
}
# if defined (DEBUG_LNLIKEBIN)
for (i=0; i<numBetaCats; i++)
printf ("%4d -- %lf %lf\n", i+1, bs[2*i], bs[2*i+1]);
# endif
/* how large is the information for one tree and one node*/
oneMatSize = numNodes * numChars * lnumRateCats * numBetaCats * N_STATES;
oneNodeSize = numChars * lnumRateCats * numBetaCats * N_STATES;
/* calculate indices */
condLikeOffset = whichChain*2*oneMatSize + whichState*oneMatSize;
scalerOffset = whichChain*2*numIntNodes*numChars + whichState*numIntNodes*numChars;
/* pass down tree */
for (n=0; n<numIntNodes; n++)
{
p = intNodeDownPassSeq[intNodeOffset + n];
// for debugging purposes
// set all nodes to update
// p->upDateCl = YES;
clUpdateFlag[p->index] = NO;
if (p->anc->anc == NULL && treeModel == UNROOTED)
{
if (p->upDateCl == YES)
{
//printf ("visiting basal node %d\n", p->index);
/* get transition probabilities */
for (m=indexL=indexR=indexA=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
theRate = partRate[m] * catRate[k];
for (b=j=0; b<numBetaCats; b++)
{
bs0 = bs[j++];
bs1 = bs[j++];
x = (1.0 / betaValues[b]) - 1.0;
alp = (x*x + x) / (2*x);
bet = (x + 1.0) / (2*x);
v = p->left->length * theRate;
eV = exp(-(alp+bet)*v);
pL[indexL++] = (bs0) + (bs1) * eV;
pL[indexL++] = (bs1) - (bs1) * eV;
pL[indexL++] = (bs0) - (bs0) * eV;
pL[indexL++] = (bs1) + (bs0) * eV;
v = p->right->length * theRate;
eV = exp(-(alp+bet)*v);
pR[indexR++] = (bs0) + (bs1) * eV;
pR[indexR++] = (bs1) - (bs1) * eV;
pR[indexR++] = (bs0) - (bs0) * eV;
pR[indexR++] = (bs1) + (bs0) * eV;
v = p->length * theRate;
eV = exp(-(alp+bet)*v);
pA[indexA++] = (bs0) + (bs1) * eV;
pA[indexA++] = (bs1) - (bs1) * eV;
pA[indexA++] = (bs0) - (bs0) * eV;
pA[indexA++] = (bs1) + (bs0) * eV;
}
}
}
/* calculate conditional likelihoods */
/* first set pointers to cond likes of left, right, p and anc */
clL = &condLike[condLikeOffset + (p->left->index)*oneNodeSize];
clR = &condLike[condLikeOffset + (p->right->index)*oneNodeSize];
clA = &condLike[condLikeOffset + (p->anc->index)*oneNodeSize];
clP = &condLike[condLikeOffset + (p->index)*oneNodeSize];
if (!strcmp(ratesModel, "equal"))
{
for (c=0; c<numChars; c++)
{
tiPL = pL;
tiPR = pR;
tiPA = pA;
for (b=0; b<numBetaCats; b++)
{
*(clP++) = (tiPL[0]*clL[0] + tiPL[1]*clL[1])
*(tiPR[0]*clR[0] + tiPR[1]*clR[1])
*(tiPA[0]*clA[0] + tiPA[1]*clA[1]);
*(clP++) = (tiPL[2]*clL[0] + tiPL[3]*clL[1])
*(tiPR[2]*clR[0] + tiPR[3]*clR[1])
*(tiPA[2]*clA[0] + tiPA[3]*clA[1]);
tiPL += 4;
tiPR += 4;
tiPA += 4;
clL += 2;
clR += 2;
clA += 2;
}
}
}
else if (!strcmp(ratesModel, "gamma"))
{
for (c=0; c<numChars; c++)
{
tiPL = pL;
tiPR = pR;
tiPA = pA;
for (k=0; k<lnumRateCats; k++)
{
for (b=0; b<numBetaCats; b++)
{
*(clP++) = (tiPL[0]*clL[0] + tiPL[1]*clL[1])
*(tiPR[0]*clR[0] + tiPR[1]*clR[1])
*(tiPA[0]*clA[0] + tiPA[1]*clA[1]);
*(clP++) = (tiPL[2]*clL[0] + tiPL[3]*clL[1])
*(tiPR[2]*clR[0] + tiPR[3]*clR[1])
*(tiPA[2]*clA[0] + tiPA[3]*clA[1]);
tiPL += 4;
tiPR += 4;
tiPA += 4;
clL += 2;
clR += 2;
clA += 2;
}
}
}
}
else if (!strcmp(ratesModel, "ssgamma"))
{
for (c=0; c<numChars; c++)
{
index = partitionId[c]* lnumRateCats * numBetaCats * N_STATES_SQUARED;
tiPL = &pL[index];
tiPR = &pR[index];
tiPA = &pA[index];
for (k=0; k<lnumRateCats; k++)
{
for (b=0; b<numBetaCats; b++)
{
*(clP++) = (tiPL[0]*clL[0] + tiPL[1]*clL[1])
*(tiPR[0]*clR[0] + tiPR[1]*clR[1])
*(tiPA[0]*clA[0] + tiPA[1]*clA[1]);
*(clP++) = (tiPL[2]*clL[0] + tiPL[3]*clL[1])
*(tiPR[2]*clR[0] + tiPR[3]*clR[1])
*(tiPA[2]*clA[0] + tiPA[3]*clA[1]);
tiPL += 4;
tiPR += 4;
tiPA += 4;
clL += 2;
clR += 2;
clA += 2;
}
}
}
}
else if (!strcmp(ratesModel, "sitespec"))
{
for (c=0; c<numChars; c++)
{
index = partitionId[c] * numBetaCats * N_STATES_SQUARED;
tiPL = &pL[index];
tiPR = &pR[index];
tiPA = &pA[index];
for (b=0; b<numBetaCats; b++)
{
*(clP++) = (tiPL[0]*clL[0] + tiPL[1]*clL[1])
*(tiPR[0]*clR[0] + tiPR[1]*clR[1])
*(tiPA[0]*clA[0] + tiPA[1]*clA[1]);
*(clP++) = (tiPL[2]*clL[0] + tiPL[3]*clL[1])
*(tiPR[2]*clR[0] + tiPR[3]*clR[1])
*(tiPA[2]*clA[0] + tiPA[3]*clA[1]);
tiPL += 4;
tiPR += 4;
tiPA += 4;
clL += 2;
clR += 2;
clA += 2;
}
}
}
p->upDateCl = NO;
clUpdateFlag[p->index] = YES;
} // done if p->upDateCl == YES for root node
} // done with root node
else
{
if (p->upDateCl == YES)
{
//printf ("visiting internal node %d\n", p->index);
/* get transition probabilities */
for (m=indexL=indexR=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
theRate = partRate[m] * catRate[k];
for (b=j=0; b<numBetaCats; b++)
{
bs0 = bs[j++];
bs1 = bs[j++];
x = (1.0 / betaValues[b]) - 1.0;
alp = (x*x + x) / (2*x);
bet = (x + 1.0) / (2*x);
v = p->left->length * theRate;
eV = exp(-(alp+bet)*v);
pL[indexL++] = (bs0) + (bs1) * eV;
pL[indexL++] = (bs1) - (bs1) * eV;
pL[indexL++] = (bs0) - (bs0) * eV;
pL[indexL++] = (bs1) + (bs0) * eV;
v = p->right->length * theRate;
eV = exp(-(alp+bet)*v);
pR[indexR++] = (bs0) + (bs1) * eV;
pR[indexR++] = (bs1) - (bs1) * eV;
pR[indexR++] = (bs0) - (bs0) * eV;
pR[indexR++] = (bs1) + (bs0) * eV;
}
}
}
/* calculate conditional likelihoods */
/* first assign pointers to right, left and p */
clL = &condLike[condLikeOffset + (p->left->index)*oneNodeSize];
clR = &condLike[condLikeOffset + (p->right->index)*oneNodeSize];
clP = &condLike[condLikeOffset + (p->index)*oneNodeSize];
if (!strcmp(ratesModel, "equal"))
{
for (c=0; c<numChars; c++)
{
tiPL = pL;
tiPR = pR;
for (b=0; b<numBetaCats; b++)
{
*(clP++) = (tiPL[0]*clL[0] + tiPL[1]*clL[1])
*(tiPR[0]*clR[0] + tiPR[1]*clR[1]);
*(clP++) = (tiPL[2]*clL[0] + tiPL[3]*clL[1])
*(tiPR[2]*clR[0] + tiPR[3]*clR[1]);
tiPL += 4;
tiPR += 4;
clL += 2;
clR += 2;
}
}
}
else if (!strcmp(ratesModel, "gamma"))
{
for (c=0; c<numChars; c++)
{
tiPL = pL;
tiPR = pR;
for (k=0; k<lnumRateCats; k++)
{
for (b=0; b<numBetaCats; b++)
{
*(clP++) = (tiPL[0]*clL[0] + tiPL[1]*clL[1])
*(tiPR[0]*clR[0] + tiPR[1]*clR[1]);
*(clP++) = (tiPL[2]*clL[0] + tiPL[3]*clL[1])
*(tiPR[2]*clR[0] + tiPR[3]*clR[1]);
tiPL += 4;
tiPR += 4;
clL += 2;
clR += 2;
}
}
}
}
else if (!strcmp(ratesModel, "ssgamma"))
{
for (c=0; c<numChars; c++)
{
index = partitionId[c] * lnumRateCats * numBetaCats * N_STATES_SQUARED;
tiPL = &pL[index];
tiPR = &pR[index];
for (k=0; k<lnumRateCats; k++)
{
for (b=0; b<numBetaCats; b++)
{
*(clP++) = (tiPL[0]*clL[0] + tiPL[1]*clL[1])
*(tiPR[0]*clR[0] + tiPR[1]*clR[1]);
*(clP++) = (tiPL[2]*clL[0] + tiPL[3]*clL[1])
*(tiPR[2]*clR[0] + tiPR[3]*clR[1]);
tiPL += 4;
tiPR += 4;
clL += 2;
clR += 2;
}
}
}
}
else if (!strcmp(ratesModel, "sitespec"))
{
for (c=0; c<numChars; c++)
{
index = partitionId[c] * numBetaCats * N_STATES_SQUARED ;
tiPL = &pL[index];
tiPR = &pR[index];
for (b=0; b<numBetaCats; b++)
{
*(clP++) = (tiPL[0]*clL[0] + tiPL[1]*clL[1])
*(tiPR[0]*clR[0] + tiPR[1]*clR[1]);
*(clP++) = (tiPL[2]*clL[0] + tiPL[3]*clL[1])
*(tiPR[2]*clR[0] + tiPR[3]*clR[1]);
tiPL += 4;
tiPR += 4;
clL += 2;
clR += 2;
}
}
}
p->upDateCl = NO;
clUpdateFlag[p->index] = YES;
} // done with interior node if p->upDateCl == YES
} // done with interior node
// deal with scaling
// first check if we need to refresh scalers
// and potentially shift scaler nodes
// we have to remember scalerIndex
// because the node may move in the tree
if (refreshScalers == YES)
{
if (n % RESCALE_FREQ == 0)
{
p->scalerNode = YES;
p->scalerIndex = n;
}
else
p->scalerNode = NO;
}
if (p->scalerNode == YES && clUpdateFlag[p->index] == YES)
{
scalerUpdateFlag[p->scalerIndex] = YES;
scP = &clScaler[scalerOffset + (p->scalerIndex)*numChars];
clP = &condLike[condLikeOffset + (p->index)*oneNodeSize];
i = j = 0;
m = lnumRateCats * numBetaCats;
for (c=0; c<numChars; c++)
{
scaler = 0.0;
for (k=0; k<m; k++)
{
if (clP[i] > scaler)
scaler = clP[i];
i++;
if (clP[i] > scaler)
scaler = clP[i];
i++;
}
for (k=0; k<m; k++)
{
clP[j++] /= scaler;
clP[j++] /= scaler;
}
lnScaler[c] -= scP[c]; //subtract old value
scP[c] = log(scaler);
lnScaler[c] += scP[c]; //add new value
}
}
} // next node
/* get likelihood at base of tree */
/* deal with conditioning by dividing like with pObserved */
p = root[whichChain*2+whichState]->left;
(*lnL) = 0.0;
pObserved = 0.0;
clP = &condLike[condLikeOffset + (p->index)*oneNodeSize];
if (!strcmp(ratesModel, "equal") || !strcmp(ratesModel, "sitespec"))
{
for (c=j=0; c<numDummyChars; c++)
{
like = 0.0;
for (b=m=0; b<numBetaCats; b++)
{
like += clP[j++] * bs[m++] * betaFreq[b];
like += clP[j++] * bs[m++] * betaFreq[b];
}
pObserved += like * exp(lnScaler[c]);
}
pObserved = 1.0 - pObserved;
if (pObserved < LIKE_EPSILON)
pObserved = LIKE_EPSILON;
for (c=numDummyChars; c<numChars; c++)
{
like = 0.0;
for (b=m=0; b<numBetaCats; b++)
{
like += clP[j++] * bs[m++] * betaFreq[b];
like += clP[j++] * bs[m++] * betaFreq[b];
}
if (like * exp(lnScaler[c]) > pObserved)
{
printf (" WARNING: Character likelihood > p(observed)\n");
goto error_exit;
}
if (like < LIKE_EPSILON) /* likelihood for a site can go to zero when */
{ /* two adjacent terminal branches have zero length. */
printf (" WARNING: In LIKE_EPSILON\n");
goto error_exit;
}
else
(*lnL) += (lnScaler[c] + log(like)) * numSitesOfPat[c];
}
}
else if (!strcmp(ratesModel, "gamma") || !strcmp(ratesModel, "ssgamma"))
{
for (c=j=0; c<numDummyChars; c++)
{
like = 0.0;
for (k=0; k<lnumRateCats; k++)
{
for (b=m=0; b<numBetaCats; b++)
{
like += clP[j++] * bs[m++] * catFreq[k] * betaFreq[b];
like += clP[j++] * bs[m++] * catFreq[k] * betaFreq[b];
}
}
pObserved += like * exp(lnScaler[c]);
}
pObserved = 1.0 - pObserved;
if (pObserved < LIKE_EPSILON)
pObserved = LIKE_EPSILON;
for (c=numDummyChars; c<numChars; c++)
{
like = 0.0;
for (k=0; k<lnumRateCats; k++)
{
for (b=m=0; b<numBetaCats; b++)
{
like += clP[j++] * bs[m++] * catFreq[k] * betaFreq[b];
like += clP[j++] * bs[m++] * catFreq[k] * betaFreq[b];
}
}
if (like * exp (lnScaler[c]) > pObserved)
{
printf (" WARNING: Character likelihood > p(observed)\n");
goto error_exit;
}
if (like < LIKE_EPSILON) /* likelihood for a site can go to zero when */
{ /* two adjacent terminal branches have zero length. */
printf (" WARNING: In LIKE_EPSILON\n");
goto error_exit;
}
else
(*lnL) += (lnScaler[c] + log(like)) * numSitesOfPat[c];
}
}
/* correct for absent characters */
(*lnL) -= log(pObserved) * (nChar);
/* free memory */
free (pL);
free (catFreq);
free (betaFreq);
return (NO_ERROR);
error_exit:
free (pL);
free (catFreq);
free (betaFreq);
return (ERROR);
# undef N_STATES_SQUARED
# undef N_STATES
}
/*----------------------------------------------------------------------
LnLikeStandardMk: Likelihood function for standard data
This function is prepared for dealing with varying number of states
It needs help by a vector array indicating the number of states for each
site pattern, instead of relying on the global nStates, as in the present code,
and a help function that sets up the Q and P matrices
It uses 1/nStates as the probability of the state at the root
It deals with ordered/unordered chars given suitable help functions
It deals with gamma, ssgamma, sitespec and equal models of rate variation
Core written 2001-03-11
------------------------------------------------------------------------*/
int LnLikeStandardMk (int whichState, int whichChain, int numChars, int numRateCats, double *lnL, int refreshScalers)
{
register int i, j, k, c, n, m;
int nPij, lnumRateCats, lnPartitions, oneMatSize, oneNodeSize,
intNodeOffset, nStatesSquared, index, nRates,
condLikeOffset, scalerOffset, indexL, indexR, indexA;
double **probs, *stateFreq, *pL, *pR, *pA, *catFreq, *catRate,
*clL, *clR, *clA, *clP, *tiPL, *tiPR, *tiPA, like, theRate,
*lnScaler, *scP, *partRate, scaler;
double likeA, likeL, likeR;
TreeNode *p;
/* initialize intNodeOffset and nStatesSquared*/
intNodeOffset = whichChain*2*numIntNodes + whichState*numIntNodes;
nStatesSquared = nStates * nStates;
/* load state frequencies */
stateFreq = (double *)malloc((size_t) (nStates * sizeof(double)));
if (!stateFreq)
{
printf ("\n ERROR: Problem allocating stateFreq\n");
goto error_exit;
}
index = whichChain*2*nStates + whichState*nStates;
for (i = 0; i < nStates; i++)
stateFreq[i] = 1.0 / nStates;
/* how many different rate categories */
/* deal with relevant models */
/* lnumRateCats contains a local copy of numRateCats if appropriate, else 1 */
/* lnPartitions contains a local copy of nPartitions if appropriate, else 1 */
/* this is to make sure that these variables are set to 1 even if not "in use" */
if (!strcmp(ratesModel, "sitespec") || !strcmp(ratesModel, "ssgamma"))
lnPartitions = nPartitions;
else
lnPartitions = 1;
if (!strcmp(ratesModel, "equal") || !strcmp(ratesModel, "sitespec"))
lnumRateCats = 1;
else if (!strcmp(ratesModel, "gamma") || !strcmp(ratesModel, "ssgamma"))
lnumRateCats = numRateCats;
nRates = lnPartitions * lnumRateCats; // number of rates needing P matrices
/* allocate memory for the calculations */
/* pL, pR and pA will contain the transition probs for Left, Right and Anc */
/* one trans prob matrix needed for each possible rate */
nPij = nRates * nStatesSquared;
pL = (double *)malloc((size_t)(3 * nPij * sizeof(double)));
if (!pL)
{
printf ("\n ERROR: Problem allocating Pij\n");
goto error_exit;
}
pR = pL + nPij;
pA = pR + nPij;
/* allocate memory for rate and rate category frequencies */
catFreq = (double *)malloc((size_t) ((2 * lnumRateCats + lnPartitions) * sizeof(double)));
if (!catFreq)
{
printf ("\n ERROR: Problem allocating space for rate multipliers and rate category freqs.\n");
goto error_exit;
}
catRate = catFreq + lnumRateCats;
partRate = catRate + lnumRateCats;
probs = (double **) malloc ((size_t) (nStates * sizeof(double *)));
if (!probs)
{
printf ("\n ERROR: Problem allocating space for transition matrices\n");
goto error_exit;
}
probs[0] = (double *) malloc ((size_t) (nStatesSquared * sizeof(double)));
if (!probs[0])
{
printf ("\n ERROR: Problem allocating space for transition matrices\n");
goto error_exit;
}
for (i=1; i<nStates; i++)
probs[i] = probs[i-1] + nStates;
// pointer to the lnSiteScaler for this tree
lnScaler = &lnSiteScaler[whichChain * 2 * numChars + whichState * numChars];
/* fill in rate categories with frequencies and rates by dividing the */
/* gamma distribution into discrete categories, if appropriate */
/* NB! this is inefficient; store values instead */
if (lnumRateCats > 1)
{
DiscreteGamma (catFreq, catRate, alpha[whichChain*2 + whichState], alpha[whichChain*2 + whichState], lnumRateCats, 0);
}
else
{
catRate[0] = 1.0;
catFreq[0] = 1.0;
}
/* initialize partition rates, if appropriate */
if (lnPartitions > 1)
{
for (i=0; i<lnPartitions; i++)
partRate[i] = scaledRates[whichChain*2*lnPartitions + whichState*lnPartitions + i];
}
else
partRate[0] = 1.0;
/* how large is the information for one tree and one node*/
oneMatSize = numNodes * numChars * lnumRateCats * nStates;
oneNodeSize = numChars * lnumRateCats * nStates;
/* calculate indices */
condLikeOffset = whichChain*2*oneMatSize + whichState*oneMatSize;
scalerOffset = whichChain*2*numIntNodes*numChars + whichState*numIntNodes*numChars;
/* pass down tree */
for (n=0; n<numIntNodes; n++)
{
p = intNodeDownPassSeq[intNodeOffset + n];
// for debugging purposes
// set all nodes to update
// p->upDateCl = YES;
clUpdateFlag[p->index] = NO;
if (p->anc->anc == NULL && treeModel == UNROOTED)
{
if (p->upDateCl == YES)
{
//printf ("visiting basal node %d\n", p->index);
/* get transition probabilities, currently only for M2 model */
/* replace this with call to suitable function(s) setting up */
/* ordered and unordered transition matrices for 2-5 states */
for (m=indexL=indexR=indexA=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
theRate = partRate[m] * catRate[k];
// calculate transition probabilities for left branch
probs[1][1] = probs[0][0] = 0.5 + 0.5 * exp(-(p->left->length*theRate));
probs[0][1] = probs[1][0] = 0.5 - 0.5 * exp(-(p->left->length*theRate));
for (i=0; i<nStates; i++)
for (j=0; j<nStates; j++)
pL[indexL++] = probs[i][j];
// calculate transition probabilities for right branch
probs[1][1] = probs[0][0] = 0.5 + 0.5 * exp(-(p->right->length*theRate));
probs[0][1] = probs[1][0] = 0.5 - 0.5 * exp(-(p->right->length*theRate));
for (i=0; i<nStates; i++)
for (j=0; j<nStates; j++)
pR[indexR++] = probs[i][j];
// calculate transition probabilities for ancestral branch
probs[1][1] = probs[0][0] = 0.5 + 0.5 * exp(-(p->length*theRate));
probs[0][1] = probs[1][0] = 0.5 - 0.5 * exp(-(p->length*theRate));
for (i=0; i<nStates; i++)
for (j=0; j<nStates; j++)
pA[indexA++] = probs[i][j];
}
}
/* calculate conditional likelihoods */
/* first set pointers to cond likes of left, right, p and anc */
clL = &condLike[condLikeOffset + (p->left->index)*oneNodeSize];
clR = &condLike[condLikeOffset + (p->right->index)*oneNodeSize];
clA = &condLike[condLikeOffset + (p->anc->index)*oneNodeSize];
clP = &condLike[condLikeOffset + (p->index)*oneNodeSize];
if (!strcmp(ratesModel, "equal"))
{
tiPL = pL;
tiPR = pR;
tiPA = pA;
for (c=0; c<numChars; c++)
{
for (i=j=0; i<nStates-1; i++)
{
likeL = likeR = likeA = 0.0;
for (m=0; m<nStates; m++)
{
likeL += tiPL[j]*clL[m];
likeR += tiPR[j]*clR[m];
likeA += tiPA[j++]*clA[m];
}
*(clP++) = likeL * likeR * likeA;
}
likeL = likeR = likeA = 0.0;
for (m=0; m<nStates; m++)
{
likeL += tiPL[j]*(*(clL++));
likeR += tiPR[j]*(*(clR++));
likeA += tiPA[j++]*(*(clA++));
}
*(clP++) = likeL * likeR * likeA;
}
}
else if (!strcmp(ratesModel, "gamma"))
{
tiPL = pL;
tiPR = pR;
tiPA = pA;
for (c=0; c<numChars; c++)
{
for (k=j=0; k<lnumRateCats; k++)
{
for (i=0; i<nStates-1; i++)
{
likeL = likeR = likeA = 0.0;
for (m=0; m<nStates; m++)
{
likeL += tiPL[j]*clL[m];
likeR += tiPR[j]*clR[m];
likeA += tiPA[j++]*clA[m];
}
*(clP++) = likeL * likeR * likeA;
}
likeL = likeR = likeA = 0.0;
for (m=0; m<nStates; m++)
{
likeL += tiPL[j]*(*(clL++));
likeR += tiPR[j]*(*(clR++));
likeA += tiPA[j++]*(*(clA++));
}
*(clP++) = likeL * likeR * likeA;
}
}
}
else if (!strcmp(ratesModel, "ssgamma"))
{
for (c=0; c<numChars; c++)
{
index = partitionId[c]*lnumRateCats*nStatesSquared;
tiPL = &pL[index];
tiPR = &pR[index];
tiPA = &pA[index];
for (k=j=0; k<lnumRateCats; k++)
{
for (i=0; i<nStates-1; i++)
{
likeL = likeR = likeA = 0.0;
for (m=0; m<nStates; m++)
{
likeL += tiPL[j]*clL[m];
likeR += tiPR[j]*clR[m];
likeA += tiPA[j++]*clA[m];
}
*(clP++) = likeL * likeR * likeA;
}
likeL = likeR = likeA = 0.0;
for (m=0; m<nStates; m++)
{
likeL += tiPL[j]*(*(clL++));
likeR += tiPR[j]*(*(clR++));
likeA += tiPA[j++]*(*(clA++));
}
*(clP++) = likeL * likeR * likeA;
}
}
}
else if (!strcmp(ratesModel, "sitespec"))
{
for (c=0; c<numChars; c++)
{
index = partitionId[c]*nStatesSquared;
tiPL = &pL[index];
tiPR = &pR[index];
tiPA = &pA[index];
for (i=j=0; i<nStates-1; i++)
{
likeL = likeR = likeA = 0.0;
for (m=0; m<nStates; m++)
{
likeL += tiPL[j]*clL[m];
likeR += tiPR[j]*clR[m];
likeA += tiPA[j++]*clA[m];
}
*(clP++) = likeL * likeR * likeA;
}
likeL = likeR = likeA = 0.0;
for (m=0; m<nStates; m++)
{
likeL += tiPL[j]*(*(clL++));
likeR += tiPR[j]*(*(clR++));
likeA += tiPA[j++]*(*(clA++));
}
*(clP++) = likeL * likeR * likeA;
}
}
p->upDateCl = NO;
clUpdateFlag[p->index] = YES;
} // done if p->upDateCl == YES for interior root
} // done with interior root
else
{
if (p->upDateCl == YES)
{
//printf ("visiting internal node %d\n", p->index);
/* get transition probabilities */
/* currently only for M2 model */
/* replace this with call to function(s) setting up */
/* the necessary transition probability matrices */
for (m=indexL=indexR=indexA=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
theRate = partRate[m] * catRate[k];
// calculate transition probabilities for left branch
probs[1][1] = probs[0][0] = 0.5 + 0.5 * exp(-(p->left->length*theRate));
probs[0][1] = probs[1][0] = 0.5 - 0.5 * exp(-(p->left->length*theRate));
for (i=0; i<nStates; i++)
for (j=0; j<nStates; j++)
pL[indexL++] = probs[i][j];
// calculate transition probabilities for right branch
probs[1][1] = probs[0][0] = 0.5 + 0.5 * exp(-(p->right->length*theRate));
probs[0][1] = probs[1][0] = 0.5 - 0.5 * exp(-(p->right->length*theRate));
for (i=0; i<nStates; i++)
for (j=0; j<nStates; j++)
pR[indexR++] = probs[i][j];
// calculate transition probabilities for ancestral branch
probs[1][1] = probs[0][0] = 0.5 + 0.5 * exp(-(p->length*theRate));
probs[0][1] = probs[1][0] = 0.5 - 0.5 * exp(-(p->length*theRate));
for (i=0; i<nStates; i++)
for (j=0; j<nStates; j++)
pA[indexA++] = probs[i][j];
}
}
/* calculate conditional likelihoods */
/* first assign pointers to right, left and p */
clL = &condLike[condLikeOffset + (p->left->index)*oneNodeSize];
clR = &condLike[condLikeOffset + (p->right->index)*oneNodeSize];
clP = &condLike[condLikeOffset + (p->index)*oneNodeSize];
if (!strcmp(ratesModel, "equal"))
{
tiPL = pL;
tiPR = pR;
for (c=0; c<numChars; c++)
{
for (i=j=0; i<nStates-1; i++)
{
likeL = likeR = 0.0;
for (m=0; m<nStates; m++)
{
likeL += tiPL[j]*clL[m];
likeR += tiPR[j++]*clR[m];
}
*(clP++) = likeL * likeR;
}
likeL = likeR = 0.0;
for (m=0; m<nStates; m++)
{
likeL += tiPL[j]*(*(clL++));
likeR += tiPR[j++]*(*(clR++));
}
*(clP++) = likeL * likeR;
}
}
else if (!strcmp(ratesModel, "gamma"))
{
tiPL = pL;
tiPR = pR;
for (c=0; c<numChars; c++)
{
for (k=j=0; k<lnumRateCats; k++)
{
for (i=0; i<nStates-1; i++)
{
likeL = likeR = 0.0;
for (m=0; m<nStates; m++)
{
likeL += tiPL[j]*clL[m];
likeR += tiPR[j++]*clR[m];
}
*(clP++) = likeL * likeR;
}
likeL = likeR = 0.0;
for (m=0; m<nStates; m++)
{
likeL += tiPL[j]*(*(clL++));
likeR += tiPR[j++]*(*(clR++));
}
*(clP++) = likeL * likeR;
}
}
}
else if (!strcmp(ratesModel, "ssgamma"))
{
for (c=0; c<numChars; c++)
{
index = partitionId[c]*lnumRateCats*nStatesSquared;
tiPL = &pL[index];
tiPR = &pR[index];
for (k=j=0; k<lnumRateCats; k++)
{
for (i=0; i<nStates-1; i++)
{
likeL = likeR = 0.0;
for (m=0; m<nStates; m++)
{
likeL += tiPL[j]*clL[m];
likeR += tiPR[j++]*clR[m];
}
*(clP++) = likeL * likeR;
}
likeL = likeR = 0.0;
for (m=0; m<nStates; m++)
{
likeL += tiPL[j]*(*(clL++));
likeR += tiPR[j++]*(*(clR++));
}
*(clP++) = likeL * likeR;
}
}
}
else if (!strcmp(ratesModel, "sitespec"))
{
for (c=0; c<numChars; c++)
{
index = partitionId[c]*nStatesSquared;
tiPL = &pL[index];
tiPR = &pR[index];
for (i=j=0; i<nStates-1; i++)
{
likeL = likeR = 0.0;
for (m=0; m<nStates; m++)
{
likeL += tiPL[j]*clL[m];
likeR += tiPR[j++]*clR[m];
}
*(clP++) = likeL * likeR;
}
likeL = likeR = 0.0;
for (m=0; m<nStates; m++)
{
likeL += tiPL[j]*(*(clL++));
likeR += tiPR[j++]*(*(clR++));
}
*(clP++) = likeL * likeR;
}
}
// done with models
p->upDateCl = NO;
clUpdateFlag[p->index] = YES;
} // done with interior node if p->upDateCl == YES
} // done with interior node
// deal with scaling
// first check if we need to refresh scalers
// and potentially shift scaler nodes
// we have to remember scalerIndex
// because the node may move in the tree
if (refreshScalers == YES)
{
if (n % RESCALE_FREQ == 0)
{
p->scalerNode = YES;
p->scalerIndex = n;
}
else
p->scalerNode = NO;
}
if (p->scalerNode == YES && clUpdateFlag[p->index] == YES)
{
scalerUpdateFlag[p->scalerIndex] = YES;
scP = &clScaler[scalerOffset + (p->scalerIndex)*numChars];
clP = &condLike[condLikeOffset + (p->index)*oneNodeSize];
i = j = 0;
for (c=0; c<numChars; c++)
{
scaler = 0.0;
for (k=0; k<lnumRateCats; k++)
{
for (m=0; m<nStates; m++)
{
if (clP[i] > scaler)
scaler = clP[i];
i++;
}
}
for (k=0; k<lnumRateCats; k++)
{
for (m=0; m<nStates; m++)
clP[j++] /= scaler;
}
lnScaler[c] -= scP[c]; //subtract old value
scP[c] = log(scaler);
lnScaler[c] += scP[c]; //add new value
}
}
}// next node
/* get likelihood at base of tree */
p = root[whichChain*2+whichState]->left;
(*lnL) = 0.0;
clP = &condLike[condLikeOffset + (p->index)*oneNodeSize];
if (!strcmp(ratesModel, "equal") || !strcmp(ratesModel, "sitespec"))
{
for (c=0; c<numChars; c++)
{
like = 0.0;
for (i=0; i<nStates; i++)
like += *(clP++) * stateFreq[i];
//printf ("%d: %1.25lf %lf %d\n", c, like, log(like), numSitesOfPat[c]);
if (like < LIKE_EPSILON) /* likelihood for a site can go to zero when */
{ /* two adjacent terminal branches have zero length. */
printf (" WARNING: In LIKE_EPSILON\n");
goto error_exit;
}
else
{
(*lnL) += (lnScaler[c] + log(like)) * numSitesOfPat[c];
}
}
}
else if (!strcmp(ratesModel, "gamma") || !strcmp(ratesModel, "ssgamma"))
{
for (c=0; c<numChars; c++)
{
like = 0.0;
for (k=0; k<lnumRateCats; k++)
{
for (m=0; m<nStates; m++)
like += ((*(clP++)) * stateFreq[m]);
like *= catFreq[k];
}
if (like < LIKE_EPSILON) /* likelihood for a site can go to zero when */
{ /* two adjacent terminal branches have zero length. */
printf (" WARNING: In LIKE_EPSILON (%d) %1.30lf\n", c, like);
goto error_exit;
}
else
{
(*lnL) += (lnScaler[c] + log(like)) * numSitesOfPat[c];
}
}
}
/* free memory */
free (pL);
free (catFreq);
free (stateFreq);
free (probs[0]);
free (probs);
return (NO_ERROR);
error_exit:
free (pL);
free (catFreq);
free (stateFreq);
free (probs[0]);
free (probs);
return (ERROR);
}
double lnP1 (double t, double l, double m, double r)
{
double p0t;
/*printf ("l = %lf, m = %lf, t = %lf, r = %lf\n", l, m, t, r);*/
p0t = r*(l-m) / (r*l + (l*(1.0-r)-m)*exp((m-l)*t) );
return (log(1.0/r) + 2.0*log(p0t) + (m-l)*t);
}
double lnVt (double t, double l, double m, double r)
{
double p0t;
p0t = r*(l-m) / (r*l + (l*(1.0-r)-m)*exp((m-l)*t) );
return (log(1.0 - (1.0/r) * p0t * exp((m-l)*t)));
}
int MarkovChain (int numTaxa, int numChars, int numRateCats, long int *seed)
{
int i, n, chain, *curS, *newS, move, acceptMove, chain1, chain2,
tempInt, *chainTempId, tempId, coldId, nProposed[NUM_PROPOSAL_TYPES],
nAccepted[NUM_PROPOSAL_TYPES], nSwapsProposed, nSwapsAccepted,
nHours, nMins, nSecs;
double *lnL, lnR, x, lnLikelihoodRatio, lnPriorRatio, lnProposalRatio, r,
*constrainedNodes, *calibratedNodes, sum, timePerGen;
time_t startingT, endingT, stoppingT1, stoppingT2;
clock_t startCPUTime, endCPUTime;
/* allocate memory for chain */
lnL = (double *)malloc((size_t) (numChains * 2 * sizeof(double)));
if (!lnL)
{
printf ("\n ERROR: Problem allocating lnL.\n");
return (ERROR);
}
curS = (int *)malloc((size_t) (numChains * sizeof(int)));
if (!curS)
{
printf ("\n ERROR: Problem allocating curS.\n");
free (lnL);
return (ERROR);
}
newS = (int *)malloc((size_t) (numChains * sizeof(int)));
if (!newS)
{
printf ("\n ERROR: Problem allocating newS.\n");
free (lnL);
free (curS);
return (ERROR);
}
chainTempId = (int *)malloc((size_t) (numChains * sizeof(int)));
if (!chainTempId)
{
printf ("\n ERROR: Problem allocating chainTempId.\n");
free (lnL);
free (curS);
free (newS);
return (ERROR);
}
for (i=0; i<numChains; i++)
chainTempId[i] = i;
if (enforceCalibrations == YES)
{
if (nConstraints > 0)
{
constrainedNodes = (double *)malloc((size_t) (nConstraints * sizeof(double)));
if (!constrainedNodes)
{
printf ("\n ERROR: Problem allocating constrainedNodes.\n");
free (lnL);
free (curS);
free (newS);
free (chainTempId);
return (ERROR);
}
}
calibratedNodes = (double *)malloc((size_t) (nCalibrations * sizeof(double)));
if (!calibratedNodes)
{
printf ("\n ERROR: Problem allocating calibratedNodes.\n");
free (lnL);
free (curS);
free (newS);
free (chainTempId);
free (constrainedNodes);
return (ERROR);
}
}
if (inferAncStates == YES)
{
ancStatesProbs = (double *)malloc((size_t) (nConstraints * nChar * nStates * sizeof(double)));
if (!ancStatesProbs)
{
printf ("ERROR: Problem allocating ancStatesProbs\n");
free (lnL);
free (curS);
free (newS);
free (chainTempId);
if (enforceCalibrations == YES)
{
free (constrainedNodes);
free (calibratedNodes);
}
return (ERROR);
}
else
allocatedMemory[ALLOC_ANC_STATES] = YES;
for (i=0; i<nConstraints*nChar*nStates; i++)
ancStatesProbs[i] = 0.0;
tempStateProbs = (double *)malloc((size_t) (nConstraints * nChar * nStates * sizeof(double)));
if (!tempStateProbs)
{
printf ("ERROR: Problem allocating ancStatesProbs\n");
free (lnL);
free (curS);
free (newS);
free (chainTempId);
if (enforceCalibrations == YES)
{
free (constrainedNodes);
free (calibratedNodes);
}
return (ERROR);
}
else
allocatedMemory[ALLOC_TEMP_ANC_STATES] = YES;
}
/* set information for acceptance rates */
for (i=0; i<NUM_PROPOSAL_TYPES; i++)
nProposed[i] = nAccepted[i] = 0;
nSwapsProposed = nSwapsAccepted = 0;
# if defined (TOPOLOGY_MOVE_STATS)
for (i=0; i<NUM_PROPOSAL_TYPES; i++)
{
nProposedTopology[i] = nAcceptedTopology[i] = 0;
nProposedNodes[i] = nAcceptedNodes[i] = 0;
}
# endif
/* initialize likelihoods for chain */
printf (" Starting likelihoods\n");
for (chain=0; chain<numChains; chain++)
{
# if defined (SMART_TI_PROBS)
UpDateAllTIs (0, chain);
UpDateAllTIs (1, chain);
# endif
UpDateAllCls (0, chain);
if (LnLike (0, chain, numChars, numRateCats, &x, YES) == ERROR)
goto error_exit;
lnL[chain*2+0] = x;
UpDateAllCls (1, chain);
if (LnLike (1, chain, numChars, numRateCats, &x, YES) == ERROR)
goto error_exit;
lnL[chain*2+1] = x;
printf (" %2d -- %1.3lf %1.3lf\n", chain+1, lnL[chain*2+0], lnL[chain*2+1]);
}
/* open output files and write headers */
if (PrepareOutputFiles() == ERROR)
goto error_exit;
/* run chain */
for (chain=0; chain<numChains; chain++)
curS[chain] = 0;
for (chain=0; chain<numChains; chain++)
newS[chain] = 1;
startingT = time(NULL);
startCPUTime = clock();
nSampled = 0;
for (n=1; n<=nGen; n++)
{
/* loop through the chains */
for (chain=0; chain<numChains; chain++)
{
/* pick a move type */
move = ProposeNewState (seed);
nProposed[move]++;
/* make the move */
lnPriorRatio = 0.0;
lnProposalRatio = 0.0;
if (move == CHANGE_QMAT)
{
/* change Q matrix */
if (Move_ChangeQMatrix (newS[chain], chain, seed, &lnPriorRatio) == ERROR)
goto error_exit;
if (LnLike (newS[chain], chain, numChars, numRateCats, &x, YES) == ERROR)
goto error_exit;
lnL[chain*2+newS[chain]] = x;
lnLikelihoodRatio = lnL[chain*2 + newS[chain]] - lnL[chain*2 + curS[chain]];
}
else if (move == CHANGE_GAMMA_SHAPE)
{
/* change shape parameter of gamma distribution */
if (Move_ChangeGammaShape (newS[chain], chain, seed, &lnPriorRatio) == ERROR)
goto error_exit;
if (LnLike (newS[chain], chain, numChars, numRateCats, &x, YES) == ERROR)
goto error_exit;
lnL[chain*2+newS[chain]] = x;
lnLikelihoodRatio = lnL[chain*2 + newS[chain]] - lnL[chain*2 + curS[chain]];
}
else if (move == CHANGE_SITE_RATES)
{
/* change site rates */
if (Move_ChangeSiteRates (newS[chain], chain, seed, &lnPriorRatio) == ERROR)
goto error_exit;
if (LnLike (newS[chain], chain, numChars, numRateCats, &x, YES) == ERROR)
goto error_exit;
lnL[chain*2+newS[chain]] = x;
lnLikelihoodRatio = lnL[chain*2 + newS[chain]] - lnL[chain*2 + curS[chain]];
}
else if (move == CHANGE_BASEFREQS)
{
/* change base frequencies */
if (Move_ChangeBaseFreqs (newS[chain], chain, seed, &lnPriorRatio, &lnProposalRatio) == ERROR)
goto error_exit;
if (LnLike (newS[chain], chain, numChars, numRateCats, &x, YES) == ERROR)
goto error_exit;
lnL[chain*2+newS[chain]] = x;
lnLikelihoodRatio = lnL[chain*2 + newS[chain]] - lnL[chain*2 + curS[chain]];
}
else if (move == CHANGE_GCSWITCH)
{
/* change gc switch parameters */
if (Move_ChangeGCSwitch (newS[chain], chain, seed, &lnPriorRatio, &lnProposalRatio) == ERROR)
goto error_exit;
if (LnLike (newS[chain], chain, numChars, numRateCats, &x, YES) == ERROR)
goto error_exit;
lnL[chain*2+newS[chain]] = x;
lnLikelihoodRatio = lnL[chain*2 + newS[chain]] - lnL[chain*2 + curS[chain]];
}
else if (move == CHANGE_UNROOT_LOCAL)
{
/* change topology of unrooted tree or rooted and unconstrained tree using LOCAL */
if (Move_ChangeUnrootedWithLocal (numTaxa, newS[chain], chain, seed, &lnProposalRatio, &lnPriorRatio) == ERROR)
goto error_exit;
if (LnLike (newS[chain], chain, numChars, numRateCats, &x, NO) == ERROR)
goto error_exit;
lnL[chain*2+newS[chain]] = x;
lnLikelihoodRatio = lnL[chain*2 + newS[chain]] - lnL[chain*2 + curS[chain]];
}
else if (move == CHANGE_ERASER)
{
/* change topology of rooted tree using eraser */
if (Move_ChangeEraser (numTaxa, newS[chain], chain, seed, &lnProposalRatio, &lnPriorRatio) == ERROR)
goto error_exit;
if (LnLike (newS[chain], chain, numChars, numRateCats, &x, NO) == ERROR)
goto error_exit;
lnL[chain*2+newS[chain]] = x;
lnLikelihoodRatio = lnL[chain*2 + newS[chain]] - lnL[chain*2 + curS[chain]];
}
else if (move == CHANGE_UNROOT_TBR)
{
/* change topology of unrooted and unconstrained tree using TBR */
if (Move_ChangeTBR (numTaxa, newS[chain], chain, seed, &lnProposalRatio, &lnPriorRatio) == ERROR)
goto error_exit;
if (LnLike (newS[chain], chain, numChars, numRateCats, &x, NO) == ERROR)
goto error_exit;
lnL[chain*2+newS[chain]] = x;
lnLikelihoodRatio = lnL[chain*2 + newS[chain]] - lnL[chain*2 + curS[chain]];
}
else if (move == CHANGE_TREE_FTBR)
{
/* change topology of unrooted and unconstrained tree using Fredrik Ronquist's TBR */
if (Move_ChangeFTBR (numTaxa, newS[chain], chain, seed, &lnProposalRatio, &lnPriorRatio) == ERROR)
goto error_exit;
if (LnLike (newS[chain], chain, numChars, numRateCats, &x, NO) == ERROR)
goto error_exit;
lnL[chain*2+newS[chain]] = x;
lnLikelihoodRatio = lnL[chain*2 + newS[chain]] - lnL[chain*2 + curS[chain]];
}
else if (move == CHANGE_BRLEN)
{
/* change topology of unrooted and unconstrained tree using Fredrik Ronquist's TBR */
if (Move_ChangeBrLen (newS[chain], chain, seed, &lnProposalRatio, &lnPriorRatio) == ERROR)
goto error_exit;
if (LnLike (newS[chain], chain, numChars, numRateCats, &x, NO) == ERROR)
goto error_exit;
lnL[chain*2+newS[chain]] = x;
lnLikelihoodRatio = lnL[chain*2 + newS[chain]] - lnL[chain*2 + curS[chain]];
}
else if (move == CHANGE_CLOCK_LOCAL)
{
/* change topology of rooted tree with clock constraint using LOCAL */
if (Move_ChangeClockWithLocal (numTaxa, newS[chain], chain, seed, &lnProposalRatio, &lnPriorRatio) == ERROR)
goto error_exit;
if (LnLike (newS[chain], chain, numChars, numRateCats, &x, NO) == ERROR)
goto error_exit;
lnL[chain*2+newS[chain]] = x;
lnLikelihoodRatio = lnL[chain*2 + newS[chain]] - lnL[chain*2 + curS[chain]];
}
else if (move == CHANGE_CLOCK_TIME_LOCAL)
{
/* change topology and times of rooted tree with clock constraint using LOCAL (divergence time estimation) */
if (Move_ChangeTimeClockWithLocal (numTaxa, newS[chain], chain, seed, &lnProposalRatio, &lnPriorRatio) == ERROR)
goto error_exit;
if (LnLike (newS[chain], chain, numChars, numRateCats, &x, NO) == ERROR)
goto error_exit;
lnL[chain*2+newS[chain]] = x;
lnLikelihoodRatio = lnL[chain*2 + newS[chain]] - lnL[chain*2 + curS[chain]];
}
else if (move == CHANGE_TREE_HEIGHT)
{
/* change m, the tree height (only implemented with divergence time estimation) */
if (Move_ChangeTreeHeight (newS[chain], chain, seed, &lnProposalRatio) == ERROR)
goto error_exit;
if (LnLike (newS[chain], chain, numChars, numRateCats, &x, YES) == ERROR)
goto error_exit;
lnL[chain*2+newS[chain]] = x;
lnLikelihoodRatio = lnL[chain*2 + newS[chain]] - lnL[chain*2 + curS[chain]];
}
else if (move == CHANGE_WORM)
{
/* change topology using the growing worm mechanism */
if (Move_SingleWorm (numTaxa, newS[chain], chain, seed, &lnProposalRatio, &lnPriorRatio) == ERROR)
goto error_exit;
if (LnLike (newS[chain], chain, numChars, numRateCats, &x, NO) == ERROR)
goto error_exit;
lnL[chain*2+newS[chain]] = x;
lnLikelihoodRatio = lnL[chain*2 + newS[chain]] - lnL[chain*2 + curS[chain]];
}
else if (move == CHANGE_TREE_SPR)
{
/* change topology using the growing worm mechanism */
if (Move_ChangeUnrootedWithSPR (numTaxa, newS[chain], chain, seed, &lnProposalRatio, &lnPriorRatio) == ERROR)
goto error_exit;
if (LnLike (newS[chain], chain, numChars, numRateCats, &x, NO) == ERROR)
goto error_exit;
lnL[chain*2+newS[chain]] = x;
lnLikelihoodRatio = lnL[chain*2 + newS[chain]] - lnL[chain*2 + curS[chain]];
}
else if (move == CHANGE_NODE_TIME)
{
/* change topology using the growing worm mechanism */
if (Move_ChangeNodeTime (numTaxa, newS[chain], chain, seed, &lnProposalRatio, &lnPriorRatio) == ERROR)
goto error_exit;
if (LnLike (newS[chain], chain, numChars, numRateCats, &x, NO) == ERROR)
goto error_exit;
lnL[chain*2+newS[chain]] = x;
lnLikelihoodRatio = lnL[chain*2 + newS[chain]] - lnL[chain*2 + curS[chain]];
}
else if (move == CHANGE_BD_PARAMS)
{
/* change parameters of the birth-death process */
if (Move_ChangeBD (newS[chain], chain, seed) == ERROR)
goto error_exit;
if (LnBDPrior (newS[chain], chain, numTaxa, &x) == ERROR)
goto error_exit;
lnPriorRatio = x;
if (LnBDPrior (curS[chain], chain, numTaxa, &x) == ERROR)
goto error_exit;
lnPriorRatio -= x;
lnLikelihoodRatio = 0.0;
}
else if (move == CHANGE_OMEGA)
{
/* change omega */
if (Move_ChangeOmega (newS[chain], chain, seed, &lnPriorRatio) == ERROR)
goto error_exit;
if (LnLike (newS[chain], chain, numChars, numRateCats, &x, YES) == ERROR)
goto error_exit;
lnL[chain*2+newS[chain]] = x;
lnLikelihoodRatio = lnL[chain*2 + newS[chain]] - lnL[chain*2 + curS[chain]];
}
else if (move == CHANGE_OMEGA_PROBS)
{
/* change base frequencies */
if (Move_ChangeOmegaProbs (newS[chain], chain, seed, &lnPriorRatio, &lnProposalRatio) == ERROR)
goto error_exit;
if (LnLike (newS[chain], chain, numChars, numRateCats, &x, YES) == ERROR)
goto error_exit;
lnL[chain*2+newS[chain]] = x;
lnLikelihoodRatio = lnL[chain*2 + newS[chain]] - lnL[chain*2 + curS[chain]];
}
else if (move == CHANGE_AUTO_CORR)
{
/* change auto correlation across sites */
if (Move_ChangeAutoCorr (newS[chain], chain, seed, &lnPriorRatio) == ERROR)
goto error_exit;
if (LnLike (newS[chain], chain, numChars, numRateCats, &x, YES) == ERROR)
goto error_exit;
lnL[chain*2+newS[chain]] = x;
lnLikelihoodRatio = lnL[chain*2 + newS[chain]] - lnL[chain*2 + curS[chain]];
}
else if (move == CHANGE_LAG)
{
/* change lag for auto correlation across sites */
if (Move_ChangeLag (newS[chain], chain, seed, &lnPriorRatio, &lnProposalRatio) == ERROR)
goto error_exit;
if (LnLike (newS[chain], chain, numChars, numRateCats, &x, YES) == ERROR)
goto error_exit;
lnL[chain*2+newS[chain]] = x;
lnLikelihoodRatio = lnL[chain*2 + newS[chain]] - lnL[chain*2 + curS[chain]];
}
else if (move == CHANGE_INV_P)
{
/* change proportion of invariant sites */
if (Move_ChangePropInv (newS[chain], chain, seed, &lnPriorRatio) == ERROR)
goto error_exit;
if (LnLike (newS[chain], chain, numChars, numRateCats, &x, YES) == ERROR)
goto error_exit;
lnL[chain*2+newS[chain]] = x;
lnLikelihoodRatio = lnL[chain*2 + newS[chain]] - lnL[chain*2 + curS[chain]];
}
else if (move == CHANGE_SWITCH_RATE)
{
/* change covarion parameter */
if (Move_ChangeSwitchRate (newS[chain], chain, seed, &lnPriorRatio) == ERROR)
goto error_exit;
if (LnLike (newS[chain], chain, numChars, numRateCats, &x, YES) == ERROR)
goto error_exit;
lnL[chain*2+newS[chain]] = x;
lnLikelihoodRatio = lnL[chain*2 + newS[chain]] - lnL[chain*2 + curS[chain]];
}
#if defined (MORPH)
else if (move == CHANGE_BETA_SHAPE)
{
/* change beta/dir shape */
if (Move_ChangeBetaShape (newS[chain], chain, seed, &lnPriorRatio) == ERROR)
goto error_exit;
if (LnLike (newS[chain], chain, numChars, numRateCats, &x, YES) == ERROR)
goto error_exit;
lnL[chain*2+newS[chain]] = x;
lnLikelihoodRatio = lnL[chain*2 + newS[chain]] - lnL[chain*2 + curS[chain]];
}
#endif
/* heat */
lnLikelihoodRatio *= (1.0 / (1.0 + chainTemp*(double)chainTempId[chain]));
lnPriorRatio *= (1.0 / (1.0 + chainTemp*(double)chainTempId[chain]));
/* calculate the acceptance probability */
if (lnLikelihoodRatio + lnPriorRatio + lnProposalRatio < -100.0)
r = 0.0;
else if (lnLikelihoodRatio + lnPriorRatio + lnProposalRatio > 0.0)
r = 1.0;
else
r = exp(lnLikelihoodRatio + lnPriorRatio + lnProposalRatio);
/* decide to accept or reject the move */
acceptMove = NO;
if (RandomNumber(seed) < r)
acceptMove = YES;
# if defined (TOPOLOGY_MOVE_STATS)
/* record diagnostics for topology moves */
switch (move)
{
case CHANGE_UNROOT_LOCAL:
case CHANGE_CLOCK_LOCAL:
case CHANGE_CLOCK_TIME_LOCAL:
case CHANGE_TREE_SPR:
case CHANGE_WORM:
case CHANGE_UNROOT_TBR:
case CHANGE_TREE_FTBR:
case CHANGE_ERASER:
if (gTopologyHasChanged == YES)
{
nProposedNodes[move] += gNodeMoves;
nProposedTopology[move]++;
if (acceptMove == YES)
{
nAcceptedNodes[move] += gNodeMoves;
nAcceptedTopology[move]++;
}
}
}
# endif
/* update the chain */
if (acceptMove == YES)
{
curS[chain] = newS[chain];
if (curS[chain] == 1)
newS[chain] = 0;
else
newS[chain] = 1;
nAccepted[move]++;
}
lnL[chain*2 + newS[chain]] = lnL[chain*2 + curS[chain]];
CopyTree (curS[chain], newS[chain], chain);
CopyConditionalLikelihoods (curS[chain], newS[chain], chain, numTaxa, numChars, numRateCats);
}
/* attemp to swap states for two chains */
if (numChains > 1)
{
nSwapsProposed++;
chain1 = RandomNumber(seed) * numChains;
do
{
chain2 = RandomNumber(seed) * numChains;
} while (chain1 == chain2);
lnR = (1.0 / (1.0 + chainTemp*(double)chainTempId[chain1])) * lnL[chain2*2 + curS[chain2]];
lnR += (1.0 / (1.0 + chainTemp*(double)chainTempId[chain2])) * lnL[chain1*2 + curS[chain1]];
lnR -= (1.0 / (1.0 + chainTemp*(double)chainTempId[chain1])) * lnL[chain1*2 + curS[chain1]];
lnR -= (1.0 / (1.0 + chainTemp*(double)chainTempId[chain2])) * lnL[chain2*2 + curS[chain2]];
if (lnR < -100.0)
r = 0.0;
else if (lnR > 0.0)
r = 1.0;
else
r = exp(lnR);
acceptMove = NO;
if (RandomNumber(seed) < r)
{
acceptMove = YES;
}
if (acceptMove == YES)
{
nSwapsAccepted++;
tempId = chainTempId[chain1];
chainTempId[chain1] = chainTempId[chain2];
chainTempId[chain2] = tempId;
}
/* print update to screen */
endingT = time(NULL);
if (n % printFreq == 0)
{
timePerGen = (double)(difftime (endingT, startingT) / n);
nSecs = (int)((nGen - n) * timePerGen);
nHours = (int)nSecs / 3600;
nSecs -= nHours * 3600;
nMins = nSecs / 60;
nSecs -= nMins * 60;
printf (" %4d -- ", n);
sum = 0.0;
for (chain=0; chain<numChains; chain++)
sum += lnL[chain*2 + curS[chain]] * (1.0 / (1.0 + chainTemp*(double)chainTempId[chain]));
printf ("%1.2lf -- ", sum);
for (chain=0; chain<numChains; chain++)
{
if (chainTempId[chain] == 0)
printf ("[%1.2lf] ", lnL[chain*2 + curS[chain]]);
else
printf ("(%1.2lf) ", lnL[chain*2 + curS[chain]]);
}
printf ("-- %d:", nHours);
if (nMins > 9)
printf ("%d:", nMins);
else
printf ("0%d:", nMins);
if (nSecs > 9)
printf ("%d", nSecs);
else
printf ("0%d", nSecs);
if (acceptMove == YES)
printf (" (%d~%d)\n", chain1+1, chain2+1);
else
printf ("\n");
}
}
else
{
endingT = time(NULL);
/* print update to screen */
if (n % printFreq == 0)
{
timePerGen = (double)(difftime (endingT, startingT) / n);
nSecs = (int)((nGen - n) * timePerGen);
nHours = (int)nSecs / 3600;
nSecs -= nHours * 3600;
nMins = nSecs / 60;
nSecs -= nMins * 60;
printf (" %4d -- %1.2lf ", n, lnL[curS[0]]);
printf ("-- %d:", nHours);
if (nMins > 9)
printf ("%d:", nMins);
else
printf ("0%d:", nMins);
if (nSecs > 9)
printf ("%d\n", nSecs);
else
printf ("0%d\n", nSecs);
}
}
/* check to see if we should continue chain */
if (n == nGen && autoclose == NO)
{
stoppingT1 = time(NULL);
printf ("\n Continue with chain? (yes/no): ");
if (YesNo() == YES)
{
tempInt = 0;
do
{
if (tempInt < 0)
printf (" Number must be greater than or equal to 0: ");
else
printf (" Additional number of generations: ");
tempInt = (int)EnterNum ();
} while (tempInt < 0);
nGen += tempInt;
}
printf ("\n");
stoppingT2 = time(NULL);
startingT -= (stoppingT2 - stoppingT1);
}
/* print states to file */
if (n % sampleFreq == 0 || n == 1 || n == nGen)
{
for (i=0; i<numChains; i++)
{
if (chainTempId[i] == 0)
{
coldId = i;
break;
}
}
chain = 0;
if (PrintStatesToFile (n, coldId, curS[coldId], lnL[coldId*2 + curS[coldId]], constrainedNodes, calibratedNodes) == ERROR)
{
printf (" ERROR: Problem printing states to file\n");
goto error_exit;
}
if (n >= mcmcBurn)
nSampled++;
if (inferAncStates == YES && n >= mcmcBurn)
{
if ((dataType == DNA || dataType == RNA) && enforceCodonModel == NO)
{
if (PrintAncStatesDNA (curS[coldId], coldId, numChars, numRateCats, n) == ERROR)
goto error_exit;
UpDateAllCls (0, coldId);
if (LnLikeDNA (0, coldId, numChars, numRateCats, &x, YES) == ERROR)
goto error_exit;
UpDateAllCls (1, coldId);
if (LnLikeDNA (1, coldId, numChars, numRateCats, &x, YES) == ERROR)
goto error_exit;
}
else if ((dataType == DNA || dataType == RNA) && enforceCodonModel == YES)
{
printf ("\n ERROR: Cannot calculate ancestral states for codon models (yet)\n");
goto error_exit;
}
else if (dataType == PROTEIN)
{
PrintAncStatesAA (curS[coldId], coldId, numChars, numRateCats, n);
UpDateAllCls (0, coldId);
if (LnLikeAA (0, coldId, numChars, numRateCats, &x, YES) == ERROR)
goto error_exit;
UpDateAllCls (1, coldId);
if (LnLikeAA (1, coldId, numChars, numRateCats, &x, YES) == ERROR)
goto error_exit;
}
}
if (inferPoseSel == YES && n >= mcmcBurn)
{
if ((dataType == DNA || dataType == RNA) && enforceCodonModel == YES && (!strcmp(codonModelType, "ny98") || !strcmp(codonModelType, "ac1ny98") || !strcmp(codonModelType, "ac2ny98")))
{
PrintPosSelProbs (curS[coldId], coldId, numChars, numRateCats, n);
}
}
if (inferRates == YES && nExcluded == 0 && n >= mcmcBurn)
{
if (((dataType == DNA || dataType == RNA) && enforceCodonModel == NO) || dataType == PROTEIN)
{
PrintRateFactors (curS[coldId], coldId, numChars, numRateCats, n);
}
}
else if (inferRates == YES && nExcluded > 0 && n == 1 && n >= mcmcBurn)
{
printf (" Warning: You requested that site rates be estimated. However, this option\n");
printf (" does not currently work when sites are excluded. Site rates will not\n");
printf (" be estimated in this run.\n");
}
}
}
endingT = time(NULL);
endCPUTime = clock();
printf (" Chain completed in %1.0f seconds\n", difftime (endingT, startingT));
printf (" Chain used %1.2f seconds of CPU time\n", (endCPUTime - startCPUTime)/(float)CLOCKS_PER_SEC);
printf (" Acceptance rates for proposal mechanisms\n");
for (i=0; i<NUM_PROPOSAL_TYPES; i++)
{
if (nProposed[i] > 0)
printf (" %1.2lf percent of the time accepted %s\n", ((double)nAccepted[i]/nProposed[i])*100.0, proposalName[i]);
}
if (nSwapsProposed > 0)
{
printf (" %1.2lf percent of the time accepted a swap of the states for two chains\n", ((double)nSwapsAccepted/nSwapsProposed)*100.0);
}
# if defined (TOPOLOGY_MOVE_STATS)
printf (" Detailed statistics for moves that change tree topology\n");
for (i = 0; i<NUM_PROPOSAL_TYPES; i++)
{
if (nProposed[i] == 0)
continue;
switch(i)
{
case CHANGE_UNROOT_LOCAL:
case CHANGE_CLOCK_LOCAL:
case CHANGE_CLOCK_TIME_LOCAL:
case CHANGE_ERASER:
printf (" %s\n", proposalName[i]);
printf (" %d moves were proposed\n", nProposed[i]);
printf (" %d moves were accepted\n",nAccepted[i]);
printf (" %d topology changes were proposed\n",nProposedTopology[i]);
printf (" %d topology changes were accepted\n",nAcceptedTopology[i]);
if (nProposedTopology[i] > 0)
printf (" %1.2f percent of proposed topology changes were accepted\n",
(float)nAcceptedTopology[i]/(float)nProposedTopology[i] * 100.0);
printf (" Proposed topology changes by definition break 1 partition\n");
break;
case CHANGE_TREE_SPR:
case CHANGE_WORM:
case CHANGE_UNROOT_TBR:
case CHANGE_TREE_FTBR:
printf (" %s\n", proposalName[i]);
printf (" %d moves were proposed\n", nProposed[i]);
printf (" %d moves were accepted\n",nAccepted[i]);
printf (" %d topology changes were proposed\n",nProposedTopology[i]);
printf (" %d topology changes were accepted\n",nAcceptedTopology[i]);
if (nProposedTopology[i] > 0) {
printf (" %1.2f percent of proposed topology changes were accepted\n",
(float)nAcceptedTopology[i]/(float)nProposedTopology[i] * 100.0);
printf (" Proposed topology changes on average broke %f partitions\n",
(float)nProposedNodes[i] / (float)nProposedTopology[i]);
if (nAcceptedTopology[i] > 0) {
printf (" Accepted topology changes on average broke %f partitions\n",
nAcceptedNodes[i] / (float)nAcceptedTopology[i]);
}
}
}
}
# endif
# if defined (MORPH)
if (numDummyChars > 0)
{
printf (" Probability of unobserved characters in ending state of chain");
LnLike (curS[coldId], coldId, numChars, numRateCats, &x, YES);
printf (": %1.8f\n",1.0 - pObserved);
}
# endif
/* free memory and leave */
free (lnL);
free (curS);
free (newS);
free (chainTempId);
if (enforceCalibrations == YES)
{
free (constrainedNodes);
free (calibratedNodes);
}
/* close output files */
fclose (pFile);
fclose (bpFile);
fclose (tFile);
return (NO_ERROR);
error_exit:
free (lnL);
free (curS);
free (newS);
free (chainTempId);
if (enforceCalibrations == YES)
{
free (constrainedNodes);
free (calibratedNodes);
}
/* close output files */
if (pFile != NULL)
fclose (pFile);
if (bpFile != NULL)
fclose (bpFile);
if (tFile != NULL)
fclose (tFile);
printf ("\n ERROR: Problem running Markov chain\n");
return (ERROR);
}
int MarkovChainPars (int numTaxa, int numChars, long int *seed)
{
int i, n, chain, *curS, *newS, acceptMove, chain1, chain2,
tempInt, *chainTempId, tempId, coldId,
nHours, nMins, nSecs;
double *lnL, lnR, lnLikelihoodRatio, lnPriorRatio, lnProposalRatio, r,
sum, timePerGen, nk, lnK;
time_t startingT, endingT, stoppingT1, stoppingT2;
clock_t startCPUTime, endCPUTime;
FILE *fp1, *fp2;
/* get number of characters */
nk = 0.0;
for (i=0; i<numChars; i++)
nk += numSitesOfPat[i];
/* calculate log of number of states */
lnK = log((double)nStates);
/* print information to the screen about run */
if (dataType == DNA)
printf (" Data type = DNA\n");
else if (dataType == RNA)
printf (" Data type = RNA\n");
else if (dataType == PROTEIN)
printf (" Data type = protein\n");
else if (dataType == RESTRICTION)
printf (" Data type = restriction site\n");
else if (dataType == STANDARD)
printf (" Data type = standard\n");
printf (" Substitution model\n");
printf (" You have selected the \"Parsimony model\" of\n");
printf (" Tuffley and Steel (1997). This model is also\n");
printf (" known as the \"no common mechanism\" model as\n");
printf (" it allows each branch and site to have a separ-\n");
printf (" ate transition matrix. You should note that this\n");
printf (" is an over-parameterized model; the number of\n");
printf (" parameters grows faster than the number of obs-\n");
printf (" ervations. You use this model at your own risk.\n");
printf (" (You should also note that this model is anything\n");
printf (" but parsimonious.)\n");
/* allocate memory for chain */
lnL = (double *)malloc((size_t) (numChains * 2 * sizeof(double)));
if (!lnL)
{
printf ("\n ERROR: Problem allocating lnL.\n");
return (ERROR);
}
curS = (int *)malloc((size_t) (numChains * sizeof(int)));
if (!curS)
{
printf ("\n ERROR: Problem allocating curS.\n");
free (lnL);
return (ERROR);
}
newS = (int *)malloc((size_t) (numChains * sizeof(int)));
if (!newS)
{
printf ("\n ERROR: Problem allocating newS.\n");
free (lnL);
free (curS);
return (ERROR);
}
chainTempId = (int *)malloc((size_t) (numChains * sizeof(int)));
if (!chainTempId)
{
printf ("\n ERROR: Problem allocating chainTempId.\n");
free (lnL);
free (curS);
free (newS);
return (ERROR);
}
for (i=0; i<numChains; i++)
chainTempId[i] = i;
/* initialize likelihoods for chain */
//printf (" Starting likelihoods\n");
for (chain=0; chain<numChains; chain++)
{
lnL[chain*2+0] = ParsimonyLength (0, chain, numChars);
lnL[chain*2+1] = ParsimonyLength (1, chain, numChars);
//printf ("%4d: %lf %lf\n", chain+1, lnL[chain*2+0], lnL[chain*2+1]);
}
/* run chain */
for (chain=0; chain<numChains; chain++)
curS[chain] = 0;
for (chain=0; chain<numChains; chain++)
newS[chain] = 1;
/* open output files and write headers */
if (PrepareParsOutputFiles() == ERROR)
goto error_exit;
startingT = time(NULL);
startCPUTime = clock();
for (n=1; n<=nGen; n++)
{
/* loop through the chains */
for (chain=0; chain<numChains; chain++)
{
/* make the move */
lnLikelihoodRatio = 0.0;
lnPriorRatio = 0.0;
lnProposalRatio = 0.0;
if (Move_ChangeNNI (numTaxa, newS[chain], chain, seed) == ERROR)
goto error_exit;
lnL[chain*2+newS[chain]] = ParsimonyLength (newS[chain], chain, numChars);
lnLikelihoodRatio = -(lnL[chain*2 + newS[chain]] + nk) * lnK + (lnL[chain*2 + curS[chain]] + nk) * lnK;
//printf (" %lf -> %lf\n", lnL[chain*2+curS[chain]], lnL[chain*2+newS[chain]]);
/* heat */
lnLikelihoodRatio *= (1.0 / (1.0 + chainTemp*(double)chainTempId[chain]));
lnPriorRatio *= (1.0 / (1.0 + chainTemp*(double)chainTempId[chain]));
/* calculate the acceptance probability */
if (lnLikelihoodRatio + lnPriorRatio + lnProposalRatio < -100.0)
r = 0.0;
else if (lnLikelihoodRatio + lnPriorRatio + lnProposalRatio > 0.0)
r = 1.0;
else
r = exp(lnLikelihoodRatio + lnPriorRatio + lnProposalRatio);
/* decide to accept or reject the move */
acceptMove = NO;
if (RandomNumber(seed) < r)
acceptMove = YES;
/* update the chain */
if (acceptMove == YES)
{
curS[chain] = newS[chain];
if (curS[chain] == 1)
newS[chain] = 0;
else
newS[chain] = 1;
}
lnL[chain*2 + newS[chain]] = lnL[chain*2 + curS[chain]];
CopyTree (curS[chain], newS[chain], chain);
}
/* attemp to swap states for two chains */
if (numChains > 1)
{
chain1 = RandomNumber(seed) * numChains;
do
{
chain2 = RandomNumber(seed) * numChains;
} while (chain1 == chain2);
lnR = (1.0 / (1.0 + chainTemp*(double)chainTempId[chain1])) * (-(lnL[chain2*2 + curS[chain2]] + nk) * lnK);
lnR += (1.0 / (1.0 + chainTemp*(double)chainTempId[chain2])) * (-(lnL[chain1*2 + curS[chain1]] + nk) * lnK);
lnR -= (1.0 / (1.0 + chainTemp*(double)chainTempId[chain1])) * (-(lnL[chain1*2 + curS[chain1]] + nk) * lnK);
lnR -= (1.0 / (1.0 + chainTemp*(double)chainTempId[chain2])) * (-(lnL[chain2*2 + curS[chain2]] + nk) * lnK);
if (lnR < -100.0)
r = 0.0;
else if (lnR > 0.0)
r = 1.0;
else
r = exp(lnR);
acceptMove = NO;
if (RandomNumber(seed) < r)
{
acceptMove = YES;
}
if (acceptMove == YES)
{
tempId = chainTempId[chain1];
chainTempId[chain1] = chainTempId[chain2];
chainTempId[chain2] = tempId;
}
/* print update to screen */
endingT = time(NULL);
if (n % printFreq == 0)
{
timePerGen = (double)(difftime (endingT, startingT) / n);
nSecs = (int)((nGen - n) * timePerGen);
nHours = (int)nSecs / 3600;
nSecs -= nHours * 3600;
nMins = nSecs / 60;
nSecs -= nMins * 60;
printf (" %4d -- ", n);
sum = 0.0;
for (chain=0; chain<numChains; chain++)
sum += (-(lnL[chain*2 + curS[chain]] + nk) * lnK) * (1.0 / (1.0 + chainTemp*(double)chainTempId[chain]));
printf ("%1.2lf -- ", sum);
for (chain=0; chain<numChains; chain++)
{
if (chainTempId[chain] == 0)
printf ("[%1.2lf] ", (-(lnL[chain*2 + curS[chain]] + nk) * lnK));
else
printf ("(%1.2lf) ", (-(lnL[chain*2 + curS[chain]] + nk) * lnK));
}
printf ("-- %d:", nHours);
if (nMins > 9)
printf ("%d:", nMins);
else
printf ("0%d:", nMins);
if (nSecs > 9)
printf ("%d", nSecs);
else
printf ("0%d", nSecs);
if (acceptMove == YES)
printf (" (%d~%d)\n", chain1+1, chain2+1);
else
printf ("\n");
}
}
else
{
endingT = time(NULL);
/* print update to screen */
if (n % printFreq == 0)
{
timePerGen = (double)(difftime (endingT, startingT) / n);
nSecs = (int)((nGen - n) * timePerGen);
nHours = (int)nSecs / 3600;
nSecs -= nHours * 3600;
nMins = nSecs / 60;
nSecs -= nMins * 60;
printf (" %4d -- %1.2lf ", n, lnL[curS[0]]);
printf ("-- %d:", nHours);
if (nMins > 9)
printf ("%d:", nMins);
else
printf ("0%d:", nMins);
if (nSecs > 9)
printf ("%d\n", nSecs);
else
printf ("0%d\n", nSecs);
}
}
/* check to see if we should continue chain */
if (n == nGen && autoclose == NO)
{
stoppingT1 = time(NULL);
printf ("\n Continue with chain? (yes/no): ");
if (YesNo() == YES)
{
tempInt = 0;
do
{
if (tempInt < 0)
printf (" Number must be greater than or equal to 0: ");
else
printf (" Additional number of generations: ");
tempInt = (int)EnterNum ();
} while (tempInt < 0);
nGen += tempInt;
}
printf ("\n");
stoppingT2 = time(NULL);
startingT -= (stoppingT2 - stoppingT1);
}
/* print states to file */
if (n % sampleFreq == 0 || n == 1 || n == nGen)
{
for (i=0; i<numChains; i++)
{
if (chainTempId[i] == 0)
{
coldId = i;
fp1 = pFile;
fp2 = bpFile;
fprintf (fp1, "%d\t%lf\t", n, -(lnL[coldId*2 + curS[coldId]] + nk) * lnK );
fprintf (fp2, " data %d, %1.2lf", n, -(lnL[coldId*2 + curS[coldId]] + nk) * lnK);
fprintf (fp1, "%lf\t", lnL[coldId*2 + curS[coldId]]);
fprintf (fp2, ", %lf", lnL[coldId*2 + curS[coldId]]);
fprintf (fp1, "\n");
fprintf (fp2, ";\n");
if (n == nGen)
fprintf (fp2, "end;\n");
fflush (fp1);
fflush (fp2);
fp2 = tFile;
fprintf (fp2, " tree rep.%d = ", n);
WriteTreeToFile (root[coldId*2 + curS[coldId]]->left, fp2, saveBrlens);
if (n == nGen)
fprintf (fp2, "end;\n");
fflush (fp2);
break;
}
}
}
}
endingT = time(NULL);
endCPUTime = clock();
printf (" Chain completed in %1.0f seconds\n", difftime (endingT, startingT));
printf (" Chain used %1.2f seconds of CPU time\n", (endCPUTime - startCPUTime)/(float)CLOCKS_PER_SEC);
/* free memory and leave */
free (lnL);
free (curS);
free (newS);
free (chainTempId);
/* close output files */
fclose (pFile);
fclose (bpFile);
fclose (tFile);
return (NO_ERROR);
error_exit:
free (lnL);
free (curS);
free (newS);
free (chainTempId);
/* close output files */
if (pFile != NULL)
fclose (pFile);
if (bpFile != NULL)
fclose (bpFile);
if (tFile != NULL)
fclose (tFile);
printf ("\n ERROR: Problem running Markov chain\n");
return (ERROR);
}
void MarkPathDown (TreeNode *p, TreeNode *q)
{
if (p != NULL)
{
MarkPathDown (p->left, q);
MarkPathDown (p->right, q);
p->flag = NO;
if (p == q)
{
p->flag = YES;
}
if (p->left != NULL && p->right != NULL)
{
if (p->left->flag == YES || p->right->flag == YES)
p->flag = YES;
}
else if (p->left != NULL && p->right == NULL)
{
if (p->left->flag == YES)
p->flag = YES;
}
/*printf ("node %d %d\n", p->index, p->flag);*/
}
}
/* change auto correlation parameter */
int Move_ChangeAutoCorr (int proposedState, int whichChain, long int *seed, double *lnPriorRatio)
{
int whichToChange;
double oldP, newP, ran, pSlide, minP, maxP;
minP = chainMins[CHANGE_AUTO_CORR];
maxP = chainMaxs[CHANGE_AUTO_CORR];
pSlide = rhoWinProp;
if (allocatedMemory[ALLOC_AUTO_GAMMA2] == NO)
{
oldP = rateCorrelation[whichChain*2 + proposedState];
ran = (RandomNumber(seed) * pSlide) - (pSlide/2.0);
newP = oldP + ran;
if (newP < minP)
newP = (minP - newP) + minP;
if (newP > maxP)
newP = maxP - (newP - maxP);
rateCorrelation[whichChain*2 + proposedState] = newP;
}
else
{
whichToChange = RandomNumber(seed) * 3;
if (whichToChange == 0)
{
oldP = rateCorrelation[whichChain*2 + proposedState];
ran = (RandomNumber(seed) * pSlide) - (pSlide/2.0);
newP = oldP + ran;
if (newP < minP)
newP = (minP - newP) + minP;
if (newP > maxP)
newP = maxP - (newP - maxP);
rateCorrelation[whichChain*2 + proposedState] = newP;
}
else
{
oldP = rateCorrelation2[whichChain*4 + proposedState*2 + (whichToChange-1)];
ran = (RandomNumber(seed) * pSlide) - (pSlide/2.0);
newP = oldP + ran;
if (newP < minP)
newP = (minP - newP) + minP;
if (newP > maxP)
newP = maxP - (newP - maxP);
rateCorrelation2[whichChain*4 + proposedState*2 + (whichToChange-1)] = newP;
}
}
/* set prior ratio */
(*lnPriorRatio) = 0.0;
UpDateAllCls (proposedState, whichChain);
# if defined (SMART_TI_PROBS)
UpDateAllTIs (proposedState, whichChain);
# endif
return (NO_ERROR);
}
/* change pi */
int Move_ChangeBaseFreqs (int proposedState, int whichChain, long int *seed, double *lnPriorRatio, double *lnProposalRatio)
{
int i;
double *dirichletParameters, *newPi, *oldPi, sum, alphaPi, priorPi, x, y, oneOverS;
oneOverS = 1.0 / nStates;
dirichletParameters = (double *)malloc((size_t) (nStates * sizeof(double)));
if (!dirichletParameters)
goto error_exit;
newPi = (double *)malloc((size_t) (nStates * sizeof(double)));
if (!newPi)
goto error_exit;
oldPi = (double *)malloc((size_t) (nStates * sizeof(double)));
if (!oldPi)
goto error_exit;
alphaPi = piAlphaProp;
priorPi = basefreqprDir;
for (i=0; i<nStates; i++)
{
oldPi[i] = baseFreq[whichChain*2*nStates + proposedState*nStates + i];
dirichletParameters[i] = oldPi[i] * alphaPi;
}
DirichletRandomVariable (dirichletParameters, newPi, nStates, seed);
sum = 0.0;
for (i=0; i<nStates; i++)
{
if (newPi[i] < 0.0001)
newPi[i] = 0.0001;
sum += newPi[i];
}
for (i=0; i<nStates; i++)
newPi[i] = newPi[i] / sum;
for (i=0; i<nStates; i++)
baseFreq[whichChain*2*nStates + proposedState*nStates + i] = newPi[i];
/* get proposal ratio */
sum = 0.0;
for (i=0; i<nStates; i++)
sum += newPi[i]*alphaPi;
x = LnGamma(sum);
for (i=0; i<nStates; i++)
x -= LnGamma(newPi[i]*alphaPi);
for (i=0; i<nStates; i++)
x += (newPi[i]*alphaPi-1.0)*log(oldPi[i]);
sum = 0.0;
for (i=0; i<nStates; i++)
sum += oldPi[i]*alphaPi;
y = LnGamma(sum);
for (i=0; i<nStates; i++)
y -= LnGamma(oldPi[i]*alphaPi);
for (i=0; i<nStates; i++)
y += (oldPi[i]*alphaPi-1.0)*log(newPi[i]);
(*lnProposalRatio) = x - y;
/* get prior ratio */
x = LnGamma(priorPi);
for (i=0; i<nStates; i++)
x -= LnGamma(oneOverS*priorPi);
for (i=0; i<nStates; i++)
x += (oneOverS*priorPi-1.0)*log(newPi[i]);
y = LnGamma(priorPi);
for (i=0; i<nStates; i++)
y -= LnGamma(oneOverS*priorPi);
for (i=0; i<nStates; i++)
y += (oneOverS*priorPi-1.0)*log(oldPi[i]);
(*lnPriorRatio) = x - y;
UpDateAllCls (proposedState, whichChain);
# if defined (SMART_TI_PROBS)
UpDateAllTIs (proposedState, whichChain);
# endif
free (dirichletParameters);
free (newPi);
free (oldPi);
return (NO_ERROR);
error_exit:
free (dirichletParameters);
free (newPi);
free (oldPi);
return (ERROR);
}
#if defined (MORPH)
/* change Beta/Dirichlet parameters for standard data */
int Move_ChangeBetaShape (int proposedState, int whichChain, long int *seed, double *lnPriorRatio)
{
double oldP, newP, ran, pSlide, minP, maxP;
// it should be possible for the user to set the following parameters
minP = chainMins[CHANGE_BETA_SHAPE];
maxP = chainMaxs[CHANGE_BETA_SHAPE];
pSlide = 10.0;
// find new value
oldP = statefreqP[whichChain*2 + proposedState];
ran = (RandomNumber(seed) * pSlide) - (pSlide/2.0);
newP = oldP + ran;
// reflect in if new value passed given boundaries
if (newP < minP)
newP = (minP - newP) + minP;
if (newP > maxP)
newP = maxP - (newP - maxP);
// set new value
statefreqP[whichChain*2 + proposedState] = newP;
/* set prior ratio */
// this is only for uniform prior, exponential prior also reasonable?
(*lnPriorRatio) = 0.0;
UpDateAllCls (proposedState, whichChain);
# if defined (SMART_TI_PROBS)
// SMART_TI_PROBS not implemented for binary and restriction data?
UpDateAllTIs (proposedState, whichChain);
# endif
return (NO_ERROR);
}
#endif
/* change branch lengths and topology (potentially) using eraser */
#undef MULTIPLE_BR_HIT
int Move_ChangeEraser (int numTaxa, int proposedState, int whichChain, long int *seed, double *lnProposalRatio, double *lnPriorRatio)
{
int i, j, topologyHasChanged;
double ran, tuning,
# if !defined (MULTIPLE_BR_HIT)
rndUM[5], oldM, newM,
# endif
lnOldBrlenPr,lnNewBrlenPr;
TreeNode *p, *a, *b, *c, *d, *u, *v;
tuning = tuningProp;
topologyHasChanged = NO;
# if defined (DEBUG_ERASER)
printf ("Before:\n");
ShowNodes (root[whichChain*2+proposedState], 2, NO);
# endif
/* set all updates to "NO" */
for (i=0; i<numNodes; i++)
{
p = allNodesDownPassSeq[whichChain*2*numNodes + proposedState*numNodes + i];
p->upDateCl = NO;
}
/* initialize proposal ratio to 0.0 */
(*lnProposalRatio) = 0.0;
lnNewBrlenPr = lnOldBrlenPr = 0.0;
/* pick an internal branch */
do
{
p = intNodeDownPassSeq[whichChain*2*numIntNodes + proposedState*numIntNodes + (int)(RandomNumber(seed)*numIntNodes)];
} while (p->anc->anc == NULL);
if (!strcmp(clockModel, "unconstrained") && treeModel == UNROOTED)
{
/* if tree is unrooted and the branch lengths are unconstrained */
u = p;
v = p->anc;
a = p->left;
b = p->right;
c = v->anc;
if (v->left == u)
d = v->right;
else
d = v->left;
# if !defined (MULTIPLE_BR_HIT)
oldM = a->length + b->length + u->length + d->length + v->length;
newM = oldM * exp(tuning *(RandomNumber(seed) - 0.5));
# endif
if (!strcmp(brlenprModel, "exponential"))
{
lnOldBrlenPr = log(brlenprExp) - brlenprExp * (a->length);
lnOldBrlenPr += log(brlenprExp) - brlenprExp * (b->length);
lnOldBrlenPr += log(brlenprExp) - brlenprExp * (u->length);
lnOldBrlenPr += log(brlenprExp) - brlenprExp * (d->length);
lnOldBrlenPr += log(brlenprExp) - brlenprExp * (v->length);
}
# if defined (MULTIPLE_BR_HIT)
(*lnProposalRatio) -= (a->length + b->length + u->length + d->length + v->length);
a->length *= exp(tuning * (RandomNumber(seed) - 0.5));
b->length *= exp(tuning * (RandomNumber(seed) - 0.5));
u->length *= exp(tuning * (RandomNumber(seed) - 0.5));
d->length *= exp(tuning * (RandomNumber(seed) - 0.5));
v->length *= exp(tuning * (RandomNumber(seed) - 0.5));
(*lnProposalRatio) += (a->length + b->length + u->length + d->length + v->length);
# else
for (i=0; i<4; i++)
rndUM[i] = RandomNumber(seed) * newM;
SortVector (rndUM, 4);
a->length = rndUM[0];
b->length = rndUM[1] - rndUM[0];
u->length = rndUM[2] - rndUM[1];
d->length = rndUM[3] - rndUM[2];
v->length = newM - rndUM[3];
# endif
if (u->isConstrained == YES || v->isConstrained == YES)
ran = 1.0;
else
ran = RandomNumber(seed);
if (ran < 0.333)
{
u->left = a;
u->right = d;
a->anc = d->anc = u;
v->left = u;
v->right = b;
u->anc = b->anc = v;
topologyHasChanged = YES;
}
else if (ran >= 0.333 && ran < 0.666)
{
u->left = b;
u->right = d;
b->anc = d->anc = u;
v->left = u;
v->right = a;
u->anc = a->anc = v;
topologyHasChanged = YES;
}
if (!strcmp(brlenprModel, "exponential"))
{
lnNewBrlenPr = log(brlenprExp) - brlenprExp * (a->length);
lnNewBrlenPr += log(brlenprExp) - brlenprExp * (b->length);
lnNewBrlenPr += log(brlenprExp) - brlenprExp * (u->length);
lnNewBrlenPr += log(brlenprExp) - brlenprExp * (d->length);
lnNewBrlenPr += log(brlenprExp) - brlenprExp * (v->length);
}
# if !defined (MULTIPLE_BR_HIT)
(*lnProposalRatio) = 5.0 * (log(newM) - log(oldM));
# endif
a->upDateCl = YES;
b->upDateCl = YES;
u->upDateCl = YES;
d->upDateCl = YES;
v->upDateCl = YES;
c->upDateCl = YES;
p = c;
while (p->anc != NULL)
{
p = p->anc;
p->upDateCl = YES;
}
# if defined (SMART_TI_PROBS)
a->upDateTi = YES;
b->upDateTi = YES;
u->upDateTi = YES;
d->upDateTi = YES;
v->upDateTi = YES;
# endif
}
/* get down pass sequence if tree topology has changed */
if (topologyHasChanged == YES)
{
i = j = 0;
GetDownPassSeq (root[whichChain*2 + proposedState], proposedState, whichChain, numTaxa, &i, &j);
}
# if defined (DEBUG_ERASER)
printf ("After:\n");
ShowNodes (root[whichChain*2+proposedState], 2, NO);
# endif
(*lnPriorRatio) = lnNewBrlenPr - lnOldBrlenPr;
# if defined (TOPOLOGY_MOVE_STATS)
if (topologyHasChanged == YES)
gTopologyHasChanged = YES;
else
gTopologyHasChanged = NO;
gNodeMoves = 1;
# endif
# if defined (SMART_TI_PROBS)
UpDateAllTIs (proposedState, whichChain);
# endif
return (NO_ERROR);
}
/* change gc switch params */
int Move_ChangeGCSwitch (int proposedState, int whichChain, long int *seed, double *lnPriorRatio, double *lnProposalRatio)
{
double ran, ran1, maxP, minP, newP, oldP, pSlide;
ran1 = RandomNumber(seed);
if (ran1 < 0.25)
{
minP = 0.0;
maxP = 0.5;
pSlide = 0.1;
oldP = gc1[whichChain*2 + proposedState];
ran = (RandomNumber(seed) * pSlide) - (pSlide/2.0);
newP = oldP + ran;
if (newP < minP)
newP = (minP - newP) + minP;
if (newP > maxP)
newP = maxP - (newP - maxP);
gc1[whichChain*2 + proposedState] = newP;
}
else if (ran1 >= 0.25 && ran1 < 0.50)
{
minP = 0.5;
maxP = 1.0;
pSlide = 0.1;
oldP = gc2[whichChain*2 + proposedState];
ran = (RandomNumber(seed) * pSlide) - (pSlide/2.0);
newP = oldP + ran;
if (newP < minP)
newP = (minP - newP) + minP;
if (newP > maxP)
newP = maxP - (newP - maxP);
gc2[whichChain*2 + proposedState] = newP;
}
else if (ran1 >= 0.50 && ran1 < 0.75)
{
minP = 0.0;
maxP = 1.0;
pSlide = 0.1;
oldP = fracA[whichChain*2 + proposedState];
ran = (RandomNumber(seed) * pSlide) - (pSlide/2.0);
newP = oldP + ran;
if (newP < minP)
newP = (minP - newP) + minP;
if (newP > maxP)
newP = maxP - (newP - maxP);
fracA[whichChain*2 + proposedState] = newP;
}
else
{
minP = 0.0;
maxP = 1.0;
pSlide = 0.1;
oldP = fracG[whichChain*2 + proposedState];
ran = (RandomNumber(seed) * pSlide) - (pSlide/2.0);
newP = oldP + ran;
if (newP < minP)
newP = (minP - newP) + minP;
if (newP > maxP)
newP = maxP - (newP - maxP);
fracG[whichChain*2 + proposedState] = newP;
}
(*lnPriorRatio) = (*lnProposalRatio) = 0.0;
UpDateAllCls (proposedState, whichChain);
# if defined (SMART_TI_PROBS)
UpDateAllTIs (proposedState, whichChain);
# endif
return (NO_ERROR);
}
/* change branch lengths and topology (potentially) using BAMBE's LOCAL (unrooted) */
int Move_ChangeClockWithLocal (int numTaxa, int proposedState, int whichChain, long int *seed, double *lnProposalRatio, double *lnPriorRatio)
{
int i, j, topologyHasChanged, isAtRoot, isTreeConstrained,
isForcedBackMove, isForcedForwardMove, dID[3], dTemp;
double ran, x, tuning, y,
dAW, dBW, dCW, dAV, dBV, dCV, h[3], oldH1, newH1, temp,
newDAW, newDBW, newDCW, newDAV, newDBV, newDCV, lnNewBrlenPr, lnOldBrlenPr, *nt, rootTime, sR, eR, sF;
TreeNode *p, *q, *a, *b, *c, *u, *v, *w;
lnNewBrlenPr = lnOldBrlenPr = 0.0;
if (!strcmp(brlenprModel, "exponential"))
{
for (i=0; i<numNodes; i++)
{
q = allNodesDownPassSeq[whichChain*2*numNodes + proposedState*numNodes + i];
lnOldBrlenPr += log(brlenprExp) - brlenprExp * (q->length);
}
}
else if (!strcmp(brlenprModel, "birth-death"))
{
sR = spRate[whichChain*2 + proposedState];
eR = exRate[whichChain*2 + proposedState];
sF = samplingFraction;
/* allocate memory */
nt = (double *)malloc((size_t) (numTaxa-1) * sizeof(double));
if (!nt)
{
printf ("\n ERROR: Problem allocating nt\n");
return (ERROR);
}
/* get node times */
for (i=0; i<numNodes; i++)
{
q = allNodesDownPassSeq[whichChain*2*numNodes + proposedState*numNodes + i];
if (q->left == NULL && q->right == NULL)
q->nodeTime = 0.0;
else
q->nodeTime += q->left->nodeTime + q->left->length;
}
rootTime = root[whichChain*2+proposedState]->left->nodeTime;
for (i=0; i<numNodes; i++)
{
q = allNodesDownPassSeq[whichChain*2*numNodes + proposedState*numNodes + i];
if (q->left == NULL && q->right == NULL)
q->nodeTime = 0.0;
else
q->nodeTime /= rootTime;
}
/* put node times into vector */
j = 0;
for (i=0; i<numNodes; i++)
{
q = allNodesDownPassSeq[whichChain*2*numNodes + proposedState*numNodes + i];
if (q->left != NULL && q->right != NULL && q->anc != NULL)
{
nt[j] = q->nodeTime;
j++;
}
}
/* calculate probabilities of tree */
lnOldBrlenPr = (numTaxa-2)*log(sR);
for (i=0; i<numTaxa-2; i++)
{
lnOldBrlenPr += lnP1(nt[i], sR, eR, sF) - lnVt(rootTime, sR, eR, sF);
}
}
# if defined (DEBUG_LOCAL_CLOCK)
printf ("Before:\n");
ShowNodes (root[whichChain*2+proposedState], 2, YES);
# endif
for (i=0; i<numNodes; i++)
{
p = allNodesDownPassSeq[whichChain*2*numNodes + proposedState*numNodes + i];
p->upDateCl = NO;
}
(*lnProposalRatio) = 0.0;
/* pick an internal branch */
do
{
p = intNodeDownPassSeq[whichChain*2*numIntNodes + proposedState*numIntNodes + (int)(RandomNumber(seed)*numIntNodes)];
} while (p->anc->anc == NULL);
isTreeConstrained = NO;
if (p->isConstrained == YES)
isTreeConstrained = YES;
isAtRoot = NO;
if (p->anc->anc->anc == NULL)
isAtRoot = YES;
if (isAtRoot == NO)
{
/* initialize pointers */
u = p;
v = u->anc;
w = v->anc;
a = u->left;
b = u->right;
if (v->left == u)
c = v->right;
else
c = v->left;
dAW = a->length + u->length + v->length;
dBW = b->length + u->length + v->length;
dCW = c->length + v->length;
h[0] = dAW;
h[1] = dBW;
h[2] = dCW;
dID[0] = 0;
dID[1] = 1;
dID[2] = 2;
if (h[0] > h[1])
{
temp = h[0];
h[0] = h[1];
h[1] = temp;
dTemp = dID[0];
dID[0] = dID[1];
dID[1] = dTemp;
}
if (h[0] > h[2])
{
temp = h[0];
h[0] = h[2];
h[2] = temp;
dTemp = dID[0];
dID[0] = dID[2];
dID[2] = dTemp;
}
if (h[1] > h[2])
{
temp = h[1];
h[1] = h[2];
h[2] = temp;
dTemp = dID[1];
dID[1] = dID[2];
dID[2] = dTemp;
}
for (i=0; i<3; i++)
{
if (dID[i] == 0)
newDAW = h[i];
else if (dID[i] == 1)
newDBW = h[i];
else
newDCW = h[i];
}
# if defined (DEBUG_LOCAL_CLOCK)
printf ("newDAW = %lf newDBW = %lf newDCW = %lf\n", newDAW, newDBW, newDCW);
# endif
if (isTreeConstrained == NO)
{
x = RandomNumber(seed) * h[0];
y = RandomNumber(seed) * h[1];
if (y > x)
{
temp = y;
y = x;
x = temp;
}
}
else
{
if (dAW < dBW)
temp = dAW;
else
temp = dBW;
x = RandomNumber(seed) * temp;
if (dCW < temp)
y = RandomNumber(seed) * dCW;
else
y = RandomNumber(seed) * temp;
if (y > x)
{
temp = y;
y = x;
x = temp;
}
}
# if defined (DEBUG_LOCAL_CLOCK)
printf ("x = %lf y = %lf\n", x, y);
# endif
if (isTreeConstrained == NO)
{
/* tree is not constrained at u */
if (x < h[0])
{
/* topology is free to vary */
ran = RandomNumber(seed);
if (ran <= 0.3333)
{
a->anc = b->anc = u;
u->left = a;
u->right = b;
v->left = u;
v->right = c;
c->anc = v;
a->length = newDAW - x;
b->length = newDBW - x;
c->length = newDCW - y;
u->length = x - y;
v->length = y;
}
else if (ran > 0.3333 && ran <= 0.6666)
{
a->anc = c->anc = u;
u->left = a;
u->right = c;
v->left = u;
v->right = b;
b->anc = v;
a->length = newDAW - x;
c->length = newDCW - x;
b->length = newDBW - y;
u->length = x - y;
v->length = y;
}
else
{
b->anc = c->anc = u;
u->left = b;
u->right = c;
v->left = u;
v->right = a;
a->anc = v;
b->length = newDBW - x;
c->length = newDCW - x;
a->length = newDAW - y;
u->length = x - y;
v->length = y;
}
}
else
{
/* topology forced */
if (dID[0] == 0)
{
/* a + b */
b->anc = c->anc = u;
u->left = b;
u->right = c;
v->left = u;
v->right = a;
a->anc = v;
b->length = newDBW - x;
c->length = newDCW - x;
a->length = newDAW - y;
u->length = x - y;
v->length = y;
}
else if (dID[0] == 1)
{
/* a + c */
a->anc = c->anc = u;
u->left = a;
u->right = c;
v->left = u;
v->right = b;
b->anc = v;
a->length = newDAW - x;
c->length = newDCW - x;
b->length = newDBW - y;
u->length = x - y;
v->length = y;
}
else
{
/* b + c */
a->anc = b->anc = u;
u->left = a;
u->right = b;
v->left = u;
v->right = c;
c->anc = v;
a->length = newDAW - x;
b->length = newDBW - x;
c->length = newDCW - y;
u->length = x - y;
v->length = y;
}
}
/* get hastings ratio here */
if (u->length > c->length && x < h[0])
(*lnProposalRatio) += log(3.0);
else if (u->length < c->length && x > h[0])
(*lnProposalRatio) += log(1.0/3.0);
else
(*lnProposalRatio) += 0.0;
}
else
{
/* tree is constrained at u */
a->length = newDAW - x;
b->length = newDBW - x;
c->length = newDCW - y;
u->length = x - y;
v->length = y;
}
# if defined (SMART_TI_PROBS)
a->upDateTi = YES;
b->upDateTi = YES;
u->upDateTi = YES;
c->upDateTi = YES;
v->upDateTi = YES;
# endif
}
else
{
/* deal with root of tree differently if this is a rooted and uncontrained tree */
/* initialize pointers */
u = p;
v = p->anc;
a = u->left;
b = u->right;
if (v->left == u)
c = v->right;
else
c = v->left;
/* v is at root of tree */
if (u->length < c->length)
isForcedBackMove = NO;
else
isForcedBackMove = YES;
dAV = a->length + u->length;
dBV = b->length + u->length;
dCV = c->length;
if (dAV < dBV && dAV < dCV)
oldH1 = dAV;
else if (dBV < dAV && dBV < dCV)
oldH1 = dBV;
else
oldH1 = dCV;
tuning = clockTuneProp;
newH1 = oldH1 * exp(tuning*(RandomNumber(seed) - 0.5));
dAV = dAV + (newH1 - oldH1);
dBV = dBV + (newH1 - oldH1);
dCV = dCV + (newH1 - oldH1);
h[0] = dAV;
h[1] = dBV;
h[2] = dCV;
dID[0] = 0;
dID[1] = 1;
dID[2] = 2;
if (h[0] > h[1])
{
temp = h[0];
h[0] = h[1];
h[1] = temp;
dTemp = dID[0];
dID[0] = dID[1];
dID[1] = dTemp;
}
if (h[0] > h[2])
{
temp = h[0];
h[0] = h[2];
h[2] = temp;
dTemp = dID[0];
dID[0] = dID[2];
dID[2] = dTemp;
}
if (h[1] > h[2])
{
temp = h[1];
h[1] = h[2];
h[2] = temp;
dTemp = dID[1];
dID[1] = dID[2];
dID[2] = dTemp;
}
for (i=0; i<3; i++)
{
if (dID[i] == 0)
newDAV = h[i];
else if (dID[i] == 1)
newDBV = h[i];
else
newDCV = h[i];
}
# if defined (DEBUG_LOCAL_CLOCK)
printf ("h[0] = %lf h[1] = %lf h[2] = %lf (%d %d %d)\n", h[0], h[1], h[2], dID[0], dID[1], dID[2]);
printf ("x = %lf\n", x);
# endif
(*lnProposalRatio) += 2.0 * (log(newH1) - log(oldH1));
if (isTreeConstrained == NO)
x = RandomNumber(seed) * h[1];
else
{
if (newDAV < newDBV)
x = RandomNumber(seed) * newDAV;
else
x = RandomNumber(seed) * newDBV;
}
if (isTreeConstrained == NO)
{
/* tree is not constrained */
if (x > h[0])
{
isForcedForwardMove = YES;
if (dID[0] == 0)
{
/* a is shortest, (b,c) forced */
u->left = b;
u->right = c;
u->anc = v;
a->anc = v;
b->anc = u;
c->anc = u;
v->left = a;
v->right = u;
u->length = x;
a->length = dAV;
b->length = dBV - x;
c->length = dCV - x;
}
else if (dID[0] == 1)
{
/* b is shortest, (a,c) forced */
u->left = a;
u->right = c;
u->anc = v;
a->anc = u;
b->anc = v;
c->anc = u;
v->left = b;
v->right = u;
u->length = x;
a->length = dAV - x;
b->length = dBV;
c->length = dCV - x;
}
else
{
/* c is shortest, (a,b) forced */
u->left = a;
u->right = b;
u->anc = v;
a->anc = u;
b->anc = u;
c->anc = v;
v->left = c;
v->right = u;
u->length = x;
a->length = dAV - x;
b->length = dBV - x;
c->length = dCV;
}
}
else
{
isForcedForwardMove = NO;
ran = RandomNumber(seed);
if (ran <= 0.33333)
{
/* a with c */
u->right = c;
b->anc = v;
c->anc = u;
if (v->left == u)
v->right = b;
else
v->left = b;
u->length = x;
a->length = newDAV - x;
b->length = newDBV;
c->length = newDCV - x;
}
else if (ran > 0.33333 && ran <= 0.66666)
{
/* b with c */
u->left = c;
a->anc = v;
c->anc = u;
if (v->left == u)
v->right = a;
else
v->left = a;
a->length += u->length;
c->length -= u->length;
u->length = x;
a->length = newDAV;
b->length = newDBV - x;
c->length = newDCV - x;
}
else
{
/* no change */
u->length = x;
a->length = newDAV - x;
b->length = newDBV - x;
c->length = newDCV;
}
}
/* get hastings ratio here */
if (isForcedForwardMove == NO && isForcedBackMove == YES)
(*lnProposalRatio) += log(3.0);
else if (isForcedForwardMove == YES && isForcedBackMove == NO)
(*lnProposalRatio) += log(1.0/3.0);
}
else
{
/* tree is constrained at node u */
u->length = x;
a->length = dAV - x;
b->length = dBV - x;
c->length = dCV;
}
# if defined (SMART_TI_PROBS)
a->upDateTi = YES;
b->upDateTi = YES;
u->upDateTi = YES;
c->upDateTi = YES;
# endif
}
p = u;
while (p->anc != NULL)
{
p->upDateCl = YES;
p = p->anc;
}
topologyHasChanged = YES;
/* get down pass sequence if tree topology has changed */
if (topologyHasChanged == YES)
{
i = j = 0;
GetDownPassSeq (root[whichChain*2 + proposedState], proposedState, whichChain, numTaxa, &i, &j);
}
# if defined (DEBUG_LOCAL_CLOCK)
printf ("After:\n");
ShowNodes (root[whichChain*2+proposedState], 2, YES);
# endif
if (!strcmp(brlenprModel, "exponential"))
{
for (i=0; i<numNodes; i++)
{
q = allNodesDownPassSeq[whichChain*2*numNodes + proposedState*numNodes + i];
lnNewBrlenPr += log(brlenprExp) - brlenprExp * (q->length);
}
}
else if (!strcmp(brlenprModel, "birth-death"))
{
/* get node times */
for (i=0; i<numNodes; i++)
{
q = allNodesDownPassSeq[whichChain*2*numNodes + proposedState*numNodes + i];
if (q->left == NULL && q->right == NULL)
q->nodeTime = 0.0;
else
q->nodeTime += q->left->nodeTime + q->left->length;
}
rootTime = root[whichChain*2+proposedState]->left->nodeTime;
for (i=0; i<numNodes; i++)
{
q = allNodesDownPassSeq[whichChain*2*numNodes + proposedState*numNodes + i];
if (q->left == NULL && q->right == NULL)
q->nodeTime = 0.0;
else
q->nodeTime /= rootTime;
}
/* put node times into vector */
j = 0;
for (i=0; i<numNodes; i++)
{
q = allNodesDownPassSeq[whichChain*2*numNodes + proposedState*numNodes + i];
if (q->left != NULL && q->right != NULL && q->anc != NULL)
{
nt[j] = q->nodeTime;
j++;
}
}
/* calculate probabilities of tree */
lnNewBrlenPr = (numTaxa-2)*log(sR);
for (i=0; i<numTaxa-2; i++)
{
lnNewBrlenPr += lnP1(nt[i], sR, eR, sF) - lnVt(rootTime, sR, eR, sF);
}
free (nt);
}
(*lnPriorRatio) = lnNewBrlenPr - lnOldBrlenPr;
# if defined (TOPOLOGY_MOVE_STATS)
if (topologyHasChanged == YES)
gTopologyHasChanged = YES;
else
gTopologyHasChanged = NO;
gNodeMoves = 1;
# endif
# if defined (SMART_TI_PROBS)
UpDateAllTIs (proposedState, whichChain);
# endif
return (NO_ERROR);
}
/* change gamma shape parameter */
int Move_ChangeGammaShape (int proposedState, int whichChain, long int *seed, double *lnPriorRatio)
{
double oldA, newA, ran, alphaSlide, minAlpha, maxAlpha;
if (!strcmp(shapeprModel, "exponential"))
{
minAlpha = 0.01;
maxAlpha = 100.0;
}
else if (!strcmp(shapeprModel, "uniform"))
{
minAlpha = shapeprUni[0];
maxAlpha = shapeprUni[1];
}
alphaSlide = alphaWinProp;
oldA = alpha[whichChain*2 + proposedState];
ran = (RandomNumber(seed) * alphaSlide) - (alphaSlide/2.0);
newA = oldA + ran;
if (newA < minAlpha)
newA = (minAlpha - newA) + minAlpha;
if (newA > maxAlpha)
newA = maxAlpha - (newA - maxAlpha);
alpha[whichChain*2 + proposedState] = newA;
/* set prior ratio */
if (!strcmp(qmatprModel, "exponential"))
(*lnPriorRatio) = (shapeprExp*oldA - shapeprExp*newA);
else if (!strcmp(qmatprModel, "uniform"))
(*lnPriorRatio) = 0.0;
UpDateAllCls (proposedState, whichChain);
# if defined (SMART_TI_PROBS)
UpDateAllTIs (proposedState, whichChain);
# endif
return (NO_ERROR);
}
/* change lag parameter */
int Move_ChangeLag (int proposedState, int whichChain, long int *seed, double *lnPriorRatio, double *lnProposalRatio)
{
int minLag, maxLag, oldLag, newLag, jumpSize;
double ran;
minLag = (int)chainMins[CHANGE_LAG];
maxLag = (int)chainMaxs[CHANGE_LAG];
# if 0
if (oldLag == 1)
{
newLag = 2;
(*lnProposalRatio) = log(0.5);
}
else if (oldLag == maxLag)
{
newLag = maxLag - 1;
(*lnProposalRatio) = log(0.5);
}
else
{
if (RandomNumber(seed) < 0.5)
newLag = oldLag + 1;
else
newLag = oldLag - 1;
(*lnProposalRatio) = 0.0;
}
if (newLag == 1)
(*lnProposalRatio) = log(2.0);
else if (newLag == maxLag)
(*lnProposalRatio) = log(2.0);
lag[whichChain*2 + proposedState] = newLag;
# else
ran = RandomNumber(seed);
if (ran <= (5.0 / 15.0))
jumpSize = 1;
else if (ran > (5.0 / 15.0) && ran <= (9.0 / 15.0))
jumpSize = 2;
else if (ran > (9.0 / 15.0) && ran <= (12.0 / 15.0))
jumpSize = 3;
else if (ran > (12.0 / 15.0) && ran <= (14.0 / 15.0))
jumpSize = 4;
else
jumpSize = 5;
oldLag = lag[whichChain*2 + proposedState];
if (oldLag - jumpSize < 1)
{
newLag = oldLag + jumpSize;
(*lnProposalRatio) = log(0.5);
}
else if (oldLag + jumpSize > maxLag)
{
newLag = oldLag - jumpSize;
(*lnProposalRatio) = log(0.5);
}
else
{
if (RandomNumber(seed) < 0.5)
newLag = oldLag + jumpSize;
else
newLag = oldLag - jumpSize;
(*lnProposalRatio) = 0.0;
}
if (newLag <= jumpSize)
(*lnProposalRatio) = log(2.0);
else if (newLag > maxLag - jumpSize)
(*lnProposalRatio) = log(2.0);
lag[whichChain*2 + proposedState] = newLag;
# endif
/* set prior ratio */
(*lnPriorRatio) = 0.0;
if (!strcmp(lagprModel, "exponential"))
{
(*lnPriorRatio) = log(exp(-(newLag-0.5)) - exp(-(newLag+0.5)));
(*lnPriorRatio) -= log(exp(-(oldLag-0.5)) - exp(-(oldLag+0.5)));
}
UpDateAllCls (proposedState, whichChain);
# if defined (SMART_TI_PROBS)
UpDateAllTIs (proposedState, whichChain);
# endif
return (NO_ERROR);
}
/* change Q matrix */
int Move_ChangeQMatrix (int proposedState, int whichChain, long int *seed, double *lnPriorRatio)
{
int param;
double oldK, newK, ran, kappaSlide, minKappa, maxKappa;
if (!strcmp(qmatprModel, "exponential"))
{
minKappa = 0.0000001;
maxKappa = 1000.0;
}
else if (!strcmp(qmatprModel, "uniform"))
{
minKappa = qmatprUni[0];
maxKappa = qmatprUni[1];
}
kappaSlide = qMatWinProp;
if ((dataType == DNA || dataType == RNA) && enforceCodonModel == NO)
{
if (nst == 2)
{
oldK = kappa[whichChain*2 + proposedState];
ran = (RandomNumber(seed) * kappaSlide) - (kappaSlide/2.0);
newK = oldK + ran;
if (newK < minKappa)
newK = (minKappa - newK) + minKappa;
if (newK > maxKappa)
newK = maxKappa - (newK - maxKappa);
kappa[whichChain*2 + proposedState] = newK;
}
else if (nst == 6)
{
ran = RandomNumber(seed);
if (ran > 0 && ran <= 0.2)
param = 1;
else if (ran > 0.2 && ran <= 0.4)
param = 2;
else if (ran > 0.4 && ran <= 0.6)
param = 3;
else if (ran > 0.6 && ran <= 0.8)
param = 4;
else if (ran > 0.8 && ran <= 1.0)
param = 5;
oldK = subParams[whichChain*12 + proposedState*6 + param];
ran = (RandomNumber(seed) * kappaSlide) - (kappaSlide/2.0);
newK = oldK + ran;
if (newK < 0.0)
newK = -newK;
if (newK > maxKappa)
newK = maxKappa - (newK - maxKappa);
subParams[whichChain*12 + proposedState*6 + param] = newK;
}
else if (nst == 12)
{
ran = RandomNumber(seed);
if (ran > 0.0 && ran <= 1.0/11.0)
param = 1;
else if (ran > 1.0/11.0 && ran <= 2.0/11.0)
param = 2;
else if (ran > 2.0/11.0 && ran <= 3.0/11.0)
param = 3;
else if (ran > 3.0/11.0 && ran <= 4.0/11.0)
param = 4;
else if (ran > 4.0/11.0 && ran <= 5.0/11.0)
param = 5;
else if (ran > 5.0/11.0 && ran <= 6.0/11.0)
param = 6;
else if (ran > 6.0/11.0 && ran <= 7.0/11.0)
param = 7;
else if (ran > 7.0/11.0 && ran <= 8.0/11.0)
param = 8;
else if (ran > 8.0/11.0 && ran <= 9.0/11.0)
param = 9;
else if (ran > 9.0/11.0 && ran <= 10.0/11.0)
param = 10;
else if (ran > 10.0/11.0 && ran <= 1.0)
param = 11;
oldK = subParams[whichChain*24 + proposedState*12 + param];
ran = (RandomNumber(seed) * kappaSlide) - (kappaSlide/2.0);
newK = oldK + ran;
if (newK < 0.0)
newK = -newK;
if (newK > maxKappa)
newK = maxKappa - (newK - maxKappa);
subParams[whichChain*24 + proposedState*12 + param] = newK;
}
else
{
printf ("\n ERROR: Should not be in this move\n");
return (ERROR);
}
}
else if ((dataType == DNA || dataType == RNA) && enforceCodonModel == YES)
{
oldK = kappa[whichChain*2 + proposedState];
ran = (RandomNumber(seed) * kappaSlide) - (kappaSlide/2.0);
newK = oldK + ran;
if (newK < minKappa)
newK = (minKappa - newK) + minKappa;
if (newK > maxKappa)
newK = maxKappa - (newK - maxKappa);
kappa[whichChain*2 + proposedState] = newK;
}
else if (dataType == PROTEIN)
{
param = RandomNumber(seed) * 189;
param++;
if (param < 1 || param >= 190)
{
printf ("\n ERROR: parameter to be changed is invalid \n");
return (ERROR);
}
oldK = subParams[whichChain*2*190 + proposedState*190 + param];
ran = (RandomNumber(seed) * kappaSlide) - (kappaSlide/2.0);
newK = oldK + ran;
if (newK < 0.0)
newK = -newK;
if (newK > maxKappa)
newK = maxKappa - (newK - maxKappa);
subParams[whichChain*2*190 + proposedState*190 + param] = newK;
}
else if (dataType == RESTRICTION)
{
oldK = kappa[whichChain*2 + proposedState];
ran = (RandomNumber(seed) * kappaSlide) - (kappaSlide/2.0);
newK = oldK + ran;
if (newK < minKappa)
newK = (minKappa - newK) + minKappa;
if (newK > maxKappa)
newK = maxKappa - (newK - maxKappa);
kappa[whichChain*2 + proposedState] = newK;
//kappa[whichChain*2 + proposedState] = 1.0;
}
/* set prior ratio */
if (!strcmp(qmatprModel, "exponential"))
(*lnPriorRatio) = (qmatprExp*oldK - qmatprExp*newK);
else if (!strcmp(qmatprModel, "uniform"))
(*lnPriorRatio) = 0.0;
UpDateAllCls (proposedState, whichChain);
# if defined (SMART_TI_PROBS)
UpDateAllTIs (proposedState, whichChain);
# endif
return (NO_ERROR);
}
/* change rates of rate categories */
int Move_ChangeSiteRates (int proposedState, int whichChain, long int *seed, double *lnPriorRatio)
{
int i, nIncludedChars;
double oldA, newA, ran, alphaSlide, minAlpha, maxAlpha, scaler;
if (!strcmp(siterateprModel, "exponential"))
{
minAlpha = 0.01;
maxAlpha = 100.0;
}
else if (!strcmp(siterateprModel, "uniform"))
{
minAlpha = siterateprUni[0];
maxAlpha = siterateprUni[1];
}
alphaSlide = rateWinProp;
(*lnPriorRatio) = 0.0;
for (i=0; i<nPartitions-1; i++)
{
oldA = unscaledRates[whichChain*2*nPartitions + proposedState*nPartitions + i];
ran = (RandomNumber(seed) * alphaSlide) - (alphaSlide/2.0);
newA = oldA + ran;
if (newA < minAlpha)
newA = (minAlpha - newA) + minAlpha;
if (newA > maxAlpha)
newA = maxAlpha - (newA - maxAlpha);
unscaledRates[whichChain*2*nPartitions + proposedState*nPartitions + i] = newA;
/* set prior ratio */
if (!strcmp(qmatprModel, "exponential"))
(*lnPriorRatio) += (siterateprExp*oldA - siterateprExp*newA);
}
scaler = 0.0;
nIncludedChars = 0;
for (i=0; i<nPartitions; i++)
{
scaler += unscaledRates[whichChain*2*nPartitions + proposedState*nPartitions + i] * nSitesInPartition[i];
nIncludedChars += nSitesInPartition[i];
}
scaler = (double)nIncludedChars / scaler;
for (i=0; i<nPartitions; i++)
{
scaledRates[whichChain*2*nPartitions + proposedState*nPartitions + i] =
unscaledRates[whichChain*2*nPartitions + proposedState*nPartitions + i] * scaler;
}
UpDateAllCls (proposedState, whichChain);
# if defined (SMART_TI_PROBS)
UpDateAllTIs (proposedState, whichChain);
# endif
return (NO_ERROR);
}
/* change branch lengths and topology (potentially) using BAMBE's LOCAL (unrooted) */
int Move_ChangeUnrootedWithLocal (int numTaxa, int proposedState, int whichChain, long int *seed, double *lnProposalRatio, double *lnPriorRatio)
{
int i, j, isAUp, topologyHasChanged, specialRoot, isTreeConstrained,
isForcedBackMove, isForcedForwardMove, dID[3], dTemp;
double ran, m, newM, x, newX, y, newY, tuning, maxV,
dAV, dBV, dCV, h[3], oldH1, newH1, temp,
newDAV, newDBV, newDCV, lnOldBrlenPr,lnNewBrlenPr;
TreeNode *p, *a, *b, *c, *d, *u, *v;
tuning = tuningProp;
# if defined (DEBUG_LOCAL)
printf ("Before:\n");
ShowNodes (root[whichChain*2+proposedState], 2, NO);
# endif
lnNewBrlenPr = lnOldBrlenPr = 0.0;
if (!strcmp(brlenprModel, "exponential"))
{
for (i=0; i<numNodes; i++)
{
p = allNodesDownPassSeq[whichChain*2*numNodes + proposedState*numNodes + i];
lnOldBrlenPr += log(brlenprExp) - brlenprExp * (p->length);
}
}
for (i=0; i<numNodes; i++)
{
p = allNodesDownPassSeq[whichChain*2*numNodes + proposedState*numNodes + i];
p->upDateCl = NO;
}
(*lnProposalRatio) = 0.0;
/* pick an internal branch */
do
{
p = intNodeDownPassSeq[whichChain*2*numIntNodes + proposedState*numIntNodes + (int)(RandomNumber(seed)*numIntNodes)];
} while (p->anc->anc == NULL);
isTreeConstrained = NO;
if (p->isConstrained == YES || p->anc->isConstrained == YES)
isTreeConstrained = YES;
specialRoot = NO;
if (p->anc->anc->anc == NULL && treeModel == ROOTED)
specialRoot = YES;
# if defined (DEBUG_LOCAL)
if (isTreeConstrained == YES)
printf ("node (%d %d) is constrained\n", p->isConstrained, p->anc->isConstrained);
# endif
if (specialRoot == NO)
{
/* set up pointers according to Larget and Simon (MBE, 1999: 754) */
v = p;
u = p->anc;
u->upDateCl = YES;
v->upDateCl = YES;
if (RandomNumber(seed) < 0.5)
{
c = v->left;
d = v->right;
}
else
{
c = v->right;
d = v->left;
}
if (RandomNumber(seed) < 0.5)
{
if (u->left == v)
a = u->right;
else
a = u->left;
b = u->anc;
isAUp = YES;
}
else
{
if (u->left == v)
b = u->right;
else
b = u->left;
a = u->anc;
isAUp = NO;
}
# if defined (DEBUG_LOCAL)
printf ("%d %d %d %d %d %d (%d)\n", u->index, v->index, a->index, b->index, c->index, d->index, isAUp);
# endif
/* get lengths of paths */
m = c->length + v->length;
if (isAUp == YES)
{
m += a->length;
x = a->length;
}
else
{
m += u->length;
x = u->length;
}
y = v->length + x;
/* change m */
ran = RandomNumber(seed);
newM = m * exp(tuning * (ran - 0.5));
# if defined (DEBUG_LOCAL)
printf ("m = %lf newM = %lf tuning = %lf\n", m, newM, tuning);
# endif
/* calculate proposal ratio */
(*lnProposalRatio) += (log(newM) - log(m));
/* change branch length proportions */
if (RandomNumber(seed) < 0.5)
{
/* detach u */
ran = RandomNumber(seed);
if (isTreeConstrained == NO)
{
newY = y * (newM / m);
newX = ran * newM;
(*lnProposalRatio) += (log(newM) - log(m));
}
else
{
newY = y * (newM / m);
newX = ran * newY;
(*lnProposalRatio) += (log(newY) - log(y));
}
}
else
{
/* detach v */
ran = RandomNumber(seed);
if (isTreeConstrained == NO)
{
newX = x * (newM / m);
newY = ran * newM;
(*lnProposalRatio) += (log(newM) - log(m));
}
else
{
newX = x * (newM / m);
newY = newX + ran * (newM - newX);
(*lnProposalRatio) += (log(newM - newX) - log(m - x));
}
}
/* check to see if topology changed */
if (newX > newY)
topologyHasChanged = YES;
else
topologyHasChanged = NO;
/* update pointers and branch lengths of tree */
if (topologyHasChanged == YES)
{
if (isAUp == YES)
{
if (v->left == c)
v->right = a;
else
v->left = a;
if (u->left == v)
u->right = d;
else
u->left = d;
a->anc = v;
d->anc = u;
c->length = newM - newX;
v->length = newX - newY;
a->length = newY;
}
else
{
if (v->left == c)
v->right = b;
else
v->left = b;
if (u->left == v)
u->right = d;
else
u->left = d;
b->anc = v;
d->anc = u;
c->length = newM - newX;
u->length = newY;
v->length = newX - newY;
}
}
else
{
if (isAUp == YES)
{
c->length = newM - newY;
u->length = newY - newX;
a->length = newX;
}
else
{
c->length = newM - newY;
v->length = newY - newX;
u->length = newX;
}
}
/* check branch lengths */
maxV = chainMaxs[CHANGE_UNROOT_LOCAL];
if (isAUp == YES)
{
if (c->length < BRLEN_EPSILON)
c->length = BRLEN_EPSILON;
if (a->length < BRLEN_EPSILON)
a->length = BRLEN_EPSILON;
if (d->length < BRLEN_EPSILON)
d->length = BRLEN_EPSILON;
if (u->length < BRLEN_EPSILON)
u->length = BRLEN_EPSILON;
if (v->length < BRLEN_EPSILON)
v->length = BRLEN_EPSILON;
if (c->length > maxV)
c->length = maxV;
if (a->length > maxV)
a->length = maxV;
if (d->length > maxV)
d->length = maxV;
if (u->length > maxV)
u->length = maxV;
if (v->length > maxV)
v->length = maxV;
}
else
{
if (c->length < BRLEN_EPSILON)
c->length = BRLEN_EPSILON;
if (b->length < BRLEN_EPSILON)
b->length = BRLEN_EPSILON;
if (d->length < BRLEN_EPSILON)
d->length = BRLEN_EPSILON;
if (u->length < BRLEN_EPSILON)
u->length = BRLEN_EPSILON;
if (v->length < BRLEN_EPSILON)
v->length = BRLEN_EPSILON;
if (c->length > maxV)
c->length = maxV;
if (b->length > maxV)
b->length = maxV;
if (d->length > maxV)
d->length = maxV;
if (u->length > maxV)
u->length = maxV;
if (v->length > maxV)
v->length = maxV;
}
v->upDateCl = YES;
p = u;
while (p->anc != NULL)
{
p->upDateCl = YES;
p = p->anc;
}
# if defined (SMART_TI_PROBS)
c->upDateTi = YES;
v->upDateTi = YES;
if (isAUp == YES)
a->upDateTi = YES;
else
u->upDateTi = YES;
a->upDateTi = YES;
u->upDateTi = YES;
# endif
}
else
{
/* deal with root of tree differently if this is a rooted and uncontrained tree */
/* check constraints again */
if (isTreeConstrained == YES)
{
if (p->isConstrained == NO && p->anc->isConstrained == YES)
isTreeConstrained = NO;
}
/* initialize pointers */
u = p;
v = p->anc;
a = u->left;
b = u->right;
if (v->left == u)
c = v->right;
else
c = v->left;
if (isTreeConstrained == NO)
{
/* node is unconstrained */
if (u->length < c->length)
isForcedBackMove = NO;
else
isForcedBackMove = YES;
dAV = a->length + u->length;
dBV = b->length + u->length;
dCV = c->length;
if (dAV < dBV && dAV < dCV)
oldH1 = dAV;
else if (dBV < dAV && dBV < dCV)
oldH1 = dBV;
else
oldH1 = dCV;
tuning = tuning;
newH1 = oldH1 * exp(tuning*(RandomNumber(seed) - 0.5));
dAV = dAV + (newH1 - oldH1);
dBV = dBV + (newH1 - oldH1);
dCV = dCV + (newH1 - oldH1);
h[0] = dAV;
h[1] = dBV;
h[2] = dCV;
dID[0] = 0;
dID[1] = 1;
dID[2] = 2;
if (h[0] > h[1])
{
temp = h[0];
h[0] = h[1];
h[1] = temp;
dTemp = dID[0];
dID[0] = dID[1];
dID[1] = dTemp;
}
if (h[0] > h[2])
{
temp = h[0];
h[0] = h[2];
h[2] = temp;
dTemp = dID[0];
dID[0] = dID[2];
dID[2] = dTemp;
}
if (h[1] > h[2])
{
temp = h[1];
h[1] = h[2];
h[2] = temp;
dTemp = dID[1];
dID[1] = dID[2];
dID[2] = dTemp;
}
for (i=0; i<3; i++)
{
if (dID[i] == 0)
newDAV = h[i];
else if (dID[i] == 1)
newDBV = h[i];
else
newDCV = h[i];
}
x = RandomNumber(seed) * h[1];
# if defined (DEBUG_LOCAL)
printf ("h[0] = %lf h[1] = %lf h[2] = %lf (%d %d %d)\n", h[0], h[1], h[2], dID[0], dID[1], dID[2]);
printf ("x = %lf\n", x);
# endif
(*lnProposalRatio) += 2.0 * (log(newH1) - log(oldH1));
if (x > h[0])
{
isForcedForwardMove = YES;
if (dID[0] == 0)
{
/* a is shortest, (b,c) forced */
u->left = b;
u->right = c;
u->anc = v;
a->anc = v;
b->anc = u;
c->anc = u;
v->left = a;
v->right = u;
u->length = x;
a->length = dAV;
b->length = dBV - x;
c->length = dCV - x;
}
else if (dID[0] == 1)
{
/* b is shortest, (a,c) forced */
u->left = a;
u->right = c;
u->anc = v;
a->anc = u;
b->anc = v;
c->anc = u;
v->left = b;
v->right = u;
u->length = x;
a->length = dAV - x;
b->length = dBV;
c->length = dCV - x;
}
else
{
/* c is shortest, (a,b) forced */
u->left = a;
u->right = b;
u->anc = v;
a->anc = u;
b->anc = u;
c->anc = v;
v->left = c;
v->right = u;
u->length = x;
a->length = dAV - x;
b->length = dBV - x;
c->length = dCV;
}
}
else
{
isForcedForwardMove = NO;
ran = RandomNumber(seed);
if (ran <= 0.33333)
{
/* a with c */
u->right = c;
b->anc = v;
c->anc = u;
if (v->left == u)
v->right = b;
else
v->left = b;
u->length = x;
a->length = newDAV - x;
b->length = newDBV;
c->length = newDCV - x;
}
else if (ran > 0.33333 && ran <= 0.66666)
{
/* b with c */
u->left = c;
a->anc = v;
c->anc = u;
if (v->left == u)
v->right = a;
else
v->left = a;
a->length += u->length;
c->length -= u->length;
u->length = x;
a->length = newDAV;
b->length = newDBV - x;
c->length = newDCV - x;
}
else
{
/* no change */
u->length = x;
a->length = newDAV - x;
b->length = newDBV - x;
c->length = newDCV;
}
}
/* get hastings ratio here */
if (isForcedForwardMove == NO && isForcedBackMove == YES)
(*lnProposalRatio) += log(3.0);
else if (isForcedForwardMove == YES && isForcedBackMove == NO)
(*lnProposalRatio) += log(1.0/3.0);
}
else
{
/* node is constrained */
dAV = a->length + u->length;
dBV = b->length + u->length;
dCV = c->length;
if (dAV < dBV)
oldH1 = dAV;
else
oldH1 = dBV;
tuning = tuning;
newH1 = oldH1 * exp(tuning*(RandomNumber(seed) - 0.5));
dAV = dAV + (newH1 - oldH1);
dBV = dBV + (newH1 - oldH1);
dCV = dCV + (newH1 - oldH1);
(*lnProposalRatio) += 2.0 * (log(newH1) - log(oldH1));
x = RandomNumber(seed) * newH1;
u->length = x;
a->length = dAV - x;
b->length = dBV - x;
c->length = dCV;
}
p = u;
while (p->anc != NULL)
{
p->upDateCl = YES;
p = p->anc;
}
topologyHasChanged = YES;
# if defined (SMART_TI_PROBS)
a->upDateTi = YES;
b->upDateTi = YES;
c->upDateTi = YES;
u->upDateTi = YES;
# endif
}
/* get down pass sequence if tree topology has changed */
if (topologyHasChanged == YES)
{
i = j = 0;
GetDownPassSeq (root[whichChain*2 + proposedState], proposedState, whichChain, numTaxa, &i, &j);
}
# if defined (DEBUG_LOCAL)
printf ("After:\n");
ShowNodes (root[whichChain*2+proposedState], 2, NO);
# endif
if (!strcmp(brlenprModel, "exponential"))
{
for (i=0; i<numNodes; i++)
{
p = allNodesDownPassSeq[whichChain*2*numNodes + proposedState*numNodes + i];
lnNewBrlenPr += log(brlenprExp) - brlenprExp * (p->length);
}
}
(*lnPriorRatio) = lnNewBrlenPr - lnOldBrlenPr;
# if defined (TOPOLOGY_MOVE_STATS)
if (topologyHasChanged == YES)
gTopologyHasChanged = YES;
else
gTopologyHasChanged = NO;
gNodeMoves = 1;
# endif
# if defined (SMART_TI_PROBS)
//UpDateAllTIs (proposedState, whichChain);
# endif
return (NO_ERROR);
}
/* change branch lengths and topology (potentially) using BAMBE's LOCAL (rooted with calibrations) */
int Move_ChangeTimeClockWithLocal (int numTaxa, int proposedState, int whichChain, long int *seed, double *lnProposalRatio, double *lnPriorRatio)
{
int i, j, isAtRoot, dID[3], dTemp, topologyHasChanged, forceAB;
double h[3], temp, maxTime1, maxTime2, minTime1, minTime2, x, y, ran, tuning,
lnNewBrlenPr, lnOldBrlenPr, *nt, rootTime, sR, eR, sF;
TreeNode *p, *q, *a, *b, *c, *u, *v, *w;
lnNewBrlenPr = lnOldBrlenPr = 0.0;
if (!strcmp(brlenprModel, "exponential"))
{
for (i=0; i<numNodes; i++)
{
q = allNodesDownPassSeq[whichChain*2*numNodes + proposedState*numNodes + i];
lnOldBrlenPr += log(brlenprExp) - brlenprExp * (q->length);
}
}
else if (!strcmp(brlenprModel, "birth-death"))
{
sR = spRate[whichChain*2 + proposedState];
eR = exRate[whichChain*2 + proposedState];
sF = samplingFraction;
/* allocate memory */
nt = (double *)malloc((size_t) (numTaxa-1) * sizeof(double));
if (!nt)
{
printf ("\n ERROR: Problem allocating nt\n");
return (ERROR);
}
/* get root time */
rootTime = root[whichChain*2+proposedState]->left->nodeTime;
/* put node times into vector */
j = 0;
for (i=0; i<numNodes; i++)
{
q = allNodesDownPassSeq[whichChain*2*numNodes + proposedState*numNodes + i];
if (q->left != NULL && q->right != NULL && q->anc != NULL)
{
nt[j] = q->nodeTime;
j++;
}
}
/* calculate probabilities of tree */
lnOldBrlenPr = (numTaxa-2)*log(sR);
for (i=0; i<numTaxa-2; i++)
{
lnOldBrlenPr += lnP1(nt[i], sR, eR, sF) - lnVt(rootTime, sR, eR, sF);
}
}
# if defined (DEBUG_LOCAL_TIME_CLOCK)
printf ("Before:\n");
ShowNodes (root[whichChain*2+proposedState], 2, YES);
# endif
/* set update flags to NO */
for (i=0; i<numNodes; i++)
{
p = allNodesDownPassSeq[whichChain*2*numNodes + proposedState*numNodes + i];
p->upDateCl = NO;
}
/* initialize proposal ratio */
(*lnProposalRatio) = 0.0;
/* pick an internal branch and assign pointers */
do
{
p = intNodeDownPassSeq[whichChain*2*numIntNodes + proposedState*numIntNodes + (int)(RandomNumber(seed)*numIntNodes)];
} while (p->anc->anc == NULL);
u = p;
v = u->anc;
if (u->anc->anc->anc == NULL)
isAtRoot = YES;
else
{
isAtRoot = NO;
w = v->anc;
}
a = u->left;
b = u->right;
if (v->left == u)
c = v->right;
else
c = v->left;
# if defined (DEBUG_LOCAL_TIME_CLOCK)
if (isAtRoot == NO)
printf ("u=%d v=%d w=%d (%d %d %d)\n", Dex2(u), Dex2(v), Dex2(w), Dex2(a), Dex2(b), Dex2(c));
else
printf ("u=%d v=%d (%d %d %d)\n", Dex2(u), Dex2(v), Dex2(a), Dex2(b), Dex2(c));
# endif
/* sort times of nodes a, b, and c */
h[0] = a->nodeTime;
h[1] = b->nodeTime;
h[2] = c->nodeTime;
dID[0] = 0;
dID[1] = 1;
dID[2] = 2;
if (h[0] < h[1])
{
temp = h[0];
h[0] = h[1];
h[1] = temp;
dTemp = dID[0];
dID[0] = dID[1];
dID[1] = dTemp;
}
if (h[0] < h[2])
{
temp = h[0];
h[0] = h[2];
h[2] = temp;
dTemp = dID[0];
dID[0] = dID[2];
dID[2] = dTemp;
}
if (h[1] < h[2])
{
temp = h[1];
h[1] = h[2];
h[2] = temp;
dTemp = dID[1];
dID[1] = dID[2];
dID[2] = dTemp;
}
# if defined (DEBUG_LOCAL_TIME_CLOCK)
printf ("%lf %lf %lf (%d %d %d)\n", h[0], h[1], h[2], dID[0], dID[1], dID[2]);
# endif
topologyHasChanged = NO;
/* no constraints or calibrations in area of move (except, v can be constrained) */
if (isAtRoot == NO)
{
/* at internal node of tree */
forceAB = NO;
maxTime1 = maxTime2 = w->nodeTime;
minTime1 = h[0];
minTime2 = h[1];
if (u->isConstrained == YES && u->isCalibrated == NO)
{
forceAB = YES;
if (a->nodeTime > b->nodeTime)
minTime1 = minTime2 = a->nodeTime;
else
minTime1 = minTime2 = b->nodeTime;
minTime2 = h[0];
}
else if (u->isCalibrated == YES)
{
forceAB = YES;
if (a->nodeTime > b->nodeTime)
minTime1 = minTime2 = a->nodeTime;
else
minTime1 = minTime2 = b->nodeTime;
minTime2 = h[0];
if (u->calTime[0] > minTime1)
minTime1 = minTime2 = u->calTime[0];
if (u->calTime[0] + u->calTime[1] < maxTime1)
maxTime1 = u->calTime[0] + u->calTime[1];
if (minTime2 < h[0])
minTime2 = h[0];
}
if (v->isCalibrated == YES)
{
if (v->calTime[0] > minTime2)
minTime2 = v->calTime[0];
if (v->calTime[0] + v->calTime[1] < maxTime2)
maxTime2 = v->calTime[0] + v->calTime[1];
if (maxTime1 > maxTime2)
maxTime1 = maxTime2;
}
x = RandomNumber(seed) * (maxTime1 - minTime1) + minTime1;
y = RandomNumber(seed) * (maxTime2 - minTime2) + minTime2;
if (x > y)
{
temp = x;
x = y;
y = temp;
}
if (x > minTime1 && forceAB == NO)
{
/* topology not forced */
ran = RandomNumber(seed);
if (ran < 0.333)
{
u->left = a;
u->right = c;
a->anc = c->anc = u;
if (v->left == u)
v->right = b;
else
v->left = b;
b->anc = v;
topologyHasChanged = YES;
}
else if (ran >= 0.333 && ran < 0.666)
{
u->left = b;
u->right = c;
b->anc = c->anc = u;
if (v->left == u)
v->right = a;
else
v->left = a;
a->anc = v;
topologyHasChanged = YES;
}
u->nodeTime = x;
v->nodeTime = y;
}
else
{
/* topology forced */
if (forceAB == NO)
{
if ((dID[1] == 0 && dID[2] == 2) || (dID[1] == 2 && dID[2] == 0))
{
u->left = a;
u->right = c;
a->anc = c->anc = u;
if (v->left == u)
v->right = b;
else
v->left = b;
b->anc = v;
topologyHasChanged = YES;
}
else if ((dID[1] == 1 && dID[2] == 2) || (dID[1] == 2 && dID[2] == 1))
{
u->left = b;
u->right = c;
b->anc = c->anc = u;
if (v->left == u)
v->right = a;
else
v->left = a;
a->anc = v;
topologyHasChanged = YES;
}
}
u->nodeTime = x;
v->nodeTime = y;
}
if (forceAB == NO)
{
if (u->nodeTime < c->nodeTime && x < h[0])
(*lnProposalRatio) += log(3.0);
else if (u->nodeTime > c->nodeTime && x > h[0])
(*lnProposalRatio) += log(1.0/3.0);
}
# if defined (DEBUG_LOCAL_TIME_CLOCK)
printf ("max1 = %lf max2 = %lf min = %lf %lf (%lf %lf)\n", maxTime1, maxTime2, minTime1, minTime2, x, y);
# endif
}
else
{
/* at root of tree */
forceAB = NO;
maxTime1 = maxTime2 = v->nodeTime;
minTime1 = h[0];
minTime2 = h[1];
tuning = timeTuneProp;
if (u->isCalibrated == NO && v->isCalibrated == NO)
{
y = minTime1 + (maxTime1 - minTime1) * exp(tuning*(RandomNumber(seed)-0.5));
(*lnProposalRatio) += log((y-minTime1) / (maxTime1-minTime1));
if (u->isConstrained == YES)
{
forceAB = YES;
minTime2 = minTime1;
}
x = minTime2 + RandomNumber(seed) * (y - minTime2);
}
else if (u->isCalibrated == YES && v->isCalibrated == NO)
{
forceAB = YES;
minTime2 = minTime1;
if (u->calTime[0] > minTime1)
minTime1 = minTime2 = u->calTime[0];
if (minTime1 > maxTime1)
{
printf ("\n ERROR: problem with order of nodes\n");
return (ERROR);
}
y = minTime1 + (maxTime1 - minTime1) * exp(tuning*(RandomNumber(seed)-0.5));
(*lnProposalRatio) += log((y-minTime1) / (maxTime1-minTime1));
if (u->calTime[0] + u->calTime[1] < y)
maxTime2 = u->calTime[0] + u->calTime[1];
else
maxTime2 = y;
x = minTime2 + RandomNumber(seed) * (maxTime2 - minTime2);
if (x > y)
{
temp = x;
x = y;
y = temp;
}
}
else if (u->isCalibrated == NO && v->isCalibrated == YES)
{
if (v->calTime[0] < minTime1)
minTime1 = v->calTime[0];
maxTime1 = v->calTime[0] + v->calTime[1];
y = minTime1 + RandomNumber(seed) * (maxTime1 - minTime1);
if (u->isConstrained == YES)
{
forceAB = YES;
minTime2 = minTime1;
}
maxTime2 = maxTime1;
x = minTime2 + RandomNumber(seed) * (maxTime2 - minTime2);
if (x > y)
{
temp = x;
x = y;
y = temp;
}
}
else if (u->isCalibrated == YES && v->isCalibrated == YES)
{
forceAB = YES;
minTime2 = minTime1;
if (u->calTime[0] > minTime1)
minTime1 = u->calTime[0];
maxTime1 = u->calTime[0] + u->calTime[1];
if (v->calTime[0] > minTime2)
minTime2 = v->calTime[0];
maxTime2 = v->calTime[0] + v->calTime[1];
x = minTime1 + RandomNumber(seed) * (maxTime1 - minTime1);
y = minTime2 + RandomNumber(seed) * (maxTime2 - minTime2);
if (x > y)
{
temp = x;
x = y;
y = temp;
}
}
if (x > minTime1 && forceAB == NO)
{
/* topology not forced */
ran = RandomNumber(seed);
if (ran < 0.333)
{
u->left = a;
u->right = c;
a->anc = c->anc = u;
if (v->left == u)
v->right = b;
else
v->left = b;
b->anc = v;
topologyHasChanged = YES;
}
else if (ran >= 0.333 && ran < 0.666)
{
u->left = b;
u->right = c;
b->anc = c->anc = u;
if (v->left == u)
v->right = a;
else
v->left = a;
a->anc = v;
topologyHasChanged = YES;
}
u->nodeTime = x;
v->nodeTime = y;
}
else
{
if (forceAB == NO)
{
/* topology forced to ac or bc */
if ((dID[1] == 0 && dID[2] == 2) || (dID[1] == 2 && dID[2] == 0))
{
u->left = a;
u->right = c;
a->anc = c->anc = u;
if (v->left == u)
v->right = b;
else
v->left = b;
b->anc = v;
topologyHasChanged = YES;
}
else if ((dID[1] == 1 && dID[2] == 2) || (dID[1] == 2 && dID[2] == 1))
{
u->left = b;
u->right = c;
b->anc = c->anc = u;
if (v->left == u)
v->right = a;
else
v->left = a;
a->anc = v;
topologyHasChanged = YES;
}
}
u->nodeTime = x;
v->nodeTime = y;
}
if (forceAB == NO)
{
if (u->nodeTime < c->nodeTime && x < h[2])
(*lnProposalRatio) += log(3.0);
else if (u->nodeTime > c->nodeTime && x > h[2])
(*lnProposalRatio) += log(1.0/3.0);
}
}
/* set update flags to YES */
p = u;
while (p->anc != NULL)
{
p->upDateCl = YES;
p = p->anc;
}
/* get down pass sequence */
if (topologyHasChanged == YES)
{
i = j = 0;
GetDownPassSeq (root[whichChain*2 + proposedState], proposedState, whichChain, numTaxa, &i, &j);
}
/* get branch lengths on tree */
//printf ("m = %lf\n", treeHeight[whichChain*2+proposedState]);
for (i=0; i<numNodes; i++)
{
p = allNodesDownPassSeq[whichChain*2*numNodes + proposedState*numNodes + i];
p->length = 0.0;
if (p->anc != NULL)
if (p->anc->anc != NULL)
p->length = (p->anc->nodeTime - p->nodeTime) * treeHeight[whichChain*2+proposedState];
if (p->length < 0.0)
{
printf ("\n ERROR: negative branch length\n");
ShowNodes (root[whichChain*2+proposedState], 2, YES);
return (ERROR);
}
if (p->length < BRLEN_EPSILON)
p->length = BRLEN_EPSILON;
}
# if defined (DEBUG_LOCAL_TIME_CLOCK)
printf ("After:\n");
ShowNodes (root[whichChain*2+proposedState], 2, YES);
# endif
if (!strcmp(brlenprModel, "exponential"))
{
for (i=0; i<numNodes; i++)
{
p = allNodesDownPassSeq[whichChain*2*numNodes + proposedState*numNodes + i];
lnNewBrlenPr += log(brlenprExp) - brlenprExp * (p->length);
}
}
else if (!strcmp(brlenprModel, "birth-death"))
{
/* get root time */
rootTime = root[whichChain*2+proposedState]->left->nodeTime;
/* put node times into vector */
j = 0;
for (i=0; i<numNodes; i++)
{
p = allNodesDownPassSeq[whichChain*2*numNodes + proposedState*numNodes + i];
if (p->left != NULL && p->right != NULL && p->anc != NULL)
{
nt[j] = p->nodeTime;
j++;
}
}
/* calculate probabilities of tree */
lnNewBrlenPr = (numTaxa-2)*log(sR);
for (i=0; i<numTaxa-2; i++)
{
lnNewBrlenPr += lnP1(nt[i], sR, eR, sF) - lnVt(rootTime, sR, eR, sF);
}
free (nt);
}
(*lnPriorRatio) = lnNewBrlenPr - lnOldBrlenPr;
/* TEMP */
//UpDateAllCls (proposedState, whichChain);
# if defined (TOPOLOGY_MOVE_STATS)
if (topologyHasChanged == YES)
gTopologyHasChanged = YES;
else
gTopologyHasChanged = NO;
gNodeMoves = 1;
# endif
# if defined (SMART_TI_PROBS)
/* NOTE: This could be made better, but this function probably will go, so don't bother. */
UpDateAllTIs (proposedState, whichChain);
# endif
return (NO_ERROR);
}
/* change topology using NNI */
int Move_ChangeNNI (int numTaxa, int proposedState, int whichChain, long int *seed)
{
int i, j;
TreeNode *p, *u, *v, *a, *b, *c;
/* pick an internal branch that is not constrained */
do
{
p = intNodeDownPassSeq[whichChain*2*numIntNodes + proposedState*numIntNodes + (int)(RandomNumber(seed)*numIntNodes)];
} while (p->anc->anc == NULL || p->isConstrained == YES);
/* set up area of rearrangement */
u = p;
v = u->anc;
a = u->left;
b = u->right;
if (v->left == u)
c = v->right;
else
c = v->left;
/* change topology */
if (RandomNumber(seed) < 0.5)
{
if (v->left == u)
v->right = b;
else
v->left = b;
u->left = a;
u->right = c;
a->anc = c->anc = u;
b->anc = v;
}
else
{
if (v->left == u)
v->right = a;
else
v->left = a;
u->left = b;
u->right = c;
b->anc = c->anc = u;
a->anc = v;
}
i = j = 0;
GetDownPassSeq (root[whichChain*2 + proposedState], proposedState, whichChain, numTaxa, &i, &j);
return (NO_ERROR);
}
int Move_ChangeNodeTime (int numTaxa, int proposedState, int whichChain, long int *seed, double *lnProposalRatio, double *lnPriorRatio)
{
int i, j, isRoot;
double minTime, maxTime, newT, oldT, tuning, lnNewBrlenPr, lnOldBrlenPr, *nt, rootTime, sR, eR, sF;
TreeNode *p, *q;
(*lnPriorRatio) = 0.0;
(*lnProposalRatio) = 0.0;
/* pick an internal branch */
do
{
p = intNodeDownPassSeq[whichChain*2*numIntNodes + proposedState*numIntNodes + (int)(RandomNumber(seed)*numIntNodes)];
} while (p->anc->anc == NULL);
isRoot = NO;
if (p->anc->anc == NULL)
isRoot = YES;
oldT = p->nodeTime;
/* get prior probability of beginning branch lengths */
if (!strcmp(brlenprModel, "exponential"))
{
lnOldBrlenPr = log(brlenprExp) - brlenprExp * (p->left->length);
lnOldBrlenPr += log(brlenprExp) - brlenprExp * (p->right->length);
lnOldBrlenPr += log(brlenprExp) - brlenprExp * (p->length);
}
else if (!strcmp(brlenprModel, "birth-death"))
{
sR = spRate[whichChain*2 + proposedState];
eR = exRate[whichChain*2 + proposedState];
sF = samplingFraction;
/* allocate memory */
nt = (double *)malloc((size_t) (numTaxa-1) * sizeof(double));
if (!nt)
{
printf ("\n ERROR: Problem allocating nt\n");
return (ERROR);
}
/* get root time */
rootTime = root[whichChain*2+proposedState]->left->nodeTime;
/* put node times into vector */
j = 0;
for (i=0; i<numNodes; i++)
{
q = allNodesDownPassSeq[whichChain*2*numNodes + proposedState*numNodes + i];
if (q->left != NULL && q->right != NULL && q->anc != NULL)
{
nt[j] = q->nodeTime;
j++;
}
}
/* calculate probabilities of tree */
lnOldBrlenPr = (numTaxa-2)*log(sR);
for (i=0; i<numTaxa-2; i++)
{
lnOldBrlenPr += lnP1(nt[i], sR, eR, sF) - lnVt(rootTime, sR, eR, sF);
}
}
/* pick an upper and lower time for the node */
if (p->left->nodeTime > p->right->nodeTime)
minTime = p->left->nodeTime;
else
minTime = p->right->nodeTime;
if (isRoot == NO)
{
maxTime = p->anc->nodeTime;
}
if (p->isCalibrated == YES)
{
if (p->calTime[0] > minTime)
minTime = p->calTime[0];
if (p->calTime[0] + p->calTime[1] < maxTime && isRoot == NO)
maxTime = p->calTime[0] + p->calTime[1];
}
/* choose new node time */
if (isRoot == NO)
{
newT = minTime + RandomNumber(seed) * (maxTime - minTime);
p->nodeTime = newT;
p->left->length = (p->nodeTime - p->left->nodeTime) * treeHeight[whichChain*2+proposedState];
p->right->length = (p->nodeTime - p->right->nodeTime) * treeHeight[whichChain*2+proposedState];
p->length = (p->anc->nodeTime - p->nodeTime) * treeHeight[whichChain*2+proposedState];
}
else
{
tuning = nodeTimeTuneProp;
newT = minTime + (maxTime - minTime) * exp(tuning*(RandomNumber(seed)-0.5));
p->nodeTime = newT;
p->left->length = (p->nodeTime - p->left->nodeTime) * treeHeight[whichChain*2+proposedState];
p->right->length = (p->nodeTime - p->right->nodeTime) * treeHeight[whichChain*2+proposedState];
(*lnProposalRatio) = log((newT-minTime) / (oldT - minTime));
}
/* get prior probability of ending branch lengths */
if (!strcmp(brlenprModel, "exponential"))
{
lnNewBrlenPr = log(brlenprExp) - brlenprExp * (p->left->length);
lnNewBrlenPr += log(brlenprExp) - brlenprExp * (p->right->length);
lnNewBrlenPr += log(brlenprExp) - brlenprExp * (p->length);
(*lnPriorRatio) = lnNewBrlenPr - lnOldBrlenPr;
}
else if (!strcmp(brlenprModel, "birth-death"))
{
/* get root time */
rootTime = root[whichChain*2+proposedState]->left->nodeTime;
/* put node times into vector */
j = 0;
for (i=0; i<numNodes; i++)
{
q = allNodesDownPassSeq[whichChain*2*numNodes + proposedState*numNodes + i];
if (q->left != NULL && q->right != NULL && q->anc != NULL)
{
nt[j] = q->nodeTime;
j++;
}
}
/* calculate probabilities of tree */
lnNewBrlenPr = (numTaxa-2)*log(sR);
for (i=0; i<numTaxa-2; i++)
{
lnNewBrlenPr += lnP1(nt[i], sR, eR, sF) - lnVt(rootTime, sR, eR, sF);
}
(*lnPriorRatio) = lnNewBrlenPr - lnOldBrlenPr;
free (nt);
}
/* update conditional likelihoods */
p->upDateCl = YES;
while (p->anc != NULL)
{
p->upDateCl = YES;
p = p->anc;
}
/* TEMP */
//UpDateAllCls (proposedState, whichChain);
# if defined (SMART_TI_PROBS)
UpDateAllTIs (proposedState, whichChain); /* NOTE: This could be made better, but this function probably will go, so don't bother. */
# endif
return (NO_ERROR);
}
/* change omega */
int Move_ChangeOmega (int proposedState, int whichChain, long int *seed, double *lnPriorRatio)
{
double oldW, newW, ran, omegaSlide, minOmega, maxOmega;
minOmega = chainMins[CHANGE_OMEGA];
maxOmega = chainMaxs[CHANGE_OMEGA];
omegaSlide = omegaWinProp;
oldW = omega[whichChain*2 + proposedState];
ran = (RandomNumber(seed) * omegaSlide) - (omegaSlide/2.0);
newW = oldW + ran;
if (newW < minOmega)
newW = (minOmega - newW) + minOmega;
if (newW > maxOmega)
newW = maxOmega - (newW - maxOmega);
omega[whichChain*2 + proposedState] = newW;
/* set prior ratio */
if (!strcmp(qmatprModel, "exponential"))
(*lnPriorRatio) = (omegaprExp*oldW - omegaprExp*newW);
else if (!strcmp(qmatprModel, "uniform"))
(*lnPriorRatio) = 0.0;
UpDateAllCls (proposedState, whichChain);
# if defined (SMART_TI_PROBS)
UpDateAllTIs (proposedState, whichChain);
# endif
return (NO_ERROR);
}
/* change omega pi */
int Move_ChangeOmegaProbs (int proposedState, int whichChain, long int *seed, double *lnPriorRatio, double *lnProposalRatio)
{
int i;
double *dirichletParameters, *newPi, *oldPi, sum, alphaPi, priorPi, x, y;
dirichletParameters = (double *)malloc((size_t) (3 * sizeof(double)));
if (!dirichletParameters)
goto error_exit;
newPi = (double *)malloc((size_t) (3 * sizeof(double)));
if (!newPi)
goto error_exit;
oldPi = (double *)malloc((size_t) (3 * sizeof(double)));
if (!oldPi)
goto error_exit;
alphaPi = omegaAlphaProp;
priorPi = 3.0;
oldPi[0] = probPos[whichChain*2 + proposedState];
oldPi[1] = probPur[whichChain*2 + proposedState];
oldPi[2] = probNeu[whichChain*2 + proposedState];
dirichletParameters[0] = oldPi[0] * alphaPi;
dirichletParameters[1] = oldPi[1] * alphaPi;
dirichletParameters[2] = oldPi[2] * alphaPi;
DirichletRandomVariable (dirichletParameters, newPi, 3, seed);
sum = 0.0;
for (i=0; i<3; i++)
{
if (newPi[i] < 0.0001)
newPi[i] = 0.0001;
sum += newPi[i];
}
for (i=0; i<3; i++)
newPi[i] = newPi[i] / sum;
probPos[whichChain*2 + proposedState] = newPi[0];
probPur[whichChain*2 + proposedState] = newPi[1];
probNeu[whichChain*2 + proposedState] = newPi[2];
/* get proposal ratio */
sum = 0.0;
for (i=0; i<3; i++)
sum += newPi[i]*alphaPi;
x = LnGamma(sum);
for (i=0; i<3; i++)
x -= LnGamma(newPi[i]*alphaPi);
for (i=0; i<3; i++)
x += (newPi[i]*alphaPi-1.0)*log(oldPi[i]);
sum = 0.0;
for (i=0; i<3; i++)
sum += oldPi[i]*alphaPi;
y = LnGamma(sum);
for (i=0; i<3; i++)
y -= LnGamma(oldPi[i]*alphaPi);
for (i=0; i<3; i++)
y += (oldPi[i]*alphaPi-1.0)*log(newPi[i]);
(*lnProposalRatio) = x - y;
/* get prior ratio */
x = LnGamma(priorPi);
for (i=0; i<3; i++)
x -= LnGamma(0.33333*priorPi);
for (i=0; i<3; i++)
x += (0.33333*priorPi-1.0)*log(newPi[i]);
y = LnGamma(priorPi);
for (i=0; i<3; i++)
y -= LnGamma(0.33333*priorPi);
for (i=0; i<3; i++)
y += (0.33333*priorPi-1.0)*log(oldPi[i]);
(*lnPriorRatio) = x - y;
UpDateAllCls (proposedState, whichChain);
# if defined (SMART_TI_PROBS)
if (!strcmp(codonModelType, "covny98"))
UpDateAllTIs (proposedState, whichChain);
# endif
free (dirichletParameters);
free (newPi);
free (oldPi);
return (NO_ERROR);
error_exit:
free (dirichletParameters);
free (newPi);
free (oldPi);
return (ERROR);
}
/* change proportion of invariant sites */
int Move_ChangePropInv (int proposedState, int whichChain, long int *seed, double *lnPriorRatio)
{
double oldP, newP, ran, pSlide, minP, maxP;
minP = 0.0;
maxP = 1.0;
pSlide = invSlideProp;
oldP = invP[whichChain*2 + proposedState];
ran = (RandomNumber(seed) * pSlide) - (pSlide/2.0);
newP = oldP + ran;
if (newP < minP)
newP = (minP - newP) + minP;
if (newP > maxP)
newP = maxP - (newP - maxP);
invP[whichChain*2 + proposedState] = newP;
(*lnPriorRatio) = 0.0;
UpDateAllCls (proposedState, whichChain);
# if defined (SMART_TI_PROBS)
UpDateAllTIs (proposedState, whichChain);
# endif
return (NO_ERROR);
}
int Move_ChangeTreeHeight (int proposedState, int whichChain, long int *seed, double *lnProposalRatio)
{
double tuning, oldM, newM;
tuning = mTuneProp;
oldM = treeHeight[whichChain*2+proposedState];
newM = oldM * exp(tuning*(RandomNumber(seed)-0.5));
treeHeight[whichChain*2+proposedState] = newM;
(*lnProposalRatio) = log(newM / oldM);
UpDateAllCls (proposedState, whichChain);
# if defined (SMART_TI_PROBS)
UpDateAllTIs (proposedState, whichChain);
# endif
return (NO_ERROR);
}
/* change branch lengths and topology (potentially) using the growing worm mechanism (unrooted) */
int Move_SingleWorm (int numTaxa, int proposedState, int whichChain, long int *seed, double *lnProposalRatio, double *lnPriorRatio)
{
int i, j, n, numBackbone, numExtendable, numDanglies, whichAnchor, isDanglyUp;
double ran, oldM, newM, tuning, extensionProb, newPoint, sum, lnNewBrlenPr, lnOldBrlenPr;
TreeNode *p, *q, *r, *a, *aa, *b, *c, *d, **backbone, *extendable[4], **danglies, *anchors[2];
lnNewBrlenPr = lnOldBrlenPr = 0.0;
if (!strcmp(brlenprModel, "exponential"))
{
for (i=0; i<numNodes; i++)
{
p = allNodesDownPassSeq[whichChain*2*numNodes + proposedState*numNodes + i];
lnOldBrlenPr += log(brlenprExp) - brlenprExp * (p->length);
}
}
extensionProb = extendPProp;
tuning = wormTuneProp;
for (i=0; i<numNodes; i++)
{
p = allNodesDownPassSeq[whichChain*2*numNodes + proposedState*numNodes + i];
p->upDateCl = NO;
p->marked = NO;
# if defined (TOPOLOGY_MOVE_STATS)
p->flag = NO;
# endif
}
# if defined (SHOW_MOVE_WORM)
printf ("Before:\n");
ShowNodes (root[whichChain*2+proposedState], 2, NO);
# endif
(*lnProposalRatio) = 0.0;
backbone = (TreeNode **)malloc((size_t) (numNodes) * sizeof(TreeNode *));
if (!backbone)
{
printf ("Could not allocate backbone (%d)\n", sizeof(TreeNode *) * (numNodes));
return (ERROR);
}
danglies = (TreeNode **)malloc((size_t) (numNodes) * sizeof(TreeNode *));
if (!danglies)
{
printf ("Could not allocate danglies (%d)\n", sizeof(TreeNode *) * (numNodes));
free (backbone);
return (ERROR);
}
for (i=0; i<numIntNodes; i++)
{
backbone[i] = NULL;
danglies[i] = NULL;
}
/* pick an internal node to start with */
p = intNodeDownPassSeq[whichChain*2*numIntNodes + proposedState*numIntNodes + (int)(RandomNumber(seed)*numIntNodes)];
# if defined (SHOW_MOVE_WORM)
printf ("Starting node = %d\n", p->index);
# endif
backbone[0] = p;
numBackbone = 1;
numExtendable = 0;
if (IsLeaf(p->anc) == NO)
extendable[numExtendable++] = p->anc;
if (IsLeaf(p->left) == NO)
extendable[numExtendable++] = p->left;
if (IsLeaf(p->right) == NO)
extendable[numExtendable++] = p->right;
backbone[0]->marked = YES;
# if defined (SHOW_MOVE_WORM)
printf (" %d -- ", numExtendable);
for (i=0; i<numExtendable; i++)
printf ("%d ", extendable[i]->index);
printf ("\n");
# endif
/* get backbone */
while (RandomNumber(seed) < extensionProb && numExtendable >= 1)
{
p = extendable[(int)(RandomNumber(seed) * numExtendable)];
backbone[numBackbone] = p;
p->marked = YES;
numBackbone++;
# if defined (SHOW_MOVE_WORM)
printf ("extended backbone to %d\n", p->index);
# endif
numExtendable = 0;
for (i=0; i<numBackbone; i++)
{
# if defined (SHOW_MOVE_WORM)
printf (" at backbone %d (%d) %d%d%d\n", backbone[i]->index, NumAdjacentMarked (backbone[i]), backbone[i]->left->marked, backbone[i]->right->marked, backbone[i]->anc->marked);
# endif
if (NumAdjacentMarked (backbone[i]) == 1)
{
if (backbone[i]->anc->marked == NO && IsLeaf(backbone[i]->anc) == NO)
extendable[numExtendable++] = backbone[i]->anc;
if (backbone[i]->left->marked == NO && IsLeaf(backbone[i]->left) == NO)
extendable[numExtendable++] = backbone[i]->left;
if (backbone[i]->right->marked == NO && IsLeaf(backbone[i]->right) == NO)
extendable[numExtendable++] = backbone[i]->right;
}
}
# if defined (SHOW_MOVE_WORM)
printf (" %d -- ", numExtendable);
for (i=0; i<numExtendable; i++)
printf ("%d ", extendable[i]->index);
printf ("\n");
# endif
}
/* get anchors and danglies */
numDanglies = 0;
whichAnchor = 0;
for (i=0; i<numBackbone; i++)
{
p = backbone[i];
n = NumAdjacentMarked (p);
if (n == 0)
{
ran = RandomNumber(seed);
if (ran < 0.3333)
{
anchors[0] = p->left;
anchors[1] = p->right;
danglies[numDanglies++] = p->anc;
}
else if (ran >= 0.3333 && ran < 0.6666)
{
anchors[0] = p->anc;
anchors[1] = p->right;
danglies[numDanglies++] = p->left;
}
else
{
anchors[0] = p->left;
anchors[1] = p->anc;
danglies[numDanglies++] = p->right;
}
}
else if (n == 1)
{
numExtendable = 0;
if (p->anc->marked == NO)
extendable[numExtendable++] = p->anc;
if (p->left->marked == NO)
extendable[numExtendable++] = p->left;
if (p->right->marked == NO)
extendable[numExtendable++] = p->right;
if (RandomNumber(seed) < 0.5)
{
anchors[whichAnchor++] = extendable[0];
danglies[numDanglies++] = extendable[1];
}
else
{
anchors[whichAnchor++] = extendable[1];
danglies[numDanglies++] = extendable[0];
}
}
else if (n == 2)
{
if (p->anc->marked == NO)
danglies[numDanglies++] = p->anc;
else if (p->left->marked == NO)
danglies[numDanglies++] = p->left;
else if (p->right->marked == NO)
danglies[numDanglies++] = p->right;
else
{
printf ("ERROR: Should have at least one dangly!\n");
free (backbone);
free (danglies);
return (ERROR);
}
}
else
{
printf ("ERROR: Too many marked neighbors!\n");
free (backbone);
free (danglies);
return (ERROR);
}
}
/* add the anchors to the backbone */
backbone[numBackbone++] = anchors[0];
backbone[numBackbone++] = anchors[1];
# if defined (SHOW_MOVE_WORM)
printf ("Backbone and danglies:\n");
printf (" %d -- ", numBackbone);
for (i=0; i<numBackbone; i++)
printf ("%d ", backbone[i]->index);
printf ("\n");
printf (" %d -- ", numDanglies);
for (i=0; i<numDanglies; i++)
printf ("%d ", danglies[i]->index);
printf ("\n");
# endif
/* get path length */
oldM = 0;
for (i=0; i<numBackbone; i++)
if (IsKink(backbone[i]) == NO)
oldM += backbone[i]->length;
# if defined (SMART_TI_PROBS)
for (i=0; i<numBackbone; i++)
if (IsKink(backbone[i]) == NO)
backbone[i]->upDateTi = YES;
# endif
/* change path length */
ran = RandomNumber(seed);
newM = oldM * exp(tuning * (ran - 0.5));
for (i=0; i<numBackbone; i++)
if (IsKink(backbone[i]) == NO)
backbone[i]->length *= (newM/oldM);
/* calculate proposal ratio */
(*lnProposalRatio) += 2.0 * (log(newM) - log(oldM));
/* pick a dangly to detach */
p = danglies[(int)(RandomNumber(seed)*numDanglies)];
/* pick a new attachment point */
newPoint = RandomNumber(seed) * newM;
sum = 0.0;
for (i=0; i<numBackbone; i++)
{
if (IsKink(backbone[i]) == NO)
{
sum += backbone[i]->length;
if (sum > newPoint)
r = backbone[i];
}
}
/* see if chosen dangly is up or down with reference to the backbone */
if (p->anc == NULL)
isDanglyUp = NO;
else
{
if (p->anc->marked == YES)
isDanglyUp = YES;
else
isDanglyUp = NO;
}
# if defined (SHOW_MOVE_WORM)
printf ("Dangly to detach = %d\n", p->index);
printf ("New attachment pt = %d\n", r->index);
printf ("isDanglyUp = %d\n", isDanglyUp);
# endif
# if defined (TOPOLOGY_MOVE_STATS)
gNodeMoves = 0;
if (isDanglyUp == YES)
a = p->anc;
else
a = p;
while (a->anc != NULL)
{
a = a->anc;
a->flag = YES;
gNodeMoves++;
}
a = r;
while (a->anc != NULL)
{
if (a->anc->left == a)
q = a->anc->right;
else
q = a->anc->left;
a = a->anc;
if (a->flag == NO && a != p)
gNodeMoves++;
else if (a->anc == NULL) // root; q == NULL
gNodeMoves--;
else if (a->flag == YES && q->flag != YES)
gNodeMoves--;
}
# endif
/* adjust topology */
if (isDanglyUp == YES)
{
/* dangly is up */
a = p->anc;
aa = a->anc;
if (a->left == p)
q = a->right;
else
q = a->left;
if (aa->left == a)
aa->left = q;
else
aa->right = q;
q->anc = aa;
q->length += a->length;
a->anc = NULL;
# if defined (SMART_TI_PROBS)
q->upDateTi = YES;
# endif
aa = r->anc;
if (aa->left == r)
aa->left = a;
else
aa->right = a;
a->anc = aa;
r->anc = a;
p->anc = a;
a->left = r;
a->right = p;
ran = RandomNumber(seed) * r->length;
a->length = r->length - ran;
r->length = ran;
# if defined (SMART_TI_PROBS)
r->upDateTi = YES;
a->upDateTi = YES;
# endif
}
else
{
/* dangly is down */
if (p->anc != NULL)
{
if (p->left->marked == YES && p->right->marked == NO)
p = p->left;
else if (p->left->marked == NO && p->right->marked == YES)
p = p->right;
else
{
printf ("ERROR: Problem determining dangly\n");
free (backbone);
free (danglies);
return (ERROR);
}
}
else
{
p = p->left;
}
for (i=0; i<numNodes; i++)
{
q = nodes + (whichChain*2*numNodes + proposedState*numNodes + i);
q->flag = NO;
}
q = r;
do
{
q->flag = YES;
q = q->anc;
} while (q->anc != NULL);
while (p->left != r && p->right != r)
{
if (p->left->flag == YES && p->right->flag == NO)
{
a = p->left;
c = p->right;
}
else if (p->left->flag == NO && p->right->flag == YES)
{
a = p->right;
c = p->left;
}
else
{
printf ("ERROR: Problem shifting tree!\n");
free (backbone);
free (danglies);
return (ERROR);
}
if (a->left == NULL || a->right == NULL)
{
printf ("ERROR: Problem trying to shift subtree to nonexistent branch\n");
free (backbone);
free (danglies);
return (ERROR);
}
if (a->left->flag == YES && a->right->flag == NO)
{
b = a->left;
d = a->right;
}
else if (a->left->flag == NO && a->right->flag == YES)
{
b = a->right;
d = a->left;
}
else
{
printf ("ERROR: Problem shifting tree!\n");
ShowNodes (root[whichChain*2+proposedState], 2, NO);
printf ("p = %d, a = %d r = %d c = %d \n", p->index, a->index, r->index, c->index);
for (i=0; i<numNodes; i++)
{
q = allNodesDownPassSeq[whichChain*2*numNodes + proposedState*numNodes + i];
printf ("%4d %d\n", q->index, q->flag);
}
for (i=0; i<numBackbone; i++)
printf ("%d ", backbone[i]->index);
printf ("\n");
free (backbone);
free (danglies);
return (ERROR);
}
p->left = a;
p->right = b;
a->left = c;
a->right = d;
a->anc = p;
b->anc = p;
c->anc = a;
d->anc = a;
c->length += a->length;
b->length /= 2.0;
a->length = b->length;
ran = RandomNumber(seed) * (a->length + b->length);
a->length = (a->length + b->length) - ran;
b->length = ran;
a->flag = NO;
# if defined (SMART_TI_PROBS)
c->upDateTi = YES;
b->upDateTi = YES;
a->upDateTi = YES;
# endif
}
}
i = j = 0;
GetDownPassSeq (root[whichChain*2+proposedState], proposedState, whichChain, numTaxa, &i, &j);
/* check for very small branches */
for (i=0; i<numNodes; i++)
{
p = allNodesDownPassSeq[whichChain*2*numNodes + proposedState*numNodes + i];
if (p->length < BRLEN_EPSILON)
p->length = BRLEN_EPSILON;
}
/* mark branches to update */
UpDateAllCls (proposedState, whichChain);
free (backbone);
free (danglies);
# if defined (SHOW_MOVE_WORM)
printf ("After:\n");
ShowNodes (root[whichChain*2+proposedState], 2, NO);
# endif
if (!strcmp(brlenprModel, "exponential"))
{
for (i=0; i<numNodes; i++)
{
p = allNodesDownPassSeq[whichChain*2*numNodes + proposedState*numNodes + i];
lnNewBrlenPr += log(brlenprExp) - brlenprExp * (p->length);
}
}
(*lnPriorRatio) = lnNewBrlenPr - lnOldBrlenPr;
# if defined (TOPOLOGY_MOVE_STATS)
if (gNodeMoves > 0)
gTopologyHasChanged = YES;
else
gTopologyHasChanged = NO;
# endif
return (NO_ERROR);
}
/* change switching rate for covarion model */
int Move_ChangeSwitchRate (int proposedState, int whichChain, long int *seed, double *lnPriorRatio)
{
int whichS;
double oldS, newS, ran, sSlide, minS, maxS, sum;
/* There are two rates for the covarion model. One rate is from on -> off and the other from off ->on.
The first rate (on -> off) is 0 and the other is 1 in the vectors, below */
minS = chainMins[CHANGE_SWITCH_RATE];
maxS = chainMaxs[CHANGE_SWITCH_RATE];
sSlide = switchWinProp;
# if 0
if (RandomNumber(seed) < 0.5)
whichS = 0;
else
whichS = 1;
if ((dataType == DNA || dataType == RNA) && enforceCodonModel == YES && !strcmp(codonModelType, "covny98"))
whichS = 0;
oldS = switchRate[whichChain*4 + proposedState*2 + whichS];
ran = (RandomNumber(seed) * sSlide) - (sSlide/2.0);
newS = oldS + ran;
if (newS < minS)
newS = (minS - newS) + minS;
if (newS > maxS)
newS = maxS - (newS - maxS);
switchRate[whichChain*4 + proposedState*2 + whichS] = newS;
# else
whichS = 0;
if ((dataType == DNA || dataType == RNA) && enforceCodonModel == YES && !strcmp(codonModelType, "covny98"))
whichS = 0;
oldS = switchRate[whichChain*4 + proposedState*2 + whichS];
ran = (RandomNumber(seed) * sSlide) - (sSlide/2.0);
newS = oldS + ran;
if (newS < minS)
newS = (minS - newS) + minS;
if (newS > maxS)
newS = maxS - (newS - maxS);
switchRate[whichChain*4 + proposedState*2 + whichS] = newS;
whichS = 1;
if ((dataType == DNA || dataType == RNA) && enforceCodonModel == YES && !strcmp(codonModelType, "covny98"))
{
whichS = 0;
}
else
{
oldS = switchRate[whichChain*4 + proposedState*2 + whichS];
ran = (RandomNumber(seed) * sSlide) - (sSlide/2.0);
newS = oldS + ran;
if (newS < minS)
newS = (minS - newS) + minS;
if (newS > maxS)
newS = maxS - (newS - maxS);
switchRate[whichChain*4 + proposedState*2 + whichS] = newS;
}
# endif
/* set stationary frequencies of on and off */
if ((dataType == DNA || dataType == RNA) && enforceCodonModel == YES && !strcmp(codonModelType, "covny98"))
{
if ((dataType == DNA || dataType == RNA) && enforceCodonModel == YES && !strcmp(codonModelType, "covny98"))
switchRate[whichChain*4 + proposedState*2 + 1] = newS;
}
else
{
sum = switchRate[whichChain*4 + proposedState*2 + 0] + switchRate[whichChain*4 + proposedState*2 + 1];
switchPi[whichChain*4 + proposedState*2 + 0] = switchRate[whichChain*4 + proposedState*2 + 1] / sum; /* stationary prob that it is on */
switchPi[whichChain*4 + proposedState*2 + 1] = switchRate[whichChain*4 + proposedState*2 + 0] / sum; /* stationary prob that it is off */
}
/* set switch prior ratio */
(*lnPriorRatio) = 0.0;
/* do this later */
UpDateAllCls (proposedState, whichChain);
# if defined (SMART_TI_PROBS)
UpDateAllTIs (proposedState, whichChain);
# endif
return (NO_ERROR);
}
/* change branch lengths and topology using SPR (unrooted, unconstrained, uncalibrated) */
int Move_ChangeUnrootedWithSPR (int numTaxa, int proposedState, int whichChain, long int *seed, double *lnProposalRatio, double *lnPriorRatio)
{
int i, j, stopLoop, nNodesSubTree1;
double v1, v2, v1a, v1b, v2a, v2b;
TreeNode *p, *q, *a, *b, *c, *d, *subRoot1, *subRoot2, **subTree1DP;
# if defined (DEBUG_SPR)
printf ("Before:\n");
ShowNodes (root[whichChain*2+proposedState], 2, NO);
# endif
subTree1DP = (TreeNode **)malloc(sizeof(TreeNode *) * 2 * numTaxa);
if (!subTree1DP)
{
printf ("\n ERROR: Could not allocate subTree1DP\n");
FreeMemory ();
return (ERROR);
}
for (i=0; i<numNodes; i++)
{
p = allNodesDownPassSeq[whichChain*2*numNodes + proposedState*numNodes + i];
p->upDateCl = NO;
}
/* pick a branch at random */
stopLoop = NO;
do
{
p = allNodesDownPassSeq[whichChain*2*numNodes + proposedState*numNodes + (int)(RandomNumber(seed)*numNodes)];
stopLoop = YES;
if (p->anc != NULL)
{
if (p->anc->anc == NULL)
stopLoop = NO;
}
} while (stopLoop == NO);
# if defined (TOPOLOGY_MOVE_STATS)
gNodeMoves = 0;
for (i=0; i<numNodes; i++)
{
a = allNodesDownPassSeq[whichChain*2*numNodes + proposedState*numNodes + i];
a->marked = NO;
}
a = p;
if (a->anc != NULL)
{
a = a->anc;
while (a->anc!=NULL)
{
a = a->anc;
a->marked = YES;
gNodeMoves++;
}
}
else
{
a = a->left;
while (a->left!=NULL)
{
a = a->left;
a->marked = YES;
gNodeMoves++;
}
}
# endif
/* now detach the chosen branch from the tree */
if (p->anc == NULL)
{
q = p->left;
v1 = q->left->length + q->right->length;
v1a = q->left->length;
v1b = q->right->length;
/* now shift tree such that that tip is sister to everyone else */
stopLoop = NO;
while (stopLoop == NO)
{
q = p->left;
a = q->left;
b = q->right;
a->upDateCl = YES;
# if defined (TOPOLOGY_MOVE_STATS)
a->marked = YES;
# endif
if (a->left != NULL && a->right != NULL)
{
c = a->left;
d = a->right;
q->left = c;
q->right = a;
c->anc = q;
a->anc = q;
a->left = d;
a->right = b;
d->anc = a;
b->anc = a;
b->length += a->length;
c->length *= 0.5;
a->length = c->length;
}
else
{
stopLoop = YES;
}
}
/* now reroot tree at left-most tip and detach old root */
p->left = q;
subRoot1 = q->left;
subRoot1->upDateCl = YES;
a = q->right;
a->anc = subRoot1;
subRoot1->left = a;
subRoot1->right = subRoot1->anc = NULL;
a->length += subRoot1->length;
subRoot1->length = 0.0;
subRoot2 = q;
subRoot2->left = p;
p->anc = subRoot2;
p->left = p->right = NULL;
subRoot2->right = subRoot2->anc = NULL;
subRoot2->upDateCl = p->upDateCl = YES;
}
else
{
q = p;
while (q->anc != NULL)
{
q->upDateCl = YES;
q = q->anc;
q->upDateCl = YES;
}
v1 = p->length;
v1a = p->anc->length;
if (p->anc->left == p)
v1b = p->anc->right->length;
else
v1b = p->anc->left->length;
subRoot1 = root[whichChain*2 + proposedState];
subRoot2 = p->anc;
if (subRoot2->left == p)
a = subRoot2->right;
else
a = subRoot2->left;
b = subRoot2->anc;
if (b->left == subRoot2)
b->left = a;
else
b->right = a;
a->anc = b;
a->length += subRoot2->length;
subRoot2->left = p;
subRoot2->right = subRoot2->anc = NULL;
subRoot2->length = 0.0;
}
/* We now have two subtrees. One is rooted at subRoot1. The other, which is the detached portion, is rooted
at subRoot2. We want to pick a branch at random on the tree rooted at subRoot1 and put subRoot2 on that
branch. */
i = 0;
GetTempDownPassSeq (subRoot1, &i, subTree1DP);
nNodesSubTree1 = i;
do
{
p = subTree1DP[(int)(RandomNumber(seed)*nNodesSubTree1)];
} while (p->anc == NULL);
v2 = p->length;
q = p->anc;
b = subRoot2->left;
if (q->left == p)
{
q->left = subRoot2;
subRoot2->left = p;
p->anc = subRoot2;
subRoot2->anc = q;
subRoot2->right = b;
}
else
{
q->right = subRoot2;
subRoot2->right = p;
p->anc = subRoot2;
subRoot2->anc = q;
subRoot2->left = b;
}
v2a = v2 * RandomNumber(seed);
v2b = v2 - v2a;
subRoot2->length = v2a;
p->length = v2b;
q = p;
q->upDateCl = YES;
while (q->anc != NULL)
{
q->upDateCl = YES;
q = q->anc;
q->upDateCl = YES;
}
/* get down pass sequence if tree topology has changed */
root[whichChain*2 + proposedState] = subRoot1;
i = j = 0;
GetDownPassSeq (root[whichChain*2 + proposedState], proposedState, whichChain, numTaxa, &i, &j);
/* get proposal and prior ratios */
(*lnProposalRatio) = log(v2) - log(v1);
(*lnPriorRatio) = 0.0;
if (!strcmp(brlenprModel, "exponential"))
{
(*lnPriorRatio) = (log(brlenprExp) - brlenprExp * (v1a)) + (log(brlenprExp) - brlenprExp * (v1b)) -
(log(brlenprExp) - brlenprExp * (v2a)) - (log(brlenprExp) - brlenprExp * (v2b));
}
//UpDateAllCls (proposedState, whichChain);
# if defined (DEBUG_SPR)
printf ("After:\n");
ShowNodes (root[whichChain*2+proposedState], 2, NO);
# endif
# if defined (TOPOLOGY_MOVE_STATS)
a = subRoot2;
while (a->anc!=NULL) {
if (a->anc->left == a)
b = a->anc->right;
else
b = a->anc->left;
a = a->anc;
if (a->marked == NO)
gNodeMoves++;
else if (a->anc == NULL)
gNodeMoves--;
else if (a->marked == YES && b->marked == NO)
gNodeMoves--;
}
if (gNodeMoves > 0)
gTopologyHasChanged = YES;
else
gTopologyHasChanged = NO;
# endif
# if defined (SMART_TI_PROBS)
// TO DO: Figure out exactly which branches need their transition matrices updated.
UpDateAllTIs (proposedState, whichChain);
# endif
free (subTree1DP);
return (NO_ERROR);
}
int Move_ChangeBD (int proposedState, int whichChain, long int *seed)
{
double oldEx, newEx, oldSp, newSp, ran, rateSlide, minExRate, minSpRate, maxExRate, maxSpRate;
rateSlide = bdWinProp;
minExRate = chainMins[CHANGE_BD_PARAMS];
maxExRate = chainMaxs[CHANGE_BD_PARAMS];
oldEx = exRate[whichChain*2 + proposedState];
ran = (RandomNumber(seed) * rateSlide) - (rateSlide/2.0);
newEx = oldEx + ran;
if (newEx < minExRate)
newEx = (minExRate - newEx) + minExRate;
if (newEx > maxExRate)
newEx = maxExRate - (newEx - maxExRate);
exRate[whichChain*2 + proposedState] = newEx;
minSpRate = exRate[whichChain*2 + proposedState];
maxSpRate = chainMaxs[CHANGE_BD_PARAMS];
oldSp = spRate[whichChain*2 + proposedState];
ran = (RandomNumber(seed) * rateSlide) - (rateSlide/2.0);
newSp = oldSp + ran;
if (newSp < minSpRate)
newSp = (minSpRate - newSp) + minSpRate;
if (newSp > maxSpRate)
newSp = maxSpRate - (newSp - maxSpRate);
spRate[whichChain*2 + proposedState] = newSp;
return (NO_ERROR);
}
/* Change branch lengths and possibly topology using probabilistic TBR branch swapping. */
int Move_ChangeTBR (int numTaxa, int proposedState, int whichChain, long int *seed, double *lnProposalRatio, double *lnPriorRatio)
{
int i, j, reconLimit, nMarkedAbove, nMarkedBelow, whichBranch, nVisited, stopLoop, hasTopologyChanged;
double tempLength, newLength, tuning, mult, forwardP, backwardP, oldM, newM, lnNewBrlenPr, lnOldBrlenPr;
TreeNode *p, *q, *u, *a, *b0, *b1, *b11, *b10;
# if defined (DEBUG_TBR)
printf ("Before:\n");
ShowNodes (root[whichChain*2+proposedState], 2, NO);
# endif
/* Set paramters of move. */
*lnProposalRatio = *lnPriorRatio = 0.0;
reconLimit = (int)reconLimProp;
tuning = wormTuneProp;
mult = exp(tuning*(RandomNumber(seed)-0.5));
forwardP = backwardP = 1.0;
oldM = newM = 0.0;
lnNewBrlenPr = lnOldBrlenPr = 0.0;
if (!strcmp(brlenprModel, "exponential"))
{
for (i=0; i<numNodes; i++)
{
p = allNodesDownPassSeq[whichChain*2*numNodes + proposedState*numNodes + i];
lnOldBrlenPr += log(brlenprExp) - brlenprExp * (p->length);
}
}
/* Set flags for updating conditional likelihoods to NO (meaning don't update CL). */
for (i=0; i<numNodes; i++)
{
p = allNodesDownPassSeq[whichChain*2*numNodes + proposedState*numNodes + i];
p->upDateCl = NO;
}
/* Pick a branch at random. This is the branch that is "removed". */
do
{
p = allNodesDownPassSeq[whichChain*2*numNodes + proposedState*numNodes + (int)(RandomNumber(seed)*numNodes)];
} while (p->anc == NULL);
q = p->anc;
oldM += p->length;
p->length *= mult;
newM += p->length;
/* Mark all branches with distance from removed branch (p). */
for (i=0; i<numNodes; i++)
{
u = allNodesDownPassSeq[whichChain*2*numNodes + proposedState*numNodes + i];
u->flag = -1;
u->marked = NO;
}
p->flag = 0;
for (i=numNodes-1; i>=0; i--)
{
u = allNodesDownPassSeq[whichChain*2*numNodes + proposedState*numNodes + i];
if (u != p && u != q && u->anc != NULL && u->flag == -1)
{
if (u->anc->flag >= 0)
u->flag = u->anc->flag + 1;
}
}
/* mark branches above p that are within reconnection limit of p */
nMarkedAbove = 0;
for (i=0; i<numNodes; i++)
{
u = allNodesDownPassSeq[whichChain*2*numNodes + proposedState*numNodes + i];
if (u != p && u->flag <= reconLimit && u->flag >= 0)
{
u->marked = YES;
nMarkedAbove++;
}
}
if (p->left != NULL && p->right != NULL)
{
if (p->right->marked == YES)
{
p->right->marked = NO;
nMarkedAbove--;
}
}
/* now pick one of the branches above p to be the new point of attachment */
if (nMarkedAbove > 0)
{
whichBranch = RandomNumber(seed) * nMarkedAbove;
nVisited = 0;
for (i=0; i<numNodes; i++)
{
u = allNodesDownPassSeq[whichChain*2*numNodes + proposedState*numNodes + i];
if (u->marked == YES)
{
if (whichBranch == nVisited)
break;
nVisited++;
}
}
a = u;
}
else
a = p;
/* update proposal probabilities */
if (nMarkedAbove > 0)
forwardP *= (1.0 / (double)(nMarkedAbove));
if (p->left != NULL && p->right != NULL)
backwardP *= 1.0 / (p->left->length + p->right->length);
/* rotate tree above p until a is just to the left or right of p */
for (i=0; i<numNodes; i++)
{
u = allNodesDownPassSeq[whichChain*2*numNodes + proposedState*numNodes + i];
u->marked = NO;
}
u = a;
u->marked = YES;
while (u != p && u->anc != NULL)
{
oldM += u->length;
u->length *= mult;
newM += u->length;
u->marked = YES;
u = u->anc;
}
if (a != p) /* update proposal */
forwardP *= 1.0 / (a->length); /* probabilities */
stopLoop = NO;
hasTopologyChanged = NO;
# if defined (TOPOLOGY_MOVE_STATS)
gNodeMoves = 0;
# endif
while (stopLoop == NO)
{
if (p->left != NULL && p->right != NULL)
{
if (p == a)
stopLoop = YES;
else if (p->left == a || p->right == a)
stopLoop = YES;
else
{
if (p->left->marked == YES)
{
b1 = p->left;
b0 = p->right;
}
else
{
b1 = p->right;
b0 = p->left;
}
if (b1->left != NULL && b1->right != NULL)
{
if (b1->left->marked == YES && b1->right->marked == NO)
{
b11 = b1->left;
b10 = b1->right;
}
else if (b1->left->marked == NO && b1->right->marked == YES)
{
b11 = b1->right;
b10 = b1->left;
}
else
{
b11 = b1->left;
b10 = b1->right;
}
}
else
stopLoop = YES;
if (stopLoop == NO)
{
if (p->right == b1)
{
p->left = b1;
p->right = b11;
b1->anc = b11->anc = p;
b1->left = b0;
b1->right = b10;
b0->anc = b10->anc = b1;
b0->length += b1->length;
tempLength = b11->length;
newLength = RandomNumber(seed) * tempLength;
b1->length = newLength;
b11->length = tempLength - newLength;
b1->marked = NO;
}
else
{
p->left = b11;
p->right = b1;
b1->anc = b11->anc = p;
b1->left = b0;
b1->right = b10;
b0->anc = b10->anc = b1;
b0->length += b1->length;
tempLength = b11->length;
newLength = RandomNumber(seed) * tempLength;
b1->length = newLength;
b11->length = tempLength - newLength;
b1->marked = NO;
}
hasTopologyChanged = YES;
# if defined (TOPOLOGY_MOVE_STATS)
gNodeMoves++;
# endif
}
}
}
else
stopLoop = YES;
}
# if defined (DEBUG_TBR)
for (i=0; i<numNodes; i++)
{
u = allNodesDownPassSeq[whichChain*2*numNodes + proposedState*numNodes + i];
printf ("%4d %d %d (p=%d q=%d)\n", u->index, u->flag, u->marked, p->index, q->index);
}
printf ("nMarkedAbove = %d, %d\n", nMarkedAbove, a->index);
printf ("Middle:\n");
ShowNodes (root[whichChain*2+proposedState], 2, NO);
# endif
/* update downpass sequence, if the topology has changed */
if (hasTopologyChanged == YES)
{
i = j = 0;
GetDownPassSeq (root[whichChain*2 + proposedState], proposedState, whichChain, numTaxa, &i, &j);
}
/* mark all branches with distance from removed branch (q) */
for (i=0; i<numNodes; i++)
{
u = allNodesDownPassSeq[whichChain*2*numNodes + proposedState*numNodes + i];
u->flag = -1;
u->marked = NO;
}
q->flag = 0;
u = q;
while (u->anc != NULL)
{
u->anc->flag = u->flag + 1;
u = u->anc;
}
for (i=numNodes-1; i>=0; i--)
{
u = allNodesDownPassSeq[whichChain*2*numNodes + proposedState*numNodes + i];
if (u != p && u != q && u->anc != NULL && u->flag == -1 && u->anc->flag >= 0)
{
u->flag = u->anc->flag + 1;
}
}
/* mark branches above q that are within reconnection limit of q */
nMarkedBelow = 0;
for (i=0; i<numNodes; i++)
{
u = allNodesDownPassSeq[whichChain*2*numNodes + proposedState*numNodes + i];
if (u != q && u->flag <= reconLimit && u->flag >= 0 && u->anc != NULL)
{
u->marked = YES;
nMarkedBelow++;
}
}
/* now pick one of the branches marked around q to be the new point of attachment */
if (nMarkedBelow > 0)
{
whichBranch = RandomNumber(seed) * nMarkedBelow;
nVisited = 0;
for (i=0; i<numNodes; i++)
{
u = allNodesDownPassSeq[whichChain*2*numNodes + proposedState*numNodes + i];
if (u->marked == YES)
{
if (whichBranch == nVisited)
break;
nVisited++;
}
}
a = u;
}
else
a = q;
/* update proposal probabilities */
if (nMarkedBelow > 0)
forwardP *= (1.0 / (double)(nMarkedBelow));
if (q->anc != NULL)
{
tempLength = q->length;
if (q->left == p)
tempLength += q->right->length;
else
tempLength += q->left->length;
backwardP *= 1.0 / tempLength;
}
if (a != q)
{
forwardP *= 1.0 / (a->length*mult);
}
/* multiply branches on path between a and q by mult */
for (i=0; i<numNodes; i++)
{
u = allNodesDownPassSeq[whichChain*2*numNodes + proposedState*numNodes + i];
u->marked = NO;
if (u == a || u == q)
u->marked = YES;
}
for (i=0; i<numNodes; i++)
{
u = allNodesDownPassSeq[whichChain*2*numNodes + proposedState*numNodes + i];
if (u->left != NULL && u->right != NULL)
{
if (u->left->marked == YES && u->right->marked == NO)
u->marked = YES;
else if (u->left->marked == NO && u->right->marked == YES)
u->marked = YES;
}
if (u->marked == YES)
{
# if defined (TOPOLOGY_MOVE_STATS)
if (u != q)
gNodeMoves++;
# endif
oldM += u->length;
u->length *= mult;
newM += u->length;
}
}
/* move q to new position at branch a */
if (q->anc == NULL || nMarkedBelow == 0)
{
/* don't do anything, as q is at the root of the tree */
}
else
{
if (q->left == p)
b1 = q->right;
else
b1 = q->left;
b0 = q->anc;
if (b0->left == q)
{
b0->left = b1;
b1->anc = b0;
b1->length += q->length;
q->length = 0.0;
q->anc = NULL;
}
else if (b0->right != NULL)
{
if (b0->right == q)
{
b0->right = b1;
b1->anc = b0;
b1->length += q->length;
q->length = 0.0;
q->anc = NULL;
}
else
{
printf ("problems in tbr\n");
}
}
if (a->anc == NULL)
printf ("problem in tbr\n");
else
{
b1 = a->anc;
if (b1->left == a)
b1->left = q;
else
b1->right = q;
q->anc = b1;
q->left = p;
q->right = a;
p->anc = a->anc = q;
tempLength = a->length;
newLength = tempLength * RandomNumber(seed);
a->length = newLength;
q->length = tempLength - newLength;
}
}
/* update downpass sequence */
i = j = 0;
GetDownPassSeq (root[whichChain*2 + proposedState], proposedState, whichChain, numTaxa, &i, &j);
/* update conditional likelihoods */
UpDateAllCls (proposedState, whichChain);
/* update proposal probabilities */
for (i=0; i<numNodes; i++)
{
u = allNodesDownPassSeq[whichChain*2*numNodes + proposedState*numNodes + i];
u->flag = -1;
u->marked = NO;
}
p->flag = 0;
for (i=numNodes-1; i>=0; i--)
{
u = allNodesDownPassSeq[whichChain*2*numNodes + proposedState*numNodes + i];
if (u != p && u != q && u->anc != NULL && u->flag == -1)
{
if (u->anc->flag >= 0)
u->flag = u->anc->flag + 1;
}
}
nMarkedAbove = 0;
for (i=0; i<numNodes; i++)
{
u = allNodesDownPassSeq[whichChain*2*numNodes + proposedState*numNodes + i];
if (u != p && u->flag <= reconLimit && u->flag >= 0)
{
u->marked = YES;
nMarkedAbove++;
}
}
if (p->left != NULL && p->right != NULL)
{
if (p->right->marked == YES)
{
p->right->marked = NO;
nMarkedAbove--;
}
}
for (i=0; i<numNodes; i++)
{
u = allNodesDownPassSeq[whichChain*2*numNodes + proposedState*numNodes + i];
u->flag = -1;
u->marked = NO;
}
q->flag = 0;
u = q;
while (u->anc != NULL)
{
u->anc->flag = u->flag + 1;
u = u->anc;
}
for (i=numNodes-1; i>=0; i--)
{
u = allNodesDownPassSeq[whichChain*2*numNodes + proposedState*numNodes + i];
if (u != p && u != q && u->anc != NULL && u->flag == -1 && u->anc->flag >= 0)
{
u->flag = u->anc->flag + 1;
}
}
nMarkedBelow = 0;
for (i=0; i<numNodes; i++)
{
u = allNodesDownPassSeq[whichChain*2*numNodes + proposedState*numNodes + i];
if (u != q && u->flag <= reconLimit && u->flag >= 0 && u->anc != NULL)
{
u->marked = YES;
nMarkedBelow++;
}
}
if (nMarkedAbove > 0)
backwardP *= (1.0 / (double)nMarkedAbove);
if (nMarkedBelow > 0)
backwardP *= (1.0 / (double)nMarkedBelow);
forwardP *= oldM;
backwardP *= newM;
*lnProposalRatio = log(backwardP) - log(forwardP);
//printf ("%lf %lf \n", log(backwardP), log(forwardP));
# if defined (DEBUG_TBR)
for (i=0; i<numNodes; i++)
{
u = allNodesDownPassSeq[whichChain*2*numNodes + proposedState*numNodes + i];
printf ("%4d %d %d (p=%d q=%d)\n", u->index, u->flag, u->marked, p->index, q->index);
}
printf ("nMarkedBelow = %d, %d\n", nMarkedBelow, a->index);
printf ("End:\n");
ShowNodes (root[whichChain*2+proposedState], 2, NO);
//exit (0);
# endif
if (!strcmp(brlenprModel, "exponential"))
{
for (i=0; i<numNodes; i++)
{
p = allNodesDownPassSeq[whichChain*2*numNodes + proposedState*numNodes + i];
lnNewBrlenPr += log(brlenprExp) - brlenprExp * (p->length);
}
}
(*lnPriorRatio) = lnNewBrlenPr - lnOldBrlenPr;
# if defined (TOPOLOGY_MOVE_STATS)
if (hasTopologyChanged == YES)
gTopologyHasChanged = YES;
else
gTopologyHasChanged = NO;
# endif
# if defined (SMART_TI_PROBS)
// TO DO: Figure out exactly which branches need their transition matrices updated.
UpDateAllTIs (proposedState, whichChain);
# endif
return (NO_ERROR);
}
/* change branch lengths and topology (potentially) using TBR (unrooted) */
int Move_ChangeFTBR (int numTaxa, int proposedState, int whichChain, long int *seed, double *lnProposalRatio, double *lnPriorRatio)
{
/* this move type picks a branch and two "danglies", modifies their length
independently according to the method of Larget & Simon (1999: MBE); it then
moves the danglies away from their original position one node at a time with
a probability determined by the extensionProb parameter
when the danglies are moved, their direction is changed
this "reflection" is necessary to enable the back move
As of 5 March 2001 06:00 the move type has been tested extensively
on unrooted and unconstrained trees (replicase.nex and adh.nex) and gives
similar results to BAMBE's local
However, convergence in branch lengths may be slow unless it is combined
with a move that changes single branchlengths or the proportionality of
adjacent branches, like BAMBE's local
The move type should work also for rooted or constrained trees
*/
int i, j, topologyHasChanged, nCrownNodes, nRootNodes, directionLeft, directionUp;
int allNodesPointer, intNodePointer, allNodesStop;
double m, x, y, tuning, maxV, extensionProb;
TreeNode *p, *a, *b, *c, *d, *u, *v;
// these parameters should be possible to set by user
extensionProb = tbrExtendPProp; // extension probability
tuning = tbrTuneProp; /* Larget & Simon's tuning parameter lambda */
// max brlen
maxV = chainMaxs[CHANGE_UNROOT_LOCAL];
topologyHasChanged = NO;
// set pointers
allNodesPointer = whichChain*2*numNodes + proposedState*numNodes;
intNodePointer = whichChain*2*numIntNodes + proposedState*numIntNodes;
allNodesStop = allNodesPointer + numNodes;
// unmark all nodes with respect to update
for (i=allNodesPointer; i<allNodesStop; i++)
{
p = allNodesDownPassSeq[i];
p->upDateCl = NO;
}
# if defined (DEBUG_FTBR)
printf ("Before:\n");
ShowNodes (root[whichChain*2+proposedState], 2, NO);
getchar();
# endif
/* pick an internal branch */
do
{
p = intNodeDownPassSeq[intNodePointer + (int)(RandomNumber(seed)*numIntNodes)];
} while (p->anc->anc == NULL);
/* set up pointers for nodes around the picked branch */
/* cut the tree into crown, root and attachment part */
/* change the relevant lengths in the attachment part */
/* the lengths of a and v are automatically contained in the */
/* "attachment" part but the length of c has to be stored in x */
v = p;
u = p->anc;
/* set up pointers for crown part */
/* this also determines direction of move in crown part */
if (RandomNumber(seed) < 0.5)
{
c = v->left;
d = v->right;
directionLeft = YES;
}
else
{
c = v->right;
d = v->left;
directionLeft = NO;
}
/* cut and reconnect crown part */
c->anc = d;
d->anc = c;
/* record c length and adjust */
m = c->length;
x = c->length * exp(tuning * (RandomNumber(seed) - 0.5)); // save the modified dangling branch for later use
if (x < BRLEN_EPSILON)
x = BRLEN_EPSILON;
if (x > maxV)
x = maxV;
/* calculate proposal and prior ratio based on length modification */
(*lnProposalRatio) = (log(x) - log(m));
if (!strcmp(brlenprModel, "exponential"))
(*lnPriorRatio) += brlenprExp * m - brlenprExp * x;
/* record v length and adjust */
m = v->length;
v->length *= exp(tuning * (RandomNumber(seed) - 0.5));
if (v->length < BRLEN_EPSILON)
v->length = BRLEN_EPSILON;
if (v->length > maxV)
v->length = maxV;
/* adjust proposal and prior ratio based on length modification */
(*lnProposalRatio) += (log(v->length) - log(m));
if (!strcmp(brlenprModel, "exponential"))
(*lnPriorRatio) += brlenprExp * m - brlenprExp * v->length;
/* mark nodes in root part */
/* also determines direction of move in root part */
if (RandomNumber(seed) < 0.5)
{
if (u->left == v)
a = u->right;
else
a = u->left;
b = u->anc;
directionUp = YES;
}
else
{
if (u->left == v)
b = u->right;
else
b = u->left;
a = u->anc;
directionUp = NO;
}
/* cut root part*/
/* store branch to be modified in u->length */
if (directionUp == NO)
{
b->anc = a;
if (a->left == u)
a->left = b;
else
a->right = b;
}
else
{
a->anc = b;
if (b->left == u)
b->left = a;
else
b->right = a;
y = a->length;
a->length = u->length;
u->length = y;
}
/* adjust length of branch to be modified */
/* if it is not the root branch of a rooted tree */
if (!(treeModel == ROOTED && u->anc->anc == NULL))
{
m = u->length;
u->length *= exp(tuning * (RandomNumber(seed) - 0.5));
if (u->length < BRLEN_EPSILON)
u->length = BRLEN_EPSILON;
if (u->length > maxV)
u->length = maxV;
/* adjust proposal and prior ratio based on length modification */
(*lnProposalRatio) += (log(u->length) - log(m));
if (!strcmp(brlenprModel, "exponential"))
(*lnPriorRatio) += brlenprExp * m - brlenprExp * u->length;
}
// adjust proposal ratio for backward move in root subtree
// if starting from interior, unconstrained branch
// double test needed to capture the case of no move
if (directionUp == NO && b->left!=NULL && b->isConstrained == NO &&
a->anc!=NULL && a->isConstrained == NO)
(*lnProposalRatio) += log(1-extensionProb);
if (directionUp == YES && a->left!=NULL && a->isConstrained == NO &&
b->anc!=NULL && b->isConstrained == NO)
(*lnProposalRatio) += log(1-extensionProb);
// adjust proposal ratio for backward move in crown subtree
// if starting from interior, unconstrained branch
// double test is needed to capture the case of no move
if (c->left!=NULL && c->isConstrained == NO &&
d->left!=NULL && d->isConstrained == NO)
(*lnProposalRatio) += log(1-extensionProb);
// move around in root subtree
nRootNodes = 0;
if (u->isConstrained == NO)
{
for (; RandomNumber(seed)<extensionProb; nRootNodes++)
{
if (directionUp == YES)
{ //going up tree
if (a->left == NULL || a->isConstrained == YES)
break; /* can't go further */
topologyHasChanged = YES;
b = a;
if (RandomNumber(seed)<0.5)
a = a->left;
else
a = a->right;
}
else
{ // going down tree
if (a->anc == NULL || a->isConstrained == YES)
break; /*can't go further */
topologyHasChanged = YES;
if (RandomNumber(seed)<0.5)
{
directionUp = YES; // switch direction
// find sister of a
if (a->left == b)
{
b = a;
a = a->right;
}
else
{
b = a;
a = a->left;
}
// as long as we are moving upwards
// the cond likes to update will be
// flagged by the last pass from u to the root
}
else
{ // continue down
b = a;
a = a->anc;
b->upDateCl = YES;
}
}
}
}
// adjust proposal ratio for forward move if stop branch is interior & unconstrained
// test of both ends makes sure that no adjustment is made if no move was made
if (directionUp == YES)
{
if (a->left != NULL && a->isConstrained == NO &&
b->anc != NULL && b->isConstrained == NO)
(*lnProposalRatio) -= log(1-extensionProb);
}
else
{
if (a->anc != NULL && a->isConstrained == NO &&
b->left != NULL && b->isConstrained == NO)
(*lnProposalRatio) -= log(1-extensionProb);
}
// move around in crown subtree
nCrownNodes = 0;
if (v->isConstrained == NO)
{
for (; RandomNumber(seed)<extensionProb; nCrownNodes++)
{
if (c->left == NULL || c->isConstrained == YES)
break; /* can't go further */
topologyHasChanged = YES;
if (RandomNumber(seed)<0.5)
{
// rotate c anticlockwise - prepare pointers for move left
c->anc = c->left; // the root will be in the direction we are heading
c->left = c->right;
c->right = d;
}
else
{
// rotate c clockwise - prepare pointers for move right
c->anc = c->right; // the root will be in the direction we are heading
c->right = c->left;
c->left = d;
}
/* OK - let's move!; c->anc points in the right direction
don't forget to move the branch lengths as well */
d = c;
c = c->anc;
d->length = c->length;
d->upDateCl = YES;
}
}
// adjust proposal ratio for forward move if stop branch is interior & unconstrained
// double test makes sure that no adjustment is made if no move was made
if (c->left != NULL && c->isConstrained == NO &&
d->left != NULL && d->isConstrained == NO)
(*lnProposalRatio) -= log(1-extensionProb);
// combine the subtrees
c->anc = v;
d->anc = v;
if (directionLeft == YES)
{
v->left = c;
v->right = d;
}
else
{
v->left = d;
v->right = c;
}
// the dangling branch is inserted in reverted position
// such that the back move will be possible
// if we have moved around in crown subtree
// otherwise it is left in its original position
if (nCrownNodes > 0)
d->length = x;
else
c->length = x;
if (directionUp == YES)
{
u->anc = b;
if (u->left == v)
u->right = a;
else
u->left = a;
a->anc = u;
if (b->left == a)
b->left = u;
else
b->right = u;
/* the dangling branch is contained in u->length
and will automatically be inserted in the right position
to enable the back move regardless of whether it was
initially directed upwards or downwards
BUT if we haven't moved in root subtree, it is advantageous (necessary
for rooted trees) to avoid switching branches, which occurs otherwise */
// if directionUp == YES
if (nRootNodes == 0)
{
x = u->length;
u->length = a->length;
a->length = x;
}
}
else
{
u->anc = a;
if (u->left == v)
u->right = b;
else
u->left = b;
b->anc = u;
if (a->left == b)
a->left = u;
else
a->right = u;
/* the modified branch contained in u->length will have
to be moved to b->length to enable back move
BUT if we haven't moved, it is better to keep it in place
(necessary for rooted trees) */
if (nRootNodes > 0)
{
x = u->length;
u->length = b->length;
b->length = x;
}
}
/* set flags for update of cond likes from v and down to root */
p = v;
while (p->anc != NULL)
{
p->upDateCl = YES;
p = p->anc;
}
/* get down pass sequence if tree topology has changed */
if (topologyHasChanged == YES)
{
i = j = 0;
GetDownPassSeq (root[whichChain*2 + proposedState], proposedState, whichChain, numTaxa, &i, &j);
}
# if defined (DEBUG_FTBR)
printf ("After:\n");
ShowNodes (root[whichChain*2+proposedState], 2, NO);
getchar();
printf ("Proposal ratio: %f\n",(*lnProposalRatio));
printf ("v: %d u: %d c: %d d: %d a: %d b: %d\n",v->index, u->index,
c->index, d->index, a->index, b->index);
printf ("No. nodes moved in root subtree: %d\n",nRootNodes);
printf ("No. nodes moved in crown subtree: %d\n",nCrownNodes);
printf ("Has topology changed? %d\n",topologyHasChanged);
getchar();
# endif
# if defined (TOPOLOGY_MOVE_STATS)
if (topologyHasChanged == YES)
gTopologyHasChanged = YES;
else
gTopologyHasChanged = NO;
gNodeMoves = nCrownNodes + nRootNodes;
# endif
# if defined (SMART_TI_PROBS)
// TO DO: Figure out exactly which branches need their transition matrices updated.
UpDateAllTIs (proposedState, whichChain);
# endif
return (NO_ERROR);
}
/* change one branch length */
int Move_ChangeBrLen (int proposedState, int whichChain, long int *seed, double *lnProposalRatio, double *lnPriorRatio)
{
int i, allNodesPointer, allNodesStop;
double lenFactor, tuning, maxV, m;
TreeNode *p;
/* this parameter should be possible to set by user
For the dataset adh.nex, multiplying Larget & Simon's suggested
tuning parameter (0.19) with 10.0 results in acceptance
probability around 50%, which is, arguably, optimal */
tuning = blTuneProp; /* Larget & Simon's tuning parameter lambda */
// max brlen
maxV = chainMaxs[CHANGE_UNROOT_LOCAL];
// set up pointers
allNodesPointer = whichChain*2*numNodes + proposedState*numNodes;
allNodesStop = allNodesPointer + numNodes;
// unmark all nodes with respect to update
for (i=allNodesPointer; i<allNodesStop; i++)
{
p = allNodesDownPassSeq[i];
p->upDateCl = NO;
}
/* pick a branch */
do
{
p = allNodesDownPassSeq[allNodesPointer + (int)(RandomNumber(seed)*numNodes)];
} while (p->anc == NULL || (treeModel == ROOTED && p->anc->anc == NULL));
/* determine length multiplication factor */
lenFactor = exp(tuning * (RandomNumber(seed) - 0.5));
m = p->length;
p->length *= lenFactor;
// check new length of p
if (p->length < BRLEN_EPSILON)
p->length = BRLEN_EPSILON;
if (p->length > maxV)
p->length = maxV;
/* set flags for update of cond likes from p->anc and down to root */
p->upDateCl = YES;
while (p->anc != NULL)
{
p->upDateCl = YES;
p = p->anc;
}
/* set flags for update of transition probabilities at p */
# if defined (SMART_TI_PROBS)
p->upDateTi = YES;
# endif
/* calculate proposal ratio */
(*lnProposalRatio) = (log(m * lenFactor) - log(m));
/* calculate prior ratio if exponential prior on branch lengths */
/* if birth-death prior we should not be in this move type */
if (!strcmp(brlenprModel, "exponential"))
(*lnPriorRatio) = brlenprExp * m - brlenprExp * m * lenFactor;
else
(*lnPriorRatio) = 0.0;
# if defined (SMART_TI_PROBS)
UpDateAllTIs (proposedState, whichChain);
# endif
return (NO_ERROR);
}
/*------------------------------------------------------------
| OpenFile: open a file, print #NEXUS if a new NEXUS file,
| print appropriate error message if operation failed
\-----------------------------------------------------------*/
FILE *OpenFile (char *filename, int isNexus)
{
FILE *fp;
if ((fp = fopen (filename, "r")) == NULL)
{
fp = fopen (filename, "w");
if (fp != NULL)
{
printf (" Creating output file %s\n", filename);
#if defined (MORPH)
if (isNexus == YES)
fprintf (fp, "#NEXUS\n");
}
#endif
}
else
{
fclose (fp);
if (autoclose == YES)
{
printf (" Appending information to file %s\n", filename);
fp = fopen (filename, "a+");
}
else
{
printf ("\n File \"%s\" already exists.\n Overwrite? (yes/no): ", filename);
if (YesNo() == YES)
{
printf (" Overwriting information to file %s\n", filename);
fp = fopen (filename, "w+");
}
else
{
printf (" Appending information to file %s\n", filename);
fp = fopen (filename, "a+");
}
}
}
if (fp == NULL)
{
printf ("\n ERROR: Could not open file (%s).\n", filename);
}
return fp;
}
int NumAdjacentMarked (TreeNode *p)
{
int i;
i = 0;
if (p->left != NULL)
{
if (p->left->marked == YES)
i++;
}
if (p->right != NULL)
{
if (p->right->marked == YES)
i++;
}
if (p->anc != NULL)
{
if (p->anc->marked == YES)
i++;
}
return (i);
}
double ParsimonyLength (int whichState, int whichChain, int numChars)
{
register int c;
int n, intNodeOffset, oneMatSize;
unsigned int *cl, *clL, *clR, *clA, x, y, z;
double pLength;
TreeNode *p;
intNodeOffset = whichChain*2*numIntNodes + whichState*numIntNodes;
oneMatSize = numNodes * numChars;
pLength = 0.0;
for (n=0; n<numIntNodes; n++)
{
p = intNodeDownPassSeq[intNodeOffset + n];
//printf ("visiting node %d\n", p->index);
cl = &stateSet[whichChain*oneMatSize + (p->index)*numChars];
if (p->anc->anc == NULL)
{
clL = &stateSet[whichChain*oneMatSize + (p->left->index)*numChars];
clR = &stateSet[whichChain*oneMatSize + (p->right->index)*numChars];
clA = &stateSet[whichChain*oneMatSize + (p->anc->index)*numChars];
for (c=0; c<numChars; c++)
{
x = clL[c];
y = clR[c];
z = x & y;
if (z == 0)
{
cl[c] = x | y;
pLength += numSitesOfPat[c];
}
else
cl[c] = z;
x = cl[c];
y = clA[c];
z = x & y;
if (z == 0)
pLength += numSitesOfPat[c];
}
}
else
{
clL = &stateSet[whichChain*oneMatSize + (p->left->index)*numChars];
clR = &stateSet[whichChain*oneMatSize + (p->right->index)*numChars];
for (c=0; c<numChars; c++)
{
x = clL[c];
y = clR[c];
z = x & y;
if (z == 0)
{
cl[c] = x | y;
pLength += numSitesOfPat[c];
}
else
cl[c] = z;
}
}
}
return (pLength);
}
int PerturnStartingTree (int numTaxa, long int *seed)
{
int i, n, chain, move;
double sum, tempPropProbs[NUM_PROPOSAL_TYPES] ,cumProposalProbs[NUM_PROPOSAL_TYPES], ran, lnPriorRatio, lnProposalRatio;
/* set up proposal probabilities */
for (i=0; i<NUM_PROPOSAL_TYPES; i++)
{
tempPropProbs[i] = relProposalProbs[i];
if (i != CHANGE_UNROOT_LOCAL && i != CHANGE_CLOCK_LOCAL && i != CHANGE_CLOCK_TIME_LOCAL)
tempPropProbs[i] = 0.0;
}
sum = 0.0;
for (i=0; i<NUM_PROPOSAL_TYPES; i++)
sum += tempPropProbs[i];
for (i=0; i<NUM_PROPOSAL_TYPES; i++)
tempPropProbs[i] /= sum;
cumProposalProbs[0] = tempPropProbs[0];
for (i=1; i<NUM_PROPOSAL_TYPES; i++)
cumProposalProbs[i] = cumProposalProbs[i-1] + tempPropProbs[i];
for (n=0; n<nPerturbations; n++)
{
for (chain=0; chain<numChains; chain++)
{
/* propose move */
ran = RandomNumber(seed);
if (ran >= 0.0 && ran <= cumProposalProbs[0])
move = CHANGE_QMAT;
else if (ran >cumProposalProbs[0] && ran <= cumProposalProbs[1])
move = CHANGE_BASEFREQS;
else if (ran >cumProposalProbs[1] && ran <= cumProposalProbs[2])
move = CHANGE_GAMMA_SHAPE;
else if (ran >cumProposalProbs[2] && ran <= cumProposalProbs[3])
move = CHANGE_SITE_RATES;
else if (ran >cumProposalProbs[3] && ran <= cumProposalProbs[4])
move = CHANGE_UNROOT_LOCAL;
else if (ran >cumProposalProbs[4] && ran <= cumProposalProbs[5])
move = CHANGE_CLOCK_LOCAL;
else if (ran >cumProposalProbs[5] && ran <= cumProposalProbs[6])
move = CHANGE_CLOCK_TIME_LOCAL;
else if (ran >cumProposalProbs[6] && ran <= cumProposalProbs[7])
move = CHANGE_TREE_HEIGHT;
else if (ran >cumProposalProbs[7] && ran <= cumProposalProbs[8])
move = CHANGE_WORM;
else if (ran >cumProposalProbs[8] && ran <= cumProposalProbs[9])
move = CHANGE_NODE_TIME;
else if (ran >cumProposalProbs[9] && ran <= cumProposalProbs[10])
move = CHANGE_BD_PARAMS;
/* make perturbation */
lnPriorRatio = lnProposalRatio = 0.0;
if (move == CHANGE_UNROOT_LOCAL)
{
/* change topology of unrooted tree or rooted and unconstrained tree using LOCAL */
if (Move_ChangeUnrootedWithLocal (numTaxa, 0, chain, seed, &lnProposalRatio, &lnPriorRatio) == ERROR)
return (ERROR);
}
else if (move == CHANGE_CLOCK_LOCAL)
{
/* change topology of rooted tree with clock constraint using LOCAL */
if (Move_ChangeClockWithLocal (numTaxa, 0, chain, seed, &lnProposalRatio, &lnPriorRatio) == ERROR)
return (ERROR);
}
else if (move == CHANGE_CLOCK_TIME_LOCAL)
{
/* change topology and times of rooted tree with clock constraint using LOCAL (divergence time estimation) */
if (Move_ChangeTimeClockWithLocal (numTaxa, 0, chain, seed, &lnProposalRatio, &lnPriorRatio) == ERROR)
return (ERROR);
}
else
{
printf (" ERROR: Unknown perturbation\n");
return (ERROR);
}
/* copy information */
CopyTree (0, 1, chain);
}
}
# if 0
for (n=0; n<numChains; n++)
{
printf ("\n Starting tree for chain %d:\n", n+1);
if (treeModel == ROOTED)
{
//ShowNodes (root[n*2+0], 2, YES);
ShowStartTree (root[n*2+0], numTaxa, YES);
}
else
{
//ShowNodes (root[n*2+0], 2, NO);
ShowStartTree (root[n*2+0], numTaxa, NO);
}
}
# endif
return (NO_ERROR);
}
/*--------------------------------------------------------------
| PrepareOutputFiles: open output files, write headers
| return ERROR and close all files if error encountered
---------------------------------------------------------------*/
int PrepareOutputFiles (void)
{
int i, j, k, isFirst;
char pFilename[100], bpFilename[100], tFilename[100];
TreeNode *p;
FILE *fp1, *fp2;
/* prepare output file names */
strcpy (pFilename, outFile);
strcpy (bpFilename, outFile);
strcpy (tFilename, outFile);
strcat (pFilename, ".p");
strcat (bpFilename, ".bp");
strcat (tFilename, ".t");
/* reset output file pointers */
pFile = bpFile = tFile = NULL;
/* open files */
if ((pFile = OpenFile(pFilename, NO))==NULL)
goto error_exit;
if ((bpFile = OpenFile(bpFilename, YES))==NULL)
goto error_exit;
if ((tFile = OpenFile(tFilename, YES))==NULL)
goto error_exit;
fp1 = pFile;
fp2 = bpFile;
/* print headers to pFile and bpFile */
fprintf (fp2, "begin bayesparams;\n");
fprintf (fp1, "Gen\tlnL\t");
fprintf (fp1, "TL\t");
fprintf (fp2, " header Gen, lnL");
fprintf (fp2, ", TL");
if ((dataType == DNA || dataType == RNA) && enforceCodonModel == NO)
{
if (nst == 2)
{
fprintf (fp1, "kappa\t");
fprintf (fp2, ", kappa");
}
else if (nst == 6)
{
fprintf (fp1, "R(GT)\tR(CT)\tR(CG)\tR(AT)\tR(AG)\tR(AC)\t");
fprintf (fp2, ", rGT, rCT, rCG, rAT, rAG, rAC");
}
else if (nst == 12)
{
fprintf (fp1, "R(AC)\tR(AG)\tR(AT)\tR(CG)\tR(CT)\tR(GT)\tR(CA)\tR(GA)\tR(TA)\tR(GC)\tR(TC)\tR(TG)\t");
fprintf (fp2, ", rAC, rAG, rAT, rCG, rCT, rGT, rCA, rGA, rTA, rGC, rTC, rTG");
}
if (dataType == DNA)
{
if (useCovarion == YES && !strcmp(covarionModelType, "gcswitch"))
{
fprintf (fp1, "pi(A1)\tpi(C1)\tpi(G1)\tpi(T1)\tpi(A2)\tpi(C2)\tpi(G2)\tpi(T2)\t");
fprintf (fp2, ", piA1, piC1, piG1, piT1, piA2, piC2, piG2, piT2");
}
else
{
fprintf (fp1, "pi(A)\tpi(C)\tpi(G)\tpi(T)\t");
fprintf (fp2, ", piA, piC, piG, piT");
}
}
else if (dataType == RNA)
{
if (useCovarion == YES && !strcmp(covarionModelType, "gcswitch"))
{
fprintf (fp1, "pi(A1)\tpi(C1)\tpi(G1)\tpi(U1)\tpi(A2)\tpi(C2)\tpi(G2)\tpi(U2)\t");
fprintf (fp2, ", piA1, piC1, piG1, piU1, piA2, piC2, piG2, piU2");
}
else
{
fprintf (fp1, "pi(A)\tpi(C)\tpi(G)\tpi(U)\t");
fprintf (fp2, ", piA, piC, piG, piU");
}
}
if (useCovarion == YES)
{
if (!strcmp(covarionModelType, "gcswitch"))
{
fprintf (fp1, "gc1gc2\tgc2gc1\t");
fprintf (fp2, ", gc1gc2, gc2gc1");
}
else if (!strcmp(covarionModelType, "ts98"))
{
fprintf (fp1, "onOff\toffOn\t");
fprintf (fp2, ", onOff, offOn");
}
}
}
else if ((dataType == DNA || dataType == RNA) && enforceCodonModel == YES)
{
fprintf (fp1, "kappa\t");
fprintf (fp2, ", kappa");
fprintf (fp1, "nonsyn_syn\t");
fprintf (fp2, ", nonsyn_syn");
if (!strcmp(codonModelType, "ny98"))
{
fprintf (fp1, "pPur\t");
fprintf (fp2, ", pPur");
fprintf (fp1, "pNeu\t");
fprintf (fp2, ", pNeu");
fprintf (fp1, "pPos\t");
fprintf (fp2, ", pPos");
}
else if (!strcmp(codonModelType, "ac1ny98"))
{
fprintf (fp1, "pPur\t");
fprintf (fp2, ", pPur");
fprintf (fp1, "pNeu\t");
fprintf (fp2, ", pNeu");
fprintf (fp1, "pPos\t");
fprintf (fp2, ", pPos");
fprintf (fp1, "rho\t");
fprintf (fp2, ", rho");
}
else if (!strcmp(codonModelType, "ac2ny98"))
{
fprintf (fp1, "pPur\t");
fprintf (fp2, ", pPur");
fprintf (fp1, "pNeu\t");
fprintf (fp2, ", pNeu");
fprintf (fp1, "pPos\t");
fprintf (fp2, ", pPos");
fprintf (fp1, "rho1\t");
fprintf (fp2, ", rho1");
fprintf (fp1, "rho2\t");
fprintf (fp2, ", rho2");
fprintf (fp1, "rho3\t");
fprintf (fp2, ", rho3");
}
else if (!strcmp(codonModelType, "covny98"))
{
fprintf (fp1, "pPur\t");
fprintf (fp2, ", pPur");
fprintf (fp1, "pNeu\t");
fprintf (fp2, ", pNeu");
fprintf (fp1, "pPos\t");
fprintf (fp2, ", pPos");
fprintf (fp1, "sr\t");
fprintf (fp2, ", sr");
}
for (i=0; i<nStates; i++)
{
fprintf (fp1, "pi(%d)\t", i+1);
fprintf (fp2, ", pi%d", i+1);
}
}
else if (dataType == PROTEIN && (aaModelType == EQUALIN || aaModelType == GTR))
{
fprintf (fp1, "pi(A)\tpi(R)\tpi(N)\tpi(D)\tpi(C)\tpi(Q)\tpi(E)\tpi(G)\tpi(H)\tpi(I)\tpi(L)\tpi(K)\tpi(M)\tpi(F)\tpi(P)\tpi(S)\tpi(T)\tpi(W)\tpi(Y)\tpi(V)\t");
fprintf (fp2, ", piA, piR, piN, piD, piC, piQ, piE, piG, piH, piI, piL, piK, piM, piF, piP, piS, piT, piW, piY, piV");
if (useCovarion == YES)
{
fprintf (fp1, "onOff\toffOn\t");
fprintf (fp2, ", onOff, offOn");
}
}
else if (dataType == RESTRICTION)
{
fprintf (fp1, "r(01)\t");
fprintf (fp2, ", r01");
}
#if defined (MORPH)
else if (dataType == STANDARD && numBetaCats > 1)
{
fprintf (fp1, "alpha\t"); // TODO: change header to something more suitable
fprintf (fp2, ", alpha");
}
#endif
if (((dataType == DNA || dataType == RNA) && enforceCodonModel == NO) || dataType == PROTEIN || dataType == RESTRICTION)
{
if (!strcmp(ratesModel, "gamma"))
{
fprintf (fp1, "alpha\t");
fprintf (fp2, ", alpha");
}
else if (!strcmp(ratesModel, "adgamma"))
{
fprintf (fp1, "alpha\t");
fprintf (fp2, ", alpha");
fprintf (fp1, "rho\t");
fprintf (fp2, ", rho");
if (!strcmp(lagprModel, "uniform") || !strcmp(lagprModel, "exponential"))
{
fprintf (fp1, "offset\t");
fprintf (fp2, ", offset");
}
}
else if (!strcmp(ratesModel, "sitespec"))
{
for (i=0; i<nPartitions; i++)
{
fprintf (fp1, "SS(%d)\t", i+1);
fprintf (fp2, ", SS%d", i+1);
}
}
else if (!strcmp(ratesModel, "invariant"))
{
fprintf (fp1, "iP\t");
fprintf (fp2, ", iP");
}
else if (!strcmp(ratesModel, "invgamma"))
{
fprintf (fp1, "alpha\t");
fprintf (fp2, ", alpha");
fprintf (fp1, "iP\t");
fprintf (fp2, ", iP");
}
else if (!strcmp(ratesModel, "ssgamma"))
{
fprintf (fp1, "alpha\t");
fprintf (fp2, ", alpha");
for (i=0; i<nPartitions; i++)
{
fprintf (fp1, "SS(%d)\t", i+1);
fprintf (fp2, ", SS%d", i+1);
}
}
else if (!strcmp(ratesModel, "ssadgamma"))
{
fprintf (fp1, "alpha\t");
fprintf (fp2, ", alpha");
fprintf (fp1, "rho\t");
fprintf (fp2, ", rho");
if (!strcmp(lagprModel, "uniform") || !strcmp(lagprModel, "exponential"))
{
fprintf (fp1, "offset\t");
fprintf (fp2, ", offset");
}
for (i=0; i<nPartitions; i++)
{
fprintf (fp1, "SS(%d)\t", i+1);
fprintf (fp2, ", SS%d", i+1);
}
}
}
if (!strcmp(brlenprModel, "birth-death"))
{
fprintf (fp1, "lambda\tmu\t");
fprintf (fp2, ", lambda, mu");
}
if (enforceCalibrations == YES)
{
fprintf (fp1, "m\t");
fprintf (fp2, ", m");
for (i=0; i<nConstraints; i++)
{
fprintf (fp2, ", ");
k = 0;
while (constraintLabels[i][k] != '|' && k < 99)
{
fprintf (fp1, "%c", constraintLabels[i][k]);
fprintf (fp2, "%c", constraintLabels[i][k]);
k++;
}
fprintf (fp1, "\t");
}
for (i=0; i<nCalibrations; i++)
{
fprintf (fp2, ", ");
k = 0;
while (calibrationLabels[i][k] != '|' && k < 99)
{
fprintf (fp1, "%c", calibrationLabels[i][k]);
fprintf (fp2, "%c", calibrationLabels[i][k]);
k++;
}
fprintf (fp1, "\t");
}
}
fprintf (fp1, "\n");
fprintf (fp2, ";\n");
fflush(fp1);
fflush(fp2);
fp2 = tFile;
fprintf (fp2, "begin trees;\n");
fprintf (fp2, " translate\n");
isFirst = YES;
j = 0;
for (i=0; i<numNodes; i++)
{
p = allNodesDownPassSeq[i]; // print any tree, they are identical
if (p->left == NULL || p->right == NULL || (treeModel == UNROOTED && p->anc == NULL))
{
if (isFirst == NO)
fprintf (fp2, ",\n");
if (treeModel == ROOTED && p->anc != NULL)
fprintf (fp2, " %4d %s", p->index + 1, p->label);
else if (treeModel == UNROOTED)
fprintf (fp2, " %4d %s", p->index + 1, p->label);
isFirst = NO;
}
}
fprintf (fp2, ";\n");
fflush (fp2);
return NO_ERROR;
error_exit:
if (pFile!=NULL)
fclose(pFile);
if (bpFile!=NULL)
fclose(bpFile);
if (tFile!=NULL)
fclose(tFile);
return ERROR;
}
int PrepareParsOutputFiles (void)
{
int i, j, isFirst;
char pFilename[100], bpFilename[100], tFilename[100];
TreeNode *p;
FILE *fp1, *fp2;
/* prepare output file names */
strcpy (pFilename, outFile);
strcpy (bpFilename, outFile);
strcpy (tFilename, outFile);
strcat (pFilename, ".p");
strcat (bpFilename, ".bp");
strcat (tFilename, ".t");
/* reset output file pointers */
pFile = bpFile = tFile = NULL;
/* open files */
if ((pFile = OpenFile(pFilename, NO))==NULL)
goto error_exit;
if ((bpFile = OpenFile(bpFilename, YES))==NULL)
goto error_exit;
if ((tFile = OpenFile(tFilename, YES))==NULL)
goto error_exit;
fp1 = pFile;
fp2 = bpFile;
/* print headers to pFile and bpFile */
fprintf (fp2, "#NEXUS\n\n");
fprintf (fp2, "begin bayesparams;\n");
fprintf (fp1, "Gen\tlnL\t");
fprintf (fp1, "TL\t");
fprintf (fp2, " header Gen, lnL");
fprintf (fp2, ", TL");
fprintf (fp1, "\n");
fprintf (fp2, ";\n");
fflush(fp1);
fflush(fp2);
fp2 = tFile;
fprintf (fp2, "begin trees;\n");
fprintf (fp2, " translate\n");
isFirst = YES;
j = 0;
for (i=0; i<numNodes; i++)
{
p = allNodesDownPassSeq[i]; // print any tree, they are identical
if (p->left == NULL || p->right == NULL || (treeModel == UNROOTED && p->anc == NULL))
{
if (isFirst == NO)
fprintf (fp2, ",\n");
if (treeModel == ROOTED && p->anc != NULL)
fprintf (fp2, " %4d %s", p->index + 1, p->label);
else if (treeModel == UNROOTED)
fprintf (fp2, " %4d %s", p->index + 1, p->label);
isFirst = NO;
}
}
fprintf (fp2, ";\n");
fflush (fp2);
return NO_ERROR;
error_exit:
if (pFile!=NULL)
fclose(pFile);
if (bpFile!=NULL)
fclose(bpFile);
if (tFile!=NULL)
fclose(tFile);
return ERROR;
}
int PrintAncStatesDNA (int whichState, int whichChain, int numChars, int numRateCats, int whichGen)
{
#define N_STATES 4
#define N_STATES_SQUARED 16
#define N_STATES_CUBE 64
register int i, j, k, c, n, n1, l, startingJ;
int lnumRateCats, lnPartitions, oneMatSize, oneNodeSize,
index, nRates, pat,
intNodeOffset, allNodeOffset, condLikeOffset;
double bs[N_STATES], *pL, *pR, *pA, *catFreq, *catRate, *partRate,
*clL, *clR, *clA, *clP, *tiPL, *tiPR, *tiPA,
*lnScaler, correlation, lnSeqProb, maxProb,
**markovTi, like[4], sum, postProb[4], *f, *b, *expPr, *logCf,
*logCb, *tempRatePr, *rateProbs, logC, temp, logLike, *ancCls;
char tempFile[100], tempFileA[100], tempFileC[100], tempFileG[100], tempFileT[100], bestNuc;
TreeNode *p, *r, *rDn, *rUp;
FILE *fp, *fopen();
# if defined (SMART_TI_PROBS)
int nForOneState;
# else
register int m;
int isComplex, indexL, indexR, indexA, nPij;
double v, lkappa, theRate, **probs, **q, *eigenValues, *eigvalsImag, **eigvecs, **inverseEigvecs, *c_ijk;
complex **Ceigvecs, **CinverseEigvecs;
# endif
/* initialize intNodeOffset */
intNodeOffset = whichChain*2*numIntNodes + whichState*numIntNodes;
allNodeOffset = whichChain*2*numNodes + whichState*numNodes;
/* initialize offset for transition probabilities */
# if defined (SMART_TI_PROBS)
nForOneState = numNodes*nodeTiSize;
# endif
/* load base frequencies */
index = whichChain*2*N_STATES + whichState*N_STATES;
bs[A] = baseFreq[index + A];
bs[C] = baseFreq[index + C];
bs[G] = baseFreq[index + G];
bs[T] = baseFreq[index + T];
/* how many different rates? */
/* lnumRateCats contains a local copy of numRateCats if appropriate, else 1 */
/* lnPartitions contains a local copy of nPartitions if appropriate, else 1 */
/* the code introduced here only makes sure that the number of partitions */
/* or rate categories is set to 1 when appropriate, in case the global variables */
/* are not set to 1 when they are not "in use" */
if (!strcmp(ratesModel, "sitespec") || !strcmp(ratesModel, "ssgamma") || !strcmp(ratesModel, "ssadgamma"))
lnPartitions = nPartitions;
else
lnPartitions = 1;
if (!strcmp(ratesModel, "equal") || !strcmp(ratesModel, "sitespec"))
lnumRateCats = 1;
else
lnumRateCats = numRateCats;
nRates = lnPartitions * lnumRateCats; // number of rates needing P matrices
/* allocate memory for the calculations */
/* pL, pR and pA will contain the transition probs for Left, Right and Anc */
/* One transition probability matrix is needed for each possible rate */
# if !defined (SMART_TI_PROBS)
probs = psdmatrix (N_STATES);
nPij = nRates * N_STATES_SQUARED;
pL = (double *)malloc((size_t)(3 * nPij * sizeof(double)));
if (!pL)
{
printf ("\n ERROR: Problem allocating Pij\n");
goto error_exit;
}
pR = pL + nPij;
pA = pR + nPij;
# endif
/* allocate memory for ancestral conditional likelihoods (it may be a tip, and we don't want to overwrite these cls) */
ancCls = (double *)malloc((size_t) (lnumRateCats * numChars * N_STATES * sizeof(double)));
if (!ancCls)
{
printf ("\n ERROR: Problem allocating space for rate multipliers and rate category freqs.\n");
goto error_exit;
}
/* allocate memory for rate and rate category frequencies */
catFreq = (double *)malloc((size_t) ((2 * lnumRateCats + lnPartitions) * sizeof(double)));
if (!catFreq)
{
printf ("\n ERROR: Problem allocating space for rate multipliers and rate category freqs.\n");
goto error_exit;
}
catRate = catFreq + lnumRateCats;
partRate = catRate + lnumRateCats;
/* allocate memory for autocorrelated gamma models */
if (!strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "ssadgamma"))
{
f = (double *)malloc((size_t) (((lnumRateCats * nChar) * 2 + lnumRateCats + nChar*2) * sizeof(double)));
if (!f)
{
printf ("\n ERROR: Problem allocating f.\n");
goto error_exit;
}
b = f + lnumRateCats * nChar;
expPr = b + lnumRateCats * nChar;
logCf = expPr + lnumRateCats;
logCb = logCf + nChar;
for (i=0; i<lnumRateCats*nChar; i++)
f[i] = b[i] = 0.0;
for (i=0; i<lnumRateCats; i++)
expPr[i] = 0.0;
for (i=0; i<nChar; i++)
logCf[i] = logCb[i] = 0.0;
tempRatePr = (double *)malloc((size_t) ((numChars * lnumRateCats + nChar * lnumRateCats) * sizeof(double)));
if (!tempRatePr)
{
printf ("\n ERROR: Problem allocating tempRatePr.\n");
goto error_exit;
}
rateProbs = tempRatePr + numChars * lnumRateCats;
for (i=0; i<nChar * lnumRateCats; i++)
rateProbs[i] = 0.0;
}
// set pointer to the lnSiteScaler for this tree
lnScaler = &lnSiteScaler[whichChain * 2 * numChars + whichState * numChars];
/* fill in rate categories with frequencies and rates by dividing the */
/* gamma distribution into discrete categories, if appropriate */
/* NB! this is inefficient; store values instead */
if (!strcmp(ratesModel,"gamma")|| !strcmp(ratesModel, "ssgamma"))
{
DiscreteGamma (catFreq, catRate, alpha[whichChain*2 + whichState], alpha[whichChain*2 + whichState], lnumRateCats, 0);
}
else if (!strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "ssadgamma"))
{
markovTi = psdmatrix (lnumRateCats);
AutodGamma (markovTi, catFreq, catRate, &correlation, alpha[whichChain*2 + whichState], rateCorrelation[whichChain*2 + whichState], lnumRateCats);
}
else if (!strcmp(ratesModel, "invgamma"))
{
DiscreteGamma (catFreq, catRate, alpha[whichChain*2 + whichState], alpha[whichChain*2 + whichState], lnumRateCats-1, 0);
catRate[lnumRateCats-1] = 0.0;
catFreq[lnumRateCats-1] = invP[whichChain*2 + whichState];
for (i=0; i<lnumRateCats-1; i++)
{
catRate[i] *= 1.0 / (1.0 - invP[whichChain*2 + whichState]);
catFreq[i] *= (1.0 - invP[whichChain*2 + whichState]);
}
}
else if (!strcmp(ratesModel, "invariant"))
{
catRate[0] = 0.0;
catRate[1] = 1.0 / (1.0 - invP[whichChain*2 + whichState]);
catFreq[0] = invP[whichChain*2 + whichState];
catFreq[1] = 1.0 - invP[whichChain*2 + whichState];
}
else { // "sitespec" or "equal"
catRate[0] = 1.0;
catFreq[0] = 1.0;
}
/* initialize partition rates, if appropriate */
if (lnPartitions > 1)
{
for (i=0; i<lnPartitions; i++)
partRate[i] = scaledRates[whichChain*2*lnPartitions + whichState*lnPartitions + i];
}
else
partRate[0] = 1.0;
/* find kappa if nst == 1 or nst == 2 */
# if !defined (SMART_TI_PROBS)
if (nst == 1)
lkappa = 1.0;
else if (nst == 2)
lkappa = kappa[whichChain*2 + whichState];
/* get eigenvalues and eigenvectors if nst=6 or nst=12 */
if (nst == 6 || nst == 12)
{
q = psdmatrix (N_STATES);
eigenValues = (double *)malloc((size_t) (2 * N_STATES * sizeof(double)));
if (!eigenValues)
{
printf ("\n ERROR: Problem allocating eigenValues and eigvalsImag.\n");
goto error_exit;
}
eigvalsImag = eigenValues + N_STATES;
eigvecs = psdmatrix (N_STATES);
inverseEigvecs = psdmatrix (N_STATES);
Ceigvecs = pscmatrix (N_STATES);
CinverseEigvecs = pscmatrix (N_STATES);
if (SetQMatrix (q, whichState, whichChain) == ERROR)
goto error_exit;
isComplex = GetEigens (N_STATES, q, eigenValues, eigvalsImag, eigvecs, inverseEigvecs, Ceigvecs, CinverseEigvecs);
if (isComplex == NO)
{
c_ijk = (double *)malloc((size_t) (N_STATES_CUBE * sizeof(double)));
if (!c_ijk)
{
printf ("\n ERROR: Problem allocating c_ijk.\n");
goto error_exit;
}
CalcCijk (c_ijk, N_STATES, eigvecs, inverseEigvecs);
}
}
# endif
/* how large is the information for one tree and one node*/
oneMatSize = numNodes * numChars * lnumRateCats * N_STATES;
oneNodeSize = numChars * lnumRateCats * N_STATES;
/* offset for conditional likelihoods */
condLikeOffset = whichChain*2*oneMatSize + whichState*oneMatSize;
/* pass down tree, finding nodes that are to have ancestral states estimated */
for (n=0; n<numNodes; n++)
{
p = allNodesDownPassSeq[allNodeOffset + n];
if (p->isConstrained == YES)
{
/* mark nodes below p */
for (n1=0; n1<numNodes; n1++)
{
r = allNodesDownPassSeq[allNodeOffset + n1];
r->flag = 0;
if (r == p)
r->flag = 1;
if (r->left != NULL && r->right != NULL)
{
if (r->left->flag == 1 || r->right->flag == 1)
r->flag = 1;
}
}
/* get conditional likelihoods down tree */
for (n1=0; n1<numIntNodes; n1++)
{
r = intNodeDownPassSeq[intNodeOffset + n1];
if (r->flag != 1)
{
//printf ("visiting interior node %d dn\n", r->index);
/* get transition probabilities */
# if defined (SMART_TI_PROBS)
pL = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (r->left->index)*nodeTiSize);
pR = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (r->right->index)*nodeTiSize);
# else
if (nst == 1 || nst == 2)
{
for (m=indexL=indexR=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
theRate = partRate[m] * catRate[k];
/* calculate transition probabilities for left branch */
HkyChangeMat (probs, r->left->length, lkappa, theRate, bs[A], bs[C], bs[G], bs[T]);
for (i=0; i<4; i++)
for (j=0; j<4; j++)
pL[indexL++] = probs[i][j];
/* calculate transition probabilities for right branch */
HkyChangeMat (probs, r->right->length, lkappa, theRate, bs[A], bs[C], bs[G], bs[T]);
for (i=0; i<4; i++)
for (j=0; j<4; j++)
pR[indexR++] = probs[i][j];
}
}
}
else // nst == 6 or nst == 12
{
for (m=indexL=indexR=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
theRate = partRate[m] * catRate[k];
// calculate transition probabilities for left branch
if (isComplex == NO)
CalcPij (c_ijk, 4, eigenValues, r->left->length, theRate, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, 4, probs, r->left->length, theRate) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<4; i++)
for (j=0; j<4; j++)
pL[indexL++] = probs[i][j];
// calculate transition probabilities for right branch
if (isComplex == NO)
CalcPij (c_ijk, 4, eigenValues, r->right->length, theRate, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, 4, probs, r->right->length, theRate) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<4; i++)
for (j=0; j<4; j++)
pR[indexR++] = probs[i][j];
}
}
}
# endif
/* first set pointers to cond likes of left, right and p */
clL = &condLike[condLikeOffset + (r->left->index)*oneNodeSize];
clR = &condLike[condLikeOffset + (r->right->index)*oneNodeSize];
clP = &condLike[condLikeOffset + (r->index)*oneNodeSize];
if (!strcmp(ratesModel, "equal"))
{
tiPL = pL;
tiPR = pR;
for (c=0; c<numChars; c++)
{
clP[A] = (tiPL[AA]*clL[A] + tiPL[AC]*clL[C] + tiPL[AG]*clL[G] + tiPL[AT]*clL[T])
*(tiPR[AA]*clR[A] + tiPR[AC]*clR[C] + tiPR[AG]*clR[G] + tiPR[AT]*clR[T]);
clP[C] = (tiPL[CA]*clL[A] + tiPL[CC]*clL[C] + tiPL[CG]*clL[G] + tiPL[CT]*clL[T])
*(tiPR[CA]*clR[A] + tiPR[CC]*clR[C] + tiPR[CG]*clR[G] + tiPR[CT]*clR[T]);
clP[G] = (tiPL[GA]*clL[A] + tiPL[GC]*clL[C] + tiPL[GG]*clL[G] + tiPL[GT]*clL[T])
*(tiPR[GA]*clR[A] + tiPR[GC]*clR[C] + tiPR[GG]*clR[G] + tiPR[GT]*clR[T]);
clP[T] = (tiPL[TA]*clL[A] + tiPL[TC]*clL[C] + tiPL[TG]*clL[G] + tiPL[TT]*clL[T])
*(tiPR[TA]*clR[A] + tiPR[TC]*clR[C] + tiPR[TG]*clR[G] + tiPR[TT]*clR[T]);
clP += 4;
clL += 4;
clR += 4;
}
}
else if (!strcmp(ratesModel, "gamma") || !strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "invariant") || !strcmp(ratesModel, "invgamma"))
{
for (c=0; c<numChars; c++)
{
tiPL = pL;
tiPR = pR;
for (k=0; k<lnumRateCats; k++)
{
clP[A] = (tiPL[AA]*clL[A] + tiPL[AC]*clL[C] + tiPL[AG]*clL[G] + tiPL[AT]*clL[T])
*(tiPR[AA]*clR[A] + tiPR[AC]*clR[C] + tiPR[AG]*clR[G] + tiPR[AT]*clR[T]);
clP[C] = (tiPL[CA]*clL[A] + tiPL[CC]*clL[C] + tiPL[CG]*clL[G] + tiPL[CT]*clL[T])
*(tiPR[CA]*clR[A] + tiPR[CC]*clR[C] + tiPR[CG]*clR[G] + tiPR[CT]*clR[T]);
clP[G] = (tiPL[GA]*clL[A] + tiPL[GC]*clL[C] + tiPL[GG]*clL[G] + tiPL[GT]*clL[T])
*(tiPR[GA]*clR[A] + tiPR[GC]*clR[C] + tiPR[GG]*clR[G] + tiPR[GT]*clR[T]);
clP[T] = (tiPL[TA]*clL[A] + tiPL[TC]*clL[C] + tiPL[TG]*clL[G] + tiPL[TT]*clL[T])
*(tiPR[TA]*clR[A] + tiPR[TC]*clR[C] + tiPR[TG]*clR[G] + tiPR[TT]*clR[T]);
clP += 4;
clL += 4;
clR += 4;
tiPL += 16;
tiPR += 16;
}
}
}
else if (!strcmp(ratesModel, "ssgamma") || !strcmp(ratesModel, "ssadgamma"))
{
for (c=0; c<numChars; c++)
{
index = partitionId[c]*lnumRateCats*N_STATES_SQUARED;
tiPL = &pL[index];
tiPR = &pR[index];
for (k=0; k<lnumRateCats; k++)
{
clP[A] = (tiPL[AA]*clL[A] + tiPL[AC]*clL[C] + tiPL[AG]*clL[G] + tiPL[AT]*clL[T])
*(tiPR[AA]*clR[A] + tiPR[AC]*clR[C] + tiPR[AG]*clR[G] + tiPR[AT]*clR[T]);
clP[C] = (tiPL[CA]*clL[A] + tiPL[CC]*clL[C] + tiPL[CG]*clL[G] + tiPL[CT]*clL[T])
*(tiPR[CA]*clR[A] + tiPR[CC]*clR[C] + tiPR[CG]*clR[G] + tiPR[CT]*clR[T]);
clP[G] = (tiPL[GA]*clL[A] + tiPL[GC]*clL[C] + tiPL[GG]*clL[G] + tiPL[GT]*clL[T])
*(tiPR[GA]*clR[A] + tiPR[GC]*clR[C] + tiPR[GG]*clR[G] + tiPR[GT]*clR[T]);
clP[T] = (tiPL[TA]*clL[A] + tiPL[TC]*clL[C] + tiPL[TG]*clL[G] + tiPL[TT]*clL[T])
*(tiPR[TA]*clR[A] + tiPR[TC]*clR[C] + tiPR[TG]*clR[G] + tiPR[TT]*clR[T]);
clP += 4;
clL += 4;
clR += 4;
tiPL += 16;
tiPR += 16;
}
}
}
else if (!strcmp(ratesModel, "sitespec"))
{
for (c=0; c<numChars; c++)
{
index = partitionId[c]*N_STATES_SQUARED;
tiPL = &pL[index];
tiPR = &pR[index];
clP[A] = (tiPL[AA]*clL[A] + tiPL[AC]*clL[C] + tiPL[AG]*clL[G] + tiPL[AT]*clL[T])
*(tiPR[AA]*clR[A] + tiPR[AC]*clR[C] + tiPR[AG]*clR[G] + tiPR[AT]*clR[T]);
clP[C] = (tiPL[CA]*clL[A] + tiPL[CC]*clL[C] + tiPL[CG]*clL[G] + tiPL[CT]*clL[T])
*(tiPR[CA]*clR[A] + tiPR[CC]*clR[C] + tiPR[CG]*clR[G] + tiPR[CT]*clR[T]);
clP[G] = (tiPL[GA]*clL[A] + tiPL[GC]*clL[C] + tiPL[GG]*clL[G] + tiPL[GT]*clL[T])
*(tiPR[GA]*clR[A] + tiPR[GC]*clR[C] + tiPR[GG]*clR[G] + tiPR[GT]*clR[T]);
clP[T] = (tiPL[TA]*clL[A] + tiPL[TC]*clL[C] + tiPL[TG]*clL[G] + tiPL[TT]*clL[T])
*(tiPR[TA]*clR[A] + tiPR[TC]*clR[C] + tiPR[TG]*clR[G] + tiPR[TT]*clR[T]);
clP += 4;
clL += 4;
clR += 4;
}
}
}
}
/* get conditional likelihoods up tree */
for (n1=numIntNodes-1; n1>=0; n1--)
{
r = intNodeDownPassSeq[intNodeOffset + n1];
if (r->flag == 1 && p != r)
{
rDn = r->anc;
if (r->left->flag == 0)
rUp = r->left;
else
rUp = r->right;
//printf ("visiting interior node %d up\n", r->index);
/* get transition probabilities */
# if defined (SMART_TI_PROBS)
pL = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (rUp->index)*nodeTiSize);
pR = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (r->index)*nodeTiSize);
# else
if (nst == 1 || nst == 2)
{
for (m=indexL=indexR=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
theRate = partRate[m] * catRate[k];
/* calculate transition probabilities for left branch */
HkyChangeMat (probs, rUp->length, lkappa, theRate, bs[A], bs[C], bs[G], bs[T]);
for (i=0; i<4; i++)
for (j=0; j<4; j++)
pL[indexL++] = probs[i][j];
/* calculate transition probabilities for right branch */
HkyChangeMat (probs, r->length, lkappa, theRate, bs[A], bs[C], bs[G], bs[T]);
for (i=0; i<4; i++)
for (j=0; j<4; j++)
pR[indexR++] = probs[i][j];
}
}
}
else // nst == 6 or nst == 12
{
for (m=indexL=indexR=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
theRate = partRate[m] * catRate[k];
// calculate transition probabilities for left branch
if (isComplex == NO)
CalcPij (c_ijk, 4, eigenValues, rUp->length, theRate, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, 4, probs, rUp->length, theRate) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<4; i++)
for (j=0; j<4; j++)
pL[indexL++] = probs[i][j];
// calculate transition probabilities for right branch
if (isComplex == NO)
CalcPij (c_ijk, 4, eigenValues, r->length, theRate, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, 4, probs, r->length, theRate) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<4; i++)
for (j=0; j<4; j++)
pR[indexR++] = probs[i][j];
}
}
}
# endif
/* first set pointers to cond likes of left, right and p */
clL = &condLike[condLikeOffset + (rUp->index)*oneNodeSize];
clR = &condLike[condLikeOffset + (rDn->index)*oneNodeSize];
clP = &condLike[condLikeOffset + (r->index)*oneNodeSize];
if (!strcmp(ratesModel, "equal"))
{
tiPL = pL;
tiPR = pR;
for (c=0; c<numChars; c++)
{
clP[A] = (tiPL[AA]*clL[A] + tiPL[AC]*clL[C] + tiPL[AG]*clL[G] + tiPL[AT]*clL[T])
*(tiPR[AA]*clR[A] + tiPR[AC]*clR[C] + tiPR[AG]*clR[G] + tiPR[AT]*clR[T]);
clP[C] = (tiPL[CA]*clL[A] + tiPL[CC]*clL[C] + tiPL[CG]*clL[G] + tiPL[CT]*clL[T])
*(tiPR[CA]*clR[A] + tiPR[CC]*clR[C] + tiPR[CG]*clR[G] + tiPR[CT]*clR[T]);
clP[G] = (tiPL[GA]*clL[A] + tiPL[GC]*clL[C] + tiPL[GG]*clL[G] + tiPL[GT]*clL[T])
*(tiPR[GA]*clR[A] + tiPR[GC]*clR[C] + tiPR[GG]*clR[G] + tiPR[GT]*clR[T]);
clP[T] = (tiPL[TA]*clL[A] + tiPL[TC]*clL[C] + tiPL[TG]*clL[G] + tiPL[TT]*clL[T])
*(tiPR[TA]*clR[A] + tiPR[TC]*clR[C] + tiPR[TG]*clR[G] + tiPR[TT]*clR[T]);
clP += 4;
clL += 4;
clR += 4;
}
}
else if (!strcmp(ratesModel, "gamma") || !strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "invariant") || !strcmp(ratesModel, "invgamma"))
{
for (c=0; c<numChars; c++)
{
tiPL = pL;
tiPR = pR;
for (k=0; k<lnumRateCats; k++)
{
clP[A] = (tiPL[AA]*clL[A] + tiPL[AC]*clL[C] + tiPL[AG]*clL[G] + tiPL[AT]*clL[T])
*(tiPR[AA]*clR[A] + tiPR[AC]*clR[C] + tiPR[AG]*clR[G] + tiPR[AT]*clR[T]);
clP[C] = (tiPL[CA]*clL[A] + tiPL[CC]*clL[C] + tiPL[CG]*clL[G] + tiPL[CT]*clL[T])
*(tiPR[CA]*clR[A] + tiPR[CC]*clR[C] + tiPR[CG]*clR[G] + tiPR[CT]*clR[T]);
clP[G] = (tiPL[GA]*clL[A] + tiPL[GC]*clL[C] + tiPL[GG]*clL[G] + tiPL[GT]*clL[T])
*(tiPR[GA]*clR[A] + tiPR[GC]*clR[C] + tiPR[GG]*clR[G] + tiPR[GT]*clR[T]);
clP[T] = (tiPL[TA]*clL[A] + tiPL[TC]*clL[C] + tiPL[TG]*clL[G] + tiPL[TT]*clL[T])
*(tiPR[TA]*clR[A] + tiPR[TC]*clR[C] + tiPR[TG]*clR[G] + tiPR[TT]*clR[T]);
clP += 4;
clL += 4;
clR += 4;
tiPL += 16;
tiPR += 16;
}
}
}
else if (!strcmp(ratesModel, "ssgamma") || !strcmp(ratesModel, "ssadgamma"))
{
for (c=0; c<numChars; c++)
{
index = partitionId[c]*lnumRateCats*N_STATES_SQUARED;
tiPL = &pL[index];
tiPR = &pR[index];
for (k=0; k<lnumRateCats; k++)
{
clP[A] = (tiPL[AA]*clL[A] + tiPL[AC]*clL[C] + tiPL[AG]*clL[G] + tiPL[AT]*clL[T])
*(tiPR[AA]*clR[A] + tiPR[AC]*clR[C] + tiPR[AG]*clR[G] + tiPR[AT]*clR[T]);
clP[C] = (tiPL[CA]*clL[A] + tiPL[CC]*clL[C] + tiPL[CG]*clL[G] + tiPL[CT]*clL[T])
*(tiPR[CA]*clR[A] + tiPR[CC]*clR[C] + tiPR[CG]*clR[G] + tiPR[CT]*clR[T]);
clP[G] = (tiPL[GA]*clL[A] + tiPL[GC]*clL[C] + tiPL[GG]*clL[G] + tiPL[GT]*clL[T])
*(tiPR[GA]*clR[A] + tiPR[GC]*clR[C] + tiPR[GG]*clR[G] + tiPR[GT]*clR[T]);
clP[T] = (tiPL[TA]*clL[A] + tiPL[TC]*clL[C] + tiPL[TG]*clL[G] + tiPL[TT]*clL[T])
*(tiPR[TA]*clR[A] + tiPR[TC]*clR[C] + tiPR[TG]*clR[G] + tiPR[TT]*clR[T]);
clP += 4;
clL += 4;
clR += 4;
tiPL += 16;
tiPR += 16;
}
}
}
else if (!strcmp(ratesModel, "sitespec"))
{
for (c=0; c<numChars; c++)
{
index = partitionId[c]*N_STATES_SQUARED;
tiPL = &pL[index];
tiPR = &pR[index];
clP[A] = (tiPL[AA]*clL[A] + tiPL[AC]*clL[C] + tiPL[AG]*clL[G] + tiPL[AT]*clL[T])
*(tiPR[AA]*clR[A] + tiPR[AC]*clR[C] + tiPR[AG]*clR[G] + tiPR[AT]*clR[T]);
clP[C] = (tiPL[CA]*clL[A] + tiPL[CC]*clL[C] + tiPL[CG]*clL[G] + tiPL[CT]*clL[T])
*(tiPR[CA]*clR[A] + tiPR[CC]*clR[C] + tiPR[CG]*clR[G] + tiPR[CT]*clR[T]);
clP[G] = (tiPL[GA]*clL[A] + tiPL[GC]*clL[C] + tiPL[GG]*clL[G] + tiPL[GT]*clL[T])
*(tiPR[GA]*clR[A] + tiPR[GC]*clR[C] + tiPR[GG]*clR[G] + tiPR[GT]*clR[T]);
clP[T] = (tiPL[TA]*clL[A] + tiPL[TC]*clL[C] + tiPL[TG]*clL[G] + tiPL[TT]*clL[T])
*(tiPR[TA]*clR[A] + tiPR[TC]*clR[C] + tiPR[TG]*clR[G] + tiPR[TT]*clR[T]);
clP += 4;
clL += 4;
clR += 4;
}
}
}
}
/* get conditional probabilities of states at p */
//printf ("getting condlikes at p %d\n", p->index);
/* get transition probabilities */
# if defined (SMART_TI_PROBS)
if (p->left == NULL || p->right == NULL || p->anc == NULL)
{
if (p->anc == NULL)
pA = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (p->left->index)*nodeTiSize);
else
pA = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (p->index)*nodeTiSize);
}
else
{
pL = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (p->left->index)*nodeTiSize);
pR = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (p->right->index)*nodeTiSize);
pA = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (p->index)*nodeTiSize);
}
# else
if (nst == 1 || nst == 2)
{
if (p->left == NULL || p->right == NULL || p->anc == NULL)
{
if (p->anc == NULL)
v = p->left->length;
else
v = p->length;
for (m=indexL=indexR=indexA=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
theRate = partRate[m] * catRate[k];
/* calculate transition probabilities for ancestral branch */
HkyChangeMat (probs, v, lkappa, theRate, bs[A], bs[C], bs[G], bs[T]);
for (i=0; i<4; i++)
for (j=0; j<4; j++)
pA[indexA++] = probs[i][j];
}
}
}
else
{
for (m=indexL=indexR=indexA=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
theRate = partRate[m] * catRate[k];
/* calculate transition probabilities for left branch */
HkyChangeMat (probs, p->left->length, lkappa, theRate, bs[A], bs[C], bs[G], bs[T]);
for (i=0; i<4; i++)
for (j=0; j<4; j++)
pL[indexL++] = probs[i][j];
/* calculate transition probabilities for right branch */
HkyChangeMat (probs, p->right->length, lkappa, theRate, bs[A], bs[C], bs[G], bs[T]);
for (i=0; i<4; i++)
for (j=0; j<4; j++)
pR[indexR++] = probs[i][j];
/* calculate transition probabilities for ancestral branch */
HkyChangeMat (probs, p->length, lkappa, theRate, bs[A], bs[C], bs[G], bs[T]);
for (i=0; i<4; i++)
for (j=0; j<4; j++)
pA[indexA++] = probs[i][j];
}
}
}
}
else // nst == 6 or nst == 12
{
if (p->left == NULL || p->right == NULL || p->anc == NULL)
{
if (p->anc == NULL)
v = p->left->length;
else
v = p->length;
for (m=indexL=indexR=indexA=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
theRate = partRate[m] * catRate[k];
// calculate transition probabilities for ancestral branch
if (isComplex == NO)
CalcPij (c_ijk, 4, eigenValues, v, theRate, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, 4, probs, v, theRate) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<4; i++)
for (j=0; j<4; j++)
pA[indexA++] = probs[i][j];
}
}
}
else
{
for (m=indexL=indexR=indexA=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
theRate = partRate[m] * catRate[k];
// calculate transition probabilities for left branch
if (isComplex == NO)
CalcPij (c_ijk, 4, eigenValues, p->left->length, theRate, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, 4, probs, p->left->length, theRate) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<4; i++)
for (j=0; j<4; j++)
pL[indexL++] = probs[i][j];
// calculate transition probabilities for right branch
if (isComplex == NO)
CalcPij (c_ijk, 4, eigenValues, p->right->length, theRate, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, 4, probs, p->right->length, theRate) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<4; i++)
for (j=0; j<4; j++)
pR[indexR++] = probs[i][j];
// calculate transition probabilities for ancestral branch
if (isComplex == NO)
CalcPij (c_ijk, 4, eigenValues, p->length, theRate, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, 4, probs, p->length, theRate) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<4; i++)
for (j=0; j<4; j++)
pA[indexA++] = probs[i][j];
}
}
}
}
# endif
if (p->left == NULL || p->right == NULL || p->anc == NULL)
{
//clP = &condLike[condLikeOffset + (p->index)*oneNodeSize];
clP = ancCls;
if (p->anc == NULL)
clA = &condLike[condLikeOffset + (p->left->index)*oneNodeSize];
else
clA = &condLike[condLikeOffset + (p->anc->index)*oneNodeSize];
if (!strcmp(ratesModel, "equal"))
{
tiPA = pA;
for (c=0; c<numChars; c++)
{
clP[A] = (tiPA[AA]*clA[A] + tiPA[AC]*clA[C] + tiPA[AG]*clA[G] + tiPA[AT]*clA[T]);
clP[C] = (tiPA[CA]*clA[A] + tiPA[CC]*clA[C] + tiPA[CG]*clA[G] + tiPA[CT]*clA[T]);
clP[G] = (tiPA[GA]*clA[A] + tiPA[GC]*clA[C] + tiPA[GG]*clA[G] + tiPA[GT]*clA[T]);
clP[T] = (tiPA[TA]*clA[A] + tiPA[TC]*clA[C] + tiPA[TG]*clA[G] + tiPA[TT]*clA[T]);
clP += 4;
clA += 4;
}
}
else if (!strcmp(ratesModel, "gamma") || !strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "invariant") || !strcmp(ratesModel, "invgamma"))
{
for (c=0; c<numChars; c++)
{
tiPA = pA;
for (k=0; k<lnumRateCats; k++)
{
clP[A] = (tiPA[AA]*clA[A] + tiPA[AC]*clA[C] + tiPA[AG]*clA[G] + tiPA[AT]*clA[T]);
clP[C] = (tiPA[CA]*clA[A] + tiPA[CC]*clA[C] + tiPA[CG]*clA[G] + tiPA[CT]*clA[T]);
clP[G] = (tiPA[GA]*clA[A] + tiPA[GC]*clA[C] + tiPA[GG]*clA[G] + tiPA[GT]*clA[T]);
clP[T] = (tiPA[TA]*clA[A] + tiPA[TC]*clA[C] + tiPA[TG]*clA[G] + tiPA[TT]*clA[T]);
clP += 4;
clA += 4;
tiPA += 16;
}
}
}
else if (!strcmp(ratesModel, "ssgamma") || !strcmp(ratesModel, "ssadgamma"))
{
for (c=0; c<numChars; c++)
{
index = partitionId[c]*lnumRateCats*N_STATES_SQUARED;
tiPA = &pA[index];
for (k=0; k<lnumRateCats; k++)
{
clP[A] = (tiPA[AA]*clA[A] + tiPA[AC]*clA[C] + tiPA[AG]*clA[G] + tiPA[AT]*clA[T]);
clP[C] = (tiPA[CA]*clA[A] + tiPA[CC]*clA[C] + tiPA[CG]*clA[G] + tiPA[CT]*clA[T]);
clP[G] = (tiPA[GA]*clA[A] + tiPA[GC]*clA[C] + tiPA[GG]*clA[G] + tiPA[GT]*clA[T]);
clP[T] = (tiPA[TA]*clA[A] + tiPA[TC]*clA[C] + tiPA[TG]*clA[G] + tiPA[TT]*clA[T]);
clP += 4;
clA += 4;
tiPA += 16;
}
}
}
else if (!strcmp(ratesModel, "sitespec"))
{
for (c=0; c<numChars; c++)
{
index = partitionId[c]*N_STATES_SQUARED;
tiPA = &pA[index];
clP[A] = (tiPA[AA]*clA[A] + tiPA[AC]*clA[C] + tiPA[AG]*clA[G] + tiPA[AT]*clA[T]);
clP[C] = (tiPA[CA]*clA[A] + tiPA[CC]*clA[C] + tiPA[CG]*clA[G] + tiPA[CT]*clA[T]);
clP[G] = (tiPA[GA]*clA[A] + tiPA[GC]*clA[C] + tiPA[GG]*clA[G] + tiPA[GT]*clA[T]);
clP[T] = (tiPA[TA]*clA[A] + tiPA[TC]*clA[C] + tiPA[TG]*clA[G] + tiPA[TT]*clA[T]);
clP += 4;
clA += 4;
}
}
}
else
{
/* first set pointers to cond likes of left, right, p and anc */
clL = &condLike[condLikeOffset + (p->left->index)*oneNodeSize];
clR = &condLike[condLikeOffset + (p->right->index)*oneNodeSize];
clA = &condLike[condLikeOffset + (p->anc->index)*oneNodeSize];
//clP = &condLike[condLikeOffset + (p->index)*oneNodeSize];
clP = ancCls;
if (!strcmp(ratesModel, "equal"))
{
tiPL = pL;
tiPR = pR;
tiPA = pA;
for (c=0; c<numChars; c++)
{
clP[A] = (tiPL[AA]*clL[A] + tiPL[AC]*clL[C] + tiPL[AG]*clL[G] + tiPL[AT]*clL[T])
*(tiPR[AA]*clR[A] + tiPR[AC]*clR[C] + tiPR[AG]*clR[G] + tiPR[AT]*clR[T])
*(tiPA[AA]*clA[A] + tiPA[AC]*clA[C] + tiPA[AG]*clA[G] + tiPA[AT]*clA[T]);
clP[C] = (tiPL[CA]*clL[A] + tiPL[CC]*clL[C] + tiPL[CG]*clL[G] + tiPL[CT]*clL[T])
*(tiPR[CA]*clR[A] + tiPR[CC]*clR[C] + tiPR[CG]*clR[G] + tiPR[CT]*clR[T])
*(tiPA[CA]*clA[A] + tiPA[CC]*clA[C] + tiPA[CG]*clA[G] + tiPA[CT]*clA[T]);
clP[G] = (tiPL[GA]*clL[A] + tiPL[GC]*clL[C] + tiPL[GG]*clL[G] + tiPL[GT]*clL[T])
*(tiPR[GA]*clR[A] + tiPR[GC]*clR[C] + tiPR[GG]*clR[G] + tiPR[GT]*clR[T])
*(tiPA[GA]*clA[A] + tiPA[GC]*clA[C] + tiPA[GG]*clA[G] + tiPA[GT]*clA[T]);
clP[T] = (tiPL[TA]*clL[A] + tiPL[TC]*clL[C] + tiPL[TG]*clL[G] + tiPL[TT]*clL[T])
*(tiPR[TA]*clR[A] + tiPR[TC]*clR[C] + tiPR[TG]*clR[G] + tiPR[TT]*clR[T])
*(tiPA[TA]*clA[A] + tiPA[TC]*clA[C] + tiPA[TG]*clA[G] + tiPA[TT]*clA[T]);
clP += 4;
clL += 4;
clR += 4;
clA += 4;
}
}
else if (!strcmp(ratesModel, "gamma") || !strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "invariant") || !strcmp(ratesModel, "invgamma"))
{
for (c=0; c<numChars; c++)
{
tiPL = pL;
tiPR = pR;
tiPA = pA;
for (k=0; k<lnumRateCats; k++)
{
clP[A] = (tiPL[AA]*clL[A] + tiPL[AC]*clL[C] + tiPL[AG]*clL[G] + tiPL[AT]*clL[T])
*(tiPR[AA]*clR[A] + tiPR[AC]*clR[C] + tiPR[AG]*clR[G] + tiPR[AT]*clR[T])
*(tiPA[AA]*clA[A] + tiPA[AC]*clA[C] + tiPA[AG]*clA[G] + tiPA[AT]*clA[T]);
clP[C] = (tiPL[CA]*clL[A] + tiPL[CC]*clL[C] + tiPL[CG]*clL[G] + tiPL[CT]*clL[T])
*(tiPR[CA]*clR[A] + tiPR[CC]*clR[C] + tiPR[CG]*clR[G] + tiPR[CT]*clR[T])
*(tiPA[CA]*clA[A] + tiPA[CC]*clA[C] + tiPA[CG]*clA[G] + tiPA[CT]*clA[T]);
clP[G] = (tiPL[GA]*clL[A] + tiPL[GC]*clL[C] + tiPL[GG]*clL[G] + tiPL[GT]*clL[T])
*(tiPR[GA]*clR[A] + tiPR[GC]*clR[C] + tiPR[GG]*clR[G] + tiPR[GT]*clR[T])
*(tiPA[GA]*clA[A] + tiPA[GC]*clA[C] + tiPA[GG]*clA[G] + tiPA[GT]*clA[T]);
clP[T] = (tiPL[TA]*clL[A] + tiPL[TC]*clL[C] + tiPL[TG]*clL[G] + tiPL[TT]*clL[T])
*(tiPR[TA]*clR[A] + tiPR[TC]*clR[C] + tiPR[TG]*clR[G] + tiPR[TT]*clR[T])
*(tiPA[TA]*clA[A] + tiPA[TC]*clA[C] + tiPA[TG]*clA[G] + tiPA[TT]*clA[T]);
clP += 4;
clL += 4;
clR += 4;
clA += 4;
tiPL += 16;
tiPR += 16;
tiPA += 16;
}
}
}
else if (!strcmp(ratesModel, "ssgamma") || !strcmp(ratesModel, "ssadgamma"))
{
for (c=0; c<numChars; c++)
{
index = partitionId[c]*lnumRateCats*N_STATES_SQUARED;
tiPL = &pL[index];
tiPR = &pR[index];
tiPA = &pA[index];
for (k=0; k<lnumRateCats; k++)
{
clP[A] = (tiPL[AA]*clL[A] + tiPL[AC]*clL[C] + tiPL[AG]*clL[G] + tiPL[AT]*clL[T])
*(tiPR[AA]*clR[A] + tiPR[AC]*clR[C] + tiPR[AG]*clR[G] + tiPR[AT]*clR[T])
*(tiPA[AA]*clA[A] + tiPA[AC]*clA[C] + tiPA[AG]*clA[G] + tiPA[AT]*clA[T]);
clP[C] = (tiPL[CA]*clL[A] + tiPL[CC]*clL[C] + tiPL[CG]*clL[G] + tiPL[CT]*clL[T])
*(tiPR[CA]*clR[A] + tiPR[CC]*clR[C] + tiPR[CG]*clR[G] + tiPR[CT]*clR[T])
*(tiPA[CA]*clA[A] + tiPA[CC]*clA[C] + tiPA[CG]*clA[G] + tiPA[CT]*clA[T]);
clP[G] = (tiPL[GA]*clL[A] + tiPL[GC]*clL[C] + tiPL[GG]*clL[G] + tiPL[GT]*clL[T])
*(tiPR[GA]*clR[A] + tiPR[GC]*clR[C] + tiPR[GG]*clR[G] + tiPR[GT]*clR[T])
*(tiPA[GA]*clA[A] + tiPA[GC]*clA[C] + tiPA[GG]*clA[G] + tiPA[GT]*clA[T]);
clP[T] = (tiPL[TA]*clL[A] + tiPL[TC]*clL[C] + tiPL[TG]*clL[G] + tiPL[TT]*clL[T])
*(tiPR[TA]*clR[A] + tiPR[TC]*clR[C] + tiPR[TG]*clR[G] + tiPR[TT]*clR[T])
*(tiPA[TA]*clA[A] + tiPA[TC]*clA[C] + tiPA[TG]*clA[G] + tiPA[TT]*clA[T]);
clP += 4;
clL += 4;
clR += 4;
clA += 4;
tiPL += 16;
tiPR += 16;
tiPA += 16;
}
}
}
else if (!strcmp(ratesModel, "sitespec"))
{
for (c=0; c<numChars; c++)
{
index = partitionId[c]*N_STATES_SQUARED;
tiPL = &pL[index];
tiPR = &pR[index];
tiPA = &pA[index];
clP[A] = (tiPL[AA]*clL[A] + tiPL[AC]*clL[C] + tiPL[AG]*clL[G] + tiPL[AT]*clL[T])
*(tiPR[AA]*clR[A] + tiPR[AC]*clR[C] + tiPR[AG]*clR[G] + tiPR[AT]*clR[T])
*(tiPA[AA]*clA[A] + tiPA[AC]*clA[C] + tiPA[AG]*clA[G] + tiPA[AT]*clA[T]);
clP[C] = (tiPL[CA]*clL[A] + tiPL[CC]*clL[C] + tiPL[CG]*clL[G] + tiPL[CT]*clL[T])
*(tiPR[CA]*clR[A] + tiPR[CC]*clR[C] + tiPR[CG]*clR[G] + tiPR[CT]*clR[T])
*(tiPA[CA]*clA[A] + tiPA[CC]*clA[C] + tiPA[CG]*clA[G] + tiPA[CT]*clA[T]);
clP[G] = (tiPL[GA]*clL[A] + tiPL[GC]*clL[C] + tiPL[GG]*clL[G] + tiPL[GT]*clL[T])
*(tiPR[GA]*clR[A] + tiPR[GC]*clR[C] + tiPR[GG]*clR[G] + tiPR[GT]*clR[T])
*(tiPA[GA]*clA[A] + tiPA[GC]*clA[C] + tiPA[GG]*clA[G] + tiPA[GT]*clA[T]);
clP[T] = (tiPL[TA]*clL[A] + tiPL[TC]*clL[C] + tiPL[TG]*clL[G] + tiPL[TT]*clL[T])
*(tiPR[TA]*clR[A] + tiPR[TC]*clR[C] + tiPR[TG]*clR[G] + tiPR[TT]*clR[T])
*(tiPA[TA]*clA[A] + tiPA[TC]*clA[C] + tiPA[TG]*clA[G] + tiPA[TT]*clA[T]);
clP += 4;
clL += 4;
clR += 4;
clA += 4;
}
}
}
/* calculate posterior probability of states at p */
//clP = &condLike[condLikeOffset + (p->index)*oneNodeSize];
clP = ancCls;
if (!strcmp(ratesModel, "equal") || !strcmp(ratesModel, "sitespec"))
{
for (c=0; c<nChar; c++)
{
pat = patternId[c];
if (pat >= 0)
{
like[A] = clP[pat*4 + A];
like[C] = clP[pat*4 + C];
like[G] = clP[pat*4 + G];
like[T] = clP[pat*4 + T];
sum = like[A] * bs[A] + like[C] * bs[C] + like[G] * bs[G] + like[T] * bs[T];
postProb[A] = (like[A] * bs[A]) / sum;
postProb[C] = (like[C] * bs[C]) / sum;
postProb[G] = (like[G] * bs[G]) / sum;
postProb[T] = (like[T] * bs[T]) / sum;
tempStateProbs[(p->constraintNum-1)*nChar*4 + c*4 + A] = postProb[A];
tempStateProbs[(p->constraintNum-1)*nChar*4 + c*4 + C] = postProb[C];
tempStateProbs[(p->constraintNum-1)*nChar*4 + c*4 + G] = postProb[G];
tempStateProbs[(p->constraintNum-1)*nChar*4 + c*4 + T] = postProb[T];
ancStatesProbs[(p->constraintNum-1)*nChar*4 + c*4 + A] += postProb[A];
ancStatesProbs[(p->constraintNum-1)*nChar*4 + c*4 + C] += postProb[C];
ancStatesProbs[(p->constraintNum-1)*nChar*4 + c*4 + G] += postProb[G];
ancStatesProbs[(p->constraintNum-1)*nChar*4 + c*4 + T] += postProb[T];
}
}
}
else if (!strcmp(ratesModel, "gamma") || !strcmp(ratesModel, "invariant") || !strcmp(ratesModel, "invgamma") || !strcmp(ratesModel, "ssgamma"))
{
for (c=0; c<nChar; c++)
{
pat = patternId[c];
if (pat >= 0)
{
like[A] = like[C] = like[G] = like[T] = 0.0;
for (k=0; k<lnumRateCats; k++)
{
like[A] += clP[pat*lnumRateCats*4 + k*4 + A] * catFreq[k];
like[C] += clP[pat*lnumRateCats*4 + k*4 + C] * catFreq[k];
like[G] += clP[pat*lnumRateCats*4 + k*4 + G] * catFreq[k];
like[T] += clP[pat*lnumRateCats*4 + k*4 + T] * catFreq[k];
}
sum = like[A] * bs[A] + like[C] * bs[C] + like[G] * bs[G] + like[T] * bs[T];
postProb[A] = (like[A] * bs[A]) / sum;
postProb[C] = (like[C] * bs[C]) / sum;
postProb[G] = (like[G] * bs[G]) / sum;
postProb[T] = (like[T] * bs[T]) / sum;
tempStateProbs[(p->constraintNum-1)*nChar*4 + c*4 + A] = postProb[A];
tempStateProbs[(p->constraintNum-1)*nChar*4 + c*4 + C] = postProb[C];
tempStateProbs[(p->constraintNum-1)*nChar*4 + c*4 + G] = postProb[G];
tempStateProbs[(p->constraintNum-1)*nChar*4 + c*4 + T] = postProb[T];
ancStatesProbs[(p->constraintNum-1)*nChar*4 + c*4 + A] += postProb[A];
ancStatesProbs[(p->constraintNum-1)*nChar*4 + c*4 + C] += postProb[C];
ancStatesProbs[(p->constraintNum-1)*nChar*4 + c*4 + G] += postProb[G];
ancStatesProbs[(p->constraintNum-1)*nChar*4 + c*4 + T] += postProb[T];
}
}
}
else if (!strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "ssadgamma"))
{
/* get probabilities of observations conditioned on each category */
for (c=0; c<numChars; c++)
{
for (k=0; k<lnumRateCats; k++)
{
tempRatePr[k * numChars + c] = clP[A]*bs[A] + clP[C]*bs[C] + clP[G]*bs[G] + clP[T]*bs[T];
clP += 4;
}
}
/* forward algorithm */
logC = 0.0;
for (c=0; c<nChar; c++)
{
if (patternId[c] >= 0)
{
pat = patternId[c];
if (c == 0)
{
for (k=0; k<lnumRateCats; k++)
f[k*nChar + c] = tempRatePr[k * numChars + pat];
}
else
{
for (l=0; l<lnumRateCats; l++)
{
temp = 0.0;
for (k=0; k<lnumRateCats; k++)
temp += f[k * nChar + (c-1)] * markovTi[k][l];
f[l * nChar + c] = temp * tempRatePr[l * numChars + pat];
}
}
sum = 0.0;
for (k=0; k<lnumRateCats; k++)
sum += f[k*nChar + c];
for (k=0; k<lnumRateCats; k++)
f[k*nChar+c] /= sum;
logC += log(sum);
logCf[c] = logC;
}
else
{
}
}
/* backward algorithm */
logC = 0.0;
for (c=nChar-1; c>=0; c--)
{
if (patternId[c] >= 0)
{
if (c == nChar - 1)
{
for (k=0; k<lnumRateCats; k++)
b[k * nChar + c] = catFreq[k];
}
else
{
pat = patternId[c+1];
for (k=0; k<lnumRateCats; k++)
{
temp = 0.0;
for (l=0; l<lnumRateCats; l++)
temp += markovTi[k][l] * tempRatePr[l * numChars + pat] * b[l * nChar + (c+1)];
b[k * nChar + c] = temp;
}
}
sum = 0.0;
for (k=0; k<lnumRateCats; k++)
sum += b[k*nChar + c];
for (k=0; k<lnumRateCats; k++)
b[k*nChar+c] /= sum;
logC += log(sum);
logCb[c] = logC;
}
else
{
}
}
temp = 0.0;
pat = patternId[0];
for (l=0; l<lnumRateCats; l++)
temp += tempRatePr[l * numChars + pat] * b[l * nChar + 0];
logLike = log (temp) + logC;
/* posterior probabilities of individual categories at site c */
for (c=0; c<nChar; c++)
{
/*printf ("%d ", c+1);*/
for (k=0; k<lnumRateCats; k++)
{
temp = (log(f[k * nChar + c]) + logCf[c] + log(b[k * nChar + c]) + logCb[c]) - logLike;
if (temp > 0.0)
expPr[k] = 1.0;
else if (temp < -100.0)
expPr[k] = 0.0;
else
expPr[k] = exp(temp);
}
for (k=0; k<lnumRateCats; k++)
{
rateProbs[c*lnumRateCats + k] += expPr[k];
}
}
//clP = &condLike[condLikeOffset + (p->index)*oneNodeSize];
clP = ancCls;
for (c=0; c<nChar; c++)
{
pat = patternId[c];
like[A] = like[C] = like[G] = like[T] = 0.0;
for (k=0; k<lnumRateCats; k++)
{
like[A] += clP[pat*lnumRateCats*4 + k*4 + A] * rateProbs[c*lnumRateCats + k];
like[C] += clP[pat*lnumRateCats*4 + k*4 + C] * rateProbs[c*lnumRateCats + k];
like[G] += clP[pat*lnumRateCats*4 + k*4 + G] * rateProbs[c*lnumRateCats + k];
like[T] += clP[pat*lnumRateCats*4 + k*4 + T] * rateProbs[c*lnumRateCats + k];
}
sum = like[A] * bs[A] + like[C] * bs[C] + like[G] * bs[G] + like[T] * bs[T];
postProb[A] = (like[A] * bs[A]) / sum;
postProb[C] = (like[C] * bs[C]) / sum;
postProb[G] = (like[G] * bs[G]) / sum;
postProb[T] = (like[T] * bs[T]) / sum;
tempStateProbs[(p->constraintNum-1)*nChar*4 + c*4 + A] = postProb[A];
tempStateProbs[(p->constraintNum-1)*nChar*4 + c*4 + C] = postProb[C];
tempStateProbs[(p->constraintNum-1)*nChar*4 + c*4 + G] = postProb[G];
tempStateProbs[(p->constraintNum-1)*nChar*4 + c*4 + T] = postProb[T];
ancStatesProbs[(p->constraintNum-1)*nChar*4 + c*4 + A] += postProb[A];
ancStatesProbs[(p->constraintNum-1)*nChar*4 + c*4 + C] += postProb[C];
ancStatesProbs[(p->constraintNum-1)*nChar*4 + c*4 + G] += postProb[G];
ancStatesProbs[(p->constraintNum-1)*nChar*4 + c*4 + T] += postProb[T];
}
}
}
}
/* summarize states */
/* print probabilities to a file */
strcpy (tempFileA, outFile);
strcpy (tempFileC, outFile);
strcpy (tempFileG, outFile);
strcpy (tempFileT, outFile);
strcat (tempFileA, ".A.");
strcat (tempFileC, ".C.");
strcat (tempFileG, ".G.");
strcat (tempFileT, ".T.");
if (nSampled == 1)
{
if (saveAncFiles == YES)
startingJ = 0;
else
startingJ = 4;
for (j=startingJ; j<5; j++)
{
if (j == 0)
strcpy (tempFile, tempFileA);
else if (j == 1)
strcpy (tempFile, tempFileC);
else if (j == 2)
strcpy (tempFile, tempFileG);
else if (j == 3)
strcpy (tempFile, tempFileT);
else
{
strcpy (tempFile, outFile);
strcat (tempFile, ".sum.");
}
for (i=0; i<nConstraints; i++)
{
strcat (tempFile, "1");
#if defined (MORPH)
fp = OpenFile(tempFile, NO);
if (fp == NULL)
{
printf ("\n ERROR: Could not open file (%s).\n", tempFile);
goto error_exit;
}
#else
if ((fp = fopen (tempFile, "r")) == NULL)
{
if ((fp = fopen (tempFile, "w")) == NULL)
{
printf ("\n ERROR: Could not open file (%s).\n", tempFile);
goto error_exit;
}
}
else
{
fclose (fp);
if (autoclose == YES)
{
printf (" Overwriting information to file %s\n", tempFile);
if ((fp = fopen (tempFile, "w+")) == NULL)
{
printf ("\n ERROR: Could not open file (%s).\n", tempFile);
goto error_exit;
}
}
else
{
printf ("\n File \"%s\" already exists.\n Overwrite? (yes/no): ", tempFile);
if (YesNo() == YES)
{
printf (" Overwriting information to file %s\n", tempFile);
if ((fp = fopen (tempFile, "w+")) == NULL)
{
printf ("\n ERROR: Could not open file (%s).\n", tempFile);
goto error_exit;
}
}
else
{
printf (" Appending information to file %s\n", tempFile);
if ((fp = fopen (tempFile, "a+")) == NULL)
{
printf ("\n ERROR: Could not open file (%s).\n", tempFile);
goto error_exit;
}
}
}
}
#endif
fclose (fp);
}
}
}
/* A */
if (saveAncFiles == YES)
{
strcpy (tempFile, tempFileA);
for (i=0; i<nConstraints; i++)
{
strcat (tempFile, "1");
if ((fp = fopen (tempFile, "a+")) == NULL)
{
printf ("\n ERROR: Could not open file (%s).\n", tempFile);
goto error_exit;
}
if (whichGen == 1)
{
fprintf (fp, "Ancestral states for nucleotide A at constraint \"");
k = 0;
while (constraintLabels[i][k] != '|' && k < 99)
{
fprintf (fp, "%c", constraintLabels[i][k]);
k++;
}
fprintf (fp, "\"\n");
}
for (c=0; c<nChar; c++)
{
if (patternId[c] >= 0)
{
pat = patternId[c];
fprintf (fp, "%lf\t", tempStateProbs[i*nChar*4 + c*4 + A]);
}
}
fprintf (fp, "\n");
fclose (fp);
}
/* C */
strcpy (tempFile, tempFileC);
for (i=0; i<nConstraints; i++)
{
strcat (tempFile, "1");
if ((fp = fopen (tempFile, "a+")) == NULL)
{
printf ("\n ERROR: Could not open file (%s).\n", tempFile);
goto error_exit;
}
if (whichGen == 1)
{
fprintf (fp, "Ancestral states for nucleotide C at constraint \"");
k = 0;
while (constraintLabels[i][k] != '|' && k < 99)
{
fprintf (fp, "%c", constraintLabels[i][k]);
k++;
}
fprintf (fp, "\"\n");
}
for (c=0; c<nChar; c++)
{
if (patternId[c] >= 0)
{
pat = patternId[c];
fprintf (fp, "%lf\t", tempStateProbs[i*nChar*4 + c*4 + C]);
}
}
fprintf (fp, "\n");
fclose (fp);
}
/* G */
strcpy (tempFile, tempFileG);
for (i=0; i<nConstraints; i++)
{
strcat (tempFile, "1");
if ((fp = fopen (tempFile, "a+")) == NULL)
{
printf ("\n ERROR: Could not open file (%s).\n", tempFile);
goto error_exit;
}
if (whichGen == 1)
{
fprintf (fp, "Ancestral states for nucleotide G at constraint \"");
k = 0;
while (constraintLabels[i][k] != '|' && k < 99)
{
fprintf (fp, "%c", constraintLabels[i][k]);
k++;
}
fprintf (fp, "\"\n");
}
for (c=0; c<nChar; c++)
{
if (patternId[c] >= 0)
{
pat = patternId[c];
fprintf (fp, "%lf\t", tempStateProbs[i*nChar*4 + c*4 + G]);
}
}
fprintf (fp, "\n");
fclose (fp);
}
/* T */
strcpy (tempFile, tempFileT);
for (i=0; i<nConstraints; i++)
{
strcat (tempFile, "1");
if ((fp = fopen (tempFile, "a+")) == NULL)
{
printf ("\n ERROR: Could not open file (%s).\n", tempFile);
goto error_exit;
}
if (whichGen == 1)
{
fprintf (fp, "Ancestral states for nucleotide T at constraint \"");
k = 0;
while (constraintLabels[i][k] != '|' && k < 99)
{
fprintf (fp, "%c", constraintLabels[i][k]);
k++;
}
fprintf (fp, "\"\n");
}
for (c=0; c<nChar; c++)
{
if (patternId[c] >= 0)
{
pat = patternId[c];
fprintf (fp, "%lf\t", tempStateProbs[i*nChar*4 + c*4 + T]);
}
}
fprintf (fp, "\n");
fclose (fp);
}
}
/* summarize states */
if (whichGen == nGen && nSampled >= 1)
{
strcpy (tempFile, outFile);
strcat (tempFile, ".sum.");
for (i=0; i<nConstraints; i++)
{
strcat (tempFile, "1");
if ((fp = fopen (tempFile, "a+")) == NULL)
{
printf ("\n ERROR: Could not open file (%s).\n", tempFile);
goto error_exit;
}
fprintf (fp, "Summary of ancestral states at constraint \"");
k = 0;
while (constraintLabels[i][k] != '|' && k < 99)
{
fprintf (fp, "%c", constraintLabels[i][k]);
k++;
}
fprintf (fp, "\"\n");
lnSeqProb = 0.0;
for (c=0; c<nChar; c++)
{
if (patternId[c] >= 0)
{
pat = patternId[c];
fprintf (fp, "%4d %4d -- ", c+1, pat);
fprintf (fp, "%lf %lf %lf %lf ",
ancStatesProbs[i*nChar*4 + c*4 + A] / nSampled, ancStatesProbs[i*nChar*4 + c*4 + C] / nSampled,
ancStatesProbs[i*nChar*4 + c*4 + G] / nSampled, ancStatesProbs[i*nChar*4 + c*4 + T] / nSampled);
maxProb = -1.0;
bestNuc = 'N';
if (ancStatesProbs[i*nChar*4 + c*4 + A] > maxProb)
{
maxProb = ancStatesProbs[i*nChar*4 + c*4 + A];
bestNuc = 'A';
}
if (ancStatesProbs[i*nChar*4 + c*4 + C] > maxProb)
{
maxProb = ancStatesProbs[i*nChar*4 + c*4 + C];
bestNuc = 'C';
}
if (ancStatesProbs[i*nChar*4 + c*4 + G] > maxProb)
{
maxProb = ancStatesProbs[i*nChar*4 + c*4 + G];
bestNuc = 'G';
}
if (ancStatesProbs[i*nChar*4 + c*4 + T] > maxProb)
{
maxProb = ancStatesProbs[i*nChar*4 + c*4 + T];
bestNuc = 'T';
}
lnSeqProb += log(maxProb/nSampled);
fprintf (fp, "%c\n", bestNuc);
}
}
fprintf (fp, "Most probable sequence [ln(Probability) = %lf]:\n", lnSeqProb);
for (c=0; c<nChar; c++)
{
if (patternId[c] >= 0)
{
pat = patternId[c];
maxProb = -1.0;
bestNuc = 'N';
if (ancStatesProbs[i*nChar*4 + c*4 + A] > maxProb)
{
maxProb = ancStatesProbs[i*nChar*4 + c*4 + A];
bestNuc = 'A';
}
if (ancStatesProbs[i*nChar*4 + c*4 + C] > maxProb)
{
maxProb = ancStatesProbs[i*nChar*4 + c*4 + C];
bestNuc = 'C';
}
if (ancStatesProbs[i*nChar*4 + c*4 + G] > maxProb)
{
maxProb = ancStatesProbs[i*nChar*4 + c*4 + G];
bestNuc = 'G';
}
if (ancStatesProbs[i*nChar*4 + c*4 + T] > maxProb)
{
maxProb = ancStatesProbs[i*nChar*4 + c*4 + T];
bestNuc = 'T';
}
fprintf (fp, "%c", bestNuc);
}
}
fprintf (fp, "\n");
fclose (fp);
}
}
/* free memory */
# if !defined (SMART_TI_PROBS)
free_psdmatrix (probs);
free (pL);
if (nst == 6 || nst == 12)
{
free_psdmatrix (q);
free (eigenValues);
free_psdmatrix (eigvecs);
free_psdmatrix (inverseEigvecs);
free_pscmatrix (Ceigvecs);
free_pscmatrix (CinverseEigvecs);
if (isComplex != YES)
free (c_ijk);
}
# endif
free (catFreq);
free (ancCls);
if (!strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "ssadgamma"))
{
free_psdmatrix(markovTi);
free (f);
free (tempRatePr);
}
return (NO_ERROR);
error_exit:
# if !defined (SMART_TI_PROBS)
free_psdmatrix (probs);
free (pL);
if (nst == 6 || nst == 12)
{
free_psdmatrix (q);
free (eigenValues);
free_psdmatrix (eigvecs);
free_psdmatrix (inverseEigvecs);
free_pscmatrix (Ceigvecs);
free_pscmatrix (CinverseEigvecs);
if (isComplex != YES)
free (c_ijk);
}
# endif
free (catFreq);
free (ancCls);
if (!strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "ssadgamma"))
{
free_psdmatrix(markovTi);
free (f);
free (tempRatePr);
}
return (ERROR);
#undef N_STATES
#undef N_STATES_SQUARED
#undef N_STATES_CUBE
}
int PrintAncStatesAA (int whichState, int whichChain, int numChars, int numRateCats, int whichGen)
{
#define N_STATES 20
#define N_STATES_SQUARED 400
#define N_STATES_CUBE 8000
register int i, j, k, c, m, n, n1, l;
int lnumRateCats, lnPartitions, oneMatSize, oneNodeSize,
index, nRates, pat,
intNodeOffset, allNodeOffset, condLikeOffset;
double bs[N_STATES], *pL, *pR, *pA, *catFreq, *catRate, *partRate,
*clL, *clR, *clA, *clP, *ancCls,
*lnScaler, correlation, lnSeqProb, maxProb,
**markovTi, like[N_STATES], sum, postProb[N_STATES], *f, *b, *expPr, *logCf,
*logCb, *tempRatePr, *rateProbs, logC, temp, logLike, likeL, likeR, likeA;
char tempFile[100], bestNuc;
TreeNode *p, *r, *rDn, *rUp;
FILE *fp, *fopen();
# if defined (SMART_TI_PROBS)
int nForOneState;
# else
int isComplex, indexL, indexR, indexA, nPij;
double v, theRate, **probs, **q, *eigenValues, *eigvalsImag, **eigvecs, **inverseEigvecs, *c_ijk;
complex **Ceigvecs, **CinverseEigvecs;
# endif
/* initialize intNodeOffset */
intNodeOffset = whichChain*2*numIntNodes + whichState*numIntNodes;
allNodeOffset = whichChain*2*numNodes + whichState*numNodes;
/* initialize offset for transition probabilities */
# if defined (SMART_TI_PROBS)
nForOneState = numNodes*nodeTiSize;
# endif
/* load base frequencies */
index = whichChain*2*N_STATES + whichState*N_STATES;
for (i=0; i<N_STATES; i++)
bs[i] = baseFreq[index + i];
/* how many different rates? */
/* lnumRateCats contains a local copy of numRateCats if appropriate, else 1 */
/* lnPartitions contains a local copy of nPartitions if appropriate, else 1 */
/* the code introduced here only makes sure that the number of partitions */
/* or rate categories is set to 1 when appropriate, in case the global variables */
/* are not set to 1 when they are not "in use" */
if (!strcmp(ratesModel, "sitespec") || !strcmp(ratesModel, "ssgamma") || !strcmp(ratesModel, "ssadgamma"))
lnPartitions = nPartitions;
else
lnPartitions = 1;
if (!strcmp(ratesModel, "equal") || !strcmp(ratesModel, "sitespec"))
lnumRateCats = 1;
else
lnumRateCats = numRateCats;
nRates = lnPartitions * lnumRateCats; // number of rates needing P matrices
/* allocate memory for the calculations */
/* pL, pR and pA will contain the transition probs for Left, Right and Anc */
/* One transition probability matrix is needed for each possible rate */
# if !defined (SMART_TI_PROBS)
probs = psdmatrix (N_STATES);
nPij = nRates * N_STATES_SQUARED;
pL = (double *)malloc((size_t)(3 * nPij * sizeof(double)));
if (!pL)
{
printf ("\n ERROR: Problem allocating Pij\n");
goto error_exit;
}
pR = pL + nPij;
pA = pR + nPij;
# endif
/* allocate memory for rate and rate category frequencies */
catFreq = (double *)malloc((size_t) ((2 * lnumRateCats + lnPartitions) * sizeof(double)));
if (!catFreq)
{
printf ("\n ERROR: Problem allocating space for rate multipliers and rate category freqs.\n");
goto error_exit;
}
catRate = catFreq + lnumRateCats;
partRate = catRate + lnumRateCats;
/* allocate memory for ancestral conditional likelihoods (it may be a tip, and we don't want to overwrite these cls) */
ancCls = (double *)malloc((size_t) (lnumRateCats * numChars * N_STATES * sizeof(double)));
if (!ancCls)
{
printf ("\n ERROR: Problem allocating space for rate multipliers and rate category freqs.\n");
goto error_exit;
}
/* allocate memory for autocorrelated gamma models */
if (!strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "ssadgamma"))
{
f = (double *)malloc((size_t) (((lnumRateCats * nChar) * 2 + lnumRateCats + nChar*2) * sizeof(double)));
if (!f)
{
printf ("\n ERROR: Problem allocating f.\n");
goto error_exit;
}
b = f + lnumRateCats * nChar;
expPr = b + lnumRateCats * nChar;
logCf = expPr + lnumRateCats;
logCb = logCf + nChar;
for (i=0; i<lnumRateCats*nChar; i++)
f[i] = b[i] = 0.0;
for (i=0; i<lnumRateCats; i++)
expPr[i] = 0.0;
for (i=0; i<nChar; i++)
logCf[i] = logCb[i] = 0.0;
tempRatePr = (double *)malloc((size_t) ((numChars * lnumRateCats + nChar * lnumRateCats) * sizeof(double)));
if (!tempRatePr)
{
printf ("\n ERROR: Problem allocating tempRatePr.\n");
goto error_exit;
}
rateProbs = tempRatePr + numChars * lnumRateCats;
for (i=0; i<nChar * lnumRateCats; i++)
rateProbs[i] = 0.0;
}
// set pointer to the lnSiteScaler for this tree
lnScaler = &lnSiteScaler[whichChain * 2 * numChars + whichState * numChars];
/* fill in rate categories with frequencies and rates by dividing the */
/* gamma distribution into discrete categories, if appropriate */
/* NB! this is inefficient; store values instead */
if (!strcmp(ratesModel,"gamma")|| !strcmp(ratesModel, "ssgamma"))
{
DiscreteGamma (catFreq, catRate, alpha[whichChain*2 + whichState], alpha[whichChain*2 + whichState], lnumRateCats, 0);
}
else if (!strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "ssadgamma"))
{
markovTi = psdmatrix (lnumRateCats);
AutodGamma (markovTi, catFreq, catRate, &correlation, alpha[whichChain*2 + whichState], rateCorrelation[whichChain*2 + whichState], lnumRateCats);
}
else if (!strcmp(ratesModel, "invgamma"))
{
DiscreteGamma (catFreq, catRate, alpha[whichChain*2 + whichState], alpha[whichChain*2 + whichState], lnumRateCats-1, 0);
catRate[lnumRateCats-1] = 0.0;
catFreq[lnumRateCats-1] = invP[whichChain*2 + whichState];
for (i=0; i<lnumRateCats-1; i++)
{
catRate[i] *= 1.0 / (1.0 - invP[whichChain*2 + whichState]);
catFreq[i] *= (1.0 - invP[whichChain*2 + whichState]);
}
}
else if (!strcmp(ratesModel, "invariant"))
{
catRate[0] = 0.0;
catRate[1] = 1.0 / (1.0 - invP[whichChain*2 + whichState]);
catFreq[0] = invP[whichChain*2 + whichState];
catFreq[1] = 1.0 - invP[whichChain*2 + whichState];
}
else { // "sitespec" or "equal"
catRate[0] = 1.0;
catFreq[0] = 1.0;
}
/* initialize partition rates, if appropriate */
if (lnPartitions > 1)
{
for (i=0; i<lnPartitions; i++)
partRate[i] = scaledRates[whichChain*2*lnPartitions + whichState*lnPartitions + i];
}
else
partRate[0] = 1.0;
/* get eigenvalues and eigenvectors if nst=6 or nst=12 */
# if !defined (SMART_TI_PROBS)
q = psdmatrix (N_STATES);
eigenValues = (double *)malloc((size_t) (2 * N_STATES * sizeof(double)));
if (!eigenValues)
{
printf ("\n ERROR: Problem allocating eigenValues and eigvalsImag.\n");
goto error_exit;
}
eigvalsImag = eigenValues + N_STATES;
eigvecs = psdmatrix (N_STATES);
inverseEigvecs = psdmatrix (N_STATES);
Ceigvecs = pscmatrix (N_STATES);
CinverseEigvecs = pscmatrix (N_STATES);
if (SetAAQMatrix (q, whichState, whichChain) == ERROR)
goto error_exit;
isComplex = GetEigens (N_STATES, q, eigenValues, eigvalsImag, eigvecs, inverseEigvecs, Ceigvecs, CinverseEigvecs);
if (isComplex == NO)
{
c_ijk = (double *)malloc((size_t) (N_STATES_CUBE * sizeof(double)));
if (!c_ijk)
{
printf ("\n ERROR: Problem allocating c_ijk.\n");
goto error_exit;
}
CalcCijk (c_ijk, N_STATES, eigvecs, inverseEigvecs);
}
# endif
/* how large is the information for one tree and one node*/
oneMatSize = numNodes * numChars * lnumRateCats * N_STATES;
oneNodeSize = numChars * lnumRateCats * N_STATES;
/* offset for conditional likelihoods */
condLikeOffset = whichChain*2*oneMatSize + whichState*oneMatSize;
/* pass down tree, finding nodes that are to have ancestral states estimated */
for (n=0; n<numNodes; n++)
{
p = allNodesDownPassSeq[allNodeOffset + n];
if (p->isConstrained == YES)
{
/* mark nodes below p */
for (n1=0; n1<numNodes; n1++)
{
r = allNodesDownPassSeq[allNodeOffset + n1];
r->flag = 0;
if (r == p)
r->flag = 1;
if (r->left != NULL && r->right != NULL)
{
if (r->left->flag == 1 || r->right->flag == 1)
r->flag = 1;
}
}
/* get conditional likelihoods down tree */
for (n1=0; n1<numIntNodes; n1++)
{
r = intNodeDownPassSeq[intNodeOffset + n1];
if (r->flag != 1)
{
//printf ("visiting interior node %d dn\n", r->index);
/* get transition probabilities */
# if defined (SMART_TI_PROBS)
pL = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (r->left->index)*nodeTiSize);
pR = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (r->right->index)*nodeTiSize);
# else
for (m=indexL=indexR=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
theRate = partRate[m] * catRate[k];
// calculate transition probabilities for left branch
if (isComplex == NO)
CalcPij (c_ijk, N_STATES, eigenValues, r->left->length, theRate, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, N_STATES, probs, r->left->length, theRate) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<N_STATES; i++)
for (j=0; j<N_STATES; j++)
pL[indexL++] = probs[i][j];
// calculate transition probabilities for right branch
if (isComplex == NO)
CalcPij (c_ijk, N_STATES, eigenValues, r->right->length, theRate, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, N_STATES, probs, r->right->length, theRate) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<N_STATES; i++)
for (j=0; j<N_STATES; j++)
pR[indexR++] = probs[i][j];
}
}
# endif
/* first set pointers to cond likes of left, right and p */
clL = &condLike[condLikeOffset + (r->left->index)*oneNodeSize];
clR = &condLike[condLikeOffset + (r->right->index)*oneNodeSize];
clP = &condLike[condLikeOffset + (r->index)*oneNodeSize];
if (!strcmp(ratesModel, "equal"))
{
for (c=0; c<numChars; c++)
{
for (i=m=0; i<N_STATES; i++)
{
likeL = likeR = 0.0;
for (j=0; j<N_STATES; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m++]*clR[j];
}
*(clP++) = likeL * likeR;
}
clL += N_STATES;
clR += N_STATES;
}
}
else if (!strcmp(ratesModel, "gamma") || !strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "invariant") || !strcmp(ratesModel, "invgamma"))
{
for (c=0; c<numChars; c++)
{
for (k=m=0; k<lnumRateCats; k++)
{
for (i=0; i<N_STATES; i++)
{
likeL = likeR = 0.0;
for (j=0; j<N_STATES; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m++]*clR[j];
}
*(clP++) = likeL * likeR;
}
clL += N_STATES;
clR += N_STATES;
}
}
}
else if (!strcmp(ratesModel, "ssgamma") || !strcmp(ratesModel, "ssadgamma"))
{
for (c=0; c<numChars; c++)
{
m = partitionId[c]*lnumRateCats*N_STATES_SQUARED;
for (k=0; k<lnumRateCats; k++)
{
for (i=0; i<N_STATES; i++)
{
likeL = likeR = 0.0;
for (j=0; j<N_STATES; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m++]*clR[j];
}
*(clP++) = likeL * likeR;
}
clL += N_STATES;
clR += N_STATES;
}
}
}
else if (!strcmp(ratesModel, "sitespec"))
{
for (c=0; c<numChars; c++)
{
m = partitionId[c]*N_STATES_SQUARED;
for (i=0; i<N_STATES; i++)
{
likeL = likeR = 0.0;
for (j=0; j<N_STATES; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m++]*clR[j];
}
*(clP++) = likeL * likeR;
}
clL += N_STATES;
clR += N_STATES;
}
}
}
}
/* get conditional likelihoods up tree */
for (n1=numIntNodes-1; n1>=0; n1--)
{
r = intNodeDownPassSeq[intNodeOffset + n1];
if (r->flag == 1 && p != r)
{
rDn = r->anc;
if (r->left->flag == 0)
rUp = r->left;
else
rUp = r->right;
//printf ("visiting interior node %d up\n", r->index);
/* get transition probabilities */
# if defined (SMART_TI_PROBS)
pL = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (rUp->index)*nodeTiSize);
pR = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (r->index)*nodeTiSize);
# else
for (m=indexL=indexR=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
theRate = partRate[m] * catRate[k];
// calculate transition probabilities for left branch
if (isComplex == NO)
CalcPij (c_ijk, N_STATES, eigenValues, rUp->length, theRate, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, N_STATES, probs, rUp->length, theRate) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<N_STATES; i++)
for (j=0; j<N_STATES; j++)
pL[indexL++] = probs[i][j];
// calculate transition probabilities for right branch
if (isComplex == NO)
CalcPij (c_ijk, N_STATES, eigenValues, r->length, theRate, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, N_STATES, probs, r->length, theRate) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<N_STATES; i++)
for (j=0; j<N_STATES; j++)
pR[indexR++] = probs[i][j];
}
}
# endif
/* first set pointers to cond likes of left, right and p */
clL = &condLike[condLikeOffset + (rUp->index)*oneNodeSize];
clR = &condLike[condLikeOffset + (rDn->index)*oneNodeSize];
clP = &condLike[condLikeOffset + (r->index)*oneNodeSize];
if (!strcmp(ratesModel, "equal"))
{
for (c=0; c<numChars; c++)
{
for (i=m=0; i<N_STATES; i++)
{
likeL = likeR = 0.0;
for (j=0; j<N_STATES; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m++]*clR[j];
}
*(clP++) = likeL * likeR;
}
clL += N_STATES;
clR += N_STATES;
}
}
else if (!strcmp(ratesModel, "gamma") || !strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "invariant") || !strcmp(ratesModel, "invgamma"))
{
for (c=0; c<numChars; c++)
{
for (k=m=0; k<lnumRateCats; k++)
{
for (i=0; i<N_STATES; i++)
{
likeL = likeR = 0.0;
for (j=0; j<N_STATES; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m++]*clR[j];
}
*(clP++) = likeL * likeR;
}
clL += N_STATES;
clR += N_STATES;
}
}
}
else if (!strcmp(ratesModel, "ssgamma") || !strcmp(ratesModel, "ssadgamma"))
{
for (c=0; c<numChars; c++)
{
m = partitionId[c]*lnumRateCats*N_STATES_SQUARED;
for (k=0; k<lnumRateCats; k++)
{
for (i=0; i<N_STATES; i++)
{
likeL = likeR = 0.0;
for (j=0; j<N_STATES; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m++]*clR[j];
}
*(clP++) = likeL * likeR;
}
clL += N_STATES;
clR += N_STATES;
}
}
}
else if (!strcmp(ratesModel, "sitespec"))
{
for (c=0; c<numChars; c++)
{
m = partitionId[c]*N_STATES_SQUARED;
for (i=0; i<N_STATES; i++)
{
likeL = likeR = 0.0;
for (j=0; j<N_STATES; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m++]*clR[j];
}
*(clP++) = likeL * likeR;
}
clL += N_STATES;
clR += N_STATES;
}
}
}
}
/* get conditional probabilities of states at p */
//printf ("getting condlikes at p %d\n", p->index);
/* get transition probabilities */
# if defined (SMART_TI_PROBS)
if (p->left == NULL || p->right == NULL || p->anc == NULL)
{
if (p->anc == NULL)
pL = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (p->left->index)*nodeTiSize);
else
pR = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (p->index)*nodeTiSize);
}
else
{
pL = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (r->left->index)*nodeTiSize);
pR = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (r->right->index)*nodeTiSize);
pA = transitionProbs + (whichChain*2*nForOneState + whichState*nForOneState + (r->index)*nodeTiSize);
}
# else
if (p->left == NULL || p->right == NULL || p->anc == NULL)
{
if (p->anc == NULL)
v = p->left->length;
else
v = p->length;
for (m=indexL=indexR=indexA=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
theRate = partRate[m] * catRate[k];
// calculate transition probabilities for ancestral branch
if (isComplex == NO)
CalcPij (c_ijk, N_STATES, eigenValues, v, theRate, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, N_STATES, probs, v, theRate) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<N_STATES; i++)
for (j=0; j<N_STATES; j++)
pA[indexA++] = probs[i][j];
}
}
}
else
{
for (m=indexL=indexR=indexA=0; m<lnPartitions; m++)
{
for (k=0; k<lnumRateCats; k++)
{
theRate = partRate[m] * catRate[k];
// calculate transition probabilities for left branch
if (isComplex == NO)
CalcPij (c_ijk, N_STATES, eigenValues, p->left->length, theRate, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, N_STATES, probs, p->left->length, theRate) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<N_STATES; i++)
for (j=0; j<N_STATES; j++)
pL[indexL++] = probs[i][j];
// calculate transition probabilities for right branch
if (isComplex == NO)
CalcPij (c_ijk, N_STATES, eigenValues, p->right->length, theRate, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, N_STATES, probs, p->right->length, theRate) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<N_STATES; i++)
for (j=0; j<N_STATES; j++)
pR[indexR++] = probs[i][j];
// calculate transition probabilities for ancestral branch
if (isComplex == NO)
CalcPij (c_ijk, N_STATES, eigenValues, p->length, theRate, probs);
else
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, N_STATES, probs, p->length, theRate) == ERROR)
{
printf ("Problem calculating transition probabilities for complex eigen values.\n");
goto error_exit;
}
for (i=0; i<N_STATES; i++)
for (j=0; j<N_STATES; j++)
pA[indexA++] = probs[i][j];
}
}
}
# endif
if (p->left == NULL || p->right == NULL || p->anc == NULL)
{
//clP = &condLike[condLikeOffset + (p->index)*oneNodeSize];
clP = ancCls;
if (p->anc == NULL)
clA = &condLike[condLikeOffset + (p->left->index)*oneNodeSize];
else
clA = &condLike[condLikeOffset + (p->anc->index)*oneNodeSize];
if (!strcmp(ratesModel, "equal"))
{
for (c=0; c<numChars; c++)
{
for (i=m=0; i<N_STATES; i++)
{
likeA = 0.0;
for (j=0; j<N_STATES; j++)
{
likeA += pA[m++]*clA[j];
}
*(clP++) = likeA;
}
clA += N_STATES;
}
}
else if (!strcmp(ratesModel, "gamma") || !strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "invariant") || !strcmp(ratesModel, "invgamma"))
{
for (c=0; c<numChars; c++)
{
for (k=m=0; k<lnumRateCats; k++)
{
for (i=0; i<N_STATES; i++)
{
likeA = 0.0;
for (j=0; j<N_STATES; j++)
{
likeA += pA[m++]*clA[j];
}
*(clP++) = likeA;
}
clA += N_STATES;
}
}
}
else if (!strcmp(ratesModel, "ssgamma") || !strcmp(ratesModel, "ssadgamma"))
{
for (c=0; c<numChars; c++)
{
m = partitionId[c]*lnumRateCats*N_STATES_SQUARED;
for (k=0; k<lnumRateCats; k++)
{
for (i=0; i<N_STATES; i++)
{
likeA = 0.0;
for (j=0; j<N_STATES; j++)
{
likeA += pA[m++]*clA[j];
}
*(clP++) = likeA;
}
clA += N_STATES;
}
}
}
else if (!strcmp(ratesModel, "sitespec"))
{
for (c=0; c<numChars; c++)
{
m = partitionId[c]*N_STATES_SQUARED;
for (i=0; i<N_STATES; i++)
{
likeA = 0.0;
for (j=0; j<N_STATES; j++)
{
likeA += pA[m++]*clA[j];
}
*(clP++) = likeA;
}
clA += N_STATES;
}
}
}
else
{
/* first set pointers to cond likes of left, right, p and anc */
clL = &condLike[condLikeOffset + (p->left->index)*oneNodeSize];
clR = &condLike[condLikeOffset + (p->right->index)*oneNodeSize];
clA = &condLike[condLikeOffset + (p->anc->index)*oneNodeSize];
//clP = &condLike[condLikeOffset + (p->index)*oneNodeSize];
clP = ancCls;
if (!strcmp(ratesModel, "equal"))
{
for (c=0; c<numChars; c++)
{
for (i=m=0; i<N_STATES; i++)
{
likeL = likeR = likeA = 0.0;
for (j=0; j<N_STATES; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m]*clR[j];
likeA += pA[m++]*clA[j];
}
*(clP++) = likeL * likeR * likeA;
}
clL += N_STATES;
clR += N_STATES;
clA += N_STATES;
}
}
else if (!strcmp(ratesModel, "gamma") || !strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "invariant") || !strcmp(ratesModel, "invgamma"))
{
for (c=0; c<numChars; c++)
{
for (k=m=0; k<lnumRateCats; k++)
{
for (i=0; i<N_STATES; i++)
{
likeL = likeR = likeA = 0.0;
for (j=0; j<N_STATES; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m]*clR[j];
likeA += pA[m++]*clA[j];
}
*(clP++) = likeL * likeR * likeA;
}
clL += N_STATES;
clR += N_STATES;
clA += N_STATES;
}
}
}
else if (!strcmp(ratesModel, "ssgamma") || !strcmp(ratesModel, "ssadgamma"))
{
for (c=0; c<numChars; c++)
{
m = partitionId[c]*lnumRateCats*N_STATES_SQUARED;
for (k=0; k<lnumRateCats; k++)
{
for (i=0; i<N_STATES; i++)
{
likeL = likeR = likeA = 0.0;
for (j=0; j<N_STATES; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m]*clR[j];
likeA += pA[m++]*clA[j];
}
*(clP++) = likeL * likeR * likeA;
}
clL += N_STATES;
clR += N_STATES;
clA += N_STATES;
}
}
}
else if (!strcmp(ratesModel, "sitespec"))
{
for (c=0; c<numChars; c++)
{
m = partitionId[c]*N_STATES_SQUARED;
for (i=0; i<N_STATES; i++)
{
likeL = likeR = likeA = 0.0;
for (j=0; j<N_STATES; j++)
{
likeL += pL[m]*clL[j];
likeR += pR[m]*clR[j];
likeA += pA[m++]*clA[j];
}
*(clP++) = likeL * likeR * likeA;
}
clL += N_STATES;
clR += N_STATES;
clA += N_STATES;
}
}
}
/* calculate posterior probability of states at p */
//clP = &condLike[condLikeOffset + (p->index)*oneNodeSize];
clP = ancCls;
if (!strcmp(ratesModel, "equal") || !strcmp(ratesModel, "sitespec"))
{
for (c=0; c<nChar; c++)
{
pat = patternId[c];
if (pat >= 0)
{
sum = 0.0;
for (i=0; i<N_STATES; i++)
{
like[i] = clP[pat*N_STATES + i];
sum += like[i] * bs[i];
}
for (i=0; i<N_STATES; i++)
{
postProb[i] = (like[i] * bs[i]) / sum;
tempStateProbs[(p->constraintNum-1)*nChar*N_STATES + c*N_STATES + i] = postProb[i];
ancStatesProbs[(p->constraintNum-1)*nChar*N_STATES + c*N_STATES + i] += postProb[i];
}
}
}
}
else if (!strcmp(ratesModel, "gamma") || !strcmp(ratesModel, "invariant") || !strcmp(ratesModel, "invgamma") || !strcmp(ratesModel, "ssgamma"))
{
for (c=0; c<nChar; c++)
{
pat = patternId[c];
if (pat >= 0)
{
for (i=0; i<N_STATES; i++)
like[i] = 0.0;
for (k=0; k<lnumRateCats; k++)
{
for (i=0; i<N_STATES; i++)
like[i] += clP[pat*lnumRateCats*N_STATES + k*N_STATES + i] * catFreq[k];
}
sum = 0.0;
for (i=0; i<N_STATES; i++)
sum += like[i] * bs[i];
for (i=0; i<N_STATES; i++)
{
postProb[i] = (like[i] * bs[i]) / sum;
tempStateProbs[(p->constraintNum-1)*nChar*N_STATES + c*N_STATES + i] = postProb[i];
ancStatesProbs[(p->constraintNum-1)*nChar*N_STATES + c*N_STATES + i] += postProb[i];
}
}
}
}
else if (!strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "ssadgamma"))
{
/* get probabilities of observations conditioned on each category */
for (c=0; c<numChars; c++)
{
for (k=0; k<lnumRateCats; k++)
{
tempRatePr[k * numChars + c] = 0.0;
for (i=0; i<N_STATES; i++)
tempRatePr[k * numChars + c] += clP[i] * bs[i];
clP += N_STATES;
}
}
/* forward algorithm */
logC = 0.0;
for (c=0; c<nChar; c++)
{
if (patternId[c] >= 0)
{
pat = patternId[c];
if (c == 0)
{
for (k=0; k<lnumRateCats; k++)
f[k*nChar + c] = tempRatePr[k * numChars + pat];
}
else
{
for (l=0; l<lnumRateCats; l++)
{
temp = 0.0;
for (k=0; k<lnumRateCats; k++)
temp += f[k * nChar + (c-1)] * markovTi[k][l];
f[l * nChar + c] = temp * tempRatePr[l * numChars + pat];
}
}
sum = 0.0;
for (k=0; k<lnumRateCats; k++)
sum += f[k*nChar + c];
for (k=0; k<lnumRateCats; k++)
f[k*nChar+c] /= sum;
logC += log(sum);
logCf[c] = logC;
}
else
{
}
}
/* backward algorithm */
logC = 0.0;
for (c=nChar-1; c>=0; c--)
{
if (patternId[c] >= 0)
{
if (c == nChar - 1)
{
for (k=0; k<lnumRateCats; k++)
b[k * nChar + c] = catFreq[k];
}
else
{
pat = patternId[c+1];
for (k=0; k<lnumRateCats; k++)
{
temp = 0.0;
for (l=0; l<lnumRateCats; l++)
temp += markovTi[k][l] * tempRatePr[l * numChars + pat] * b[l * nChar + (c+1)];
b[k * nChar + c] = temp;
}
}
sum = 0.0;
for (k=0; k<lnumRateCats; k++)
sum += b[k*nChar + c];
for (k=0; k<lnumRateCats; k++)
b[k*nChar+c] /= sum;
logC += log(sum);
logCb[c] = logC;
}
else
{
}
}
temp = 0.0;
pat = patternId[0];
for (l=0; l<lnumRateCats; l++)
temp += tempRatePr[l * numChars + pat] * b[l * nChar + 0];
logLike = log (temp) + logC;
/* posterior probabilities of individual categories at site c */
for (c=0; c<nChar; c++)
{
/*printf ("%d ", c+1);*/
for (k=0; k<lnumRateCats; k++)
{
temp = (log(f[k * nChar + c]) + logCf[c] + log(b[k * nChar + c]) + logCb[c]) - logLike;
if (temp > 0.0)
expPr[k] = 1.0;
else if (temp < -100.0)
expPr[k] = 0.0;
else
expPr[k] = exp(temp);
}
for (k=0; k<lnumRateCats; k++)
{
rateProbs[c*lnumRateCats + k] += expPr[k];
}
}
//clP = &condLike[condLikeOffset + (p->index)*oneNodeSize];
clP = ancCls;
for (c=0; c<nChar; c++)
{
pat = patternId[c];
if (pat >= 0)
{
for (i=0; i<N_STATES; i++)
like[i] = 0.0;
for (k=0; k<lnumRateCats; k++)
{
for (i=0; i<N_STATES; i++)
like[i] += clP[pat*lnumRateCats*N_STATES + k*N_STATES + i] * rateProbs[c*lnumRateCats + k];
}
sum = 0.0;
for (i=0; i<N_STATES; i++)
sum += like[i] * bs[i];
for (i=0; i<N_STATES; i++)
{
postProb[i] = (like[i] * bs[i]) / sum;
tempStateProbs[(p->constraintNum-1)*nChar*N_STATES + c*N_STATES + i] = postProb[i];
ancStatesProbs[(p->constraintNum-1)*nChar*N_STATES + c*N_STATES + i] += postProb[i];
}
}
}
}
}
}
/* summarize states */
/* print probabilities to a file */
if (nSampled == 1)
{
strcpy (tempFile, outFile);
strcat (tempFile, ".sum.");
for (i=0; i<nConstraints; i++)
{
strcat (tempFile, "1");
if ((fp = fopen (tempFile, "r")) == NULL)
{
if ((fp = fopen (tempFile, "w")) == NULL)
{
printf ("\n ERROR: Could not open file (%s).\n", tempFile);
goto error_exit;
}
}
else
{
fclose (fp);
if (autoclose == YES)
{
printf (" Overwriting information to file %s\n", tempFile);
if ((fp = fopen (tempFile, "w+")) == NULL)
{
printf ("\n ERROR: Could not open file (%s).\n", tempFile);
goto error_exit;
}
}
else
{
printf ("\n File \"%s\" already exists.\n Overwrite? (yes/no): ", tempFile);
if (YesNo() == YES)
{
printf (" Overwriting information to file %s\n", tempFile);
if ((fp = fopen (tempFile, "w+")) == NULL)
{
printf ("\n ERROR: Could not open file (%s).\n", tempFile);
goto error_exit;
}
}
else
{
printf (" Appending information to file %s\n", tempFile);
if ((fp = fopen (tempFile, "a+")) == NULL)
{
printf ("\n ERROR: Could not open file (%s).\n", tempFile);
goto error_exit;
}
}
}
}
fclose (fp);
}
}
/* summarize states */
if (whichGen == nGen && nSampled >= 1)
{
strcpy (tempFile, outFile);
strcat (tempFile, ".sum.");
for (i=0; i<nConstraints; i++)
{
strcat (tempFile, "1");
if ((fp = fopen (tempFile, "a+")) == NULL)
{
printf ("\n ERROR: Could not open file (%s).\n", tempFile);
goto error_exit;
}
fprintf (fp, "Summary of ancestral states at constraint \"");
k = 0;
while (constraintLabels[i][k] != '|' && k < 99)
{
fprintf (fp, "%c", constraintLabels[i][k]);
k++;
}
fprintf (fp, "\"\n");
lnSeqProb = 0.0;
for (c=0; c<nChar; c++)
{
if (patternId[c] >= 0)
{
pat = patternId[c];
fprintf (fp, "%4d %4d -- ", c+1, pat);
for (j=0; j<N_STATES; j++)
fprintf (fp, "%lf ", ancStatesProbs[i*nChar*N_STATES + c*N_STATES + j] / nSampled);
maxProb = -1.0;
bestNuc = 'N';
for (j=0; j<N_STATES; j++)
{
if (ancStatesProbs[i*nChar*N_STATES + c*N_STATES + j] > maxProb)
{
maxProb = ancStatesProbs[i*nChar*N_STATES + c*N_STATES + j];
bestNuc = WhichAA (j);
}
}
lnSeqProb += log(maxProb/nSampled);
fprintf (fp, "%c\n", bestNuc);
}
}
fprintf (fp, "Most probable sequence [ln(Probability) = %lf]:\n", lnSeqProb);
for (c=0; c<nChar; c++)
{
if (patternId[c] >= 0)
{
pat = patternId[c];
maxProb = -1.0;
bestNuc = 'N';
for (j=0; j<N_STATES; j++)
{
if (ancStatesProbs[i*nChar*N_STATES + c*N_STATES + j] > maxProb)
{
maxProb = ancStatesProbs[i*nChar*N_STATES + c*N_STATES + j];
bestNuc = WhichAA (j);
}
}
fprintf (fp, "%c", bestNuc);
}
}
fprintf (fp, "\n");
fclose (fp);
}
}
/* free memory */
# if !defined (SMART_TI_PROBS)
free_psdmatrix (probs);
free (pL);
free_psdmatrix (q);
free (eigenValues);
free_psdmatrix (eigvecs);
free_psdmatrix (inverseEigvecs);
free_pscmatrix (Ceigvecs);
free_pscmatrix (CinverseEigvecs);
if (isComplex != YES)
free (c_ijk);
# endif
free (catFreq);
free (ancCls);
if (!strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "ssadgamma"))
{
free_psdmatrix(markovTi);
free (f);
free (tempRatePr);
}
return (NO_ERROR);
error_exit:
# if !defined (SMART_TI_PROBS)
free_psdmatrix (probs);
free (pL);
free_psdmatrix (q);
free (eigenValues);
free_psdmatrix (eigvecs);
free_psdmatrix (inverseEigvecs);
free_pscmatrix (Ceigvecs);
free_pscmatrix (CinverseEigvecs);
if (isComplex != YES)
free (c_ijk);
# endif
free (catFreq);
free (ancCls);
if (!strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "ssadgamma"))
{
free_psdmatrix(markovTi);
free (f);
free (tempRatePr);
}
return (ERROR);
#undef N_STATES
#undef N_STATES_SQUARED
#undef N_STATES_CUBE
}
int PrintPosSelProbs (int whichState, int whichChain, int numChars, int numRateCats, int whichGen)
{
int i, k, c, l, oneMatSize, nLocalCats, nOff, kTimesS, pat;
double likePur, likeNeu, likePos, *clP, *bs, *tempProb, a[3][3],
*f, *b, *e, sum, logC, *logCf, *logCb, temp, logLike, x;
char tempFile1[100], tempFile2[100];
FILE *fp1, *fp2, *fopen();
TreeNode *p;
/* open files, allocate some memory */
strcpy (tempFile1, outFile);
strcpy (tempFile2, outFile);
strcat (tempFile1, ".possummary");
strcat (tempFile2, ".posexhaust");
if (nSampled == 1)
{
if ((fp1 = fopen (tempFile1, "r")) == NULL)
{
if ((fp1 = fopen (tempFile1, "w")) == NULL)
{
printf ("\n ERROR: Could not open file (%s).\n", tempFile1);
goto error_exit;
}
}
else
{
fclose (fp1);
if (autoclose == YES)
{
printf (" Overwriting information to file %s\n", tempFile1);
if ((fp1 = fopen (tempFile1, "w+")) == NULL)
{
printf ("\n ERROR: Could not open file (%s).\n", tempFile1);
goto error_exit;
}
}
else
{
printf ("\n File \"%s\" already exists.\n Overwrite? (yes/no): ", tempFile1);
if (YesNo() == YES)
{
printf (" Overwriting information to file %s\n", tempFile1);
if ((fp1 = fopen (tempFile1, "w+")) == NULL)
{
printf ("\n ERROR: Could not open file (%s).\n", tempFile1);
goto error_exit;
}
}
else
{
printf (" Appending information to file %s\n", tempFile1);
if ((fp1 = fopen (tempFile1, "a+")) == NULL)
{
printf ("\n ERROR: Could not open file (%s).\n", tempFile1);
goto error_exit;
}
}
}
}
if ((fp2 = fopen (tempFile2, "r")) == NULL)
{
if ((fp2 = fopen (tempFile2, "w")) == NULL)
{
printf ("\n ERROR: Could not open file (%s).\n", tempFile2);
goto error_exit;
}
}
else
{
fclose (fp2);
if (autoclose == YES)
{
printf (" Overwriting information to file %s\n", tempFile2);
if ((fp2 = fopen (tempFile2, "w+")) == NULL)
{
printf ("\n ERROR: Could not open file (%s).\n", tempFile2);
goto error_exit;
}
}
else
{
printf ("\n File \"%s\" already exists.\n Overwrite? (yes/no): ", tempFile2);
if (YesNo() == YES)
{
printf (" Overwriting information to file %s\n", tempFile2);
if ((fp2 = fopen (tempFile2, "w+")) == NULL)
{
printf ("\n ERROR: Could not open file (%s).\n", tempFile2);
goto error_exit;
}
}
else
{
printf (" Appending information to file %s\n", tempFile2);
if ((fp2 = fopen (tempFile2, "a+")) == NULL)
{
printf ("\n ERROR: Could not open file (%s).\n", tempFile2);
goto error_exit;
}
}
}
}
fprintf (fp2, "Probability that each site is in the positively selected category\n");
for (i=0; i<(nChar/3); i++)
{
if (patternId[i] >= 0)
{
fprintf (fp2, "%d\t", i+1);
}
}
fprintf (fp2, "\n");
posSelProbs = (double *)malloc((size_t) ((nChar/3) * sizeof(double)));
if (!posSelProbs)
{
printf ("\n ERROR: Problem allocating posSelProbs.\n");
goto error_exit;
}
for (i=0; i<(nChar/3); i++)
posSelProbs[i] = 0.0;
}
else
{
if ((fp1 = fopen (tempFile1, "a+")) == NULL)
{
printf ("\n ERROR: Could not open file (%s).\n", tempFile1);
goto error_exit;
}
if ((fp2 = fopen (tempFile2, "a+")) == NULL)
{
printf ("\n ERROR: Could not open file (%s).\n", tempFile2);
goto error_exit;
}
}
/* start calculations of posterior probabilities by initializing necessary variables*/
if (!strcmp(codonModelType, "ac1ny98"))
InitTiMatrix (a, rateCorrelation[whichChain*2 + whichState], 0.0, 0.0, probPur[whichChain*2 + whichState], probNeu[whichChain*2 + whichState], probPos[whichChain*2 + whichState], 1);
else if (!strcmp(codonModelType, "ac2ny98"))
InitTiMatrix (a, rateCorrelation[whichChain*2 + whichState], rateCorrelation2[whichChain*4 + whichState*2 + 0], rateCorrelation2[whichChain*4 + whichState*2 + 1], probPur[whichChain*2 + whichState], probNeu[whichChain*2 + whichState], probPos[whichChain*2 + whichState], 2);
if (!strcmp(codonModelType, "ac1ny98") || !strcmp(codonModelType, "ac2ny98"))
{
f = (double *)malloc((size_t) (3 * (nChar/3) * sizeof(double)));
if (!f)
{
printf ("\n ERROR: Problem allocating f.\n");
goto error_exit;
}
for (i=0; i<3*(nChar/3); i++)
f[i] = 0.0;
b = (double *)malloc((size_t) (3 * (nChar/3) * sizeof(double)));
if (!b)
{
printf ("\n ERROR: Problem allocating b.\n");
goto error_exit;
}
for (i=0; i<3*(nChar/3); i++)
b[i] = 0.0;
e = (double *)malloc((size_t) (3 * (nChar/3) * sizeof(double)));
if (!e)
{
printf ("\n ERROR: Problem allocating e.\n");
goto error_exit;
}
for (i=0; i<3*(nChar/3); i++)
e[i] = 0.0;
logCf = (double *)malloc((size_t) ((nChar/3) * sizeof(double)));
if (!logCf)
{
printf ("\n ERROR: Problem allocating f.\n");
goto error_exit;
}
for (i=0; i<(nChar/3); i++)
logCf[i] = 0.0;
logCb = (double *)malloc((size_t) ((nChar/3) * sizeof(double)));
if (!logCb)
{
printf ("\n ERROR: Problem allocating b.\n");
goto error_exit;
}
for (i=0; i<(nChar/3); i++)
logCb[i] = 0.0;
}
bs = (double *)malloc((size_t) (nStates * sizeof(double)));
if (!bs)
{
printf ("\n ERROR: Problem allocating bs.\n");
goto error_exit;
}
for (i=0; i<nStates; i++)
bs[i] = baseFreq[whichChain*2*nStates + whichState*nStates + i];
if (!strcmp(codonModelType, "ny98"))
{
tempProb = (double *)malloc((size_t) (numChars * sizeof(double)));
if (!tempProb)
{
printf ("\n ERROR: Problem allocating tempProb.\n");
goto error_exit;
}
}
else
{
tempProb = (double *)malloc((size_t) (3 * numChars * sizeof(double)));
if (!tempProb)
{
printf ("\n ERROR: Problem allocating tempProb.\n");
goto error_exit;
}
}
/* calculate posterior probabilities */
if (!strcmp(codonModelType, "ny98"))
{
nLocalCats = numRateCats;
oneMatSize = numNodes * numChars * nLocalCats * nStates;
p = root[whichChain*2 + whichState]->left;
clP = &condLike[whichChain*2*oneMatSize + whichState*oneMatSize + (p->index)*numChars*numRateCats*nStates];
nOff = numRateCats*nStates;
for (c=0; c<numChars; c++, *(clP+=nOff))
{
likePur = likeNeu = likePos = 0.0;
for (i=0; i<nStates; i++)
likePos += clP[i] * bs[i];
for (i=0; i<nStates; i++)
likePur += clP[nStates + i] * bs[i];
kTimesS = 2 * nStates;
for (i=0; i<nStates; i++)
likeNeu += clP[kTimesS + i] * bs[i];
//printf ("%4d -- %lf %lf %lf\n", c, likePos, likePur, likeNeu);
tempProb[c] = (likePos * probPos[whichChain*2 + whichState]) / (likePos * probPos[whichChain*2 + whichState] + likePur * probPur[whichChain*2 + whichState] + likeNeu * probNeu[whichChain*2 + whichState]);
}
for (i=0; i<(nChar/3); i++)
{
if (patternId[i] >= 0)
{
pat = patternId[i];
fprintf (fp2, "%1.4lf\t", tempProb[pat]);
posSelProbs[i] += tempProb[pat];
}
}
fprintf (fp2, "\n");
}
else if (!strcmp(codonModelType, "ac1ny98") || !strcmp(codonModelType, "ac2ny98"))
{
/* get emission probabilities */
nLocalCats = numRateCats;
oneMatSize = numNodes * numChars * nLocalCats * nStates;
p = root[whichChain*2 + whichState]->left;
clP = &condLike[whichChain*2*oneMatSize + whichState*oneMatSize + (p->index)*numChars*numRateCats*nStates];
nOff = numRateCats * nStates;
for (c=0; c<numChars; c++, *(clP+=nOff))
{
likePur = likeNeu = likePos = 0.0;
for (i=0; i<nStates; i++)
likePos += clP[i] * bs[i];
for (i=0; i<nStates; i++)
likePur += clP[nStates + i] * bs[i];
kTimesS = 2 * nStates;
for (i=0; i<nStates; i++)
likeNeu += clP[kTimesS + i] * bs[i];
tempProb[0 * numChars + c] = likePur;
tempProb[1 * numChars + c] = likeNeu;
tempProb[2 * numChars + c] = likePos;
}
for (i=0; i<(nChar/3); i++)
{
if (patternId[i] >= 0)
{
pat = patternId[i];
e[0 * (nChar/3) + i] = tempProb[0 * numChars + pat];
e[1 * (nChar/3) + i] = tempProb[1 * numChars + pat];
e[2 * (nChar/3) + i] = tempProb[2 * numChars + pat];
}
}
/* forward algorithm */
logC = 0.0;
for (i=0; i<(nChar/3); i++)
{
if (i == 0)
{
for (k=0; k<3; k++)
f[k * (nChar/3) + i] = e[k * (nChar/3) + i];
}
else
{
for (l=0; l<3; l++)
{
temp = 0.0;
for (k=0; k<3; k++)
temp += f[k * (nChar/3) + (i-1)] * a[k][l];
f[l * (nChar/3) + i] = temp * e[l * (nChar/3) + i];
}
}
sum = 0.0;
for (k=0; k<3; k++)
sum += f[k * (nChar/3) + i];
for (k=0; k<3; k++)
f[k * (nChar/3)+i] /= sum;
logC += log(sum);
logCf[i] = logC;
}
temp = f[0 * (nChar/3) + ((nChar/3)-1)] * probPur[whichChain*2 + whichState];
temp += f[1 * (nChar/3) + ((nChar/3)-1)] * probNeu[whichChain*2 + whichState];
temp += f[2 * (nChar/3) + ((nChar/3)-1)] * probPos[whichChain*2 + whichState];
logLike = log(temp) + logC;
/* backward algorithm */
logC = 0.0;
for (i=(nChar/3)-1; i>=0; i--)
{
if (i == (nChar/3) - 1)
{
b[0 * (nChar/3) + i] = probPur[whichChain*2 + whichState];
b[1 * (nChar/3) + i] = probNeu[whichChain*2 + whichState];
b[2 * (nChar/3) + i] = probPos[whichChain*2 + whichState];
}
else
{
for (k=0; k<3; k++)
{
temp = 0.0;
for (l=0; l<3; l++)
temp += a[k][l] * e[l * (nChar/3) + (i+1)] * b[l * (nChar/3) + (i+1)];
b[k * (nChar/3) + i] = temp;
}
}
sum = 0.0;
for (k=0; k<3; k++)
sum += b[k * (nChar/3) + i];
for (k=0; k<3; k++)
b[k * (nChar/3) + i] /= sum;
logC += log(sum);
logCb[i] = logC;
}
temp = 0.0;
for (l=0; l<3; l++)
temp += e[l * (nChar/3) + 0] * b[l * (nChar/3) + 0];
logLike = log (temp) + logC;
for (i=0; i<(nChar/3); i++)
{
temp = (log(f[2 * (nChar/3) + i]) + logCf[i] + log(b[2 * (nChar/3) + i]) + logCb[i]) - logLike;
if (temp > 0.0)
x = 1.0;
else if (temp < -100.0)
x = 0.0;
else
x = exp(temp);
fprintf (fp2, "%1.4lf\t", x);
posSelProbs[i] += x;
//printf ("%4d -- %lf %lf\n", i+1, temp, x);
}
fprintf (fp2, "\n");
}
else
{
printf ("\n ERROR: Unknown model for positive selection.\n");
goto error_exit;
}
/* print summary of probabilities to a file */
if (whichGen == nGen && nSampled >= 1)
{
fprintf (fp1, "Summary of posterior probability of being in positively selected class\n");
for (i=0; i<(nChar/3); i++)
{
fprintf (fp1, "%d\t%1.4lf\n", i+1, posSelProbs[i] / nSampled);
}
free (posSelProbs);
}
free (bs);
free (tempProb);
fclose (fp1);
fclose (fp2);
if (!strcmp(codonModelType, "ac1ny98") || !strcmp(codonModelType, "ac2ny98"))
{
free (f);
free (b);
free (e);
free (logCf);
free (logCb);
}
return (NO_ERROR);
error_exit:
free (bs);
free (tempProb);
#if defined (MORPH)
if (fp1 != NULL)
fclose (fp1);
if (fp2 != NULL)
fclose (fp2);
#else
fclose (fp1);
fclose (fp2);
#endif
free (posSelProbs);
if (!strcmp(codonModelType, "ac1ny98") || !strcmp(codonModelType, "ac2ny98"))
{
free (f);
free (b);
free (e);
free (logCf);
free (logCb);
}
return (ERROR);
}
int PrintRateFactors (int whichState, int whichChain, int numChars, int numRateCats, int whichGen)
{
int i, k, c, l, oneMatSize, nLocalCats, nOff, kTimesS, pat;
double *clP, *bs, *tempRatePr, **a, correlation, like, *aveRate,
*f, *b, *expPr, sum, logC, *logCf, *logCb, temp, logLike, x, mult, *catFreq, *catRate;
char tempFile1[100], tempFile2[100];
FILE *fp1, *fp2, *fopen();
TreeNode *p;
/* calculate number of rate categories */
if (!strcmp(ratesModel, "equal"))
nLocalCats = 1;
else if (!strcmp(ratesModel, "gamma") || !strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "invariant") || !strcmp(ratesModel, "invgamma"))
nLocalCats = numRateCats;
else if (!strcmp(ratesModel, "sitespec"))
nLocalCats = nPartitions;
else if (!strcmp(ratesModel, "ssgamma") || !strcmp(ratesModel, "ssadgamma"))
nLocalCats = numRateCats;
/* open files, allocate some memory */
strcpy (tempFile1, outFile);
strcat (tempFile1, ".ratesummary");
strcpy (tempFile2, outFile);
strcat (tempFile2, ".exhaustrates");
if (nSampled == 1)
{
if ((fp1 = fopen (tempFile1, "r")) == NULL)
{
if ((fp1 = fopen (tempFile1, "w")) == NULL)
{
printf ("\n ERROR: Could not open file (%s).\n", tempFile1);
goto error_exit;
}
}
else
{
fclose (fp1);
if (autoclose == YES)
{
printf (" Overwriting information to file %s\n", tempFile1);
if ((fp1 = fopen (tempFile1, "w+")) == NULL)
{
printf ("\n ERROR: Could not open file (%s).\n", tempFile1);
goto error_exit;
}
}
else
{
printf ("\n File \"%s\" already exists.\n Overwrite? (yes/no): ", tempFile1);
if (YesNo() == YES)
{
printf (" Overwriting information to file %s\n", tempFile1);
if ((fp1 = fopen (tempFile1, "w+")) == NULL)
{
printf ("\n ERROR: Could not open file (%s).\n", tempFile1);
goto error_exit;
}
}
else
{
printf (" Appending information to file %s\n", tempFile1);
if ((fp1 = fopen (tempFile1, "a+")) == NULL)
{
printf ("\n ERROR: Could not open file (%s).\n", tempFile1);
goto error_exit;
}
}
}
}
if ((fp2 = fopen (tempFile2, "r")) == NULL)
{
if ((fp2 = fopen (tempFile2, "w")) == NULL)
{
printf ("\n ERROR: Could not open file (%s).\n", tempFile2);
goto error_exit;
}
}
else
{
fclose (fp2);
if (autoclose == YES)
{
printf (" Overwriting information to file %s\n", tempFile2);
if ((fp2 = fopen (tempFile2, "w+")) == NULL)
{
printf ("\n ERROR: Could not open file (%s).\n", tempFile2);
goto error_exit;
}
}
else
{
printf ("\n File \"%s\" already exists.\n Overwrite? (yes/no): ", tempFile2);
if (YesNo() == YES)
{
printf (" Overwriting information to file %s\n", tempFile2);
if ((fp2 = fopen (tempFile2, "w+")) == NULL)
{
printf ("\n ERROR: Could not open file (%s).\n", tempFile2);
goto error_exit;
}
}
else
{
printf (" Appending information to file %s\n", tempFile2);
if ((fp2 = fopen (tempFile2, "a+")) == NULL)
{
printf ("\n ERROR: Could not open file (%s).\n", tempFile2);
goto error_exit;
}
}
}
}
fprintf (fp2, "Rate factor for each site\n");
for (i=0; i<nChar; i++)
{
if (patternId[i] >= 0)
{
fprintf (fp2, "%d\t", i+1);
}
}
fprintf (fp2, "\n");
rateFactors = (double *)malloc((size_t) (nChar * sizeof(double)));
if (!rateFactors)
{
printf ("\n ERROR: Problem allocating rateFactors.\n");
goto error_exit;
}
for (i=0; i<nChar; i++)
rateFactors[i] = 0.0;
if (!strcmp(ratesModel, "sitespec"))
{
rateProbs = (double *)malloc((size_t) (nChar * sizeof(double)));
if (!rateProbs)
{
printf ("\n ERROR: Problem allocating rateFactors.\n");
goto error_exit;
}
for (i=0; i<nChar; i++)
rateProbs[i] = 0.0;
}
else
{
rateProbs = (double *)malloc((size_t) (nChar * nLocalCats * sizeof(double)));
if (!rateProbs)
{
printf ("\n ERROR: Problem allocating rateFactors.\n");
goto error_exit;
}
for (i=0; i<nChar*nLocalCats; i++)
rateProbs[i] = 0.0;
}
}
else
{
if ((fp1 = fopen (tempFile1, "a+")) == NULL)
{
printf ("\n ERROR: Could not open file (%s).\n", tempFile1);
goto error_exit;
}
if ((fp2 = fopen (tempFile2, "a+")) == NULL)
{
printf ("\n ERROR: Could not open file (%s).\n", tempFile2);
goto error_exit;
}
}
/* start calculations of rate factors by initializing necessary variables*/
catFreq = (double *)malloc((size_t) (nLocalCats * sizeof(double)));
if (!catFreq)
{
printf ("\n ERROR: Problem allocating catFreq.\n");
goto error_exit;
}
catRate = (double *)malloc((size_t) (nLocalCats * sizeof(double)));
if (!catRate)
{
printf ("\n ERROR: Problem allocating catRate.\n");
goto error_exit;
}
/* fill in rate categories */
if (!strcmp(ratesModel, "gamma") || !strcmp(ratesModel, "ssgamma"))
{
DiscreteGamma (catFreq, catRate, alpha[whichChain*2 + whichState], alpha[whichChain*2 + whichState], nLocalCats, 0);
}
else if (!strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "ssadgamma"))
{
a = psdmatrix (nLocalCats);
AutodGamma (a, catFreq, catRate, &correlation, alpha[whichChain*2 + whichState], rateCorrelation[whichChain*2 + whichState], nLocalCats);
}
else if (!strcmp(ratesModel, "invgamma"))
{
DiscreteGamma (catFreq, catRate, alpha[whichChain*2 + whichState], alpha[whichChain*2 + whichState], nLocalCats-1, 0);
catRate[nLocalCats-1] = 0.0;
catFreq[nLocalCats-1] = invP[whichChain*2 + whichState];
for (i=0; i<nLocalCats-1; i++)
{
catRate[i] *= 1.0 / (1.0 - invP[whichChain*2 + whichState]);
catFreq[i] *= (1.0 - invP[whichChain*2 + whichState]);
}
}
else if (!strcmp(ratesModel, "invariant"))
{
catRate[0] = 0.0;
catRate[1] = 1.0 / (1.0 - invP[whichChain*2 + whichState]);
catFreq[0] = invP[whichChain*2 + whichState];
catFreq[1] = 1.0 - invP[whichChain*2 + whichState];
}
else if (!strcmp(ratesModel, "sitespec"))
{
for (i=0; i<nLocalCats; i++)
{
catRate[i] = scaledRates[whichChain*2*nLocalCats + whichState*nLocalCats + i];
catFreq[i] = 1.0;
}
}
else
{
catRate[0] = 1.0;
catFreq[0] = 1.0;
}
if (!strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "ssadgamma"))
{
f = (double *)malloc((size_t) (nLocalCats * nChar * sizeof(double)));
if (!f)
{
printf ("\n ERROR: Problem allocating f.\n");
goto error_exit;
}
for (i=0; i<nLocalCats*nChar; i++)
f[i] = 0.0;
b = (double *)malloc((size_t) (nLocalCats * nChar * sizeof(double)));
if (!b)
{
printf ("\n ERROR: Problem allocating b.\n");
goto error_exit;
}
for (i=0; i<nLocalCats*nChar; i++)
b[i] = 0.0;
expPr = (double *)malloc((size_t) (nLocalCats * sizeof(double)));
if (!expPr)
{
printf ("\n ERROR: Problem allocating expPr.\n");
goto error_exit;
}
for (i=0; i<nLocalCats; i++)
expPr[i] = 0.0;
logCf = (double *)malloc((size_t) (nChar * sizeof(double)));
if (!logCf)
{
printf ("\n ERROR: Problem allocating f.\n");
goto error_exit;
}
for (i=0; i<nChar; i++)
logCf[i] = 0.0;
logCb = (double *)malloc((size_t) (nChar * sizeof(double)));
if (!logCb)
{
printf ("\n ERROR: Problem allocating b.\n");
goto error_exit;
}
for (i=0; i<nChar; i++)
logCb[i] = 0.0;
}
bs = (double *)malloc((size_t) (nStates * sizeof(double)));
if (!bs)
{
printf ("\n ERROR: Problem allocating bs.\n");
goto error_exit;
}
for (i=0; i<nStates; i++)
bs[i] = baseFreq[whichChain*2*nStates + whichState*nStates + i];
tempRatePr = (double *)malloc((size_t) (numChars * nLocalCats * sizeof(double)));
if (!tempRatePr)
{
printf ("\n ERROR: Problem allocating tempRatePr.\n");
goto error_exit;
}
aveRate = (double *)malloc((size_t) (nChar * nLocalCats * sizeof(double)));
if (!aveRate)
{
printf ("\n ERROR: Problem allocating aveRate.\n");
goto error_exit;
}
oneMatSize = numNodes * numChars * numRateCats * nStates;
/* calculate conditional probabilites at base of tree...f(x | r) */
p = root[whichChain*2+whichState]->left;
if (!strcmp(ratesModel, "equal") || !strcmp(ratesModel, "sitespec"))
{
clP = &condLike[whichChain*2*oneMatSize + whichState*oneMatSize + (p->index)*numChars*nStates];
for (c=0; c<numChars; c++, *(clP+=nStates))
{
like = 0.0;
for (i=0; i<nStates; i++)
like += clP[i] * bs[i];
tempRatePr[0 * numChars + c] = like;
}
}
else if (!strcmp(ratesModel, "gamma") || !strcmp(ratesModel, "invariant") || !strcmp(ratesModel, "invgamma") || !strcmp(ratesModel, "ssgamma"))
{
clP = &condLike[whichChain*2*oneMatSize + whichState*oneMatSize + (p->index)*numChars*nLocalCats*nStates];
nOff = nLocalCats * nStates;
for (c=0; c<numChars; c++, *(clP+=nOff))
{
for (k=0; k<nLocalCats; k++)
{
kTimesS = k * nStates;
like = 0.0;
for (i=0; i<nStates; i++)
like += clP[kTimesS + i] * bs[i];
tempRatePr[k * numChars + c] = like;
}
}
}
else if (!strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "ssadgamma"))
{
clP = &condLike[whichChain*2*oneMatSize + whichState*oneMatSize + (p->index)*numChars*nLocalCats*nStates];
nOff = nLocalCats * nStates;
for (c=0; c<numChars; c++, *(clP+=nOff))
{
for (k=0; k<nLocalCats; k++)
{
kTimesS = k * nStates;
like = 0.0;
for (i=0; i<nStates; i++)
like += clP[kTimesS + i] * bs[i];
tempRatePr[k * numChars + c] = like;
}
}
}
/* get average rates */
if (!strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "ssadgamma"))
{
/* forward algorithm */
logC = 0.0;
for (c=0; c<nChar; c++)
{
if (patternId[c] >= 0)
{
pat = patternId[c];
if (c == 0)
{
for (k=0; k<nLocalCats; k++)
f[k*nChar + c] = tempRatePr[k * numChars + pat];
}
else
{
for (l=0; l<nLocalCats; l++)
{
temp = 0.0;
for (k=0; k<nLocalCats; k++)
temp += f[k * nChar + (c-1)] * a[k][l];
f[l * nChar + c] = temp * tempRatePr[l * numChars + pat];
}
}
sum = 0.0;
for (k=0; k<nLocalCats; k++)
sum += f[k*nChar + c];
for (k=0; k<nLocalCats; k++)
f[k*nChar+c] /= sum;
logC += log(sum);
logCf[c] = logC;
}
else
{
}
}
/* backward algorithm */
logC = 0.0;
for (c=nChar-1; c>=0; c--)
{
if (patternId[c] >= 0)
{
if (c == nChar - 1)
{
for (k=0; k<nLocalCats; k++)
b[k * nChar + c] = catFreq[k];
}
else
{
pat = patternId[c+1];
for (k=0; k<nLocalCats; k++)
{
temp = 0.0;
for (l=0; l<nLocalCats; l++)
temp += a[k][l] * tempRatePr[l * numChars + pat] * b[l * nChar + (c+1)];
b[k * nChar + c] = temp;
}
}
sum = 0.0;
for (k=0; k<nLocalCats; k++)
sum += b[k*nChar + c];
for (k=0; k<nLocalCats; k++)
b[k*nChar+c] /= sum;
logC += log(sum);
logCb[c] = logC;
}
else
{
}
}
temp = 0.0;
pat = patternId[0];
for (l=0; l<nLocalCats; l++)
temp += tempRatePr[l * numChars + pat] * b[l * nChar + 0];
logLike = log (temp) + logC;
/* posterior probabilities of individual categories at site c */
for (c=0; c<nChar; c++)
{
/*printf ("%d ", c+1);*/
for (k=0; k<nLocalCats; k++)
{
temp = (log(f[k * nChar + c]) + logCf[c] + log(b[k * nChar + c]) + logCb[c]) - logLike;
/*if (temp > 0.0)
printf ("x.xxxxxx ");
else if (temp < -100.0)
printf ("%lf ", 0.0);
else
printf ("%lf ", exp(temp));*/
if (temp > 0.0)
expPr[k] = 1.0;
else if (temp < -100.0)
expPr[k] = 0.0;
else
expPr[k] = exp(temp);
}
if (!strcmp(ratesModel, "adgamma"))
{
x = 0.0;
for (k=0; k<nLocalCats; k++)
{
x += expPr[k] * catRate[k];
rateProbs[c*nLocalCats + k] += expPr[k];
}
aveRate[c] = x;
}
else
{
pat = patternId[c];
mult = scaledRates[whichChain*2*nPartitions + whichState*nPartitions + partitionId[pat]];
x = 0.0;
for (k=0; k<nLocalCats; k++)
{
x += expPr[k] * catRate[k];
rateProbs[c*nLocalCats + k] += expPr[k];
}
aveRate[c] = x * mult;
fprintf (fp2, "%1.4lf\t", x);
}
fprintf (fp2, "%1.4lf\t", aveRate[c]);
/*printf ("\n");*/
}
}
else if (!strcmp(ratesModel, "sitespec"))
{
for (c=0; c<nChar; c++)
{
if (patternId[c] >= 0)
{
pat = patternId[c];
aveRate[c] = catRate[partitionId[pat]];
rateProbs[c] = 1.0;
fprintf (fp2, "%1.4lf\t", aveRate[c]);
}
}
}
else if (!strcmp(ratesModel, "ssgamma"))
{
for (c=0; c<nChar; c++)
{
if (patternId[c] >= 0)
{
pat = patternId[c];
mult = scaledRates[whichChain*2*nPartitions + whichState*nPartitions + partitionId[pat]];
sum = 0.0;
for (k=0; k<nLocalCats; k++)
sum += tempRatePr[k * numChars + pat] * catFreq[k];
x = 0.0;
for (k=0; k<nLocalCats; k++)
{
x += (tempRatePr[k * numChars + pat] * catFreq[k] / sum) * catRate[k];
rateProbs[c*nLocalCats + k] += (tempRatePr[k * numChars + pat] * catFreq[k] / sum);
}
aveRate[c] = x * mult;
fprintf (fp2, "%1.4lf\t", aveRate[c]);
}
}
}
else
{
for (c=0; c<nChar; c++)
{
if (patternId[c] >= 0)
{
pat = patternId[c];
sum = 0.0;
for (k=0; k<nLocalCats; k++)
sum += tempRatePr[k * numChars + pat] * catFreq[k];
x = 0.0;
for (k=0; k<nLocalCats; k++)
{
x += (tempRatePr[k * numChars + pat] * catFreq[k] / sum) * catRate[k];
rateProbs[c*nLocalCats + k] += (tempRatePr[k * numChars + pat] * catFreq[k] / sum);
}
aveRate[c] = x;
fprintf (fp2, "%1.4lf\t", x);
}
}
}
fprintf (fp2, "\n");
for (c=0; c<nChar; c++)
rateFactors[c] += aveRate[c];
/* print summary of probabilities to a file */
if (whichGen == nGen && nSampled >= 1)
{
fprintf (fp1, "Summary of rate factors for each site\n");
for (i=0; i<nChar; i++)
{
fprintf (fp1, "%d\t%1.4lf\t", i+1, rateFactors[i] / nSampled);
if (!strcmp(ratesModel, "sitespec"))
{
fprintf (fp1, "%1.4lf\t", 1.0);
}
else
{
for (k=0; k<nLocalCats; k++)
fprintf (fp1, "%1.4lf\t", rateProbs[i*nLocalCats + k] / nSampled);
}
fprintf (fp1, "\n");
}
free (rateFactors);
free (rateProbs);
}
free (bs);
free (tempRatePr);
free (aveRate);
fclose (fp1);
fclose (fp2);
if (!strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "ssadgamma"))
{
free (f);
free (b);
free (expPr);
free (logCf);
free (logCb);
free_psdmatrix(a);
}
return (NO_ERROR);
error_exit:
free (bs);
free (tempRatePr);
#if defined (MORPH)
if (fp1 != NULL)
fclose (fp1);
if (fp2 != NULL)
fclose (fp2);
#else
fclose(fp1);
fclose(fp2);
#endif
free (rateFactors);
free (aveRate);
if (!strcmp(ratesModel, "adgamma") || !strcmp(ratesModel, "ssadgamma"))
{
free (f);
free (b);
free (expPr);
free (logCf);
free (logCb);
free_psdmatrix(a);
}
return (ERROR);
}
int PrintStatesToFile (int n, int coldId, int whichState, double logLike, double *constrainedNodes, double *calibratedNodes)
{
int i;
double tl, bs[8];
TreeNode *p;
FILE *fp1, *fp2;
/* set pointers for first part */
fp1 = pFile;
fp2 = bpFile;
fprintf (fp1, "%d\t%lf\t", n, logLike);
fprintf (fp2, " data %d, %1.2lf", n, logLike);
tl = GetTreeLength (whichState, coldId);
fprintf (fp1, "%lf\t", tl);
fprintf (fp2, ", %lf", tl);
if ((dataType == DNA || dataType == RNA) && enforceCodonModel == NO)
{
if (nst == 2)
{
fprintf (fp1, "%lf\t", kappa[coldId*2 + whichState]);
fprintf (fp2, ", %lf", kappa[coldId*2 + whichState]);
}
else if (nst == 6)
{
for (i=0; i<6; i++)
{
fprintf (fp1, "%lf\t", subParams[coldId*12 + whichState*6 + i]);
fprintf (fp2, ", %lf", subParams[coldId*12 + whichState*6 + i]);
}
}
else if (nst == 12)
{
for (i=0; i<12; i++)
{
fprintf (fp1, "%lf\t", subParams[coldId*24 + whichState*12 + i]);
fprintf (fp2, ", %lf", subParams[coldId*24 + whichState*12 + i]);
}
}
if (dataType == DNA || dataType == RNA)
{
if (useCovarion == YES && !strcmp(covarionModelType, "gcswitch"))
{
bs[0] = (1.0 - gc1[coldId*2 + whichState]) * (fracA[coldId*2 + whichState]);
bs[1] = (gc1[coldId*2 + whichState]) * (1.0 - fracG[coldId*2 + whichState]);
bs[2] = (gc1[coldId*2 + whichState]) * (fracG[coldId*2 + whichState]);
bs[3] = (1.0 - gc1[coldId*2 + whichState]) * (1.0 - fracA[coldId*2 + whichState]);
bs[4] = (1.0 - gc2[coldId*2 + whichState]) * (fracA[coldId*2 + whichState]);
bs[5] = (gc2[coldId*2 + whichState]) * (1.0 - fracG[coldId*2 + whichState]);
bs[6] = (gc2[coldId*2 + whichState]) * (fracG[coldId*2 + whichState]);
bs[7] = (1.0 - gc2[coldId*2 + whichState]) * (1.0 - fracA[coldId*2 + whichState]);
for (i=0; i<8; i++)
{
fprintf (fp1, "%lf\t", bs[i]);
fprintf (fp2, ", %lf", bs[i]);
}
}
else
{
for (i=0; i<nStates; i++)
{
fprintf (fp1, "%lf\t", baseFreq[coldId*2*nStates + whichState*nStates + i]);
fprintf (fp2, ", %lf", baseFreq[coldId*2*nStates + whichState*nStates + i]);
}
}
}
if (useCovarion == YES)
{
fprintf (fp1, "%lf\t%lf\t", switchRate[coldId*4 + whichState*2 + 0], switchRate[coldId*4 + whichState*2 + 1]);
fprintf (fp2, ", %lf, %lf", switchRate[coldId*4 + whichState*2 + 0], switchRate[coldId*4 + whichState*2 + 1]);
}
}
else if ((dataType == DNA || dataType == RNA) && enforceCodonModel == YES)
{
fprintf (fp1, "%lf\t", kappa[coldId*2 + whichState]);
fprintf (fp2, ", %lf", kappa[coldId*2 + whichState]);
fprintf (fp1, "%lf\t", omega[coldId*2 + whichState]);
fprintf (fp2, ", %lf", omega[coldId*2 + whichState]);
if (!strcmp(codonModelType, "ny98"))
{
fprintf (fp1, "%lf\t", probPur[coldId*2 + whichState]);
fprintf (fp2, ", %lf", probPur[coldId*2 + whichState]);
fprintf (fp1, "%lf\t", probNeu[coldId*2 + whichState]);
fprintf (fp2, ", %lf", probNeu[coldId*2 + whichState]);
fprintf (fp1, "%lf\t", probPos[coldId*2 + whichState]);
fprintf (fp2, ", %lf", probPos[coldId*2 + whichState]);
}
else if (!strcmp(codonModelType, "ac1ny98"))
{
fprintf (fp1, "%lf\t", probPur[coldId*2 + whichState]);
fprintf (fp2, ", %lf", probPur[coldId*2 + whichState]);
fprintf (fp1, "%lf\t", probNeu[coldId*2 + whichState]);
fprintf (fp2, ", %lf", probNeu[coldId*2 + whichState]);
fprintf (fp1, "%lf\t", probPos[coldId*2 + whichState]);
fprintf (fp2, ", %lf", probPos[coldId*2 + whichState]);
fprintf (fp1, "%lf\t", rateCorrelation[coldId*2 + whichState]);
fprintf (fp2, ", %lf", rateCorrelation[coldId*2 + whichState]);
}
else if (!strcmp(codonModelType, "ac2ny98"))
{
fprintf (fp1, "%lf\t", probPur[coldId*2 + whichState]);
fprintf (fp2, ", %lf", probPur[coldId*2 + whichState]);
fprintf (fp1, "%lf\t", probNeu[coldId*2 + whichState]);
fprintf (fp2, ", %lf", probNeu[coldId*2 + whichState]);
fprintf (fp1, "%lf\t", probPos[coldId*2 + whichState]);
fprintf (fp2, ", %lf", probPos[coldId*2 + whichState]);
fprintf (fp1, "%lf\t", rateCorrelation[coldId*2 + whichState]);
fprintf (fp2, ", %lf", rateCorrelation[coldId*2 + whichState]);
fprintf (fp1, "%lf\t", rateCorrelation2[coldId*4 + whichState*2 + 0]);
fprintf (fp2, ", %lf", rateCorrelation2[coldId*4 + whichState*2 + 0]);
fprintf (fp1, "%lf\t", rateCorrelation2[coldId*4 + whichState*2 + 1]);
fprintf (fp2, ", %lf", rateCorrelation2[coldId*4 + whichState*2 + 1]);
}
else if (!strcmp(codonModelType, "covny98"))
{
fprintf (fp1, "%lf\t", probPur[coldId*2 + whichState]);
fprintf (fp2, ", %lf", probPur[coldId*2 + whichState]);
fprintf (fp1, "%lf\t", probNeu[coldId*2 + whichState]);
fprintf (fp2, ", %lf", probNeu[coldId*2 + whichState]);
fprintf (fp1, "%lf\t", probPos[coldId*2 + whichState]);
fprintf (fp2, ", %lf", probPos[coldId*2 + whichState]);
fprintf (fp1, "%lf\t", switchRate[coldId*4 + whichState*2 + 0]);
fprintf (fp2, ", %lf", switchRate[coldId*4 + whichState*2 + 0]);
}
for (i=0; i<nStates; i++)
{
fprintf (fp1, "%lf\t", baseFreq[coldId*2*nStates + whichState*nStates + i]);
fprintf (fp2, ", %lf", baseFreq[coldId*2*nStates + whichState*nStates + i]);
}
}
else if (dataType == PROTEIN)
{
if (aaModelType == EQUALIN || aaModelType == GTR)
{
for (i=0; i<nStates; i++)
{
fprintf (fp1, "%lf\t", baseFreq[coldId*2*nStates + whichState*nStates + i]);
fprintf (fp2, ", %lf", baseFreq[coldId*2*nStates + whichState*nStates + i]);
}
}
if (useCovarion == YES)
{
fprintf (fp1, "%lf\t%lf\t", switchRate[coldId*4 + whichState*2 + 0], switchRate[coldId*4 + whichState*2 + 1]);
fprintf (fp2, ", %lf, %lf", switchRate[coldId*4 + whichState*2 + 0], switchRate[coldId*4 + whichState*2 + 1]);
}
}
else if (dataType == RESTRICTION)
{
fprintf (fp1, "%lf\t", kappa[coldId*2 + whichState]);
fprintf (fp2, ", %lf", kappa[coldId*2 + whichState]);
}
#if defined (MORPH)
else if (dataType == STANDARD && numBetaCats > 1)
{
fprintf (fp1, "%lf\t", statefreqP[coldId*2 + whichState]);
fprintf (fp2, ", %lf", statefreqP[coldId*2 + whichState]);
}
#endif
if (((dataType == DNA || dataType == RNA) && enforceCodonModel == NO) || dataType == PROTEIN || dataType == RESTRICTION)
{
if (!strcmp(ratesModel, "gamma"))
{
fprintf (fp1, "%lf\t", alpha[coldId*2 + whichState]);
fprintf (fp2, ", %lf", alpha[coldId*2 + whichState]);
}
else if (!strcmp(ratesModel, "adgamma"))
{
fprintf (fp1, "%lf\t", alpha[coldId*2 + whichState]);
fprintf (fp2, ", %lf", alpha[coldId*2 + whichState]);
fprintf (fp1, "%lf\t", rateCorrelation[coldId*2 + whichState]);
fprintf (fp2, ", %lf", rateCorrelation[coldId*2 + whichState]);
if (!strcmp(lagprModel, "uniform") || !strcmp(lagprModel, "exponential"))
{
fprintf (fp1, "%d\t", lag[coldId*2 + whichState]);
fprintf (fp2, ", %d", lag[coldId*2 + whichState]);
}
}
else if (!strcmp(ratesModel, "sitespec"))
{
for (i=0; i<nPartitions; i++)
{
fprintf (fp1, "%lf\t", scaledRates[coldId*2*nPartitions + whichState*nPartitions + i]);
fprintf (fp2, ", %lf", scaledRates[coldId*2*nPartitions + whichState*nPartitions + i]);
}
}
else if (!strcmp(ratesModel, "invariant"))
{
fprintf (fp1, "%lf\t", invP[coldId*2 + whichState]);
fprintf (fp2, ", %lf", invP[coldId*2 + whichState]);
}
else if (!strcmp(ratesModel, "invgamma"))
{
fprintf (fp1, "%lf\t", alpha[coldId*2 + whichState]);
fprintf (fp2, ", %lf", alpha[coldId*2 + whichState]);
fprintf (fp1, "%lf\t", invP[coldId*2 + whichState]);
fprintf (fp2, ", %lf", invP[coldId*2 + whichState]);
}
else if (!strcmp(ratesModel, "ssgamma"))
{
fprintf (fp1, "%lf\t", alpha[coldId*2 + whichState]);
fprintf (fp2, ", %lf", alpha[coldId*2 + whichState]);
for (i=0; i<nPartitions; i++)
{
fprintf (fp1, "%lf\t", scaledRates[coldId*2*nPartitions + whichState*nPartitions + i]);
fprintf (fp2, ", %lf", scaledRates[coldId*2*nPartitions + whichState*nPartitions + i]);
}
}
else if (!strcmp(ratesModel, "ssadgamma"))
{
fprintf (fp1, "%lf\t", alpha[coldId*2 + whichState]);
fprintf (fp2, ", %lf", alpha[coldId*2 + whichState]);
fprintf (fp1, "%lf\t", rateCorrelation[coldId*2 + whichState]);
fprintf (fp2, ", %lf", rateCorrelation[coldId*2 + whichState]);
if (!strcmp(lagprModel, "uniform") || !strcmp(lagprModel, "exponential"))
{
fprintf (fp1, "%d\t", lag[coldId*2 + whichState]);
fprintf (fp2, ", %d", lag[coldId*2 + whichState]);
}
for (i=0; i<nPartitions; i++)
{
fprintf (fp1, "%lf\t", scaledRates[coldId*2*nPartitions + whichState*nPartitions + i]);
fprintf (fp2, ", %lf", scaledRates[coldId*2*nPartitions + whichState*nPartitions + i]);
}
}
}
if (!strcmp(brlenprModel, "birth-death"))
{
fprintf (fp1, "%lf\t%lf\t", spRate[coldId*2 + whichState], exRate[coldId*2 + whichState]);
fprintf (fp2, ", %lf, %lf", spRate[coldId*2 + whichState], exRate[coldId*2 + whichState]);
}
if (enforceCalibrations == YES)
{
fprintf (fp1, "%lf\t", treeHeight[coldId*2 + whichState]);
fprintf (fp2, ", %lf", treeHeight[coldId*2 + whichState]);
for (i=0; i<numNodes; i++)
{
p = allNodesDownPassSeq[coldId*2*numNodes + whichState*numNodes + i];
if (p->isConstrained == YES)
{
if (p->constraintNum-1 >= nConstraints)
{
printf ("\n ERROR: Constraint out of bounds\n");
return ERROR;
}
else
constrainedNodes[p->constraintNum-1] = p->nodeTime;
}
if (p->isCalibrated == YES)
{
if (p->calibrationNum-1 >= nCalibrations)
{
printf ("\n ERROR: Calibration out of bounds\n");
return ERROR;
}
else
calibratedNodes[p->calibrationNum-1] = p->nodeTime;
}
}
for (i=0; i<nConstraints; i++)
{
fprintf (fp1, "%lf\t", constrainedNodes[i]);
fprintf (fp2, ", %lf", constrainedNodes[i]);
}
for (i=0; i<nCalibrations; i++)
{
fprintf (fp1, "%lf\t", calibratedNodes[i]);
fprintf (fp2, ", %lf", calibratedNodes[i]);
}
}
fprintf (fp1, "\n");
fprintf (fp2, ";\n");
if (n == nGen)
fprintf (fp2, "end;\n");
fflush (fp1);
fflush (fp2);
fp2 = tFile;
fprintf (fp2, " tree rep.%d = ", n);
WriteTreeToFile (root[coldId*2 + whichState]->left, fp2, saveBrlens);
if (n == nGen)
fprintf (fp2, "end;\n");
fflush (fp2);
return (NO_ERROR);
}
int ProposeNewState (long int *seed)
{
int i, proposedState;
double ran, sum, cumProposalProbs[NUM_PROPOSAL_TYPES];
sum = 0.0;
for (i=0; i<NUM_PROPOSAL_TYPES; i++)
sum += relProposalProbs[i];
for (i=0; i<NUM_PROPOSAL_TYPES; i++)
relProposalProbs[i] /= sum;
cumProposalProbs[0] = relProposalProbs[0];
for (i=1; i<NUM_PROPOSAL_TYPES; i++)
cumProposalProbs[i] = cumProposalProbs[i-1] + relProposalProbs[i];
ran = RandomNumber(seed);
proposedState = 100;
if (ran >= 0.0 && ran <= cumProposalProbs[0])
proposedState = CHANGE_QMAT;
else if (ran >cumProposalProbs[0] && ran <= cumProposalProbs[1])
proposedState = CHANGE_BASEFREQS;
else if (ran >cumProposalProbs[1] && ran <= cumProposalProbs[2])
proposedState = CHANGE_GAMMA_SHAPE;
else if (ran >cumProposalProbs[2] && ran <= cumProposalProbs[3])
proposedState = CHANGE_SITE_RATES;
else if (ran >cumProposalProbs[3] && ran <= cumProposalProbs[4])
proposedState = CHANGE_UNROOT_LOCAL;
else if (ran >cumProposalProbs[4] && ran <= cumProposalProbs[5])
proposedState = CHANGE_CLOCK_LOCAL;
else if (ran >cumProposalProbs[5] && ran <= cumProposalProbs[6])
proposedState = CHANGE_CLOCK_TIME_LOCAL;
else if (ran >cumProposalProbs[6] && ran <= cumProposalProbs[7])
proposedState = CHANGE_TREE_HEIGHT;
else if (ran >cumProposalProbs[7] && ran <= cumProposalProbs[8])
proposedState = CHANGE_WORM;
else if (ran >cumProposalProbs[8] && ran <= cumProposalProbs[9])
proposedState = CHANGE_NODE_TIME;
else if (ran >cumProposalProbs[9] && ran <= cumProposalProbs[10])
proposedState = CHANGE_BD_PARAMS;
else if (ran >cumProposalProbs[10] && ran <= cumProposalProbs[11])
proposedState = CHANGE_OMEGA;
else if (ran >cumProposalProbs[11] && ran <= cumProposalProbs[12])
proposedState = CHANGE_OMEGA_PROBS;
else if (ran >cumProposalProbs[12] && ran <= cumProposalProbs[13])
proposedState = CHANGE_AUTO_CORR;
else if (ran >cumProposalProbs[13] && ran <= cumProposalProbs[14])
proposedState = CHANGE_LAG;
else if (ran >cumProposalProbs[14] && ran <= cumProposalProbs[15])
proposedState = CHANGE_TREE_SPR;
else if (ran >cumProposalProbs[15] && ran <= cumProposalProbs[16])
proposedState = CHANGE_INV_P;
else if (ran >cumProposalProbs[16] && ran <= cumProposalProbs[17])
proposedState = CHANGE_SWITCH_RATE;
else if (ran >cumProposalProbs[17] && ran <= cumProposalProbs[18])
proposedState = CHANGE_UNROOT_TBR;
else if (ran >cumProposalProbs[18] && ran <= cumProposalProbs[19])
proposedState = CHANGE_GCSWITCH;
else if (ran >cumProposalProbs[19] && ran <= cumProposalProbs[20])
proposedState = CHANGE_TREE_FTBR;
else if (ran >cumProposalProbs[20] && ran <= cumProposalProbs[21])
proposedState = CHANGE_BRLEN;
else if (ran >cumProposalProbs[21] && ran <= cumProposalProbs[22])
proposedState = CHANGE_ERASER;
#if defined (MORPH)
else if (ran >cumProposalProbs[22] && ran <= cumProposalProbs[23])
proposedState = CHANGE_BETA_SHAPE;
#endif
return (proposedState);
}
/*-------| RandomNumber |------------------------------------------------
| This pseudorandom number generator is described in:
| Park, S. K. and K. W. Miller. 1988. Random number generators: good
| ones are hard to find. Communications of the ACM, 31(10):1192-1201.
*/
double RandomNumber (long int *seed)
{
long int lo, hi, test;
hi = (*seed) / 127773;
lo = (*seed) % 127773;
test = 16807 * lo - 2836 * hi;
if (test > 0)
*seed = test;
else
*seed = test + 2147483647;
return (double)(*seed) / (double)2147483647;
}
double RndGamma (double s, long int *seed)
{
double r=0.0;
if (s <= 0.0)
puts ("jgl gamma..");
else if (s < 1.0)
r = RndGamma1 (s, seed);
else if (s > 1.0)
r = RndGamma2 (s, seed);
else
r =- log(RandomNumber(seed));
return (r);
}
double RndGamma1 (double s, long int *seed)
{
double r, x=0.0, small=1e-37, w;
static double a, p, uf, ss=10.0, d;
if (s!=ss)
{
a = 1.0-s;
p = a/(a+s*exp(-a));
uf = p*pow(small/a,s);
d = a*log(a);
ss = s;
}
for (;;)
{
r = RandomNumber(seed);
if (r > p)
x = a-log((1.0-r)/(1.0-p)), w=a*log(x)-d;
else if (r>uf)
x = a*pow(r/p,1/s), w=x;
else
return (0.0);
r = RandomNumber(seed);
if (1.0-r <= w && r > 0.0)
if (r*(w+1.0) >= 1.0 || -log(r) <= w)
continue;
break;
}
return (x);
}
double RndGamma2 (double s, long int *seed)
{
double r ,d, f, g, x;
static double b, h, ss=0;
if (s!=ss)
{
b = s-1.0;
h = sqrt(3.0*s-0.75);
ss = s;
}
for (;;)
{
r = RandomNumber(seed);
g = r-r*r;
f = (r-0.5)*h/sqrt(g);
x = b+f;
if (x <= 0.0)
continue;
r = RandomNumber(seed);
d = 64*r*r*g*g*g;
if (d*x < x-2.0*f*f || log(d) < 2*(b*log(x/b)-f))
break;
}
return (x);
}
int RunChain (void)
{
int i, n, numTaxa, numChars, numRateCats;
long int seed;
printf (" Running Markov chain\n");
seed = randomSeed;
/* set all of the indicators for allocated memory to "NO" */
for (i=0; i<NUM_ALLOCS; i++)
allocatedMemory[i] = NO;
/* check and set all of the model and chain parameters */
if (useParsCriterion == NO)
{
if (SetModel (&numRateCats) == ERROR)
{
FreeMemory ();
return (ERROR);
}
}
else
treeModel = UNROOTED;
/* compress character matrix */
if (useParsCriterion == NO)
{
if (CompressMatrix (&numTaxa, &numChars) == ERROR)
{
FreeMemory ();
return (ERROR);
}
}
else
{
if (CompressMatrixPars (&numTaxa, &numChars) == ERROR)
{
FreeMemory ();
return (ERROR);
}
}
/* build starting tree(s) */
if (BuildStartingTree (numTaxa, numChars, &seed, NO) == ERROR)
{
FreeMemory ();
return (ERROR);
}
/* set up trees */
if (SetUpTrees (numTaxa) == ERROR)
{
FreeMemory ();
return (ERROR);
}
/* initialize conditional likelihoods */
if (useParsCriterion == NO)
{
if (InitializeConditionalLikes (numTaxa, numChars, numRateCats) == ERROR)
{
FreeMemory ();
return (ERROR);
}
}
else
{
if (InitializeTipStates (numTaxa, numChars) == ERROR)
{
FreeMemory ();
return (ERROR);
}
}
/* set up transition probabilities */
# if defined (SMART_TI_PROBS)
if (useParsCriterion == NO)
{
printf (" Setting up transition probabilities\n");
if (SetUpTransitionProbs (numRateCats) == ERROR)
{
FreeMemory ();
return (ERROR);
}
}
# endif
/* copy trees and conditional likelihoods from memory space 0 -> 1 */
if (useParsCriterion == NO)
{
printf (" Copying states in memory\n");
for (n=0; n<numChains; n++)
{
for (i=0; i<numNodes; i++)
clUpdateFlag[i] = YES;
CopyTree (0, 1, n);
CopyConditionalLikelihoods (0, 1, n, numTaxa, numChars, numRateCats);
}
}
else
{
printf (" Copying trees in memory\n");
for (n=0; n<numChains; n++)
CopyTree (0, 1, n);
}
/* add some number of random perturbations to the starting trees */
if (!strcmp(startingTreeModel, "user") && nPerturbations > 0)
{
printf (" Perturbing starting trees\n");
if (PerturnStartingTree (numTaxa, &seed) == ERROR)
{
FreeMemory ();
return (ERROR);
}
}
/* run Markov chain */
printf (" Running Markov chain\n");
if (useParsCriterion == NO)
{
if (MarkovChain (numTaxa, numChars, numRateCats, &seed) == ERROR)
{
FreeMemory ();
return (ERROR);
}
}
else
{
if (MarkovChainPars (numTaxa, numChars, &seed) == ERROR)
{
FreeMemory ();
return (ERROR);
}
}
/* free memory */
FreeMemory ();
printf (" Chain successfully run\n");
randomSeed = seed;
return (NO_ERROR);
}
void SetCode (void)
{
int i, s, s1, s2, s3;
printf (" Setting genetic code\n");
codon[ 0] = 12; /* AAA Lys */
codon[ 1] = 3; /* AAC Asn */
codon[ 2] = 12; /* AAG Lys */
codon[ 3] = 3; /* AAT Asn */
codon[ 4] = 17; /* ACA Thr */
codon[ 5] = 17; /* ACC Thr */
codon[ 6] = 17; /* ACG Thr */
codon[ 7] = 17; /* ACT Thr */
codon[ 8] = 2; /* AGA Arg */
codon[ 9] = 16; /* AGC Ser */
codon[10] = 2; /* AGG Arg */
codon[11] = 16; /* AGT Ser */
codon[12] = 10; /* ATA Ile */
codon[13] = 10; /* ATC Ile */
codon[14] = 13; /* ATG Met */
codon[15] = 10; /* ATT Ile */
codon[16] = 6; /* CAA Gln */
codon[17] = 9; /* CAC His */
codon[18] = 6; /* CAG Gln */
codon[19] = 9; /* CAT His */
codon[20] = 15; /* CCA Pro */
codon[21] = 15; /* CCC Pro */
codon[22] = 15; /* CCG Pro */
codon[23] = 15; /* CCT Pro */
codon[24] = 2; /* CGA Arg */
codon[25] = 2; /* CGC Arg */
codon[26] = 2; /* CGG Arg */
codon[27] = 2; /* CGT Arg */
codon[28] = 11; /* CTA Leu */
codon[29] = 11; /* CTC Leu */
codon[30] = 11; /* CTG Leu */
codon[31] = 11; /* CTT Leu */
codon[32] = 7; /* GAA Glu */
codon[33] = 4; /* GAC Asp */
codon[34] = 7; /* GAG Glu */
codon[35] = 4; /* GAT Asp */
codon[36] = 1; /* GCA Ala */
codon[37] = 1; /* GCC Ala */
codon[38] = 1; /* GCG Ala */
codon[39] = 1; /* GCT Ala */
codon[40] = 8; /* GGA Gly */
codon[41] = 8; /* GGC Gly */
codon[42] = 8; /* GGG Gly */
codon[43] = 8; /* GGT Gly */
codon[44] = 20; /* GTA Val */
codon[45] = 20; /* GTC Val */
codon[46] = 20; /* GTG Val */
codon[47] = 20; /* GTT Val */
codon[48] = 21; /* TAA Stop*/
codon[49] = 19; /* TAC Tyr */
codon[50] = 21; /* TAG Stop*/
codon[51] = 19; /* TAT Tyr */
codon[52] = 16; /* TCA Ser */
codon[53] = 16; /* TCC Ser */
codon[54] = 16; /* TCG Ser */
codon[55] = 16; /* TCT Ser */
codon[56] = 21; /* TGA Stop*/
codon[57] = 5; /* TGC Cys */
codon[58] = 18; /* TGG Trp */
codon[59] = 5; /* TGT Cys */
codon[60] = 11; /* TTA Leu */
codon[61] = 14; /* TTC Phe */
codon[62] = 11; /* TTG Leu */
codon[63] = 14; /* TTT Phe */
if (aaCode == VERTMT)
{
printf (" Vertebrate mitochondrial code\n");
printf (" UGA: Ter -> Trp\n");
printf (" AUA: Ile -> Met\n");
printf (" AGA: Arg -> Ter\n");
printf (" AGG: Arg -> Ter\n");
codon[ 8] = 21; /* AGA Stop */
codon[10] = 21; /* AGG Stop */
codon[12] = 13; /* ATA Met */
codon[56] = 18; /* TGA Trp */
}
else if (aaCode == MYCO)
{
printf (" Mycoplasma nuclear code\n");
printf (" UGA: Ter -> Trp\n");
codon[56] = 18; /* TGA Trp */
}
else if (aaCode == YEAST)
{
printf (" Yeast mitochondrial code\n");
printf (" UGA: Ter -> Trp\n");
printf (" AUA: Ile -> Met\n");
printf (" CUA: Leu -> Thr\n");
printf (" CUC: Leu -> Thr\n");
printf (" CUG: Leu -> Thr\n");
printf (" CUU: Leu -> Thr\n");
codon[12] = 13; /* ATA Met */
codon[28] = 17; /* CTA Thr */
codon[29] = 17; /* CTC Thr */
codon[30] = 17; /* CTG Thr */
codon[31] = 17; /* CTT Thr */
codon[56] = 18; /* TGA Trp */
}
else if (aaCode == CILIATES)
{
printf (" Ciliate nuclear code\n");
printf (" UAA: Ter -> Gln\n");
printf (" UAG: Ter -> Gln\n");
codon[48] = 6; /* TAA Gln */
codon[50] = 6; /* TAG Gln */
}
else if (aaCode == METMT)
{
printf (" Metazoan (except vertebrates) mitochondrial code\n");
printf (" UGA: Ter -> Trp\n");
printf (" AUA: Ile -> Met\n");
printf (" AGA: Arg -> Ser\n");
printf (" AGG: Arg -> Ser\n");
codon[ 8] = 16; /* AGA Ser */
codon[10] = 16; /* AGG Ser */
codon[12] = 13; /* ATA Met */
codon[56] = 18; /* TGA Trp */
}
else
{
printf (" Universal code\n");
}
nStates = 0;
for (i=0; i<64; i++)
{
if (codon[i] != 21)
nStates++;
}
printf (" There are a total of %d coding triplets\n", nStates);
s = 0;
for (s1=0; s1<4; s1++)
{
for (s2=0; s2<4; s2++)
{
for (s3=0; s3<4; s3++)
{
if (codon[s1*16 + s2*4 + s3] != 21)
{
transCodon[s] = codon[s1*16 + s2*4 + s3];
codonNucs[s][0] = s1;
codonNucs[s][1] = s2;
codonNucs[s][2] = s3;
s++;
}
}
}
}
}
int SetModel (int *numRateCats)
{
int i, j, chain, nIncludedTaxa, nIncludedChars, x, y, isDiff;
double scaler, sum;
/* set all proposal mechanisms to zero */
for (i=0; i<NUM_PROPOSAL_TYPES; i++)
{
relProposalProbs[i] = 0.0;
chainMins[i] = 0.0;
chainMaxs[i] = 0.0;
}
/* check to see what type of data was input ***************************************************/
if (dataType == DNA || dataType == RNA)
{
nStates = 4;
if (dataType == DNA)
printf (" Data type = DNA\n");
else if (dataType == RNA)
printf (" Data type = RNA\n");
#if defined (TRANSLATE_TO_AA)
if (treatAsAA == YES)
printf (" Translated to amino acids and analyzed as such\n");
if (enforceCodonModel == YES || treatAsAA == YES)
#else
if (enforceCodonModel == YES)
#endif
{
/* set genetic code */
SetCode ();
#if defined (TRANSLATE_TO_AA)
if (treatAsAA == YES)
{
TranslateToAA();
nStates = 20;
dataType = PROTEIN;
}
#endif
}
}
else if (dataType == PROTEIN)
{
nStates = 20;
printf (" Data type = protein\n");
}
else if (dataType == RESTRICTION)
{
nStates = 2;
printf (" Data type = restriction site\n");
}
else if (dataType == STANDARD)
{
nStates = 2;
printf (" Data type = standard\n");
}
else
{
printf ("\n ERROR: Unknown data type.\n");
FreeMemory ();
return (ERROR);
}
numBetaCats = 1; /* this is the number of categories for the beta distribution for morphological data */
/* check coding of data ***********************************************************************/
if (dataType == DNA || dataType == RNA)
{
if (!strcmp(codingType, "variable") || !strcmp(codingType, "informative") || !strcmp(codingType, "noabsence") || !strcmp(codingType, "nopresence"))
{
printf ("\n ERROR: Only coding=all is allowed for DNA/RNA data.\n");
FreeMemory ();
return (ERROR);
}
}
else if (dataType == PROTEIN)
{
if (!strcmp(codingType, "variable") || !strcmp(codingType, "informative") || !strcmp(codingType, "noabsence") || !strcmp(codingType, "nopresence"))
{
printf ("\n ERROR: Only coding=all is allowed for AA data.\n");
FreeMemory ();
return (ERROR);
}
}
else if (dataType == RESTRICTION)
{
if (!strcmp(codingType, "informative"))
{
printf ("\n ERROR: coding=informative is not allowed for restriction site data.\n");
FreeMemory ();
return (ERROR);
}
}
else if (dataType == STANDARD)
{
if (!strcmp(codingType, "noabsence") || !strcmp(codingType, "nopresence"))
{
printf ("\n ERROR: coding=noabsence/nopresence is not allowed for standard data.\n");
FreeMemory ();
return (ERROR);
}
}
/* check to see if the data matrix is of a reasonable size ************************************/
nIncludedTaxa = 0;
for (i=0; i<nTaxa; i++)
{
if (excludedTaxa[i] == NO)
{
nIncludedTaxa++;
}
}
nIncludedChars = 0;
for (i=0; i<nChar; i++)
{
if (excludedSites[i] == NO)
{
nIncludedChars++;
}
}
if (nIncludedTaxa < 4)
{
printf ("\n ERROR: The data matrix is too small. Must have at least four taxa.\n");
FreeMemory ();
return (ERROR);
}
if (nIncludedChars < 1)
{
printf ("\n ERROR: Too few characters.\n");
FreeMemory ();
return (ERROR);
}
printf (" Data matrix included %d taxa and %d sites\n", nIncludedTaxa, nIncludedChars);
if (excludedTaxa[outgroupNum] == YES)
{
printf (" WARNING: The old outgroup taxon was excluded. The new\n");
printf (" outgroup is species ");
for (j=0; j<nTaxa; j++)
{
if (excludedTaxa[j] == NO)
break;
}
i = 0;
while (taxonLabels[j*100+i] != '|')
{
printf ("%c", taxonLabels[j*100+i]);
i++;
}
printf ("\n");
localOutgroup = 0;
}
else
{
i = 0;
for (j=0; j<nTaxa; j++)
{
if (j == outgroupNum)
break;
if (excludedTaxa[j] == NO)
i++;
}
localOutgroup = i;
}
printf (" Outgroup is species ");
j = 0;
for (i=0; i<nTaxa; i++)
{
if (excludedTaxa[i] == NO)
{
if (j == localOutgroup)
break;
j++;
}
}
j = 0;
while (taxonLabels[i*100+j] != '|')
{
printf ("%c", taxonLabels[i*100+j]);
j++;
}
printf ("\n");
/* check tree priors ***************************************************************************/
printf (" Branch length constraints\n");
if (!strcmp(clockModel, "unconstrained"))
{
printf (" Branch lengths are unconstrained\n");
treeModel = UNROOTED;
if (isUserTreeDefined == YES && isTreeRooted == YES)
{
if (DerootTree (userTreeRoot) == ERROR)
{
FreeMemory ();
return (ERROR);
}
isTreeRooted = NO;
}
}
else if (!strcmp(clockModel, "relaxed"))
{
printf ("\n ERROR: Sorry, but the relaxed clock is not yet implemented.\n");
FreeMemory ();
return (ERROR);
treeModel = ROOTED;
if (isUserTreeDefined == YES && isTreeRooted == NO)
{
if (RootTree (userTreeRoot) == ERROR)
{
FreeMemory ();
return (ERROR);
}
isTreeRooted = YES;
}
}
else if (!strcmp(clockModel, "strict"))
{
printf (" Branch lengths are constrained to satisfy the clock requirement\n");
if (!strcmp(startingTreeModel, "user"))
{
isStartingTreeRandom = NO;
if (isUserTreeDefined == NO)
{
printf ("\n ERROR: You requested that the chain start with a user-\n");
printf (" specified tree, but never entered a tree using\n");
printf (" \"usertree\".\n");
FreeMemory ();
return (ERROR);
}
}
else
isStartingTreeRandom = YES;
if (isStartingTreeRandom == NO && isUserTreeDefined == YES && isTreeRooted == NO)
{
printf ("\n WARNING: You requested that the chain start with a user-\n");
printf (" specified tree. Such a tree was provided, but the\n");
printf (" tree is unrooted. The strict clock model requires\n");
printf (" rooted trees. The tree is being rooted at the outgroup\n");
printf (" species\n\n");
if (RootTree (userTreeRoot) == ERROR)
{
FreeMemory ();
return (ERROR);
}
}
treeModel = ROOTED;
if (isUserTreeDefined == YES && isTreeRooted == NO)
{
if (RootTree (userTreeRoot) == ERROR)
{
FreeMemory ();
return (ERROR);
}
isTreeRooted = YES;
}
}
else
{
printf ("\n ERROR: Unknown branch constraint model\n");
FreeMemory ();
return (ERROR);
}
if (!strcmp(brlenprModel, "uniform"))
{
printf (" Branch lengths have a uniform(%1.4lf, %1.4lf) prior\n", brlenprUni[0], brlenprUni[1]);
}
else if (!strcmp(brlenprModel, "exponential"))
{
printf (" Branch lengths have an exponential(%1.4lf) prior\n", brlenprExp);
}
else if (!strcmp(brlenprModel, "birth-death"))
{
if (treeModel == UNROOTED)
{
printf ("\n ERROR: The birth-death prior requires rooted trees.\n");
FreeMemory ();
return (ERROR);
}
if (!(!strcmp(clockModel, "strict")))
{
printf ("\n ERROR: The birth-death prior requires the clock constraint.\n");
FreeMemory ();
return (ERROR);
}
spRate = (double *)malloc((size_t) (numChains * 2 * sizeof(double)));
if (!spRate)
{
printf ("ERROR: Problem allocating spRate\n");
return (ERROR);
}
else
allocatedMemory[ALLOC_SP_RATE] = YES;
exRate = (double *)malloc((size_t) (numChains * 2 * sizeof(double)));
if (!exRate)
{
printf ("ERROR: Problem allocating exRate\n");
return (ERROR);
}
else
allocatedMemory[ALLOC_EX_RATE] = YES;
if (speciationRate == extinctionRate)
{
printf ("\n Warning: Speciation and extinction rates cannot\n");
printf (" be equal. Setting extinction rate to be\n");
printf (" 90 percent of the speciation rate.\n\n");
extinctionRate = speciationRate * 0.9;
}
for (i=0; i<numChains*2; i++)
{
spRate[i] = speciationRate;
exRate[i] = extinctionRate;
}
relProposalProbs[CHANGE_BD_PARAMS] = moveRates[CHANGE_BD_PARAMS];
chainMins[CHANGE_BD_PARAMS] = BRLEN_EPSILON;
chainMaxs[CHANGE_BD_PARAMS] = 100.0;
printf (" Branch lengths and topology have a birth-death process prior\n");
}
else
{
printf ("\n ERROR: Unknown prior model on branch lengths\n");
FreeMemory ();
return (ERROR);
}
/* check constraints and calibrations **********************************************************/
if (enforceConstraints == YES)
{
if (nConstraints <= 0)
{
printf ("\n ERROR: You requested that constraits be enforced without ever\n");
printf (" defining constraints.\n");
FreeMemory ();
return (ERROR);
}
/* TO DO: check to see if constraints have been defined */
printf (" Enforcing constraints\n");
}
if (enforceCalibrations == YES)
{
printf ("\n NOTICE: You requested that calibrations be used so that \n");
printf (" speciation times can be estimated. This part of the \n");
printf (" program is temporarily deactivated as the MCMC \n");
printf (" routines that I originally implemented are unstable. \n");
printf (" Please wait until a later version to perform speciation\n");
printf (" time estimation.\n");
FreeMemory ();
return (ERROR);
if (nCalibrations <= 0)
{
printf ("\n ERROR: You requested that calibrations be used without ever\n");
printf (" defining calibrations.\n");
FreeMemory ();
return (ERROR);
}
if (!strcmp(clockModel, "unconstrained"))
{
printf ("\n ERROR: Calibrations only work when the strict or relaxed molecular\n");
printf (" clocks have been specified. You specified that the branch lengths\n");
printf (" are unconstrained. You need to change this using \"lset clock=strict\" or\n");
printf (" \"lset clock=relaxed\".\n");
FreeMemory ();
return (ERROR);
}
if (!strcmp(startingTreeModel, "user"))
{
printf ("\n WARNING: You requested that the chain start with a user-\n");
printf (" specified tree. Such a tree was provided, but the\n");
printf (" tree is unrooted. Tree calibrations require rooted\n");
printf (" input trees. Hence, the tree is being rooted at the outgroup\n");
printf (" species\n\n");
if (RootTree (userTreeRoot) == ERROR)
{
FreeMemory ();
return (ERROR);
}
}
printf (" Enforcing calibrations\n");
treeHeight = (double *)malloc((size_t) (numChains * 2 * sizeof(double)));
if (!treeHeight)
{
printf ("ERROR: Problem allocating treeHeight\n");
return (ERROR);
}
else
allocatedMemory[ALLOC_TREE_HEIGHT] = YES;
}
if (inferAncStates == YES)
{
if (nConstraints <= 0)
{
printf ("\n ERROR: You requested that ancestral states be estimated. This option\n");
printf (" requires that you specify constraints. The constraints\n");
printf (" correspond to the node(s) that will have the ancestral\n");
printf (" states estimated.\n");
FreeMemory ();
return (ERROR);
}
printf (" Estimating ancestral states at constrained nodes\n");
}
/* figure out starting tree for chain **********************************************************/
if (!strcmp(startingTreeModel, "random"))
{
isStartingTreeRandom = YES;
}
else if (!strcmp(startingTreeModel, "user"))
{
isStartingTreeRandom = NO;
if (isUserTreeDefined == NO)
{
printf ("\n ERROR: You requested that the chain start with a user-\n");
printf (" specified tree, but never entered a tree using\n");
printf (" \"usertree\".\n");
FreeMemory ();
return (ERROR);
}
}
else
{
printf ("\n ERROR: Unknown starting tree (should be \"random\" or \"user\"\n");
FreeMemory ();
return (ERROR);
}
/* how many chains *****************************************************************************/
if (numChains <= 0)
{
printf ("\n ERROR: Invalid number of chains\n");
}
else
{
printf (" Number of chains = %d\n", numChains);
if (numChains > 1)
{
printf (" Chains (i: {1, ..., %d}) are incrementally heated, with the heat\n", numChains);
printf (" being 1 / (1 + (i - 1) T), where T = %lf\n", chainTemp);
}
}
/* how many substitution parameters ************************************************************/
chainMins[CHANGE_QMAT] = 0.000001;
chainMaxs[CHANGE_QMAT] = 1000.0;
printf (" Substitution model\n");
if (dataType == DNA || dataType == RNA)
{
if (enforceCodonModel == NO)
{
/* 4 X 4 model of DNA substitution */
if (!strcmp(subModel, "1"))
{
printf (" All substitution types have equal rates.\n");
printf (" This corresponds to the JC69 or F81 models.\n");
nst = 1;
}
else if (!strcmp(subModel, "2"))
{
printf (" Two substitution types. Transitions have one\n");
printf (" rate whereas tranversions have another.\n");
printf (" This corresponds to the K80 or HKY85 models.\n");
nst = 2;
kappa = (double *)malloc((size_t) (numChains * 2 * sizeof(double)));
if (!kappa)
{
printf ("\n ERROR: Problem allocating kappa.\n");
FreeMemory ();
return (ERROR);
}
else
allocatedMemory[ALLOC_KAPPA] = YES;
for (i=0; i<2*numChains; i++)
kappa[i] = tRatio;
printf (" Starting kappa = %lf\n", kappa[0]);
}
else if (!strcmp(subModel, "6"))
{
printf (" There are six substitution types: A <-> C, A <-> G, A <-> T\n");
printf (" C <-> G, C <-> T, and G <-> T, each with a potentially\n");
printf (" different rate. This corresponds to the GTR model.\n");
nst = 6;
subParams = (double *)malloc((size_t) (numChains * 2 * 6 * sizeof(double)));
if (!subParams)
{
printf ("\n ERROR: Problem allocating subParams.\n");
FreeMemory ();
return (ERROR);
}
else
allocatedMemory[ALLOC_SUBPARAMS] = YES;
for (chain=0; chain<numChains; chain++)
{
for (i=0; i<6; i++)
{
subParams[chain*2*nst + 0*6 + i] = revRates[i];
subParams[chain*2*nst + 1*6 + i] = revRates[i];
}
}
printf (" Starting rates = ");
for (i=0; i<6; i++)
printf ("%1.3lf ", subParams[i]);
printf ("\n");
}
else if (!strcmp(subModel, "12"))
{
printf (" There are 12 substitution types: A -> C, A -> G, A -> T\n");
printf (" C -> A, C -> G, C -> T, G -> A, G -> C, G -> T, T -> A\n");
printf (" T -> C and T -> G. This corresponds to the general\n");
printf (" nonreversible model.\n");
nst = 12;
if (isStartingTreeRandom == NO && isUserTreeDefined == YES && isTreeRooted == NO)
{
printf ("\n WARNING: You requested that the chain start with a user-\n");
printf (" specified tree. Such a tree was provided, but the\n");
printf (" tree is unrooted. The nonreversible model requires\n");
printf (" rooted trees. The tree is being rooted at the outgroup\n");
printf (" species\n\n");
if (RootTree (userTreeRoot) == ERROR)
{
FreeMemory ();
return (ERROR);
}
}
subParams = (double *)malloc((size_t) (numChains * 2 * 12 * sizeof(double)));
if (!subParams)
{
printf ("\n ERROR: Problem allocating subParams.\n");
FreeMemory ();
return (ERROR);
}
else
allocatedMemory[ALLOC_SUBPARAMS] = YES;
for (chain=0; chain<numChains; chain++)
{
for (i=0; i<12; i++)
{
subParams[chain*2*12 + 0*12 + i] = nonRevRates[i];
subParams[chain*2*12 + 1*12 + i] = nonRevRates[i];
}
}
printf (" Starting rates = ");
for (i=0; i<6; i++)
printf ("%1.3lf ", subParams[i]);
printf ("\n ");
for (i=6; i<12; i++)
printf ("%1.3lf ", subParams[i]);
printf ("\n");
treeModel = ROOTED;
if (isUserTreeDefined == YES && isTreeRooted == NO)
{
if (RootTree (userTreeRoot) == ERROR)
{
FreeMemory ();
return (ERROR);
}
isTreeRooted = YES;
}
}
else
{
printf ("\n ERROR: Unknown substitution model\n");
FreeMemory ();
return (ERROR);
}
}
else
{
/* 61 X 61 (codon) model of DNA substitution */
nst = 61;
kappa = (double *)malloc((size_t) (numChains * 2 * sizeof(double)));
if (!kappa)
{
printf ("\n ERROR: Problem allocating kappa.\n");
FreeMemory ();
return (ERROR);
}
else
allocatedMemory[ALLOC_KAPPA] = YES;
for (i=0; i<2*numChains; i++)
kappa[i] = tRatio;
omega = (double *)malloc((size_t) (numChains * 2 * sizeof(double)));
if (!omega)
{
printf ("\n ERROR: Problem allocating omega.\n");
FreeMemory ();
return (ERROR);
}
else
allocatedMemory[ALLOC_OMEGA] = YES;
for (i=0; i<2*numChains; i++)
omega[i] = omegaRatio;
}
}
else if (dataType == PROTEIN)
{
if (SetAARates () == ERROR)
{
FreeMemory ();
return (ERROR);
}
if (aaModelType == POISSON)
{
printf (" All substitution types have equal rates.\n");
}
else if (aaModelType == EQUALIN)
{
printf (" Equal input model of amino acid substitution.\n");
}
else if (aaModelType == JONES)
{
printf (" Empirical model (Jones et al., 1990).\n");
}
else if (aaModelType == DAYHOFF)
{
printf (" Empirical model (Dayhoff et al., 1978).\n");
}
else if (aaModelType == GTR)
{
printf (" General time reversible model (very parameter rich).\n");
nst = 190;
subParams = (double *)malloc((size_t) (numChains * 2 * nst * sizeof(double)));
if (!subParams)
{
printf ("\n ERROR: Problem allocating subParams.\n");
FreeMemory ();
return (ERROR);
}
else
allocatedMemory[ALLOC_SUBPARAMS] = YES;
for (chain=0; chain<numChains; chain++)
{
for (i=0; i<nst; i++)
{
subParams[chain*2*nst + 0*nst + i] = 1.0;
subParams[chain*2*nst + 1*nst + i] = 1.0;
}
}
}
else
{
printf ("\n ERROR: Unknown substitution model\n");
FreeMemory ();
return (ERROR);
}
}
else if (dataType == RESTRICTION)
{
nst = 1;
printf (" General two state model for gain and loss of site.\n");
kappa = (double *)malloc((size_t) (numChains * 2 * sizeof(double)));
if (!kappa)
{
printf ("\n ERROR: Problem allocating kappa.\n");
FreeMemory ();
return (ERROR);
}
else
allocatedMemory[ALLOC_KAPPA] = YES;
for (i=0; i<2*numChains; i++)
kappa[i] = tRatio;
}
else if (dataType == STANDARD)
{
nst = 1;
printf (" General two state model for gain and loss of character.\n");
}
if (dataType == DNA || dataType == RNA)
{
if (enforceCodonModel == NO)
{
/* 4 X 4 model of DNA substitution */
if (nst > 1)
{
if (!strcmp(qmatprModel, "fixed"))
{
printf (" Instantaneous rate matrix is fixed\n");
}
else if (!strcmp(qmatprModel, "exponential"))
{
printf (" Instantaneous rate matrix has exponential(%1.4lf) prior\n", qmatprExp);
relProposalProbs[CHANGE_QMAT] = moveRates[CHANGE_QMAT];
}
else if (!strcmp(qmatprModel, "uniform"))
{
printf (" Instantaneous rate matrix has uniform(%1.4lf, %1.4lf) prior\n", qmatprUni[0], qmatprUni[1]);
relProposalProbs[CHANGE_QMAT] = moveRates[CHANGE_QMAT];
chainMins[CHANGE_QMAT] = qmatprUni[0];
chainMaxs[CHANGE_QMAT] = qmatprUni[1];
}
else
{
printf ("\n ERROR: Unknown prior model on instantaneous rates\n");
FreeMemory ();
return (ERROR);
}
}
}
else
{
/* 61 X 61 (codon) model of DNA substitution */
if (!strcmp(qmatprModel, "fixed"))
{
printf (" Kappa is fixed\n");
}
else if (!strcmp(qmatprModel, "exponential"))
{
printf (" Kappa has an exponential(%1.4lf) prior\n", qmatprExp);
relProposalProbs[CHANGE_QMAT] = moveRates[CHANGE_QMAT];
}
else if (!strcmp(qmatprModel, "uniform"))
{
printf (" Kappa has a uniform(%1.4lf, %1.4lf) prior\n", qmatprUni[0], qmatprUni[1]);
relProposalProbs[CHANGE_QMAT] = moveRates[CHANGE_QMAT];
chainMins[CHANGE_QMAT] = qmatprUni[0];
chainMaxs[CHANGE_QMAT] = qmatprUni[1];
}
else
{
printf ("\n ERROR: Unknown prior model on instantaneous rates\n");
FreeMemory ();
return (ERROR);
}
if (!strcmp(omegaprModel, "fixed"))
{
printf (" Omega is fixed\n");
}
else if (!strcmp(omegaprModel, "exponential"))
{
printf (" Omega has an exponential(%1.4lf) prior\n", omegaprExp);
relProposalProbs[CHANGE_OMEGA] = moveRates[CHANGE_OMEGA];
}
else if (!strcmp(qmatprModel, "uniform"))
{
printf (" Omega has a uniform(%1.4lf, %1.4lf) prior\n", omegaprUni[0], omegaprUni[1]);
relProposalProbs[CHANGE_OMEGA] = moveRates[CHANGE_OMEGA];
chainMins[CHANGE_OMEGA] = omegaprUni[0];
chainMaxs[CHANGE_OMEGA] = omegaprUni[1];
}
else
{
printf ("\n ERROR: Unknown prior model on instantaneous rates\n");
FreeMemory ();
return (ERROR);
}
}
}
else if (dataType == PROTEIN)
{
if (aaModelType == GTR)
{
if (!strcmp(qmatprModel, "fixed"))
{
printf (" Instantaneous rate matrix is fixed\n");
}
else if (!strcmp(qmatprModel, "exponential"))
{
printf (" Instantaneous rate matrix has exponential(%1.4lf) prior\n", qmatprExp);
relProposalProbs[CHANGE_QMAT] = moveRates[CHANGE_QMAT];
}
else if (!strcmp(qmatprModel, "uniform"))
{
printf (" Instantaneous rate matrix has uniform(%1.4lf, %1.4lf) prior\n", qmatprUni[0], qmatprUni[1]);
relProposalProbs[CHANGE_QMAT] = moveRates[CHANGE_QMAT];
chainMins[CHANGE_QMAT] = qmatprUni[0];
chainMaxs[CHANGE_QMAT] = qmatprUni[1];
}
else
{
printf ("\n ERROR: Unknown prior model on instantaneous rates\n");
FreeMemory ();
return (ERROR);
}
}
}
else if (dataType == RESTRICTION)
{
if (!strcmp(qmatprModel, "fixed"))
{
printf (" Instantaneous rate matrix is fixed\n");
}
else if (!strcmp(qmatprModel, "exponential"))
{
printf (" Instantaneous rate matrix has exponential(%1.4lf) prior\n", qmatprExp);
relProposalProbs[CHANGE_QMAT] = moveRates[CHANGE_QMAT];
}
else if (!strcmp(qmatprModel, "uniform"))
{
printf (" Instantaneous rate matrix has uniform(%1.4lf, %1.4lf) prior\n", qmatprUni[0], qmatprUni[1]);
relProposalProbs[CHANGE_QMAT] = moveRates[CHANGE_QMAT];
chainMins[CHANGE_QMAT] = qmatprUni[0];
chainMaxs[CHANGE_QMAT] = qmatprUni[1];
}
else
{
printf ("\n ERROR: Unknown prior model on instantaneous rates\n");
FreeMemory ();
return (ERROR);
}
}
else if (dataType == STANDARD)
{
if (!strcmp(stateFreqPrModel, "fixed"))
{
printf (" State frequencies are fixed to 0.5\n");
}
#if defined (MORPH)
else if (!strcmp(stateFreqPrModel, "dirichlet"))
{
numBetaCats = 5; /* this should be set to some arbitrary (but odd) number by user */
printf (" Stationary frequencies follow a symmetric dirichlet/beta distribution\n");
printf (" The shape of this distribution is estimated\n");
printf (" Starting shape parameter: %1.4lf\n", statefreqprDir);
printf (" Shape parameter has a uniform(%1.4lf, %1.4lf) prior\n", 0.0, 100.0);
printf (" The distribution is divided into %d discrete categories\n", numBetaCats);
statefreqP = (double *)malloc((size_t) (numChains * 2 * sizeof(double)));
if (!statefreqP)
{
printf ("\n ERROR: Problem allocating statefreqP.\n");
FreeMemory ();
return (ERROR);
}
else
allocatedMemory[ALLOC_BETA] = YES;
for (i=0; i<2*numChains; i++)
statefreqP[i] = statefreqprDir;
relProposalProbs[CHANGE_BETA_SHAPE] = moveRates[CHANGE_BETA_SHAPE];
chainMins[CHANGE_BETA_SHAPE] = 0.0;
chainMaxs[CHANGE_BETA_SHAPE] = 100.0;
}
#endif
else
{
printf ("\n ERROR: Unknown prior model on state frequencies\n");
FreeMemory ();
return (ERROR);
}
}
/* set base frequencies ************************************************************************/
chainMins[CHANGE_BASEFREQS] = 0.0;
chainMaxs[CHANGE_BASEFREQS] = 1.0;
printf (" Base frequencies\n");
if (((dataType == DNA || dataType == RNA) && enforceCodonModel == NO) && useCovarion == YES && !strcmp(covarionModelType, "gcswitch"))
{
gc1 = (double *)malloc((size_t) (numChains * 2 * sizeof(double)));
if (!gc1)
{
printf ("\n ERROR: Problem allocating gc1.\n");
FreeMemory ();
return (ERROR);
}
else
allocatedMemory[ALLOC_GC1] = YES;
gc2 = (double *)malloc((size_t) (numChains * 2 * sizeof(double)));
if (!gc2)
{
printf ("\n ERROR: Problem allocating gc2.\n");
FreeMemory ();
return (ERROR);
}
else
allocatedMemory[ALLOC_GC2] = YES;
fracA = (double *)malloc((size_t) (numChains * 2 * sizeof(double)));
if (!fracA)
{
printf ("\n ERROR: Problem allocating fracA.\n");
FreeMemory ();
return (ERROR);
}
else
allocatedMemory[ALLOC_FRAC_A] = YES;
fracG = (double *)malloc((size_t) (numChains * 2 * sizeof(double)));
if (!fracG)
{
printf ("\n ERROR: Problem allocating fracA.\n");
FreeMemory ();
return (ERROR);
}
else
allocatedMemory[ALLOC_FRAC_G] = YES;
for (i=0; i<2*numChains; i++)
{
gc1[i] = 0.25;
gc2[i] = 0.75;
fracA[i] = 0.50;
fracG[i] = 0.50;
}
printf (" Two classes of base frequencies, with switching between\n");
printf (" the classes. The first class has GC content constrained\n");
printf (" to be less than 1/2 and the other has GC content con-\n");
printf (" strained to be greater than 1/2.\n");
relProposalProbs[CHANGE_GCSWITCH] = moveRates[CHANGE_GCSWITCH];
}
else if (dataType == DNA || dataType == RNA || dataType == PROTEIN)
{
baseFreq = (double *)malloc((size_t) (numChains * 2 * nStates * sizeof(double)));
if (!baseFreq)
{
printf ("\n ERROR: Problem allocating baseFreq.\n");
FreeMemory ();
return (ERROR);
}
else
allocatedMemory[ALLOC_BASEFREQS] = YES;
if (dataType == DNA || dataType == RNA)
{
if (enforceCodonModel == NO)
{
/* 4 X 4 model of DNA substitution */
if (nst == 12)
{
printf (" Base frequencies are determined by the Q matrix (model of\n");
printf (" DNA substitution is non-reversible).\n");
for (i=0; i<numChains*2*nStates; i++)
baseFreq[i] = 0.25;
}
else
{
if (!strcmp(baseFreqModel, "equal"))
{
printf (" Equal base frequencies\n");
for (i=0; i<numChains*2*nStates; i++)
baseFreq[i] = 0.25;
}
else if (!strcmp(baseFreqModel, "empirical"))
{
printf (" Empirical base frequencies\n");
GetEmpiricalBaseFreqs ();
}
else if (!strcmp(baseFreqModel, "estimate"))
{
printf (" Base frequencies to be estimated\n");
for (i=0; i<numChains*2*nStates; i++)
baseFreq[i] = 0.25;
}
else
{
printf ("\n ERROR: Unknown base frequency model\n");
FreeMemory ();
return (ERROR);
}
printf (" Starting base frequencies = %1.3lf %1.3lf %1.3lf %1.3lf\n",
baseFreq[0], baseFreq[1], baseFreq[2], baseFreq[3]);
}
if (nst < 12)
{
if (!strcmp(basefreqprModel, "fixed"))
{
printf (" Base frequencies are fixed\n");
}
else if (!strcmp(basefreqprModel, "dirichlet"))
{
printf (" Base frequencies have a dirichlet(%1.4lf) prior\n", basefreqprDir);
relProposalProbs[CHANGE_BASEFREQS] = moveRates[CHANGE_BASEFREQS];
}
else
{
printf ("\n ERROR: Unknown prior model on base frequencies\n");
FreeMemory ();
return (ERROR);
}
}
}
else
{
/* 61 X 61 (codon) model of DNA substitution */
if (!strcmp(baseFreqModel, "equal"))
{
printf (" Equal codon frequencies\n");
for (i=0; i<numChains*2*nStates; i++)
baseFreq[i] = (1.0 / (double)nStates);
}
else if (!strcmp(baseFreqModel, "empirical"))
{
printf (" Empirical codon frequencies are not implemented with codon\n");
printf (" models. Initial codon frequencies set to 1/61.\n");
for (i=0; i<numChains*2*nStates; i++)
baseFreq[i] = (1.0 / (double)nStates);
}
else if (!strcmp(baseFreqModel, "estimate"))
{
printf (" Codon frequencies to be estimated\n");
for (i=0; i<numChains*2*nStates; i++)
baseFreq[i] = (1.0 / (double)nStates);
}
else
{
printf ("\n ERROR: Unknown codon frequency model\n");
FreeMemory ();
return (ERROR);
}
if (!strcmp(basefreqprModel, "fixed"))
{
printf (" Codon frequencies are fixed\n");
}
else if (!strcmp(basefreqprModel, "dirichlet"))
{
printf (" Codon frequencies have a dirichlet(%1.4lf) prior\n", basefreqprDir);
relProposalProbs[CHANGE_BASEFREQS] = moveRates[CHANGE_BASEFREQS];
}
else
{
printf ("\n ERROR: Unknown prior model on base frequencies\n");
FreeMemory ();
return (ERROR);
}
}
}
else if (dataType == PROTEIN)
{
if (aaModelType == JONES)
{
for (j=0; j<numChains; j++)
{
for (i=0; i<20; i++)
{
baseFreq[j*2*20 + 0*20 + i] = jonesPi[i];
baseFreq[j*2*20 + 1*20 + i] = jonesPi[i];
}
}
}
else if (aaModelType == DAYHOFF)
{
for (j=0; j<numChains; j++)
{
for (i=0; i<20; i++)
{
baseFreq[j*2*20 + 0*20 + i] = dayhoffPi[i];
baseFreq[j*2*20 + 1*20 + i] = dayhoffPi[i];
}
}
}
else
{
if (!strcmp(baseFreqModel, "equal"))
{
printf (" Equal amino acid frequencies\n");
for (i=0; i<numChains*2*nStates; i++)
baseFreq[i] = 0.05;
}
else if (!strcmp(baseFreqModel, "empirical"))
{
printf (" Empirical amino acid frequencies\n");
GetEmpiricalAAFreqs ();
}
else if (!strcmp(baseFreqModel, "estimate"))
{
printf (" Amino acid frequencies to be estimated\n");
for (i=0; i<numChains*2*nStates; i++)
baseFreq[i] = 0.05;
}
else
{
printf ("\n ERROR: Unknown base frequency model\n");
FreeMemory ();
return (ERROR);
}
}
printf (" Starting aa frequencies = %1.3lf %1.3lf %1.3lf %1.3lf %1.3lf \n", baseFreq[0], baseFreq[1], baseFreq[2], baseFreq[3], baseFreq[4]);
printf (" %1.3lf %1.3lf %1.3lf %1.3lf %1.3lf \n", baseFreq[5], baseFreq[6], baseFreq[7], baseFreq[8], baseFreq[9]);
printf (" %1.3lf %1.3lf %1.3lf %1.3lf %1.3lf \n", baseFreq[10], baseFreq[11], baseFreq[12], baseFreq[13], baseFreq[14]);
printf (" %1.3lf %1.3lf %1.3lf %1.3lf %1.3lf \n", baseFreq[15], baseFreq[16], baseFreq[17], baseFreq[18], baseFreq[19]);
if (!strcmp(basefreqprModel, "fixed"))
{
printf (" Amino acid frequencies are fixed\n");
}
else if (!strcmp(basefreqprModel, "dirichlet"))
{
if (aaModelType == EQUALIN || aaModelType == GTR)
{
printf (" Amino acid frequencies have a dirichlet(%1.4lf) prior\n", basefreqprDir);
relProposalProbs[CHANGE_BASEFREQS] = moveRates[CHANGE_BASEFREQS];
}
}
else
{
printf ("\n ERROR: Unknown prior model on amino acid frequencies\n");
FreeMemory ();
return (ERROR);
}
}
}
else if (dataType == RESTRICTION)
{
printf (" State frequencies are determined by the Q matrix.\n");
}
else if (dataType == STANDARD)
{
printf (" State frequencies are determined by the Q matrix.\n");
}
/* rate variation across sites *****************************************************************/
(*numRateCats) = 1;
if (dataType == RESTRICTION)
{
if (!strcmp(ratesModel, "equal") || !strcmp(ratesModel, "gamma") || !strcmp(ratesModel, "invariant") || !strcmp(ratesModel, "invgamma"))
{
/* I believe that these are the only models that work for restriction sites */
}
else
{
printf ("\n ERROR: This rate across sites model is not supported\n");
printf (" for restriction site data\n");
FreeMemory ();
return (ERROR);
}
}
else if (dataType == STANDARD)
{
#if !defined (MORPH)
if (!strcmp(ratesModel, "equal") || !strcmp(ratesModel, "gamma") || !strcmp(ratesModel, "invariant") || !strcmp(ratesModel, "invgamma"))
#else
if (!strcmp(ratesModel, "equal") || !strcmp(ratesModel, "gamma") || !strcmp(ratesModel, "invariant")
|| !strcmp(ratesModel, "invgamma") || !strcmp(ratesModel, "ssgamma") || !strcmp(ratesModel, "sitespec"))
#endif
{
// These models are supported!
}
else
{
printf ("\n ERROR: This rate across sites model is not supported\n");
printf (" for standard data\n");
FreeMemory ();
return (ERROR);
}
}
#if !defined (MORPH)
if (enforceCodonModel == NO || (enforceCodonModel == YES && dataType == PROTEIN) || (enforceCodonModel == YES && dataType == RESTRICTION) || (enforceCodonModel == YES && dataType == STANDARD))
#else
if (enforceCodonModel == NO || dataType == PROTEIN || dataType == RESTRICTION || dataType == STANDARD)
#endif
{
printf (" Among-site rate variation\n");
/* codon model is not being used */
(*numRateCats) = 1;
if (!strcmp(ratesModel, "equal"))
{
printf (" Equal rates across sites\n");
}
else if (!strcmp(ratesModel, "gamma") || !strcmp(ratesModel, "adgamma"))
{
chainMins[CHANGE_GAMMA_SHAPE] = 0.000001;
chainMaxs[CHANGE_GAMMA_SHAPE] = 100.0;
printf (" Gamma-distributed rates across sites\n");
if (nRateCats <= 1)
{
printf ("\n ERROR: Too few rate categories. ncat must be at least 2\n");
FreeMemory ();
return (ERROR);
}
(*numRateCats) = nRateCats;
printf (" Gamma distribution approximated with %d categories\n", (*numRateCats));
alpha = (double *)malloc((size_t) (numChains * 2 * sizeof(double)));
if (!alpha)
{
printf ("\n ERROR: Problem allocating alpha.\n");
FreeMemory ();
return (ERROR);
}
else
allocatedMemory[ALLOC_GAMMA_SHAPE] = YES;
for (i=0; i<2*numChains; i++)
alpha[i] = shape;
printf (" Starting gamma shape parameter: %1.4lf\n", shape);
if (!strcmp(shapeprModel, "fixed"))
{
printf (" Gamma shape parameter is fixed\n");
}
else if (!strcmp(shapeprModel, "uniform"))
{
printf (" Gamma shape parameter has a uniform(%1.4lf, %1.4lf) prior\n", shapeprUni[0], shapeprUni[1]);
relProposalProbs[CHANGE_GAMMA_SHAPE] = moveRates[CHANGE_GAMMA_SHAPE];
chainMins[CHANGE_GAMMA_SHAPE] = shapeprUni[0];
chainMaxs[CHANGE_GAMMA_SHAPE] = shapeprUni[1];
}
else if (!strcmp(shapeprModel, "exponential"))
{
printf (" Gamma shape parameter has an exponential(%1.4lf) prior\n", shapeprExp);
relProposalProbs[CHANGE_GAMMA_SHAPE] = moveRates[CHANGE_GAMMA_SHAPE];
}
else
{
printf ("\n ERROR: Unknown prior model for gamma shape parameter\n");
FreeMemory ();
return (ERROR);
}
if (!strcmp(ratesModel, "adgamma"))
{
printf (" Auto-discrete-gamma model implemented (correlated rates across sites)\n");
rateCorrelation = (double *)malloc((size_t) (numChains * 2 * sizeof(double)));
if (!rateCorrelation)
{
printf ("\n ERROR: Problem allocating rateCorrelation.\n");
FreeMemory ();
return (ERROR);
}
else
allocatedMemory[ALLOC_AUTO_GAMMA] = YES;
for (i=0; i<2*numChains; i++)
rateCorrelation[i] = 0.0;
relProposalProbs[CHANGE_AUTO_CORR] = moveRates[CHANGE_AUTO_CORR];
chainMins[CHANGE_AUTO_CORR] = -1.0;
chainMaxs[CHANGE_AUTO_CORR] = 1.0;
lag = (int *)malloc((size_t) (numChains * 2 * sizeof(int)));
if (!lag)
{
printf ("\n ERROR: Problem allocating lag.\n");
FreeMemory ();
return (ERROR);
}
else
allocatedMemory[ALLOC_LAG] = YES;
for (i=0; i<2*numChains; i++)
lag[i] = lagNumber;
if (!strcmp(lagprModel, "uniform") || !strcmp(lagprModel, "exponential"))
{
relProposalProbs[CHANGE_LAG] = moveRates[CHANGE_LAG];
chainMins[CHANGE_LAG] = 1;
chainMaxs[CHANGE_LAG] = 50;
}
}
}
else if (!strcmp(ratesModel, "invariant"))
{
relProposalProbs[CHANGE_INV_P] = moveRates[CHANGE_INV_P];
chainMins[CHANGE_INV_P] = 0.0;
chainMaxs[CHANGE_INV_P] = 1.0;
printf (" Proportion of invariant sites among-site rate variation\n");
(*numRateCats) = 2;
invP = (double *)malloc((size_t) (numChains * 2 * sizeof(double)));
if (!invP)
{
printf ("\n ERROR: Problem allocating invP.\n");
FreeMemory ();
return (ERROR);
}
else
allocatedMemory[ALLOC_INV_P] = YES;
for (i=0; i<2*numChains; i++)
invP[i] = 0.1;
printf (" Starting proportion invariant: %1.4lf\n", 0.1);
printf (" Proportion sites invariant has a uniform (0,1) prior\n");
}
else if (!strcmp(ratesModel, "invgamma"))
{
chainMins[CHANGE_GAMMA_SHAPE] = 0.000001;
chainMaxs[CHANGE_GAMMA_SHAPE] = 100.0;
printf (" Gamma-distributed rates across sites\n");
if (nRateCats <= 1)
{
printf ("\n ERROR: Too few rate categories. ncat must be at least 2\n");
FreeMemory ();
return (ERROR);
}
(*numRateCats) = nRateCats + 1;
printf (" Gamma distribution approximated with %d categories\n", (*numRateCats));
alpha = (double *)malloc((size_t) (numChains * 2 * sizeof(double)));
if (!alpha)
{
printf ("\n ERROR: Problem allocating alpha.\n");
FreeMemory ();
return (ERROR);
}
else
allocatedMemory[ALLOC_GAMMA_SHAPE] = YES;
for (i=0; i<2*numChains; i++)
alpha[i] = shape;
printf (" Starting gamma shape parameter: %1.4lf\n", shape);
if (!strcmp(shapeprModel, "fixed"))
{
printf (" Gamma shape parameter is fixed\n");
}
else if (!strcmp(shapeprModel, "uniform"))
{
printf (" Gamma shape parameter has a uniform(%1.4lf, %1.4lf) prior\n", shapeprUni[0], shapeprUni[1]);
relProposalProbs[CHANGE_GAMMA_SHAPE] = moveRates[CHANGE_GAMMA_SHAPE];
chainMins[CHANGE_GAMMA_SHAPE] = shapeprUni[0];
chainMaxs[CHANGE_GAMMA_SHAPE] = shapeprUni[1];
}
else if (!strcmp(shapeprModel, "exponential"))
{
printf (" Gamma shape parameter has an exponential(%1.4lf) prior\n", shapeprExp);
relProposalProbs[CHANGE_GAMMA_SHAPE] = moveRates[CHANGE_GAMMA_SHAPE];
}
else
{
printf ("\n ERROR: Unknown prior model for gamma shape parameter\n");
FreeMemory ();
return (ERROR);
}
relProposalProbs[CHANGE_INV_P] = moveRates[CHANGE_INV_P];
chainMins[CHANGE_INV_P] = 0.0;
chainMaxs[CHANGE_INV_P] = 1.0;
printf (" Proportion of invariant sites among-site rate variation\n");
invP = (double *)malloc((size_t) (numChains * 2 * sizeof(double)));
if (!invP)
{
printf ("\n ERROR: Problem allocating invP.\n");
FreeMemory ();
return (ERROR);
}
else
allocatedMemory[ALLOC_INV_P] = YES;
for (i=0; i<2*numChains; i++)
invP[i] = 0.1;
printf (" Starting proportion invariant: %1.4lf\n", 0.1);
printf (" Proportion sites invariant has a uniform (0,1) prior\n");
}
else if (!strcmp(ratesModel, "sitespec") || !strcmp(ratesModel, "ssgamma") || !strcmp(ratesModel, "ssadgamma"))
{
chainMins[CHANGE_SITE_RATES] = 0.000001;
chainMaxs[CHANGE_SITE_RATES] = 100.0;
printf (" Site specific rates across sites\n");
if (!strcmp(partitionName, "none defined"))
{
printf ("\n ERROR: You must specify the partition name in \"lset sitepartition=<name>\"\n");
FreeMemory ();
return (ERROR);
}
if (isPartitionDefined == NO)
{
printf ("\n ERROR: You must define a partition\n");
FreeMemory ();
return (ERROR);
}
x = strlen(partitionName);
y = strlen(defPartitionName);
if (x != y)
{
printf ("\n ERROR: The partition you defined (using \"partition\") \n");
printf (" and the partition you specified (using \"lset\") do\n");
printf (" not match.\n");
FreeMemory ();
return (ERROR);
}
else
{
isDiff = NO;
i = 0;
while (partitionName[i] != '\0')
{
if (partitionName[i] != defPartitionName[i])
isDiff = YES;
i++;
}
if (isDiff == YES)
{
printf ("\n ERROR: The partition you defined (using \"partition\") \n");
printf (" and the partition you specified (using \"lset\") do\n");
printf (" not match.\n");
FreeMemory ();
return (ERROR);
}
}
printf (" Partition name: \"%s\"\n", partitionName);
printf (" Data is partitioned into %d parts\n", nPartitions);
if (nPartitions <= 1)
{
printf ("\n ERROR: There are too few partitions of the data. You must\n");
printf (" have at least two partitions.\n");
FreeMemory ();
return (ERROR);
}
else if (nPartitions > 49)
{
printf ("\n ERROR: There are too many partitions of the data. You must\n");
printf (" have fewer than 49 partitions.\n");
FreeMemory ();
return (ERROR);
}
scaledRates = (double *)malloc((size_t) (numChains * 2 * nPartitions * sizeof(double)));
if (!scaledRates)
{
printf ("\n ERROR: Problem allocating scaledRates.\n");
FreeMemory ();
return (ERROR);
}
else
allocatedMemory[ALLOC_SITE_RATES] = YES;
unscaledRates = (double *)malloc((size_t) (numChains * 2 * nPartitions * sizeof(double)));
if (!unscaledRates)
{
printf ("\n ERROR: Problem allocating unscaledRates.\n");
FreeMemory ();
return (ERROR);
}
else
allocatedMemory[ALLOC_UNSCALED_SITE_RATES] = YES;
for (chain=0; chain<numChains; chain++)
{
for (i=0; i<nPartitions; i++)
{
unscaledRates[chain*2*nPartitions + 0*nPartitions + i] = siteRates[i];
unscaledRates[chain*2*nPartitions + 1*nPartitions + i] = siteRates[i];
}
}
nSitesInPartition = (int *)malloc((size_t) (nPartitions * sizeof(int)));
if (!nSitesInPartition)
{
printf ("\n ERROR: Problem allocating nSitesInPartition.\n");
FreeMemory ();
return (ERROR);
}
else
allocatedMemory[ALLOC_NSITES_IN_PART] = YES;
for (i=0; i<nPartitions; i++)
nSitesInPartition[i] = 0;
for (i=0; i<nChar; i++)
{
if (excludedSites[i] == NO)
{
if (sitePartitions[i] == 0)
{
printf ("\n ERROR: Site %d is not assigned to a partition\n", i+1);
FreeMemory ();
return (ERROR);
}
nSitesInPartition[ sitePartitions[i] - 1 ]++;
}
}
scaler = 0.0;
for (i=0; i<nPartitions; i++)
scaler += unscaledRates[i] * nSitesInPartition[i];
scaler = (double)nIncludedChars / scaler;
for (chain=0; chain<numChains; chain++)
{
for (i=0; i<nPartitions; i++)
{
scaledRates[chain*2*nPartitions + 0*nPartitions + i] = unscaledRates[chain*2*nPartitions + 0*nPartitions + i] * scaler;
scaledRates[chain*2*nPartitions + 0*nPartitions + i] = unscaledRates[chain*2*nPartitions + 1*nPartitions + i] * scaler;
}
}
for (i=0; i<nPartitions; i++)
{
printf (" Partition %d contains %d sites and has an initial rate of %1.4lf\n",
i+1, nSitesInPartition[i], scaledRates[0*2*nPartitions + 0*nPartitions + i]);
}
if (!strcmp(siterateprModel, "fixed"))
{
printf (" Site rates are fixed\n");
}
else if (!strcmp(siterateprModel, "uniform"))
{
printf (" Site rates have a uniform(%1.4lf, %1.4lf) prior\n", siterateprUni[0], siterateprUni[1]);
relProposalProbs[CHANGE_SITE_RATES] = moveRates[CHANGE_SITE_RATES];
chainMins[CHANGE_SITE_RATES] = siterateprUni[0];
chainMaxs[CHANGE_SITE_RATES] = siterateprUni[1];
}
else if (!strcmp(siterateprModel, "exponential"))
{
printf (" Site rates have an exponential(%1.4lf) prior\n", siterateprExp);
relProposalProbs[CHANGE_SITE_RATES] = moveRates[CHANGE_SITE_RATES];
}
else
{
printf ("\n ERROR: Unknown prior model for site rates\n");
FreeMemory ();
return (ERROR);
}
if (!strcmp(ratesModel, "ssgamma"))
{
chainMins[CHANGE_GAMMA_SHAPE] = 0.000001;
chainMaxs[CHANGE_GAMMA_SHAPE] = 100.0;
printf (" Gamma-distributed rates across sites for each codon\n");
if (nRateCats <= 1)
{
printf ("\n ERROR: Too few rate categories. ncat must be at least 2\n");
FreeMemory ();
return (ERROR);
}
(*numRateCats) = nRateCats;
printf (" Gamma distribution approximated with %d categories\n", (*numRateCats));
alpha = (double *)malloc((size_t) (numChains * 2 * sizeof(double)));
if (!alpha)
{
printf ("\n ERROR: Problem allocating alpha.\n");
FreeMemory ();
return (ERROR);
}
else
allocatedMemory[ALLOC_GAMMA_SHAPE] = YES;
for (i=0; i<2*numChains; i++)
alpha[i] = shape;
printf (" Starting gamma shape parameter: %1.4lf\n", shape);
if (!strcmp(shapeprModel, "fixed"))
{
printf (" Gamma shape parameter is fixed\n");
}
else if (!strcmp(shapeprModel, "uniform"))
{
printf (" Gamma shape parameter has a uniform(%1.4lf, %1.4lf) prior\n", shapeprUni[0], shapeprUni[1]);
relProposalProbs[CHANGE_GAMMA_SHAPE] = moveRates[CHANGE_GAMMA_SHAPE];
chainMins[CHANGE_GAMMA_SHAPE] = shapeprUni[0];
chainMaxs[CHANGE_GAMMA_SHAPE] = shapeprUni[1];
}
else if (!strcmp(shapeprModel, "exponential"))
{
printf (" Gamma shape parameter has an exponential(%1.4lf) prior\n", shapeprExp);
relProposalProbs[CHANGE_GAMMA_SHAPE] = moveRates[CHANGE_GAMMA_SHAPE];
}
else
{
printf ("\n ERROR: Unknown prior model for gamma shape parameter\n");
FreeMemory ();
return (ERROR);
}
}
if (!strcmp(ratesModel, "ssadgamma"))
{
chainMins[CHANGE_GAMMA_SHAPE] = 0.000001;
chainMaxs[CHANGE_GAMMA_SHAPE] = 100.0;
printf (" Gamma-distributed rates across sites for each codon\n");
if (nRateCats <= 1)
{
printf ("\n ERROR: Too few rate categories. ncat must be at least 2\n");
FreeMemory ();
return (ERROR);
}
(*numRateCats) = nRateCats;
printf (" Gamma distribution approximated with %d categories\n", (*numRateCats));
alpha = (double *)malloc((size_t) (numChains * 2 * sizeof(double)));
if (!alpha)
{
printf ("\n ERROR: Problem allocating alpha.\n");
FreeMemory ();
return (ERROR);
}
else
allocatedMemory[ALLOC_GAMMA_SHAPE] = YES;
for (i=0; i<2*numChains; i++)
alpha[i] = shape;
printf (" Starting gamma shape parameter: %1.4lf\n", shape);
if (!strcmp(shapeprModel, "fixed"))
{
printf (" Gamma shape parameter is fixed\n");
}
else if (!strcmp(shapeprModel, "uniform"))
{
printf (" Gamma shape parameter has a uniform(%1.4lf, %1.4lf) prior\n", shapeprUni[0], shapeprUni[1]);
relProposalProbs[CHANGE_GAMMA_SHAPE] = moveRates[CHANGE_GAMMA_SHAPE];
chainMins[CHANGE_GAMMA_SHAPE] = shapeprUni[0];
chainMaxs[CHANGE_GAMMA_SHAPE] = shapeprUni[1];
}
else if (!strcmp(shapeprModel, "exponential"))
{
printf (" Gamma shape parameter has an exponential(%1.4lf) prior\n", shapeprExp);
relProposalProbs[CHANGE_GAMMA_SHAPE] = moveRates[CHANGE_GAMMA_SHAPE];
}
else
{
printf ("\n ERROR: Unknown prior model for gamma shape parameter\n");
FreeMemory ();
return (ERROR);
}
printf (" Auto-discrete-gamma model implemented (correlated rates across sites)\n");
rateCorrelation = (double *)malloc((size_t) (numChains * 2 * sizeof(double)));
if (!rateCorrelation)
{
printf ("\n ERROR: Problem allocating rateCorrelation.\n");
FreeMemory ();
return (ERROR);
}
else
allocatedMemory[ALLOC_AUTO_GAMMA] = YES;
for (i=0; i<2*numChains; i++)
rateCorrelation[i] = 0.0;
relProposalProbs[CHANGE_AUTO_CORR] = moveRates[CHANGE_AUTO_CORR];
chainMins[CHANGE_AUTO_CORR] = -1.0;
chainMaxs[CHANGE_AUTO_CORR] = 1.0;
lag = (int *)malloc((size_t) (numChains * 2 * sizeof(int)));
if (!lag)
{
printf ("\n ERROR: Problem allocating lag.\n");
FreeMemory ();
return (ERROR);
}
else
allocatedMemory[ALLOC_LAG] = YES;
for (i=0; i<2*numChains; i++)
lag[i] = lagNumber;
if (!strcmp(lagprModel, "uniform") || !strcmp(lagprModel, "exponential"))
{
relProposalProbs[CHANGE_LAG] = moveRates[CHANGE_LAG];
chainMins[CHANGE_LAG] = 1;
chainMaxs[CHANGE_LAG] = 50;
}
}
}
else
{
printf ("\n ERROR: Unknown rate variation model\n");
FreeMemory ();
return (ERROR);
}
}
else
{
printf (" Among-site omega variation\n");
/* enforcing 61 X 61 codon model */
if (!strcmp(codonModelType, "ny98") || !strcmp(codonModelType, "ac1ny98") || !strcmp(codonModelType, "ac2ny98") || !strcmp(codonModelType, "covny98"))
{
printf (" Omega varies across sites according to Nielsen and Yang (1998) model\n");
if (!strcmp(codonModelType, "covny98"))
(*numRateCats) = 1;
else
(*numRateCats) = 3;
for (i=0; i<2*numChains; i++)
omega[i] = 2.0;
probPur = (double *)malloc((size_t) (numChains * 2 * sizeof(double)));
if (!probPur)
{
printf ("\n ERROR: Problem allocating probPur.\n");
FreeMemory ();
return (ERROR);
}
else
allocatedMemory[ALLOC_PUR] = YES;
for (i=0; i<2*numChains; i++)
probPur[i] = 0.3333333;
probNeu = (double *)malloc((size_t) (numChains * 2 * sizeof(double)));
if (!probNeu)
{
printf ("\n ERROR: Problem allocating probNeu.\n");
FreeMemory ();
return (ERROR);
}
else
allocatedMemory[ALLOC_NEU] = YES;
for (i=0; i<2*numChains; i++)
probNeu[i] = 0.3333333;
probPos = (double *)malloc((size_t) (numChains * 2 * sizeof(double)));
if (!probPos)
{
printf ("\n ERROR: Problem allocating probPos.\n");
FreeMemory ();
return (ERROR);
}
else
allocatedMemory[ALLOC_POS] = YES;
for (i=0; i<2*numChains; i++)
probPos[i] = 0.3333333;
chainMins[CHANGE_OMEGA_PROBS] = 0.0;
chainMaxs[CHANGE_OMEGA_PROBS] = 1.0;
relProposalProbs[CHANGE_OMEGA_PROBS] = moveRates[CHANGE_OMEGA_PROBS];
relProposalProbs[CHANGE_OMEGA] = moveRates[CHANGE_OMEGA];
chainMins[CHANGE_OMEGA] = 1.0;
chainMaxs[CHANGE_OMEGA] = 50.0;
if (!strcmp(codonModelType, "ac1ny98"))
{
printf (" Auto-correlated codon model implemented (correlated omega across sites)\n");
rateCorrelation = (double *)malloc((size_t) (numChains * 2 * sizeof(double)));
if (!rateCorrelation)
{
printf ("\n ERROR: Problem allocating rateCorrelation.\n");
FreeMemory ();
return (ERROR);
}
else
allocatedMemory[ALLOC_AUTO_GAMMA] = YES;
for (i=0; i<2*numChains; i++)
rateCorrelation[i] = 0.0;
relProposalProbs[CHANGE_AUTO_CORR] = moveRates[CHANGE_AUTO_CORR];
chainMins[CHANGE_AUTO_CORR] = 0.0;
chainMaxs[CHANGE_AUTO_CORR] = 1.0;
}
else if (!strcmp(codonModelType, "ac2ny98"))
{
printf (" Auto-correlated codon model implemented (correlated omega across sites)\n");
rateCorrelation = (double *)malloc((size_t) (numChains * 2 * sizeof(double)));
if (!rateCorrelation)
{
printf ("\n ERROR: Problem allocating rateCorrelation.\n");
FreeMemory ();
return (ERROR);
}
else
allocatedMemory[ALLOC_AUTO_GAMMA] = YES;
for (i=0; i<2*numChains; i++)
rateCorrelation[i] = 0.0;
rateCorrelation2 = (double *)malloc((size_t) (2 * numChains * 2 * sizeof(double)));
if (!rateCorrelation2)
{
printf ("\n ERROR: Problem allocating rateCorrelation2.\n");
FreeMemory ();
return (ERROR);
}
else
allocatedMemory[ALLOC_AUTO_GAMMA2] = YES;
for (i=0; i<4*numChains; i++)
rateCorrelation2[i] = 0.0;
relProposalProbs[CHANGE_AUTO_CORR] = moveRates[CHANGE_AUTO_CORR];
chainMins[CHANGE_AUTO_CORR] = 0.0;
chainMaxs[CHANGE_AUTO_CORR] = 1.0;
}
}
else
{
(*numRateCats) = 1;
printf (" Equal omega across sites\n");
chainMins[CHANGE_OMEGA_PROBS] = 0.0;
chainMaxs[CHANGE_OMEGA_PROBS] = 1.0;
relProposalProbs[CHANGE_OMEGA_PROBS] = 0.0;
}
}
/* set up covarion model */
if (useCovarion == YES)
{
if (((dataType == DNA || dataType == RNA) && enforceCodonModel == NO) || dataType == PROTEIN)
{
if (!strcmp(covarionModelType, "ts98"))
{
printf (" Rates vary along tree according to covarion/covariotide\n");
printf (" model of Tuffley and Steel (1998).\n");
}
}
else
{
printf ("\n ERROR: Covarion/covariotide model is only implemented for DNA sequences\n");
printf (" without enforcing the codon model.\n");
FreeMemory ();
return (ERROR);
}
if (dataType == PROTEIN && !strcmp(covarionModelType, "gcswitch"))
{
printf ("\n ERROR: This model is only implemented for DNA/RNA sequence information.\n");
FreeMemory ();
return (ERROR);
}
if (nst == 12)
{
printf ("\n ERROR: Sorry, but only time-reversible models are allowed with \n");
printf (" the covarion model.\n");
FreeMemory ();
return (ERROR);
}
switchRate = (double *)malloc((size_t) (4 * numChains * sizeof(double)));
if (!switchRate)
{
printf ("\n ERROR: Problem allocating switchRate.\n");
FreeMemory ();
return (ERROR);
}
else
allocatedMemory[ALLOC_SWITCH_RATE] = YES;
for (i=0; i<4*numChains; i++)
switchRate[i] = 0.05;
switchPi = (double *)malloc((size_t) (4 * numChains * sizeof(double)));
if (!switchPi)
{
printf ("\n ERROR: Problem allocating switchPi.\n");
FreeMemory ();
return (ERROR);
}
else
allocatedMemory[ALLOC_SWITCH_PI] = YES;
for (i=0; i<4*numChains; i++)
switchPi[i] = 0.5;
relProposalProbs[CHANGE_SWITCH_RATE] = moveRates[CHANGE_SWITCH_RATE];
chainMins[CHANGE_SWITCH_RATE] = 0.0001;
chainMaxs[CHANGE_SWITCH_RATE] = 100.0;
}
/* set up switch model for codons */
if ((dataType == DNA || dataType == RNA) && enforceCodonModel == YES && !strcmp(codonModelType, "covny98"))
{
printf (" Codons change categories along the tree.\n");
switchRate = (double *)malloc((size_t) (4 * numChains * sizeof(double)));
if (!switchRate)
{
printf ("\n ERROR: Problem allocating switchRate.\n");
FreeMemory ();
return (ERROR);
}
else
allocatedMemory[ALLOC_SWITCH_RATE] = YES;
for (i=0; i<4*numChains; i++)
switchRate[i] = 0.05;
relProposalProbs[CHANGE_SWITCH_RATE] = moveRates[CHANGE_SWITCH_RATE];
chainMins[CHANGE_SWITCH_RATE] = 0.0001;
chainMaxs[CHANGE_SWITCH_RATE] = 100.0;
}
/* set up moves for topology */
if (!strcmp(clockModel, "unconstrained") && treeModel == UNROOTED)
{
relProposalProbs[CHANGE_UNROOT_LOCAL] = moveRates[CHANGE_UNROOT_LOCAL];
chainMins[CHANGE_UNROOT_LOCAL] = BRLEN_EPSILON;
chainMaxs[CHANGE_UNROOT_LOCAL] = 100.0;
relProposalProbs[CHANGE_TREE_FTBR] = moveRates[CHANGE_TREE_FTBR];
chainMins[CHANGE_TREE_FTBR] = BRLEN_EPSILON;
chainMaxs[CHANGE_TREE_FTBR] = 100.0;
relProposalProbs[CHANGE_BRLEN] = moveRates[CHANGE_BRLEN];
chainMins[CHANGE_BRLEN] = BRLEN_EPSILON;
chainMaxs[CHANGE_BRLEN] = 100.0;
relProposalProbs[CHANGE_ERASER] = moveRates[CHANGE_ERASER];
chainMins[CHANGE_ERASER] = BRLEN_EPSILON;
chainMaxs[CHANGE_ERASER] = 100.0;
if (!strcmp(brlenprModel, "uniform"))
{
chainMins[CHANGE_UNROOT_LOCAL] = brlenprUni[0];
if (chainMins[CHANGE_UNROOT_LOCAL] < BRLEN_EPSILON)
chainMins[CHANGE_UNROOT_LOCAL] = BRLEN_EPSILON;
chainMaxs[CHANGE_UNROOT_LOCAL] = brlenprUni[1];
}
if (enforceCalibrations == NO && enforceConstraints == NO)
{
relProposalProbs[CHANGE_WORM] = moveRates[CHANGE_WORM];
chainMins[CHANGE_WORM] = BRLEN_EPSILON;
chainMaxs[CHANGE_WORM] = 10.0;
relProposalProbs[CHANGE_TREE_SPR] = moveRates[CHANGE_TREE_SPR];
chainMins[CHANGE_TREE_SPR] = BRLEN_EPSILON;
chainMaxs[CHANGE_TREE_SPR] = 10.0;
relProposalProbs[CHANGE_UNROOT_TBR] = moveRates[CHANGE_UNROOT_TBR];
chainMins[CHANGE_UNROOT_TBR] = BRLEN_EPSILON;
chainMaxs[CHANGE_UNROOT_TBR] = 10.0;
}
}
else if (!strcmp(clockModel, "unconstrained") && treeModel == ROOTED)
{
relProposalProbs[CHANGE_UNROOT_LOCAL] = moveRates[CHANGE_UNROOT_LOCAL];
chainMins[CHANGE_UNROOT_LOCAL] = BRLEN_EPSILON;
chainMaxs[CHANGE_UNROOT_LOCAL] = 10.0;
relProposalProbs[CHANGE_TREE_FTBR] = moveRates[CHANGE_TREE_FTBR];
chainMins[CHANGE_TREE_FTBR] = BRLEN_EPSILON;
chainMaxs[CHANGE_TREE_FTBR] = 100.0;
relProposalProbs[CHANGE_BRLEN] = moveRates[CHANGE_BRLEN];
chainMins[CHANGE_BRLEN] = BRLEN_EPSILON;
chainMaxs[CHANGE_BRLEN] = 100.0;
if (!strcmp(brlenprModel, "uniform"))
{
chainMins[CHANGE_UNROOT_LOCAL] = brlenprUni[0];
if (chainMins[CHANGE_UNROOT_LOCAL] < BRLEN_EPSILON)
chainMins[CHANGE_UNROOT_LOCAL] = BRLEN_EPSILON;
chainMaxs[CHANGE_UNROOT_LOCAL] = brlenprUni[1];
}
}
else if (!strcmp(clockModel, "strict") && treeModel == ROOTED)
{
if (enforceCalibrations == NO)
{
relProposalProbs[CHANGE_CLOCK_LOCAL] = moveRates[CHANGE_CLOCK_LOCAL];
chainMins[CHANGE_CLOCK_LOCAL] = BRLEN_EPSILON;
chainMaxs[CHANGE_CLOCK_LOCAL] = 10.0;
}
else
{
relProposalProbs[CHANGE_CLOCK_TIME_LOCAL] = moveRates[CHANGE_CLOCK_TIME_LOCAL];
chainMins[CHANGE_CLOCK_TIME_LOCAL] = BRLEN_EPSILON;
chainMaxs[CHANGE_CLOCK_TIME_LOCAL] = 10.0;
relProposalProbs[CHANGE_TREE_HEIGHT] = moveRates[CHANGE_TREE_HEIGHT];
chainMins[CHANGE_TREE_HEIGHT] = BRLEN_EPSILON;
chainMaxs[CHANGE_TREE_HEIGHT] = 100.0;
relProposalProbs[CHANGE_NODE_TIME] = moveRates[CHANGE_NODE_TIME];
chainMins[CHANGE_NODE_TIME] = BRLEN_EPSILON;
chainMaxs[CHANGE_NODE_TIME] = 100.0;
}
}
/* show proposal mechanisms that are turned on */
printf (" Proposal mechanisms\n");
sum = 0.0;
for (i=0; i<NUM_PROPOSAL_TYPES; i++)
sum += relProposalProbs[i];
for (i=0; i<NUM_PROPOSAL_TYPES; i++)
{
if (relProposalProbs[i] > 0.0)
printf (" %1.2lf percent of the time attempts %s\n", (relProposalProbs[i]/sum)*100.0, proposalName[i]);
}
return (NO_ERROR);
}
#if defined (TRANSLATE_TO_AA)
/*-------------------------------------------------------------------
TranslateToAA: Translate data matrix from DNA or RNA to AA
-------------------------------------------------------------------*/
void TranslateToAA (void)
{
}
#endif
int SetAARates (void)
{
aaJones[ 0][ 0] = 0; aaJones[ 0][ 1] = 58; aaJones[ 0][ 2] = 54; aaJones[ 0][ 3] = 81; aaJones[ 0][ 4] = 56;
aaJones[ 0][ 5] = 57; aaJones[ 0][ 6] = 105; aaJones[ 0][ 7] = 179; aaJones[ 0][ 8] = 27; aaJones[ 0][ 9] = 36;
aaJones[ 0][10] = 30; aaJones[ 0][11] = 35; aaJones[ 0][12] = 54; aaJones[ 0][13] = 15; aaJones[ 0][14] = 194;
aaJones[ 0][15] = 378; aaJones[ 0][16] = 475; aaJones[ 0][17] = 9; aaJones[ 0][18] = 11; aaJones[ 0][19] = 298;
aaJones[ 1][ 0] = 58; aaJones[ 1][ 1] = 0; aaJones[ 1][ 2] = 45; aaJones[ 1][ 3] = 16; aaJones[ 1][ 4] = 113;
aaJones[ 1][ 5] = 310; aaJones[ 1][ 6] = 29; aaJones[ 1][ 7] = 137; aaJones[ 1][ 8] = 328; aaJones[ 1][ 9] = 22;
aaJones[ 1][10] = 38; aaJones[ 1][11] = 646; aaJones[ 1][12] = 44; aaJones[ 1][13] = 5; aaJones[ 1][14] = 74;
aaJones[ 1][15] = 101; aaJones[ 1][16] = 64; aaJones[ 1][17] = 126; aaJones[ 1][18] = 20; aaJones[ 1][19] = 17;
aaJones[ 2][ 0] = 54; aaJones[ 2][ 1] = 45; aaJones[ 2][ 2] = 0; aaJones[ 2][ 3] = 528; aaJones[ 2][ 4] = 34;
aaJones[ 2][ 5] = 86; aaJones[ 2][ 6] = 58; aaJones[ 2][ 7] = 81; aaJones[ 2][ 8] = 391; aaJones[ 2][ 9] = 47;
aaJones[ 2][10] = 12; aaJones[ 2][11] = 263; aaJones[ 2][12] = 30; aaJones[ 2][13] = 10; aaJones[ 2][14] = 15;
aaJones[ 2][15] = 503; aaJones[ 2][16] = 232; aaJones[ 2][17] = 8; aaJones[ 2][18] = 70; aaJones[ 2][19] = 16;
aaJones[ 3][ 0] = 81; aaJones[ 3][ 1] = 16; aaJones[ 3][ 2] = 528; aaJones[ 3][ 3] = 0; aaJones[ 3][ 4] = 10;
aaJones[ 3][ 5] = 49; aaJones[ 3][ 6] = 767; aaJones[ 3][ 7] = 130; aaJones[ 3][ 8] = 112; aaJones[ 3][ 9] = 11;
aaJones[ 3][10] = 7; aaJones[ 3][11] = 26; aaJones[ 3][12] = 15; aaJones[ 3][13] = 4; aaJones[ 3][14] = 15;
aaJones[ 3][15] = 59; aaJones[ 3][16] = 38; aaJones[ 3][17] = 4; aaJones[ 3][18] = 46; aaJones[ 3][19] = 31;
aaJones[ 4][ 0] = 56; aaJones[ 4][ 1] = 113; aaJones[ 4][ 2] = 34; aaJones[ 4][ 3] = 10; aaJones[ 4][ 4] = 0;
aaJones[ 4][ 5] = 9; aaJones[ 4][ 6] = 5; aaJones[ 4][ 7] = 59; aaJones[ 4][ 8] = 69; aaJones[ 4][ 9] = 17;
aaJones[ 4][10] = 23; aaJones[ 4][11] = 7; aaJones[ 4][12] = 31; aaJones[ 4][13] = 78; aaJones[ 4][14] = 14;
aaJones[ 4][15] = 223; aaJones[ 4][16] = 42; aaJones[ 4][17] = 115; aaJones[ 4][18] = 209; aaJones[ 4][19] = 62;
aaJones[ 5][ 0] = 57; aaJones[ 5][ 1] = 310; aaJones[ 5][ 2] = 86; aaJones[ 5][ 3] = 49; aaJones[ 5][ 4] = 9;
aaJones[ 5][ 5] = 0; aaJones[ 5][ 6] = 323; aaJones[ 5][ 7] = 26; aaJones[ 5][ 8] = 597; aaJones[ 5][ 9] = 9;
aaJones[ 5][10] = 72; aaJones[ 5][11] = 292; aaJones[ 5][12] = 43; aaJones[ 5][13] = 4; aaJones[ 5][14] = 164;
aaJones[ 5][15] = 53; aaJones[ 5][16] = 51; aaJones[ 5][17] = 18; aaJones[ 5][18] = 24; aaJones[ 5][19] = 20;
aaJones[ 6][ 0] = 105; aaJones[ 6][ 1] = 29; aaJones[ 6][ 2] = 58; aaJones[ 6][ 3] = 767; aaJones[ 6][ 4] = 5;
aaJones[ 6][ 5] = 323; aaJones[ 6][ 6] = 0; aaJones[ 6][ 7] = 119; aaJones[ 6][ 8] = 26; aaJones[ 6][ 9] = 12;
aaJones[ 6][10] = 9; aaJones[ 6][11] = 181; aaJones[ 6][12] = 18; aaJones[ 6][13] = 5; aaJones[ 6][14] = 18;
aaJones[ 6][15] = 30; aaJones[ 6][16] = 32; aaJones[ 6][17] = 10; aaJones[ 6][18] = 7; aaJones[ 6][19] = 45;
aaJones[ 7][ 0] = 179; aaJones[ 7][ 1] = 137; aaJones[ 7][ 2] = 81; aaJones[ 7][ 3] = 130; aaJones[ 7][ 4] = 59;
aaJones[ 7][ 5] = 26; aaJones[ 7][ 6] = 119; aaJones[ 7][ 7] = 0; aaJones[ 7][ 8] = 23; aaJones[ 7][ 9] = 6;
aaJones[ 7][10] = 6; aaJones[ 7][11] = 27; aaJones[ 7][12] = 14; aaJones[ 7][13] = 5; aaJones[ 7][14] = 24;
aaJones[ 7][15] = 201; aaJones[ 7][16] = 33; aaJones[ 7][17] = 55; aaJones[ 7][18] = 8; aaJones[ 7][19] = 47;
aaJones[ 8][ 0] = 27; aaJones[ 8][ 1] = 328; aaJones[ 8][ 2] = 391; aaJones[ 8][ 3] = 112; aaJones[ 8][ 4] = 69;
aaJones[ 8][ 5] = 597; aaJones[ 8][ 6] = 26; aaJones[ 8][ 7] = 23; aaJones[ 8][ 8] = 0; aaJones[ 8][ 9] = 16;
aaJones[ 8][10] = 56; aaJones[ 8][11] = 45; aaJones[ 8][12] = 33; aaJones[ 8][13] = 40; aaJones[ 8][14] = 115;
aaJones[ 8][15] = 73; aaJones[ 8][16] = 46; aaJones[ 8][17] = 8; aaJones[ 8][18] = 573; aaJones[ 8][19] = 11;
aaJones[ 9][ 0] = 36; aaJones[ 9][ 1] = 22; aaJones[ 9][ 2] = 47; aaJones[ 9][ 3] = 11; aaJones[ 9][ 4] = 17;
aaJones[ 9][ 5] = 9; aaJones[ 9][ 6] = 12; aaJones[ 9][ 7] = 6; aaJones[ 9][ 8] = 16; aaJones[ 9][ 9] = 0;
aaJones[ 9][10] = 229; aaJones[ 9][11] = 21; aaJones[ 9][12] = 479; aaJones[ 9][13] = 89; aaJones[ 9][14] = 10;
aaJones[ 9][15] = 40; aaJones[ 9][16] = 245; aaJones[ 9][17] = 9; aaJones[ 9][18] = 32; aaJones[ 9][19] = 961;
aaJones[10][ 0] = 30; aaJones[10][ 1] = 38; aaJones[10][ 2] = 12; aaJones[10][ 3] = 7; aaJones[10][ 4] = 23;
aaJones[10][ 5] = 72; aaJones[10][ 6] = 9; aaJones[10][ 7] = 6; aaJones[10][ 8] = 56; aaJones[10][ 9] = 229;
aaJones[10][10] = 0; aaJones[10][11] = 14; aaJones[10][12] = 388; aaJones[10][13] = 248; aaJones[10][14] = 102;
aaJones[10][15] = 59; aaJones[10][16] = 25; aaJones[10][17] = 52; aaJones[10][18] = 24; aaJones[10][19] = 180;
aaJones[11][ 0] = 35; aaJones[11][ 1] = 646; aaJones[11][ 2] = 263; aaJones[11][ 3] = 26; aaJones[11][ 4] = 7;
aaJones[11][ 5] = 292; aaJones[11][ 6] = 181; aaJones[11][ 7] = 27; aaJones[11][ 8] = 45; aaJones[11][ 9] = 21;
aaJones[11][10] = 14; aaJones[11][11] = 0; aaJones[11][12] = 65; aaJones[11][13] = 4; aaJones[11][14] = 21;
aaJones[11][15] = 47; aaJones[11][16] = 103; aaJones[11][17] = 10; aaJones[11][18] = 8; aaJones[11][19] = 14;
aaJones[12][ 0] = 54; aaJones[12][ 1] = 44; aaJones[12][ 2] = 30; aaJones[12][ 3] = 15; aaJones[12][ 4] = 31;
aaJones[12][ 5] = 43; aaJones[12][ 6] = 18; aaJones[12][ 7] = 14; aaJones[12][ 8] = 33; aaJones[12][ 9] = 479;
aaJones[12][10] = 388; aaJones[12][11] = 65; aaJones[12][12] = 0; aaJones[12][13] = 43; aaJones[12][14] = 16;
aaJones[12][15] = 29; aaJones[12][16] = 226; aaJones[12][17] = 24; aaJones[12][18] = 18; aaJones[12][19] = 323;
aaJones[13][ 0] = 15; aaJones[13][ 1] = 5; aaJones[13][ 2] = 10; aaJones[13][ 3] = 4; aaJones[13][ 4] = 78;
aaJones[13][ 5] = 4; aaJones[13][ 6] = 5; aaJones[13][ 7] = 5; aaJones[13][ 8] = 40; aaJones[13][ 9] = 89;
aaJones[13][10] = 248; aaJones[13][11] = 4; aaJones[13][12] = 43; aaJones[13][13] = 0; aaJones[13][14] = 17;
aaJones[13][15] = 92; aaJones[13][16] = 12; aaJones[13][17] = 53; aaJones[13][18] = 536; aaJones[13][19] = 62;
aaJones[14][ 0] = 194; aaJones[14][ 1] = 74; aaJones[14][ 2] = 15; aaJones[14][ 3] = 15; aaJones[14][ 4] = 14;
aaJones[14][ 5] = 164; aaJones[14][ 6] = 18; aaJones[14][ 7] = 24; aaJones[14][ 8] = 115; aaJones[14][ 9] = 10;
aaJones[14][10] = 102; aaJones[14][11] = 21; aaJones[14][12] = 16; aaJones[14][13] = 17; aaJones[14][14] = 0;
aaJones[14][15] = 285; aaJones[14][16] = 118; aaJones[14][17] = 6; aaJones[14][18] = 10; aaJones[14][19] = 23;
aaJones[15][ 0] = 378; aaJones[15][ 1] = 101; aaJones[15][ 2] = 503; aaJones[15][ 3] = 59; aaJones[15][ 4] = 223;
aaJones[15][ 5] = 53; aaJones[15][ 6] = 30; aaJones[15][ 7] = 201; aaJones[15][ 8] = 73; aaJones[15][ 9] = 40;
aaJones[15][10] = 59; aaJones[15][11] = 47; aaJones[15][12] = 29; aaJones[15][13] = 92; aaJones[15][14] = 285;
aaJones[15][15] = 0; aaJones[15][16] = 477; aaJones[15][17] = 35; aaJones[15][18] = 63; aaJones[15][19] = 38;
aaJones[16][ 0] = 475; aaJones[16][ 1] = 64; aaJones[16][ 2] = 232; aaJones[16][ 3] = 38; aaJones[16][ 4] = 42;
aaJones[16][ 5] = 51; aaJones[16][ 6] = 32; aaJones[16][ 7] = 33; aaJones[16][ 8] = 46; aaJones[16][ 9] = 245;
aaJones[16][10] = 25; aaJones[16][11] = 103; aaJones[16][12] = 226; aaJones[16][13] = 12; aaJones[16][14] = 118;
aaJones[16][15] = 477; aaJones[16][16] = 0; aaJones[16][17] = 12; aaJones[16][18] = 21; aaJones[16][19] = 112;
aaJones[17][ 0] = 9; aaJones[17][ 1] = 126; aaJones[17][ 2] = 8; aaJones[17][ 3] = 4; aaJones[17][ 4] = 115;
aaJones[17][ 5] = 18; aaJones[17][ 6] = 10; aaJones[17][ 7] = 55; aaJones[17][ 8] = 8; aaJones[17][ 9] = 9;
aaJones[17][10] = 52; aaJones[17][11] = 10; aaJones[17][12] = 24; aaJones[17][13] = 53; aaJones[17][14] = 6;
aaJones[17][15] = 35; aaJones[17][16] = 12; aaJones[17][17] = 0; aaJones[17][18] = 71; aaJones[17][19] = 25;
aaJones[18][ 0] = 11; aaJones[18][ 1] = 20; aaJones[18][ 2] = 70; aaJones[18][ 3] = 46; aaJones[18][ 4] = 209;
aaJones[18][ 5] = 24; aaJones[18][ 6] = 7; aaJones[18][ 7] = 8; aaJones[18][ 8] = 573; aaJones[18][ 9] = 32;
aaJones[18][10] = 24; aaJones[18][11] = 8; aaJones[18][12] = 18; aaJones[18][13] = 536; aaJones[18][14] = 10;
aaJones[18][15] = 63; aaJones[18][16] = 21; aaJones[18][17] = 71; aaJones[18][18] = 0; aaJones[18][19] = 16;
aaJones[19][ 0] = 298; aaJones[19][ 1] = 17; aaJones[19][ 2] = 16; aaJones[19][ 3] = 31; aaJones[19][ 4] = 62;
aaJones[19][ 5] = 20; aaJones[19][ 6] = 45; aaJones[19][ 7] = 47; aaJones[19][ 8] = 11; aaJones[19][ 9] = 961;
aaJones[19][10] = 180; aaJones[19][11] = 14; aaJones[19][12] = 323; aaJones[19][13] = 62; aaJones[19][14] = 23;
aaJones[19][15] = 38; aaJones[19][16] = 112; aaJones[19][17] = 25; aaJones[19][18] = 16; aaJones[19][19] = 0;
jonesPi[ 0] = 0.076748;
jonesPi[ 1] = 0.051691;
jonesPi[ 2] = 0.042645;
jonesPi[ 3] = 0.051544;
jonesPi[ 4] = 0.019803;
jonesPi[ 5] = 0.040752;
jonesPi[ 6] = 0.061830;
jonesPi[ 7] = 0.073152;
jonesPi[ 8] = 0.022944;
jonesPi[ 9] = 0.053761;
jonesPi[10] = 0.091904;
jonesPi[11] = 0.058676;
jonesPi[12] = 0.023826;
jonesPi[13] = 0.040126;
jonesPi[14] = 0.050901;
jonesPi[15] = 0.068765;
jonesPi[16] = 0.058565;
jonesPi[17] = 0.014261;
jonesPi[18] = 0.032102;
jonesPi[19] = 0.066005;
aaDayhoff[ 0][ 0] = 0; aaDayhoff[ 0][ 1] = 27; aaDayhoff[ 0][ 2] = 98; aaDayhoff[ 0][ 3] = 120; aaDayhoff[ 0][ 4] = 36;
aaDayhoff[ 0][ 5] = 89; aaDayhoff[ 0][ 6] = 198; aaDayhoff[ 0][ 7] = 240; aaDayhoff[ 0][ 8] = 23; aaDayhoff[ 0][ 9] = 65;
aaDayhoff[ 0][10] = 41; aaDayhoff[ 0][11] = 26; aaDayhoff[ 0][12] = 72; aaDayhoff[ 0][13] = 18; aaDayhoff[ 0][14] = 250;
aaDayhoff[ 0][15] = 409; aaDayhoff[ 0][16] = 371; aaDayhoff[ 0][17] = 0; aaDayhoff[ 0][18] = 24; aaDayhoff[ 0][19] = 208;
aaDayhoff[ 1][ 0] = 27; aaDayhoff[ 1][ 1] = 0; aaDayhoff[ 1][ 2] = 32; aaDayhoff[ 1][ 3] = 0; aaDayhoff[ 1][ 4] = 23;
aaDayhoff[ 1][ 5] = 246; aaDayhoff[ 1][ 6] = 1; aaDayhoff[ 1][ 7] = 9; aaDayhoff[ 1][ 8] = 240; aaDayhoff[ 1][ 9] = 64;
aaDayhoff[ 1][10] = 15; aaDayhoff[ 1][11] = 464; aaDayhoff[ 1][12] = 90; aaDayhoff[ 1][13] = 14; aaDayhoff[ 1][14] = 103;
aaDayhoff[ 1][15] = 154; aaDayhoff[ 1][16] = 26; aaDayhoff[ 1][17] = 201; aaDayhoff[ 1][18] = 8; aaDayhoff[ 1][19] = 24;
aaDayhoff[ 2][ 0] = 98; aaDayhoff[ 2][ 1] = 32; aaDayhoff[ 2][ 2] = 0; aaDayhoff[ 2][ 3] = 905; aaDayhoff[ 2][ 4] = 0;
aaDayhoff[ 2][ 5] = 103; aaDayhoff[ 2][ 6] = 148; aaDayhoff[ 2][ 7] = 139; aaDayhoff[ 2][ 8] = 535; aaDayhoff[ 2][ 9] = 77;
aaDayhoff[ 2][10] = 34; aaDayhoff[ 2][11] = 318; aaDayhoff[ 2][12] = 1; aaDayhoff[ 2][13] = 14; aaDayhoff[ 2][14] = 42;
aaDayhoff[ 2][15] = 495; aaDayhoff[ 2][16] = 229; aaDayhoff[ 2][17] = 23; aaDayhoff[ 2][18] = 95; aaDayhoff[ 2][19] = 15;
aaDayhoff[ 3][ 0] = 120; aaDayhoff[ 3][ 1] = 0; aaDayhoff[ 3][ 2] = 905; aaDayhoff[ 3][ 3] = 0; aaDayhoff[ 3][ 4] = 0;
aaDayhoff[ 3][ 5] = 134; aaDayhoff[ 3][ 6] = 1153; aaDayhoff[ 3][ 7] = 125; aaDayhoff[ 3][ 8] = 86; aaDayhoff[ 3][ 9] = 24;
aaDayhoff[ 3][10] = 0; aaDayhoff[ 3][11] = 71; aaDayhoff[ 3][12] = 0; aaDayhoff[ 3][13] = 0; aaDayhoff[ 3][14] = 13;
aaDayhoff[ 3][15] = 95; aaDayhoff[ 3][16] = 66; aaDayhoff[ 3][17] = 0; aaDayhoff[ 3][18] = 0; aaDayhoff[ 3][19] = 18;
aaDayhoff[ 4][ 0] = 36; aaDayhoff[ 4][ 1] = 23; aaDayhoff[ 4][ 2] = 0; aaDayhoff[ 4][ 3] = 0; aaDayhoff[ 4][ 4] = 0;
aaDayhoff[ 4][ 5] = 0; aaDayhoff[ 4][ 6] = 0; aaDayhoff[ 4][ 7] = 11; aaDayhoff[ 4][ 8] = 28; aaDayhoff[ 4][ 9] = 44;
aaDayhoff[ 4][10] = 0; aaDayhoff[ 4][11] = 0; aaDayhoff[ 4][12] = 0; aaDayhoff[ 4][13] = 0; aaDayhoff[ 4][14] = 19;
aaDayhoff[ 4][15] = 161; aaDayhoff[ 4][16] = 16; aaDayhoff[ 4][17] = 0; aaDayhoff[ 4][18] = 96; aaDayhoff[ 4][19] = 49;
aaDayhoff[ 5][ 0] = 89; aaDayhoff[ 5][ 1] = 246; aaDayhoff[ 5][ 2] = 103; aaDayhoff[ 5][ 3] = 134; aaDayhoff[ 5][ 4] = 0;
aaDayhoff[ 5][ 5] = 0; aaDayhoff[ 5][ 6] = 716; aaDayhoff[ 5][ 7] = 28; aaDayhoff[ 5][ 8] = 606; aaDayhoff[ 5][ 9] = 18;
aaDayhoff[ 5][10] = 73; aaDayhoff[ 5][11] = 153; aaDayhoff[ 5][12] = 114; aaDayhoff[ 5][13] = 0; aaDayhoff[ 5][14] = 153;
aaDayhoff[ 5][15] = 56; aaDayhoff[ 5][16] = 53; aaDayhoff[ 5][17] = 0; aaDayhoff[ 5][18] = 0; aaDayhoff[ 5][19] = 35;
aaDayhoff[ 6][ 0] = 198; aaDayhoff[ 6][ 1] = 1; aaDayhoff[ 6][ 2] = 148; aaDayhoff[ 6][ 3] = 1153; aaDayhoff[ 6][ 4] = 0;
aaDayhoff[ 6][ 5] = 716; aaDayhoff[ 6][ 6] = 0; aaDayhoff[ 6][ 7] = 81; aaDayhoff[ 6][ 8] = 43; aaDayhoff[ 6][ 9] = 61;
aaDayhoff[ 6][10] = 11; aaDayhoff[ 6][11] = 83; aaDayhoff[ 6][12] = 30; aaDayhoff[ 6][13] = 0; aaDayhoff[ 6][14] = 51;
aaDayhoff[ 6][15] = 79; aaDayhoff[ 6][16] = 34; aaDayhoff[ 6][17] = 0; aaDayhoff[ 6][18] = 22; aaDayhoff[ 6][19] = 37;
aaDayhoff[ 7][ 0] = 240; aaDayhoff[ 7][ 1] = 9; aaDayhoff[ 7][ 2] = 139; aaDayhoff[ 7][ 3] = 125; aaDayhoff[ 7][ 4] = 11;
aaDayhoff[ 7][ 5] = 28; aaDayhoff[ 7][ 6] = 81; aaDayhoff[ 7][ 7] = 0; aaDayhoff[ 7][ 8] = 10; aaDayhoff[ 7][ 9] = 0;
aaDayhoff[ 7][10] = 7; aaDayhoff[ 7][11] = 27; aaDayhoff[ 7][12] = 17; aaDayhoff[ 7][13] = 15; aaDayhoff[ 7][14] = 34;
aaDayhoff[ 7][15] = 234; aaDayhoff[ 7][16] = 30; aaDayhoff[ 7][17] = 0; aaDayhoff[ 7][18] = 0; aaDayhoff[ 7][19] = 54;
aaDayhoff[ 8][ 0] = 23; aaDayhoff[ 8][ 1] = 240; aaDayhoff[ 8][ 2] = 535; aaDayhoff[ 8][ 3] = 86; aaDayhoff[ 8][ 4] = 28;
aaDayhoff[ 8][ 5] = 606; aaDayhoff[ 8][ 6] = 43; aaDayhoff[ 8][ 7] = 10; aaDayhoff[ 8][ 8] = 0; aaDayhoff[ 8][ 9] = 7;
aaDayhoff[ 8][10] = 44; aaDayhoff[ 8][11] = 26; aaDayhoff[ 8][12] = 0; aaDayhoff[ 8][13] = 48; aaDayhoff[ 8][14] = 94;
aaDayhoff[ 8][15] = 35; aaDayhoff[ 8][16] = 22; aaDayhoff[ 8][17] = 27; aaDayhoff[ 8][18] = 127; aaDayhoff[ 8][19] = 44;
aaDayhoff[ 9][ 0] = 65; aaDayhoff[ 9][ 1] = 64; aaDayhoff[ 9][ 2] = 77; aaDayhoff[ 9][ 3] = 24; aaDayhoff[ 9][ 4] = 44;
aaDayhoff[ 9][ 5] = 18; aaDayhoff[ 9][ 6] = 61; aaDayhoff[ 9][ 7] = 0; aaDayhoff[ 9][ 8] = 7; aaDayhoff[ 9][ 9] = 0;
aaDayhoff[ 9][10] = 257; aaDayhoff[ 9][11] = 46; aaDayhoff[ 9][12] = 336; aaDayhoff[ 9][13] = 196; aaDayhoff[ 9][14] = 12;
aaDayhoff[ 9][15] = 24; aaDayhoff[ 9][16] = 192; aaDayhoff[ 9][17] = 0; aaDayhoff[ 9][18] = 37; aaDayhoff[ 9][19] = 889;
aaDayhoff[10][ 0] = 41; aaDayhoff[10][ 1] = 15; aaDayhoff[10][ 2] = 34; aaDayhoff[10][ 3] = 0; aaDayhoff[10][ 4] = 0;
aaDayhoff[10][ 5] = 73; aaDayhoff[10][ 6] = 11; aaDayhoff[10][ 7] = 7; aaDayhoff[10][ 8] = 44; aaDayhoff[10][ 9] = 257;
aaDayhoff[10][10] = 0; aaDayhoff[10][11] = 18; aaDayhoff[10][12] = 527; aaDayhoff[10][13] = 157; aaDayhoff[10][14] = 32;
aaDayhoff[10][15] = 17; aaDayhoff[10][16] = 33; aaDayhoff[10][17] = 46; aaDayhoff[10][18] = 28; aaDayhoff[10][19] = 175;
aaDayhoff[11][ 0] = 26; aaDayhoff[11][ 1] = 464; aaDayhoff[11][ 2] = 318; aaDayhoff[11][ 3] = 71; aaDayhoff[11][ 4] = 0;
aaDayhoff[11][ 5] = 153; aaDayhoff[11][ 6] = 83; aaDayhoff[11][ 7] = 27; aaDayhoff[11][ 8] = 26; aaDayhoff[11][ 9] = 46;
aaDayhoff[11][10] = 18; aaDayhoff[11][11] = 0; aaDayhoff[11][12] = 243; aaDayhoff[11][13] = 0; aaDayhoff[11][14] = 33;
aaDayhoff[11][15] = 96; aaDayhoff[11][16] = 136; aaDayhoff[11][17] = 0; aaDayhoff[11][18] = 13; aaDayhoff[11][19] = 10;
aaDayhoff[12][ 0] = 72; aaDayhoff[12][ 1] = 90; aaDayhoff[12][ 2] = 1; aaDayhoff[12][ 3] = 0; aaDayhoff[12][ 4] = 0;
aaDayhoff[12][ 5] = 114; aaDayhoff[12][ 6] = 30; aaDayhoff[12][ 7] = 17; aaDayhoff[12][ 8] = 0; aaDayhoff[12][ 9] = 336;
aaDayhoff[12][10] = 527; aaDayhoff[12][11] = 243; aaDayhoff[12][12] = 0; aaDayhoff[12][13] = 92; aaDayhoff[12][14] = 17;
aaDayhoff[12][15] = 62; aaDayhoff[12][16] = 104; aaDayhoff[12][17] = 0; aaDayhoff[12][18] = 0; aaDayhoff[12][19] = 258;
aaDayhoff[13][ 0] = 18; aaDayhoff[13][ 1] = 14; aaDayhoff[13][ 2] = 14; aaDayhoff[13][ 3] = 0; aaDayhoff[13][ 4] = 0;
aaDayhoff[13][ 5] = 0; aaDayhoff[13][ 6] = 0; aaDayhoff[13][ 7] = 15; aaDayhoff[13][ 8] = 48; aaDayhoff[13][ 9] = 196;
aaDayhoff[13][10] = 157; aaDayhoff[13][11] = 0; aaDayhoff[13][12] = 92; aaDayhoff[13][13] = 0; aaDayhoff[13][14] = 11;
aaDayhoff[13][15] = 46; aaDayhoff[13][16] = 13; aaDayhoff[13][17] = 76; aaDayhoff[13][18] = 698; aaDayhoff[13][19] = 12;
aaDayhoff[14][ 0] = 250; aaDayhoff[14][ 1] = 103; aaDayhoff[14][ 2] = 42; aaDayhoff[14][ 3] = 13; aaDayhoff[14][ 4] = 19;
aaDayhoff[14][ 5] = 153; aaDayhoff[14][ 6] = 51; aaDayhoff[14][ 7] = 34; aaDayhoff[14][ 8] = 94; aaDayhoff[14][ 9] = 12;
aaDayhoff[14][10] = 32; aaDayhoff[14][11] = 33; aaDayhoff[14][12] = 17; aaDayhoff[14][13] = 11; aaDayhoff[14][14] = 0;
aaDayhoff[14][15] = 245; aaDayhoff[14][16] = 78; aaDayhoff[14][17] = 0; aaDayhoff[14][18] = 0; aaDayhoff[14][19] = 48;
aaDayhoff[15][ 0] = 409; aaDayhoff[15][ 1] = 154; aaDayhoff[15][ 2] = 495; aaDayhoff[15][ 3] = 95; aaDayhoff[15][ 4] = 161;
aaDayhoff[15][ 5] = 56; aaDayhoff[15][ 6] = 79; aaDayhoff[15][ 7] = 234; aaDayhoff[15][ 8] = 35; aaDayhoff[15][ 9] = 24;
aaDayhoff[15][10] = 17; aaDayhoff[15][11] = 96; aaDayhoff[15][12] = 62; aaDayhoff[15][13] = 46; aaDayhoff[15][14] = 245;
aaDayhoff[15][15] = 0; aaDayhoff[15][16] = 550; aaDayhoff[15][17] = 75; aaDayhoff[15][18] = 34; aaDayhoff[15][19] = 30;
aaDayhoff[16][ 0] = 371; aaDayhoff[16][ 1] = 26; aaDayhoff[16][ 2] = 229; aaDayhoff[16][ 3] = 66; aaDayhoff[16][ 4] = 16;
aaDayhoff[16][ 5] = 53; aaDayhoff[16][ 6] = 34; aaDayhoff[16][ 7] = 30; aaDayhoff[16][ 8] = 22; aaDayhoff[16][ 9] = 192;
aaDayhoff[16][10] = 33; aaDayhoff[16][11] = 136; aaDayhoff[16][12] = 104; aaDayhoff[16][13] = 13; aaDayhoff[16][14] = 78;
aaDayhoff[16][15] = 550; aaDayhoff[16][16] = 0; aaDayhoff[16][17] = 0; aaDayhoff[16][18] = 42; aaDayhoff[16][19] = 157;
aaDayhoff[17][ 0] = 0; aaDayhoff[17][ 1] = 201; aaDayhoff[17][ 2] = 23; aaDayhoff[17][ 3] = 0; aaDayhoff[17][ 4] = 0;
aaDayhoff[17][ 5] = 0; aaDayhoff[17][ 6] = 0; aaDayhoff[17][ 7] = 0; aaDayhoff[17][ 8] = 27; aaDayhoff[17][ 9] = 0;
aaDayhoff[17][10] = 46; aaDayhoff[17][11] = 0; aaDayhoff[17][12] = 0; aaDayhoff[17][13] = 76; aaDayhoff[17][14] = 0;
aaDayhoff[17][15] = 75; aaDayhoff[17][16] = 0; aaDayhoff[17][17] = 0; aaDayhoff[17][18] = 61; aaDayhoff[17][19] = 0;
aaDayhoff[18][ 0] = 24; aaDayhoff[18][ 1] = 8; aaDayhoff[18][ 2] = 95; aaDayhoff[18][ 3] = 0; aaDayhoff[18][ 4] = 96;
aaDayhoff[18][ 5] = 0; aaDayhoff[18][ 6] = 22; aaDayhoff[18][ 7] = 0; aaDayhoff[18][ 8] = 127; aaDayhoff[18][ 9] = 37;
aaDayhoff[18][10] = 28; aaDayhoff[18][11] = 13; aaDayhoff[18][12] = 0; aaDayhoff[18][13] = 698; aaDayhoff[18][14] = 0;
aaDayhoff[18][15] = 34; aaDayhoff[18][16] = 42; aaDayhoff[18][17] = 61; aaDayhoff[18][18] = 0; aaDayhoff[18][19] = 28;
aaDayhoff[19][ 0] = 208; aaDayhoff[19][ 1] = 24; aaDayhoff[19][ 2] = 15; aaDayhoff[19][ 3] = 18; aaDayhoff[19][ 4] = 49;
aaDayhoff[19][ 5] = 35; aaDayhoff[19][ 6] = 37; aaDayhoff[19][ 7] = 54; aaDayhoff[19][ 8] = 44; aaDayhoff[19][ 9] = 889;
aaDayhoff[19][10] = 175; aaDayhoff[19][11] = 10; aaDayhoff[19][12] = 258; aaDayhoff[19][13] = 12; aaDayhoff[19][14] = 48;
aaDayhoff[19][15] = 30; aaDayhoff[19][16] = 157; aaDayhoff[19][17] = 0; aaDayhoff[19][18] = 28; aaDayhoff[19][19] = 0;
dayhoffPi[ 0] = 0.087127;
dayhoffPi[ 1] = 0.040904;
dayhoffPi[ 2] = 0.040432;
dayhoffPi[ 3] = 0.046872;
dayhoffPi[ 4] = 0.033474;
dayhoffPi[ 5] = 0.038255;
dayhoffPi[ 6] = 0.049530;
dayhoffPi[ 7] = 0.088612;
dayhoffPi[ 8] = 0.033618;
dayhoffPi[ 9] = 0.036886;
dayhoffPi[10] = 0.085357;
dayhoffPi[11] = 0.080482;
dayhoffPi[12] = 0.014753;
dayhoffPi[13] = 0.039772;
dayhoffPi[14] = 0.050680;
dayhoffPi[15] = 0.069577;
dayhoffPi[16] = 0.058542;
dayhoffPi[17] = 0.010494;
dayhoffPi[18] = 0.029916;
dayhoffPi[19] = 0.064718;
return (NO_ERROR);
}
int SetAAQMatrix (double **a, int whichTree, int whichChain)
{
register int i, j, count, temp;
double scaler, mult;
/* set diagonal of Q matrix to 0 */
for (i=0; i<nStates; i++)
a[i][i] = 0.0;
if (aaModelType == POISSON)
{
scaler = 0.0;
for (i=0; i<nStates; i++)
{
for (j=i+1; j<nStates; j++)
{
a[i][i] -= (a[i][j] = 0.05);
a[j][j] -= (a[j][i] = 0.05);
scaler += 0.05 * a[i][j];
scaler += 0.05 * a[j][i];
}
}
}
else if (aaModelType == EQUALIN)
{
scaler = 0.0;
for (i=0; i<nStates; i++)
{
for (j=i+1; j<nStates; j++)
{
a[i][i] -= (a[i][j] = baseFreq[whichChain*2*nStates + whichTree*nStates + j]);
a[j][j] -= (a[j][i] = baseFreq[whichChain*2*nStates + whichTree*nStates + i]);
scaler += baseFreq[whichChain*2*nStates + whichTree*nStates + i] * a[i][j];
scaler += baseFreq[whichChain*2*nStates + whichTree*nStates + j] * a[j][i];
}
}
}
else if (aaModelType == JONES)
{
scaler = 0.0;
for (i=0; i<nStates; i++)
{
for (j=i+1; j<nStates; j++)
{
a[i][i] -= (a[i][j] = jonesPi[j] * aaJones[i][j]);
a[j][j] -= (a[j][i] = jonesPi[i] * aaJones[j][i]);
scaler += jonesPi[i] * a[i][j];
scaler += jonesPi[j] * a[j][i];
}
}
}
else if (aaModelType == DAYHOFF)
{
scaler = 0.0;
for (i=0; i<nStates; i++)
{
for (j=i+1; j<nStates; j++)
{
a[i][i] -= (a[i][j] = dayhoffPi[j] * aaDayhoff[i][j]);
a[j][j] -= (a[j][i] = dayhoffPi[i] * aaDayhoff[j][i]);
scaler += dayhoffPi[i] * a[i][j];
scaler += dayhoffPi[j] * a[j][i];
}
}
}
else if (aaModelType == GTR)
{
temp = whichChain*2*190 + whichTree*190;
count = 0;
scaler = 0.0;
for (i=0; i<nStates; i++)
{
for (j=i+1; j<nStates; j++)
{
if (count >= 190)
{
printf (" ERROR: AA model went out of bounds\n");
return (ERROR);
}
mult = subParams[temp + count];
a[i][i] -= (a[i][j] = baseFreq[whichChain*2*nStates + whichTree*nStates + j] * mult);
a[j][j] -= (a[j][i] = baseFreq[whichChain*2*nStates + whichTree*nStates + i] * mult);
scaler += baseFreq[whichChain*2*nStates + whichTree*nStates + i] * a[i][j];
scaler += baseFreq[whichChain*2*nStates + whichTree*nStates + j] * a[j][i];
count++;
}
}
}
/* rescale Q matrix */
scaler = 1.0 / scaler;
for (i=0; i<nStates; i++)
for (j=0; j<nStates; j++)
a[i][j] *= scaler;
# if 0
for (i=0; i<nStates; i++)
{
for (j=0; j<nStates; j++)
printf ("%0.5lf ", a[i][j]);
printf ("\n");
}
# endif
return (NO_ERROR);
}
int SetCodonQMatrix (double **a, int whichTree, int whichChain, double nonsyn, double kap)
{
register int i, j, k, nDiff, isTransition;
double scaler, mult;
/* set diagonal of Q matrix to 0 */
for (i=0; i<nStates; i++)
a[i][i] = 0.0;
scaler = 0.0;
for (i=0; i<nStates; i++)
{
for (j=i+1; j<nStates; j++)
{
nDiff = 0;
for (k=0; k<3; k++)
{
if (codonNucs[i][k] != codonNucs[j][k])
{
nDiff++;
if ((codonNucs[i][k] == 0 && codonNucs[j][k] == 2) || (codonNucs[i][k] == 2 && codonNucs[j][k] == 0) ||
(codonNucs[i][k] == 1 && codonNucs[j][k] == 3) || (codonNucs[i][k] == 3 && codonNucs[j][k] == 1))
isTransition = YES;
else
isTransition = NO;
}
}
if (nDiff > 1)
{
mult = 0.0;
}
else
{
if (transCodon[i] == transCodon[j])
mult = 1.0;
else
mult = nonsyn;
if (isTransition == YES)
mult *= kap;
}
a[i][i] -= (a[i][j] = baseFreq[whichChain*2*nStates + whichTree*nStates + j] * mult);
a[j][j] -= (a[j][i] = baseFreq[whichChain*2*nStates + whichTree*nStates + i] * mult);
scaler += baseFreq[whichChain*2*nStates + whichTree*nStates + i] * a[i][j];
scaler += baseFreq[whichChain*2*nStates + whichTree*nStates + j] * a[j][i];
}
}
/* rescale Q matrix */
scaler = 1.0 / scaler;
for (i=0; i<nStates; i++)
for (j=0; j<nStates; j++)
a[i][j] *= scaler;
# if 0
printf ("k = %lf w = %lf\n", kap, nonsyn);
for (i=0; i<nStates; i++)
{
for (j=0; j<nStates; j++)
printf ("%0.4lf ", a[i][j]);
printf ("\n");
}
# endif
return (NO_ERROR);
}
int SetCodonSwitchQMatrix (double **a, int whichTree, int whichChain, double nonsyn, double kap, double sr)
{
register int i, j, k, nDiff, isTransition, temp, nLocalStates, twoTimesS;
double scaler, piPur, piNeu, piPos, multPur, multNeu, multPos, **sPur, **sNeu, **sPos, codonFreq;
sPur = psdmatrix (nStates);
sNeu = psdmatrix (nStates);
sPos = psdmatrix (nStates);
temp = whichChain*2*nStates + whichTree*nStates;
piPur = probPur[whichChain*2 + whichTree];
piNeu = probNeu[whichChain*2 + whichTree];
piPos = probPos[whichChain*2 + whichTree];
nLocalStates = 3 * nStates;
twoTimesS = 2 * nStates;
/* set diagonal of Q matrix to 0 */
for (i=0; i<nStates; i++)
{
sPur[i][i] = sNeu[i][i] = sPos[i][i] = 0.0;
}
/* set three q matrices */
for (i=0; i<nStates; i++)
{
for (j=i+1; j<nStates; j++)
{
nDiff = 0;
for (k=0; k<3; k++)
{
if (codonNucs[i][k] != codonNucs[j][k])
{
nDiff++;
if ((codonNucs[i][k] == 0 && codonNucs[j][k] == 2) || (codonNucs[i][k] == 2 && codonNucs[j][k] == 0) ||
(codonNucs[i][k] == 1 && codonNucs[j][k] == 3) || (codonNucs[i][k] == 3 && codonNucs[j][k] == 1))
isTransition = YES;
else
isTransition = NO;
}
}
if (nDiff > 1)
{
multPur = multNeu = multPos = 0.0;
}
else
{
if (transCodon[i] == transCodon[j])
{
multPur = 1.0;
multNeu = 1.0;
multPos = 1.0;
}
else
{
multPur = 0.0;
multNeu = 1.0;
multPos = nonsyn;
}
if (isTransition == YES)
{
multPur *= kap;
multNeu *= kap;
multPos *= kap;
}
}
sPur[i][j] = baseFreq[temp + j] * multPur;
sPur[j][i] = baseFreq[temp + i] * multPur;
sNeu[i][j] = baseFreq[temp + j] * multNeu;
sNeu[j][i] = baseFreq[temp + i] * multNeu;
sPos[i][j] = baseFreq[temp + j] * multPos;
sPos[j][i] = baseFreq[temp + i] * multPos;
}
}
/* get scalers for q matrices */
scaler = 0.0;
for (i=0; i<nStates; i++)
{
for (j=0; j<nStates; j++)
{
if (i != j)
{
codonFreq = baseFreq[temp + i];
scaler += codonFreq * piPur * sPur[i][j];
scaler += codonFreq * piNeu * sNeu[i][j];
scaler += codonFreq * piPos * sPos[i][j];
}
}
}
/* rescale Q matrices (off diagonals) */
scaler = 1.0 / scaler;
for (i=0; i<nStates; i++)
{
for (j=0; j<nStates; j++)
{
if (i != j)
{
sPur[i][j] *= scaler;
sNeu[i][j] *= scaler;
sPos[i][j] *= scaler;
}
}
}
/* rescale Q matrices (diagonals) */
for (i=0; i<nStates; i++)
{
multPur = multNeu = multPos = 0.0;
for (j=0; j<nStates; j++)
{
if (i != j)
{
multPur += sPur[i][j];
multNeu += sNeu[i][j];
multPos += sPos[i][j];
}
}
multPur += (piNeu + piPos) * sr;
multNeu += (piPur + piPos) * sr;
multPos += (piNeu + piNeu) * sr;
sPur[i][i] = -multPur;
sNeu[i][i] = -multNeu;
sPos[i][i] = -multPos;
}
/* fill in a matrix */
for (i=0; i<nLocalStates; i++)
for (j=0; j<nLocalStates; j++)
a[i][j] = 0.0;
for (i=0; i<nStates; i++)
{
for (j=0; j<nStates; j++)
{
a[i][j] = sPur[i][j];
a[nStates+i][nStates+j] = sNeu[i][j];
a[twoTimesS+i][twoTimesS+j] = sPos[i][j];
if (i == j)
{
a[i][nStates + j] = piNeu * sr;
a[i][twoTimesS + j] = piPos * sr;
a[nStates + i][j] = piPur * sr;
a[nStates + i][twoTimesS + j] = piPos * sr;
a[twoTimesS + i][j] = piPur * sr;
a[twoTimesS + i][nStates + j] = piNeu * sr;
}
}
}
free_psdmatrix (sPur);
free_psdmatrix (sNeu);
free_psdmatrix (sPos);
# if 0
printf ("k = %lf w = %lf\n", kap, nonsyn);
for (i=0; i<nLocalStates; i++)
{
for (j=0; j<nLocalStates; j++)
printf ("%0.4lf ", a[i][j]);
printf ("\n");
}
printf ("%lf %lf %lf %lf\n", piPur, piNeu, piPos, sr);
# endif
return (NO_ERROR);
}
int SetAACovQMatrix (double **a, int whichTree, int whichChain, double r)
{
register int i, j, count, temp;
double scaler, mult, s[20][20], probOn, sum, s1, s2;
probOn = switchPi[whichChain*4 + whichTree*2 + 0];
s1 = switchRate[whichChain*4 + whichTree*2 + 0];
s2 = switchRate[whichChain*4 + whichTree*2 + 1];
/* set matrix a to 0 */
for (i=0; i<40; i++)
for (j=0; j<40; j++)
a[i][j] = 0.0;
if (aaModelType == POISSON)
{
scaler = 0.0;
for (i=0; i<nStates; i++)
{
for (j=i+1; j<nStates; j++)
{
s[i][j] = 0.05;
s[j][i] = 0.05;
scaler += 0.05 * s[i][j] * probOn;
scaler += 0.05 * s[j][i] * probOn;
}
}
}
else if (aaModelType == EQUALIN)
{
scaler = 0.0;
for (i=0; i<nStates; i++)
{
for (j=i+1; j<nStates; j++)
{
s[i][j] = baseFreq[whichChain*2*nStates + whichTree*nStates + j];
s[j][i] = baseFreq[whichChain*2*nStates + whichTree*nStates + i];
scaler += baseFreq[whichChain*2*nStates + whichTree*nStates + i] * s[i][j] * probOn;
scaler += baseFreq[whichChain*2*nStates + whichTree*nStates + j] * s[j][i] * probOn;
}
}
}
else if (aaModelType == JONES)
{
scaler = 0.0;
for (i=0; i<nStates; i++)
{
for (j=i+1; j<nStates; j++)
{
s[i][j] = jonesPi[j] * aaJones[i][j];
s[j][i] = jonesPi[i] * aaJones[j][i];
scaler += jonesPi[i] * s[i][j] * probOn;
scaler += jonesPi[j] * s[j][i] * probOn;
}
}
}
else if (aaModelType == DAYHOFF)
{
scaler = 0.0;
for (i=0; i<nStates; i++)
{
for (j=i+1; j<nStates; j++)
{
s[i][j] = dayhoffPi[j] * aaDayhoff[i][j];
s[j][i] = dayhoffPi[i] * aaDayhoff[j][i];
scaler += dayhoffPi[i] * s[i][j] * probOn;
scaler += dayhoffPi[j] * s[j][i] * probOn;
}
}
}
else if (aaModelType == GTR)
{
temp = whichChain*2*190 + whichTree*190;
count = 0;
scaler = 0.0;
for (i=0; i<nStates; i++)
{
for (j=i+1; j<nStates; j++)
{
if (count >= 190)
{
printf (" ERROR: AA model went out of bounds\n");
return (ERROR);
}
mult = subParams[temp + count];
s[i][j] = baseFreq[whichChain*2*nStates + whichTree*nStates + j] * mult;
s[j][i] = baseFreq[whichChain*2*nStates + whichTree*nStates + i] * mult;
scaler += baseFreq[whichChain*2*nStates + whichTree*nStates + i] * s[i][j] * probOn;
scaler += baseFreq[whichChain*2*nStates + whichTree*nStates + j] * s[j][i] * probOn;
count++;
}
}
}
/* rescale off diagonal elements of Q matrix */
scaler = 1.0 / scaler;
for (i=0; i<nStates; i++)
{
for (j=0; j<nStates; j++)
{
if (i != j)
s[i][j] *= scaler;
}
}
/* now, scale by rate factor */
for (i=0; i<nStates; i++)
{
for (j=0; j<nStates; j++)
{
if (i != j)
s[i][j] *= r;
}
}
/* put in diagonal elements */
for (i=0; i<nStates; i++)
{
sum = 0.0;
for (j=0; j<nStates; j++)
{
if (i != j)
sum += s[i][j];
s[i][i] = -(sum + s1);
}
}
/* now, put s into top left portion of a matrix and other parts of the matrix */
for (i=0; i<nStates; i++)
for (j=0; j<nStates; j++)
a[i][j] = s[i][j];
for (i=nStates; i<2*nStates; i++)
a[i][i] = -s2;
for (i=0; i<nStates; i++)
{
a[i][nStates+i] = s1;
a[nStates+i][i] = s2;
}
# if 0
for (i=0; i<nStates; i++)
{
for (j=0; j<nStates; j++)
printf ("%0.5lf ", a[i][j]);
printf ("\n");
}
# endif
return (NO_ERROR);
}
int SetDNACovQMatrix (double **a, int whichTree, int whichChain, double r)
{
register int i, j;
double scaler, mult, s[4][4], probOn, sum, s1, s2;
probOn = switchPi[whichChain*4 + whichTree*2 + 0];
s1 = switchRate[whichChain*4 + whichTree*2 + 0];
s2 = switchRate[whichChain*4 + whichTree*2 + 1];
/* set matrix a to 0 */
for (i=0; i<8; i++)
for (j=0; j<8; j++)
a[i][j] = 0.0;
if (nst == 1)
{
scaler = 0.0;
for (i=0; i<4; i++)
{
for (j=i+1; j<4; j++)
{
s[i][j] = baseFreq[whichChain*8 + whichTree*4 + j];
s[j][i] = baseFreq[whichChain*8 + whichTree*4 + i];
scaler += baseFreq[whichChain*8 + whichTree*4 + i] * s[i][j] * probOn;
scaler += baseFreq[whichChain*8 + whichTree*4 + j] * s[j][i] * probOn;
}
}
}
else if (nst == 2)
{
scaler = 0.0;
for (i=0; i<4; i++)
{
for (j=i+1; j<4; j++)
{
if ((i == 0 && j == 2) || (i == 2 && j == 0) || (i == 1 && j == 3) || (i == 3 && j == 1))
mult = kappa[whichChain*2 + whichTree];
else if (i == 0 && j == 2)
mult = 1.0;
s[i][j] = baseFreq[whichChain*8 + whichTree*4 + j] * mult;
s[j][i] = baseFreq[whichChain*8 + whichTree*4 + i] * mult;
scaler += baseFreq[whichChain*8 + whichTree*4 + i] * s[i][j] * probOn;
scaler += baseFreq[whichChain*8 + whichTree*4 + j] * s[j][i] * probOn;
}
}
}
else if (nst == 6)
{
scaler = 0.0;
for (i=0; i<4; i++)
{
for (j=i+1; j<4; j++)
{
if (i == 0 && j == 1)
mult = subParams[whichChain*12 + whichTree*6 + 5];
else if (i == 0 && j == 2)
mult = subParams[whichChain*12 + whichTree*6 + 4];
else if (i == 0 && j == 3)
mult = subParams[whichChain*12 + whichTree*6 + 3];
else if (i == 1 && j == 2)
mult = subParams[whichChain*12 + whichTree*6 + 2];
else if (i == 1 && j == 3)
mult = subParams[whichChain*12 + whichTree*6 + 1];
else if (i == 2 && j == 3)
mult = subParams[whichChain*12 + whichTree*6 + 0];
s[i][j] = baseFreq[whichChain*8 + whichTree*4 + j] * mult;
s[j][i] = baseFreq[whichChain*8 + whichTree*4 + i] * mult;
scaler += baseFreq[whichChain*8 + whichTree*4 + i] * s[i][j] * probOn;
scaler += baseFreq[whichChain*8 + whichTree*4 + j] * s[j][i] * probOn;
}
}
}
/* rescale off diagonal elements of Q matrix */
scaler = 1.0 / scaler;
for (i=0; i<4; i++)
{
for (j=0; j<4; j++)
{
if (i != j)
s[i][j] *= scaler;
}
}
/* now, scale by rate factor */
for (i=0; i<4; i++)
{
for (j=0; j<4; j++)
{
if (i != j)
s[i][j] *= r;
}
}
/* put in diagonal elements */
for (i=0; i<4; i++)
{
sum = 0.0;
for (j=0; j<4; j++)
{
if (i != j)
sum += s[i][j];
s[i][i] = -(sum + s1);
}
}
/* now, put s into top left portion of a matrix and other parts of the matrix */
for (i=0; i<4; i++)
for (j=0; j<4; j++)
a[i][j] = s[i][j];
for (i=4; i<8; i++)
a[i][i] = -s2;
a[0][4] = s1;
a[1][5] = s1;
a[2][6] = s1;
a[3][7] = s1;
a[4][0] = s2;
a[5][1] = s2;
a[6][2] = s2;
a[7][3] = s2;
# if 0
for (i=0; i<8; i++)
{
for (j=0; j<8; j++)
printf ("%0.5lf ", a[i][j]);
printf ("\n");
}
# endif
return (NO_ERROR);
}
int SetGCSwitchQMatrix (double **a, int whichTree, int whichChain, double r)
{
register int i, j;
double scaler, mult, q0[4][4], q1[4][4], bs0[4], bs1[4], prob0, prob1, sum, s01, s10;
s01 = switchRate[whichChain*4 + whichTree*2 + 0];
s10 = switchRate[whichChain*4 + whichTree*2 + 1];
prob0 = s10 / (s01+s10);
prob1 = s01 / (s01+s10);
bs0[A] = (1.0 - gc1[whichChain*2 + whichTree]) * (fracA[whichChain*2 + whichTree]);
bs0[C] = (gc1[whichChain*2 + whichTree]) * (1.0 - fracG[whichChain*2 + whichTree]);
bs0[G] = (gc1[whichChain*2 + whichTree]) * (fracG[whichChain*2 + whichTree]);
bs0[T] = (1.0 - gc1[whichChain*2 + whichTree]) * (1.0 - fracA[whichChain*2 + whichTree]);
bs1[A] = (1.0 - gc2[whichChain*2 + whichTree]) * (fracA[whichChain*2 + whichTree]);
bs1[C] = (gc2[whichChain*2 + whichTree]) * (1.0 - fracG[whichChain*2 + whichTree]);
bs1[G] = (gc2[whichChain*2 + whichTree]) * (fracG[whichChain*2 + whichTree]);
bs1[T] = (1.0 - gc2[whichChain*2 + whichTree]) * (1.0 - fracA[whichChain*2 + whichTree]);
/* set matrix a to 0 */
for (i=0; i<8; i++)
for (j=0; j<8; j++)
a[i][j] = 0.0;
if (nst == 1)
{
scaler = 0.0;
for (i=0; i<4; i++)
{
for (j=i+1; j<4; j++)
{
q0[i][j] = bs0[j];
q0[j][i] = bs0[i];
scaler += bs0[i] * q0[i][j] * prob0;
scaler += bs0[j] * q0[j][i] * prob0;
q1[i][j] = bs1[j];
q1[j][i] = bs1[i];
scaler += bs1[i] * q1[i][j] * prob1;
scaler += bs1[j] * q1[j][i] * prob1;
}
}
}
else if (nst == 2)
{
scaler = 0.0;
for (i=0; i<4; i++)
{
for (j=i+1; j<4; j++)
{
if ((i == 0 && j == 2) || (i == 2 && j == 0) || (i == 1 && j == 3) || (i == 3 && j == 1))
mult = kappa[whichChain*2 + whichTree];
else if (i == 0 && j == 2)
mult = 1.0;
q0[i][j] = bs0[j] * mult;
q0[j][i] = bs0[i] * mult;
scaler += bs0[i] * q0[i][j] * prob0;
scaler += bs0[j] * q0[j][i] * prob0;
q1[i][j] = bs1[j] * mult;
q1[j][i] = bs1[i] * mult;
scaler += bs1[i] * q1[i][j] * prob1;
scaler += bs1[j] * q1[j][i] * prob1;
}
}
}
else if (nst == 6)
{
scaler = 0.0;
for (i=0; i<4; i++)
{
for (j=i+1; j<4; j++)
{
if (i == 0 && j == 1)
mult = subParams[whichChain*12 + whichTree*6 + 5];
else if (i == 0 && j == 2)
mult = subParams[whichChain*12 + whichTree*6 + 4];
else if (i == 0 && j == 3)
mult = subParams[whichChain*12 + whichTree*6 + 3];
else if (i == 1 && j == 2)
mult = subParams[whichChain*12 + whichTree*6 + 2];
else if (i == 1 && j == 3)
mult = subParams[whichChain*12 + whichTree*6 + 1];
else if (i == 2 && j == 3)
mult = subParams[whichChain*12 + whichTree*6 + 0];
q0[i][j] = bs0[j] * mult;
q0[j][i] = bs0[i] * mult;
scaler += bs0[i] * q0[i][j] * prob0;
scaler += bs0[j] * q0[j][i] * prob0;
q1[i][j] = bs1[j] * mult;
q1[j][i] = bs1[i] * mult;
scaler += bs1[i] * q1[i][j] * prob1;
scaler += bs1[j] * q1[j][i] * prob1;
}
}
}
/* rescale off diagonal elements of Q matrix */
scaler = 1.0 / scaler;
for (i=0; i<4; i++)
{
for (j=0; j<4; j++)
{
if (i != j)
{
q0[i][j] *= scaler;
q1[i][j] *= scaler;
}
}
}
/* now, scale by rate factor */
for (i=0; i<4; i++)
{
for (j=0; j<4; j++)
{
if (i != j)
{
q0[i][j] *= r;
q1[i][j] *= r;
}
}
}
/* put in diagonal elements */
for (i=0; i<4; i++)
{
sum = 0.0;
for (j=0; j<4; j++)
{
if (i != j)
sum += q0[i][j];
q0[i][i] = -(sum + s01);
}
sum = 0.0;
for (j=0; j<4; j++)
{
if (i != j)
sum += q1[i][j];
q1[i][i] = -(sum + s10);
}
}
/* now, put q0 into top left portion of matrix and q1 in bottom right portion*/
for (i=0; i<4; i++)
for (j=0; j<4; j++)
a[i][j] = q0[i][j];
for (i=4; i<8; i++)
for (j=4; j<8; j++)
a[i][j] = q1[i-4][j-4];
a[0][4] = s01;
a[1][5] = s01;
a[2][6] = s01;
a[3][7] = s01;
a[4][0] = s10;
a[5][1] = s10;
a[6][2] = s10;
a[7][3] = s10;
# if 0
for (i=0; i<8; i++)
{
for (j=0; j<8; j++)
printf ("%0.5lf ", a[i][j]);
printf ("\n");
}
# endif
return (NO_ERROR);
}
int SetQMatrix (double **a, int whichTree, int whichChain)
{
register int i, j, k;
int isComplex, stopLoop;
double scaler, mult, **q, *eigenValues, *eigvalsImag,
**eigvecs, **inverseEigvecs, *c_ijk, **probs, v, max;
complex **Ceigvecs, **CinverseEigvecs;
/* set diagonal of Q matrix to 0 */
for (i=0; i<4; i++)
a[i][i] = 0.0;
if (nst == 6)
{
scaler = 0.0;
for (i=0; i<4; i++)
{
for (j=i+1; j<4; j++)
{
if (i == 0 && j == 1)
mult = subParams[whichChain*12 + whichTree*6 + 5];
else if (i == 0 && j == 2)
mult = subParams[whichChain*12 + whichTree*6 + 4];
else if (i == 0 && j == 3)
mult = subParams[whichChain*12 + whichTree*6 + 3];
else if (i == 1 && j == 2)
mult = subParams[whichChain*12 + whichTree*6 + 2];
else if (i == 1 && j == 3)
mult = subParams[whichChain*12 + whichTree*6 + 1];
else if (i == 2 && j == 3)
mult = subParams[whichChain*12 + whichTree*6 + 0];
a[i][i] -= (a[i][j] = baseFreq[whichChain*8 + whichTree*4 + j] * mult);
a[j][j] -= (a[j][i] = baseFreq[whichChain*8 + whichTree*4 + i] * mult);
scaler += baseFreq[whichChain*8 + whichTree*4 + i] * a[i][j];
scaler += baseFreq[whichChain*8 + whichTree*4 + j] * a[j][i];
}
}
/* rescale Q matrix */
scaler = 1.0 / scaler;
for (i=0; i<4; i++)
for (j=0; j<4; j++)
a[i][j] *= scaler;
}
else if (nst == 12)
{
for (i=0; i<4; i++)
{
for (j=0; j<4; j++)
{
if (i != j)
{
if (i == 0 && j == 1)
mult = subParams[whichChain*24 + whichTree*12 + 0];
else if (i == 0 && j == 2)
mult = subParams[whichChain*24 + whichTree*12 + 1];
else if (i == 0 && j == 3)
mult = subParams[whichChain*24 + whichTree*12 + 2];
else if (i == 1 && j == 2)
mult = subParams[whichChain*24 + whichTree*12 + 3];
else if (i == 1 && j == 3)
mult = subParams[whichChain*24 + whichTree*12 + 4];
else if (i == 2 && j == 3)
mult = subParams[whichChain*24 + whichTree*12 + 5];
else if (i == 1 && j == 0)
mult = subParams[whichChain*24 + whichTree*12 + 6];
else if (i == 2 && j == 0)
mult = subParams[whichChain*24 + whichTree*12 + 7];
else if (i == 3 && j == 0)
mult = subParams[whichChain*24 + whichTree*12 + 8];
else if (i == 2 && j == 1)
mult = subParams[whichChain*24 + whichTree*12 + 9];
else if (i == 3 && j == 1)
mult = subParams[whichChain*24 + whichTree*12 + 10];
else if (i == 3 && j == 2)
mult = subParams[whichChain*24 + whichTree*12 + 11];
a[i][i] -= (a[i][j] = mult);
}
}
}
/* now, figure out base frequencies (if v -> infty) */
probs = psdmatrix (4);
q = psdmatrix (4);
eigenValues = (double *)malloc((size_t) (4 * sizeof(double)));
if (!eigenValues)
{
printf ("\n ERROR: Cannot allocate eigenValues.\n");
return (ERROR);
}
eigvalsImag = (double *)malloc((size_t) (4 * sizeof(double)));
if (!eigvalsImag)
{
printf ("\n ERROR: Cannot allocate eigvalsImag.\n");
free (eigenValues);
return (ERROR);
}
eigvecs = psdmatrix (4);
inverseEigvecs = psdmatrix (4);
Ceigvecs = pscmatrix (4);
CinverseEigvecs = pscmatrix (4);
for (i=0; i<4; i++)
for (j=0; j<4; j++)
q[i][j] = a[i][j];
isComplex = GetEigens (4, q, eigenValues, eigvalsImag, eigvecs, inverseEigvecs, Ceigvecs, CinverseEigvecs);
if (isComplex == NO)
{
c_ijk = (double *)malloc((size_t) (4 * 4 * 4 * sizeof(double)));
if (!c_ijk)
{
printf ("\n ERROR: Cannot allocate c_ijk.\n");
free (eigenValues);
free (eigvalsImag);
return (ERROR);
}
CalcCijk (c_ijk, 4, eigvecs, inverseEigvecs);
}
stopLoop = NO;
v = 0.1;
do
{
if (isComplex == NO)
{
CalcPij (c_ijk, 4, eigenValues, v, 1.0, probs);
}
else
{
if (ComplexChangeMatrix (eigenValues, eigvalsImag, Ceigvecs, CinverseEigvecs, 4, probs, v, 1.0) == ERROR)
printf ("Problem calculating transition probabilities for complex eigen values.\n");
}
stopLoop = YES;
for (i=0; i<4; i++)
{
max = 0.0;
for (j=0; j<3; j++)
{
for (k=j+1; k<4; k++)
{
if (fabs(probs[j][i] - probs[k][i]) > max)
max = fabs(probs[j][i] - probs[k][i]);
}
}
if (max > 0.00000001)
stopLoop = NO;
}
/*printf ("v = %lf\n", v);
for (i=0; i<4; i++)
{
for (j=0; j<4; j++)
printf ("%lf ", probsL[i][j]);
printf ("\n");
}*/
v *= 2.0;
if (v > 10000.0)
{
printf ("\n ERROR: Q matrix does not have a stationary distribution\n");
for (i=0; i<4; i++)
{
for (j=0; j<4; j++)
printf ("%lf ", a[i][j]);
printf ("\n");
}
free_psdmatrix (probs);
free_psdmatrix (q);
free (eigenValues);
free (eigvalsImag);
free_psdmatrix (eigvecs);
free_psdmatrix (inverseEigvecs);
free_pscmatrix (Ceigvecs);
free_pscmatrix (CinverseEigvecs);
if (isComplex == NO)
free (c_ijk);
return (ERROR);
}
} while (stopLoop == NO);
baseFreq[whichChain*8 + whichTree*4 + A] = probs[whichTree][0];
baseFreq[whichChain*8 + whichTree*4 + C] = probs[whichTree][1];
baseFreq[whichChain*8 + whichTree*4 + G] = probs[whichTree][2];
baseFreq[whichChain*8 + whichTree*4 + T] = probs[whichTree][3];
free_psdmatrix (probs);
free_psdmatrix (q);
free (eigenValues);
free (eigvalsImag);
free_psdmatrix (eigvecs);
free_psdmatrix (inverseEigvecs);
free_pscmatrix (Ceigvecs);
free_pscmatrix (CinverseEigvecs);
if (isComplex == NO)
free (c_ijk);
/* get scaler */
scaler = 0.0;
for (i=0; i<4; i++)
scaler += baseFreq[whichChain*8 + whichTree*4 + i] * (-a[i][i]);
/* rescale Q matrix */
scaler = 1.0 / scaler;
for (i=0; i<4; i++)
for (j=0; j<4; j++)
a[i][j] *= scaler;
/*printf ("%lf %lf %lf %lf\n", baseFreq[whichChain*8 + whichTree*4 + A], baseFreq[whichChain*8 + whichTree*4 + C],
baseFreq[whichChain*8 + whichTree*4 + G], baseFreq[whichChain*8 + whichTree*4 + T]);*/
}
else
{
printf ("\n ERROR: Unknown model type in Q matrix\n");
return (ERROR);
}
# if 0
for (i=0; i<4; i++)
{
for (j=0; j<4; j++)
printf ("%0.5lf ", a[i][j]);
printf ("\n");
}
# endif
return (NO_ERROR);
}
# if defined (SMART_TI_PROBS)
int SetUpTransitionProbs (int numRateCats)
{
int i, lnStates, nRates, lnPartitions, lnumRateCats;
/* how many states and rates are there? */
if ((dataType == DNA || dataType == RNA) && enforceCodonModel == NO)
{
if (!strcmp(ratesModel, "sitespec") || !strcmp(ratesModel, "ssgamma") || !strcmp(ratesModel, "ssadgamma"))
lnPartitions = nPartitions;
else
lnPartitions = 1;
if (!strcmp(ratesModel, "equal") || !strcmp(ratesModel, "sitespec"))
lnumRateCats = 1;
else
lnumRateCats = numRateCats;
nRates = lnPartitions * lnumRateCats;
if (useCovarion == NO)
{
lnStates = 4;
}
else
{
lnStates = 2 * nStates;
}
}
else if ((dataType == DNA || dataType == RNA) && enforceCodonModel == YES)
{
if (useCovarion == NO)
{
if (!strcmp(codonModelType, "covny98"))
lnStates = 3 * nStates;
else
lnStates = nStates;
if (!strcmp(codonModelType, "ny98") || !strcmp(codonModelType, "ac1ny98") || !strcmp(codonModelType, "ac2ny98"))
nRates = 3;
else
nRates = 1;
}
else
{
return (ERROR);
}
}
else if (dataType == PROTEIN)
{
if (!strcmp(ratesModel, "sitespec") || !strcmp(ratesModel, "ssgamma") || !strcmp(ratesModel, "ssadgamma"))
lnPartitions = nPartitions;
else
lnPartitions = 1;
if (!strcmp(ratesModel, "equal") || !strcmp(ratesModel, "sitespec"))
lnumRateCats = 1;
else
lnumRateCats = numRateCats;
nRates = lnPartitions * lnumRateCats;
if (useCovarion == NO)
{
lnStates = 20;
}
else
{
lnStates = 2 * nStates;
}
}
else if (dataType == RESTRICTION)
{
if (!strcmp(ratesModel, "sitespec") || !strcmp(ratesModel, "ssgamma") || !strcmp(ratesModel, "ssadgamma"))
lnPartitions = nPartitions;
else
lnPartitions = 1;
if (!strcmp(ratesModel, "equal") || !strcmp(ratesModel, "sitespec"))
lnumRateCats = 1;
else
lnumRateCats = numRateCats;
nRates = lnPartitions * lnumRateCats;
if (useCovarion == NO)
{
lnStates = 2;
}
else
{
return (ERROR);
}
}
else if (dataType == STANDARD)
{
if (!strcmp(ratesModel, "sitespec") || !strcmp(ratesModel, "ssgamma") || !strcmp(ratesModel, "ssadgamma"))
lnPartitions = nPartitions;
else
lnPartitions = 1;
if (!strcmp(ratesModel, "equal") || !strcmp(ratesModel, "sitespec"))
lnumRateCats = 1;
else
lnumRateCats = numRateCats;
nRates = lnPartitions * lnumRateCats;
if (useCovarion == NO)
{
lnStates = 2;
}
else
{
return (ERROR);
}
}
else
return (ERROR);
/* how big is the information at one node */
nodeTiSize = nRates * lnStates * lnStates;
/* allocate enough memory for all of the transition probabilities on the tree */
transitionProbs = (double *)malloc((size_t) (numChains * 2 * numNodes * nodeTiSize * sizeof(double)));
if (!transitionProbs)
{
printf ("ERROR: Problem allocating transitionProbs\n");
return (ERROR);
}
else
allocatedMemory[ALLOC_TI_PROBS] = YES;
updateTiFlag = (int *)malloc((size_t) (numNodes * sizeof(int)));
if (!updateTiFlag)
{
printf ("ERROR: Problem allocating updateTiFlag\n");
return (ERROR);
}
else
allocatedMemory[ALLOC_TI_FLAGS] = YES;
for (i=0; i<numNodes; i++)
updateTiFlag[i] = NO;
return (NO_ERROR);
}
# endif
int SetUpTrees (int numTaxa)
{
int i, j, n;
TreeNode *p;
if (treeModel == ROOTED)
{
numNodes = 2*numTaxa;
numIntNodes = numTaxa-1;
}
else
{
numNodes = 2*numTaxa-2;
numIntNodes = numTaxa - 2;
}
printf (" Allocating traversal memory\n");
intNodeDownPassSeq = (TreeNode **)malloc((size_t) (numChains*2*numIntNodes) * sizeof(TreeNode *));
if (!intNodeDownPassSeq)
{
printf ("\n ERROR: Problem allocating intNodeDownPassSeq\n");
FreeMemory ();
return (ERROR);
}
else
allocatedMemory[ALLOC_INTDOWNPASS] = YES;
allNodesDownPassSeq = (TreeNode **)malloc((size_t) (numChains*2*numNodes) * sizeof(TreeNode *));
if (!allNodesDownPassSeq)
{
printf ("\n ERROR: Problem allocating allNodesDownPassSeq\n");
FreeMemory ();
return (ERROR);
}
else
allocatedMemory[ALLOC_ALLDOWNPASS] = YES;
printf (" Getting downpass information\n");
for (n=0; n<numChains; n++)
{
i = j = 0;
GetDownPassSeq (root[n*2+0], 0, n, numTaxa, &i, &j);
for (i=0; i<numNodes; i++)
{
p = allNodesDownPassSeq[n*2*numNodes+i];
p->scaler = 0.0;
p->scalerNode = NO;
if (p->length < BRLEN_EPSILON)
p->length = 2 * BRLEN_EPSILON;
}
//printf ("Starting tree %d:\n", n);
//ShowTree (spTreeRoot[n*2+0], 2);
}
clUpdateFlag = (int *)malloc((size_t) numNodes * sizeof(int));
if (!clUpdateFlag)
{
printf ("\n ERROR: Problem allocating clUpdateFlag\n");
FreeMemory ();
return (ERROR);
}
else
allocatedMemory[ALLOC_CLUPDATE_FLAG] = YES;
for (i=0; i<numNodes; i++)
clUpdateFlag[i] = NO;
scalerUpdateFlag = (int *)malloc((size_t) numNodes * sizeof(int));
if (!scalerUpdateFlag)
{
printf ("\n ERROR: Problem allocating scalerUpdateFlag\n");
FreeMemory ();
return (ERROR);
}
else
allocatedMemory[ALLOC_SCALER_UPDATE_FLAG] = YES;
for (i=0; i<numNodes; i++)
scalerUpdateFlag[i] = NO;
return (NO_ERROR);
}
#define EDDIE_NODES
int ShowStartTree (TreeNode *r, int nt, int isThisTreeRooted)
{
int i, j, k, nNodes, x, nLines, nLevels, levelDepth, from, to;
char treeLine[SCREENWIDTH2], labelLine[100];
TreeNode **downPass, *p;
/* get down pass sequence */
if (isThisTreeRooted == YES)
nNodes = 2 * nt;
else
nNodes = 2 * nt - 2;
downPass = (TreeNode **)malloc((size_t) (2 * nTaxa * sizeof(TreeNode *)));
if (!downPass)
{
printf (" ERROR: Could not allocate downPass\n");
return (ERROR);
}
i = 0;
GetTempDownPassSeq (r, &i, downPass);
/* get coordinates */
x = 0;
nLines = 0;
for (i=0; i<nNodes; i++)
{
p = downPass[i];
if (p->left == NULL && p->right == NULL)
{
p->x = x;
x += 2;
p->y = 0;
nLines += 2;
}
else if (p->left != NULL && p->right != NULL && p->anc != NULL)
{
p->x = p->left->x + (p->right->x - p->left->x) / 2;
if (p->left->y > p->right->y)
p->y = p->left->y + 1;
else
p->y = p->right->y + 1;
}
else
{
p->x = x;
x += 2;
p->y = 0;
}
}
/* print tree out, line-by-line */
levelDepth = SCREENWIDTH / r->left->y;
nLevels = r->left->y;
for (j=0; j<=nLines-2; j++)
{
if (j % 2 == 0)
{
for (i=0; i<nNodes; i++)
{
p = downPass[i];
if (p->left == NULL && p->x == j)
{
strcpy (labelLine, p->label);
}
}
}
for (i=0; i<SCREENWIDTH; i++)
treeLine[i] = ' ';
treeLine[SCREENWIDTH-1] = '\0';
for (i=0; i<nNodes; i++)
{
p = downPass[i];
if (p->anc != NULL)
{
if (p->anc->anc != NULL)
{
if (p->x == j)
{
from = (nLevels - p->anc->y) * levelDepth;
to = (nLevels - p->y) * levelDepth;
if (p->y == 0)
to = SCREENWIDTH-1;
if (to >= SCREENWIDTH)
to = SCREENWIDTH-1;
for (k=from; k<to; k++)
treeLine[k] = '-';
if (p->anc->left == p)
treeLine[from] = '/';
else
treeLine[from] = '\\';
if (p->left != NULL)
{
# if defined (EDDIE_NODES)
treeLine[to] = '|';
# else
treeLine[to] = '+';
# endif
}
if (p->anc->anc == r && p->anc->right == p)
{
if (isThisTreeRooted == NO)
{
if (p->left != NULL)
# if defined (EDDIE_NODES)
treeLine[to] = '|';
# else
treeLine[to] = '+';
# endif
}
else
treeLine[from] = '\\';
}
}
else if (p->left != NULL && p->right != NULL)
{
if (j < p->x && j > p->left->x)
{
from = (nLevels - p->y) * levelDepth;
treeLine[from] = '|';
}
else if (j > p->x && j < p->right->x)
{
from = (nLevels - p->y) * levelDepth;
treeLine[from] = '|';
}
}
}
else
{
if (p->x == j)
{
treeLine[0] = '|'; /* temp */
}
else if (j < p->x && j > p->left->x)
{
treeLine[0] = '|';
}
else if (j > p->x && j < p->right->x)
{
treeLine[0] = '|';
}
if (isThisTreeRooted == NO)
{
if (j > p->x && j <= nLines-2)
treeLine[0] = '|';
if (j == p->right->x)
# if defined (EDDIE_NODES)
treeLine[0] = '|';
# else
treeLine[0] = '+';
# endif
}
else
{
if (j == p->x)
# if defined (EDDIE_NODES)
treeLine[0] = '|';
# else
treeLine[0] = '+';
# endif
}
}
}
}
if (j % 2 == 0)
printf (" %s %s\n", treeLine, labelLine);
else
printf (" %s \n", treeLine);
}
if (isThisTreeRooted == NO)
{
for (i=0; i<SCREENWIDTH; i++)
treeLine[i] = ' ';
treeLine[SCREENWIDTH-1] = '\0';
printf (" |\n");
for (k=0; k<SCREENWIDTH; k++)
treeLine[k] = '-';
treeLine[SCREENWIDTH-1] = '\0';
treeLine[0] = '\\';
strcpy (labelLine, r->label);
labelLine[19] = '\0';
printf (" %s %s\n", treeLine, labelLine);
}
free (downPass);
return (NO_ERROR);
}
void UpDateAllCls (int whichState, int whichChain)
{
int i;
TreeNode *p;
for (i=0; i<numNodes; i++)
{
p = allNodesDownPassSeq[whichChain*2*numNodes + whichState*numNodes + i];
p->upDateCl = YES;
}
}
#if defined (SMART_TI_PROBS)
void UpDateAllTIs (int whichState, int whichChain)
{
int i;
TreeNode *p;
for (i=0; i<numNodes; i++)
{
p = allNodesDownPassSeq[whichChain*2*numNodes + whichState*numNodes + i];
p->upDateTi = YES;
}
}
#endif
char WhichAA (int x)
{
if (x == 0)
return ('A');
else if (x == 1)
return ('R');
else if (x == 2)
return ('N');
else if (x == 3)
return ('D');
else if (x == 4)
return ('C');
else if (x == 5)
return ('Q');
else if (x == 6)
return ('E');
else if (x == 7)
return ('G');
else if (x == 8)
return ('H');
else if (x == 9)
return ('I');
else if (x == 10)
return ('L');
else if (x == 11)
return ('K');
else if (x == 12)
return ('M');
else if (x == 13)
return ('F');
else if (x == 14)
return ('P');
else if (x == 15)
return ('S');
else if (x == 16)
return ('T');
else if (x == 17)
return ('W');
else if (x == 18)
return ('Y');
else if (x == 19)
return ('V');
else
return ('?');
}
void WriteTreeToFile (TreeNode *p, FILE *fp, int showBrlens)
{
if (p != NULL)
{
if (p->left == NULL && p->right == NULL)
{
if (showBrlens == YES)
fprintf (fp, "%d:%1.6lf", p->index + 1, p->length);
else
fprintf (fp, "%d", p->index + 1);
}
else
{
if (p->anc != NULL)
fprintf (fp, "(");
WriteTreeToFile (p->left, fp, showBrlens);
if (p->anc != NULL)
fprintf (fp, ",");
WriteTreeToFile (p->right, fp, showBrlens);
if (p->anc != NULL)
{
if (p->anc->anc == NULL)
{
if (treeModel == UNROOTED)
{
if (showBrlens == YES)
fprintf (fp, ",%d:%1.6lf);\n", p->anc->index + 1, p->length);
else
fprintf (fp, ",%d);\n", p->anc->index + 1);
}
else
fprintf (fp, ");\n");
}
else
{
if (showBrlens == YES)
fprintf (fp, "):%1.6lf", p->length);
else
fprintf (fp, ")");
}
}
}
}
}
void WriteTreeToScreen (TreeNode *p, int showBrlens)
{
if (p != NULL)
{
if (p->left == NULL && p->right == NULL)
{
if (showBrlens == YES)
printf ("%s:%1.6lf", p->label, p->length);
else
printf ("%s", p->label);
}
else
{
if (p->anc != NULL)
printf ("(");
WriteTreeToScreen (p->left, showBrlens);
if (p->anc != NULL)
printf (",");
WriteTreeToScreen (p->right, showBrlens);
if (p->anc != NULL)
{
if (p->anc->anc == NULL)
{
if (showBrlens == YES)
printf (",%s:%1.6lf);\n", p->anc->label, p->length);
else
printf (",%s);\n", p->anc->label);
}
else
{
if (showBrlens == YES)
printf ("):%1.6lf", p->length);
else
printf (")");
}
}
}
}
}
int YesNo (void)
{
char tempString[20], *s;
unsigned int i;
for (;;)
{
fgets (tempString,20,stdin);
s = strtok(tempString," ;\n");
for (i=0; i<strlen(tempString); i++)
s[i] = tolower(s[i]);
if (!strcmp(tempString,"yes") || !strcmp(tempString,"y"))
return YES;
else if (!strcmp(tempString,"no") || !strcmp(tempString,"n"))
return NO;
printf (" Enter Yes or No: ");
}
}
|